diff --git a/.gitignore b/.gitignore index a299936..70bea5a 100644 --- a/.gitignore +++ b/.gitignore @@ -85,5 +85,4 @@ ios-final.xcresult # The Rust style compiler and renderer (wasm + their JS bindings), fetched from a # MapConductor/vectortile release by scripts/fetch-vector-assets.mjs. The tag and # checksums are pinned in scripts/vector-assets.json; the bytes are not tracked. -react-vectorstyle/vendor/ react-vectortile/vendor/ diff --git a/.gitmodules b/.gitmodules index 4e74f78..d249114 100644 --- a/.gitmodules +++ b/.gitmodules @@ -94,3 +94,6 @@ [submodule "react-for-deckgl"] path = react-for-deckgl url = git@github.com:MapConductor/react-for-deckgl.git +[submodule "js-vectorstyle"] + path = js-vectorstyle + url = git@github.com:mapconductor/js-vectorstyle.git diff --git a/examples/basic/package.json b/examples/basic/package.json index e70a70d..93fdaa2 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -31,7 +31,7 @@ "@mapconductor/react-heatmap": "*", "@mapconductor/react-icons": "*", "@mapconductor/react-marker-clustering": "*", - "@mapconductor/react-vectorstyle": "*", + "@mapconductor/js-vectorstyle": "*", "@mapconductor/react-vectortile": "*", "@zip.js/zip.js": "^2.8.26", "maplibre-gl": "^6.15.0", diff --git a/examples/basic/src/pages/vectorstyle/StyleAdjustmentsPage.tsx b/examples/basic/src/pages/vectorstyle/StyleAdjustmentsPage.tsx index a1edfe8..62ac7c7 100644 --- a/examples/basic/src/pages/vectorstyle/StyleAdjustmentsPage.tsx +++ b/examples/basic/src/pages/vectorstyle/StyleAdjustmentsPage.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import type { MapDesignTypeInterface, MapViewStateInterface } from '@mapconductor/js-sdk-core'; -import { buildStyleRules, createVectorStyle, LayerRole, NO_STYLE_RULES } from '@mapconductor/react-vectorstyle'; +import { buildStyleRules, createVectorStyle, LayerRole, NO_STYLE_RULES } from '@mapconductor/js-vectorstyle'; import { VectorTileRasteriser } from '@mapconductor/react-vectortile'; import { ControlPanel, SliderControl } from '../../components/ControlPanel'; import { MapViewContainer } from '../../MapViewContainer'; diff --git a/examples/basic/src/pages/vectortile/categories.ts b/examples/basic/src/pages/vectortile/categories.ts index ac082d9..898b3d8 100644 --- a/examples/basic/src/pages/vectortile/categories.ts +++ b/examples/basic/src/pages/vectortile/categories.ts @@ -1,4 +1,4 @@ -import { LayerRole, buildStyleRules, NO_STYLE_RULES, type StyleRules } from '@mapconductor/react-vectorstyle'; +import { LayerRole, buildStyleRules, NO_STYLE_RULES, type StyleRules } from '@mapconductor/js-vectorstyle'; /** A category that can be painted as well as switched off. */ export type ColourCategory = 'water' | 'land' | 'street' | 'building'; diff --git a/js-vectorstyle b/js-vectorstyle new file mode 160000 index 0000000..e36c418 --- /dev/null +++ b/js-vectorstyle @@ -0,0 +1 @@ +Subproject commit e36c418de904d5a4270034b83478487f2a76c9fb diff --git a/package-lock.json b/package-lock.json index 05d640e..7c85a7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,7 +42,7 @@ "react-geojson/", "react-kml/", "react-heatmap/", - "react-vectorstyle/", + "js-vectorstyle/", "react-vectortile/", "react-marker-clustering/", "examples/*" @@ -72,6 +72,7 @@ "dependencies": { "@mapconductor/js-sdk-core": "*", "@mapconductor/js-sdk-react": "*", + "@mapconductor/js-vectorstyle": "*", "@mapconductor/react-for-arcgis": "*", "@mapconductor/react-for-azuremaps": "*", "@mapconductor/react-for-cesium": "*", @@ -92,7 +93,6 @@ "@mapconductor/react-icons": "*", "@mapconductor/react-kml": "*", "@mapconductor/react-marker-clustering": "*", - "@mapconductor/react-vectorstyle": "*", "@mapconductor/react-vectortile": "*", "@zip.js/zip.js": "^2.8.26", "maplibre-gl": "^6.15.0", @@ -262,6 +262,18 @@ "node": ">=0.10.0" } }, + "js-vectorstyle": { + "name": "@mapconductor/js-vectorstyle", + "version": "0.1.0", + "license": "Apache-2.0", + "devDependencies": { + "tsup": "^8.5.1", + "typescript": "^5.9.3" + }, + "peerDependencies": { + "@mapconductor/js-sdk-core": "^0.2.1" + } + }, "node_modules/@amcharts/amcharts5": { "version": "5.18.0", "resolved": "https://registry.npmjs.org/@amcharts/amcharts5/-/amcharts5-5.18.0.tgz", @@ -3054,6 +3066,10 @@ "resolved": "js-sdk-react", "link": true }, + "node_modules/@mapconductor/js-vectorstyle": { + "resolved": "js-vectorstyle", + "link": true + }, "node_modules/@mapconductor/react-for-arcgis": { "resolved": "react-for-arcgis", "link": true @@ -3150,10 +3166,6 @@ "resolved": "react-marker-clustering", "link": true }, - "node_modules/@mapconductor/react-vectorstyle": { - "resolved": "react-vectorstyle", - "link": true - }, "node_modules/@mapconductor/react-vectortile": { "resolved": "react-vectortile", "link": true @@ -15871,14 +15883,6 @@ } } }, - "react-vectorstyle": { - "name": "@mapconductor/react-vectorstyle", - "version": "0.1.0", - "license": "Apache-2.0", - "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.1" - } - }, "react-vectortile": { "name": "@mapconductor/react-vectortile", "version": "0.2.1", @@ -15886,7 +15890,7 @@ "dependencies": { "@mapconductor/js-sdk-core": "^0.2.0", "@mapconductor/js-sdk-react": "^0.2.1", - "@mapconductor/react-vectorstyle": "^0.1.0" + "@mapconductor/js-vectorstyle": "^0.1.0" }, "devDependencies": { "@types/react": "^19.2.0", diff --git a/package.json b/package.json index 2c3e177..148e117 100644 --- a/package.json +++ b/package.json @@ -37,19 +37,19 @@ "react-geojson/", "react-kml/", "react-heatmap/", - "react-vectorstyle/", + "js-vectorstyle/", "react-vectortile/", "react-marker-clustering/", "examples/*" ], "scripts": { "build": "npm run build --workspaces --if-present", - "build:packages": "npm run build --if-present --workspace @mapconductor/js-sdk-core --workspace @mapconductor/js-sdk-react --workspace @mapconductor/react-icons --workspace @mapconductor/react-for-googlemaps --workspace @mapconductor/react-for-maplibre --workspace @mapconductor/react-for-mapbox --workspace @mapconductor/react-for-leaflet --workspace @mapconductor/react-for-openlayers --workspace @mapconductor/react-for-arcgis --workspace @mapconductor/react-for-mapkit --workspace @mapconductor/react-for-azuremaps --workspace @mapconductor/react-for-cesium --workspace @mapconductor/react-for-here --workspace @mapconductor/react-for-tomtom --workspace @mapconductor/react-for-maptiler --workspace @mapconductor/react-for-longdo --workspace @mapconductor/react-for-mappls --workspace @mapconductor/react-for-deckgl --workspace @mapconductor/reactnative-for-googlemaps --workspace @mapconductor/reactnative-for-maplibre --workspace @mapconductor/reactnative-for-arcgis --workspace @mapconductor/reactnative-for-longdo --workspace @mapconductor/reactnative-for-maptiler --workspace @mapconductor/reactnative-for-tomtom --workspace @mapconductor/reactnative-for-mapbox --workspace @mapconductor/react-geojson --workspace @mapconductor/react-kml --workspace @mapconductor/react-heatmap --workspace @mapconductor/react-vectorstyle --workspace @mapconductor/react-vectortile --workspace @mapconductor/react-marker-clustering", + "build:packages": "npm run build --if-present --workspace @mapconductor/js-sdk-core --workspace @mapconductor/js-sdk-react --workspace @mapconductor/react-icons --workspace @mapconductor/react-for-googlemaps --workspace @mapconductor/react-for-maplibre --workspace @mapconductor/react-for-mapbox --workspace @mapconductor/react-for-leaflet --workspace @mapconductor/react-for-openlayers --workspace @mapconductor/react-for-arcgis --workspace @mapconductor/react-for-mapkit --workspace @mapconductor/react-for-azuremaps --workspace @mapconductor/react-for-cesium --workspace @mapconductor/react-for-here --workspace @mapconductor/react-for-tomtom --workspace @mapconductor/react-for-maptiler --workspace @mapconductor/react-for-longdo --workspace @mapconductor/react-for-mappls --workspace @mapconductor/react-for-deckgl --workspace @mapconductor/reactnative-for-googlemaps --workspace @mapconductor/reactnative-for-maplibre --workspace @mapconductor/reactnative-for-arcgis --workspace @mapconductor/reactnative-for-longdo --workspace @mapconductor/reactnative-for-maptiler --workspace @mapconductor/reactnative-for-tomtom --workspace @mapconductor/reactnative-for-mapbox --workspace @mapconductor/react-geojson --workspace @mapconductor/react-kml --workspace @mapconductor/react-heatmap --workspace @mapconductor/js-vectorstyle --workspace @mapconductor/react-vectortile --workspace @mapconductor/react-marker-clustering", "dev": "npm run build:packages && (npm run dev:packages & npm run dev:examples & wait)", "dev:rn": "npm run build:packages && (npm run dev:packages & npm run dev:rn:examples & wait)", "dev:rn:android": "npm run build && npm run expo:android --workspace @mapconductor/example-rn-basic", "dev:rn:ios": "npm run build && npm run expo:prebuild:ios --workspace @mapconductor/example-rn-basic && npm run expo:ios --workspace @mapconductor/example-rn-basic", - "dev:packages": "(npm run dev --workspace @mapconductor/js-sdk-core -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/js-sdk-react -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-icons -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-googlemaps -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-maplibre -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-mapbox -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-leaflet -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-openlayers -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-mapkit -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-azuremaps -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-cesium -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-maptiler -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-longdo -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-mappls -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-deckgl -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-googlemaps -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-maplibre -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-arcgis -- --tsconfig ../tsconfig.dev.json & npm run dev -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-longdo -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-maptiler --workspace @mapconductor/reactnative-for-tomtom -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-mapbox -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-geojson -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-kml -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-heatmap -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-marker-clustering -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-vectorstyle -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-vectortile -- --tsconfig ../tsconfig.dev.json & wait)", + "dev:packages": "(npm run dev --workspace @mapconductor/js-sdk-core -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/js-sdk-react -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-icons -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-googlemaps -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-maplibre -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-mapbox -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-leaflet -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-openlayers -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-mapkit -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-azuremaps -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-cesium -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-maptiler -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-longdo -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-mappls -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-for-deckgl -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-googlemaps -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-maplibre -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-arcgis -- --tsconfig ../tsconfig.dev.json & npm run dev -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-longdo -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-maptiler --workspace @mapconductor/reactnative-for-tomtom -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/reactnative-for-mapbox -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-geojson -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-kml -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-heatmap -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-marker-clustering -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/js-vectorstyle -- --tsconfig ../tsconfig.dev.json & npm run dev --workspace @mapconductor/react-vectortile -- --tsconfig ../tsconfig.dev.json & wait)", "dev:examples": "npm run dev --workspace @mapconductor/example-basic", "dev:rn:examples": "npm run expo:start --workspace @mapconductor/example-rn-basic -- --clear", "link:local": "node scripts/link-local-workspaces.mjs", diff --git a/react-vectorstyle/api/react-vectorstyle.api.d.ts b/react-vectorstyle/api/react-vectorstyle.api.d.ts deleted file mode 100644 index 81e6670..0000000 --- a/react-vectorstyle/api/react-vectorstyle.api.d.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { MapStyleHost, MapViewStyle } from '@mapconductor/js-sdk-core'; -import { StyleAffects } from '../vendor/vectorstyle/dist/index.js'; -export { CompiledStyle, StyleAffects, compileStyle } from '../vendor/vectorstyle/dist/index.js'; - -/** - * What to change about a style, and where. - * - * ```ts - * const rules = buildStyleRules((r) => { - * r.all({ color: '#000000' }); - * r.role(LayerRole.label, { visible: false }); - * r.role(LayerRole.roadCasing, { color: '#303030' }); - * r.role(LayerRole.road, { color: '#ffffff', widthScale: 1.3 }); - * }); - * ``` - * - * Rules apply in order and override each other property by property, the way - * CSS does: the last rule to name a colour wins, and a rule that says - * nothing about width leaves the width alone. Reordering the two road rules - * above gives a different map, which is the point — only the app knows - * whether the casings should keep their own colour. - * - * ## It is JSON underneath, on purpose - * - * `json` is the real definition, not a serialisation of the builder. The - * same text is what the compiler reads on Android, iOS and the web, so a - * rule set can be written by hand, stored, shipped from a server, or diffed - * between two versions of an app — and {@link parseStyleRules} takes it - * straight back. The builder is sugar over that, there so the common case is - * checked by the compiler rather than by a typo. - * - * Nothing is validated here. A rule set is checked when it is compiled - * against a style, which is the only place that can tell whether - * `role('road')` means anything. - */ -interface StyleRules { - /** The canonical form. */ - readonly json: string; -} -/** No adjustments: the style as its author wrote it. */ -declare const NO_STYLE_RULES: StyleRules; -/** - * Takes a rules document as it stands. - * - * Not checked here — a document is checked when it is compiled against a - * style, and the compiler reports then. - */ -declare function parseStyleRules(json: string): StyleRules; -/** - * The roles the built-in schema profiles assign. - * - * Open strings rather than a closed union: a style cut to a schema nobody - * here has heard of can name its own roles through `customSchema`, and - * adding a role to the built-in tables must not be a breaking change on - * three platforms. - */ -declare const LayerRole: { - readonly background: "background"; - readonly water: "water"; - readonly waterway: "waterway"; - readonly land: "land"; - readonly landuse: "landuse"; - readonly park: "park"; - readonly building: "building"; - readonly road: "road"; - /** - * The wide dark line drawn under a road to give it an edge. - * - * A style draws every road twice, and "make roads white" applied to both - * halves gives a white slab rather than a road. Nothing in the tile - * distinguishes them — only the layer's name does — so this is the one - * role decided by a naming convention, and the compiler reports how many - * layers it found. - */ - readonly roadCasing: "road-casing"; - readonly rail: "rail"; - readonly transit: "transit"; - readonly boundary: "boundary"; - readonly aeroway: "aeroway"; - readonly label: "label"; - readonly poi: "poi"; -}; -/** A style layer's `type`. */ -type StyleLayerKind = 'background' | 'fill' | 'line' | 'circle' | 'symbol' | 'other'; -/** Which layers a rule reaches. */ -type StyleSelector = 'all' -/** What the layer *is*, across schemas that name their sources differently. */ - | { - readonly role: string; -} -/** The layer's `id`, as a glob: `*` for any run, `?` for one character. */ - | { - readonly layerId: string; -} | { - readonly sourceLayer: string; -} | { - readonly kind: StyleLayerKind; -} | { - readonly anyOf: readonly StyleSelector[]; -} | { - readonly allOf: readonly StyleSelector[]; -} | { - readonly not: StyleSelector; -}; -/** A function of the colour already there, for what a literal cannot express. */ -type StyleColorFilter = { - readonly desaturate: number; -} | { - readonly darken: number; -} | { - readonly lighten: number; -} | { - readonly invertLightness: true; -} | { - readonly mix: { - readonly color: string; - readonly amount?: number; - }; -}; -/** What to change about the layers a selector matched. */ -interface StylePatch { - /** `layout.visibility`. */ - readonly visible?: boolean; - /** - * The layer's colour, whichever property that is for its type: - * `fill-color` on a fill, `line-color` on a line, `text-color` and - * `icon-color` on a symbol, `background-color` on the background. - * - * Any CSS colour the style spec accepts. - */ - readonly color?: string; - readonly colorFilter?: StyleColorFilter; - /** `*-opacity`, 0 to 1. */ - readonly opacity?: number; - /** - * Multiplies how fat the layer is drawn: `line-width` on a line, - * `circle-radius` on a circle. - * - * A multiplier rather than a value because the width is almost always an - * expression over zoom, and replacing it with a number would throw that - * curve away. - */ - readonly widthScale?: number; - /** Replaces the layer's filter, as a MapLibre filter expression. */ - readonly filter?: unknown; - readonly minZoom?: number; - readonly maxZoom?: number; - /** - * Any style-spec property by name. The last word: applied after - * everything above, including over a `color` in the same rule. - * - * The escape hatch for what the fields above do not name — - * `text-field`, `fill-pattern`, `line-dasharray`, a `fill-extrusion` - * height. A property the SDK's own rasteriser cannot draw will show only - * on a map that renders the style itself; the compiler says so. - */ - readonly properties?: Readonly>; -} -/** Writes the `rules` array. */ -interface StyleRulesBuilder { - /** - * Which tile schema the style's `source-layer` names come from. - * - * Left alone it is worked out from the style, which is right for - * OpenMapTiles, Shortbread and Mapbox Streets. - */ - schema(name: string): void; - /** Teaches the compiler a schema of your own: role name to `source-layer` names. */ - customSchema(roles: Readonly>): void; - all(patch: StylePatch): void; - role(role: string, patch: StylePatch): void; - layerId(glob: string, patch: StylePatch): void; - sourceLayer(name: string, patch: StylePatch): void; - kind(kind: StyleLayerKind, patch: StylePatch): void; - /** For a selector built by hand: `allOf`, `not` and friends. */ - where(selector: StyleSelector, patch: StylePatch): void; -} -/** Writes a rules document with the type checker checking the shape. */ -declare function buildStyleRules(block: (rules: StyleRulesBuilder) => void): StyleRules; - -/** Which style the rules are applied to. */ -type VectorStyleSource = -/** The document itself. The app already has it. */ -{ - readonly text: string; -} -/** - * A `style.json` to fetch. - * - * Fetched by this module rather than by the map, because the rules have - * to be compiled against it before the map is given anything. - */ - | { - readonly url: string; - readonly headers?: Readonly>; -} -/** - * Whatever the map is already drawing. - * - * For adjusting a basemap the app did not supply. The module reads the - * design's style URL from the host and fetches it; a backend that has no - * such thing cannot be adjusted this way and says so. - */ - | 'currentDesign'; -/** - * What to do about an adjustment the map would not take. - * - * `'report'` says so and leaves the rest applied — the default, because the - * alternative makes the map reload, and not reloading is the point. - * `'reload'` hands the map the adjusted document instead, which is correct - * and expensive. - */ -type UnsupportedPolicy = 'report' | 'reload'; -/** Draws a style the map cannot read itself. Implemented by the vector tile module. */ -interface VectorStyleRasteriser { - install(host: MapStyleHost, styleJson: string, affects: StyleAffects): VectorStyleRasterisation; -} -/** A rasteriser's work in progress. */ -interface VectorStyleRasterisation { - /** - * Draws a different style with the same tiles. The geometry has not - * changed, only the paint over it, so this costs a re-rasterise and no - * network. - */ - restyle(styleJson: string, affects: StyleAffects): void; - dispose(): void; -} -interface VectorStyleOptions { - /** Which style to adjust. Defaults to whatever the map is already drawing. */ - readonly document?: VectorStyleSource; - readonly rules?: StyleRules; - /** - * Draws the style for a backend that cannot read one. - * - * `@mapconductor/react-vectortile` supplies one. Left out, a map without - * vector style support is told so in the diagnostics rather than left - * blank — there is nothing sensible this can do on its own. - */ - readonly rasteriser?: VectorStyleRasteriser; - readonly onUnsupported?: UnsupportedPolicy; - readonly onDiagnostics?: (diagnostics: readonly string[]) => void; - /** Where the compiler's `.wasm` is served from, if not the default. */ - readonly wasmUrl?: string | URL; -} -/** - * A vector style, with adjustments, as the map's appearance. - * - * ```tsx - * - * ``` - * - * What happens underneath depends on the backend, and the app does not have - * to know: - * - * - **A map that reads vector styles** (MapLibre, Mapbox, MapTiler) is given - * the document and told the per-layer differences. Changing the rules - * later sends new differences and **reloads nothing** — which is the whole - * reason the adjustments are compiled into deltas as well as a document. - * - **A map that cannot** (Google Maps, Leaflet, Cesium, OpenLayers...) is - * handed raster tiles drawn from the adjusted document, if the app passed - * a `rasteriser`. Changing the rules re-rasterises and refetches nothing. - * - * Either way the same rules produce the same map, because both paths start - * from one compilation of one style. - * - * Quietly doing nothing is the failure this design is built against, so - * `onDiagnostics` always hears how many layers each rule matched, which - * matched none, and what this backend would not take. - */ -declare function createVectorStyle(options?: VectorStyleOptions): MapViewStyle; - -export { LayerRole, NO_STYLE_RULES, type StyleColorFilter, type StyleLayerKind, type StylePatch, type StyleRules, type StyleRulesBuilder, type StyleSelector, type UnsupportedPolicy, type VectorStyleOptions, type VectorStyleRasterisation, type VectorStyleRasteriser, type VectorStyleSource, buildStyleRules, createVectorStyle, parseStyleRules }; diff --git a/react-vectorstyle/package.json b/react-vectorstyle/package.json deleted file mode 100644 index 45b315a..0000000 --- a/react-vectorstyle/package.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "@mapconductor/react-vectorstyle", - "version": "0.1.0", - "description": "Declarative adjustments to a MapLibre style, as a MapConductor map's appearance", - "type": "module", - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - } - }, - "files": [ - "dist", - "vendor", - "README.md" - ], - "scripts": { - "prebuild": "node ../scripts/fetch-vector-assets.mjs", - "build": "tsup", - "clean": "rm -rf dist", - "test": "node --test \"test/*.test.mjs\"" - }, - "keywords": [ - "maps", - "maplibre", - "style", - "typescript" - ], - "author": "MapConductor", - "license": "Apache-2.0", - "sideEffects": false, - "peerDependencies": { - "@mapconductor/js-sdk-core": "^0.2.1" - } -} diff --git a/react-vectorstyle/src/StyleRules.ts b/react-vectorstyle/src/StyleRules.ts deleted file mode 100644 index 05635bf..0000000 --- a/react-vectorstyle/src/StyleRules.ts +++ /dev/null @@ -1,211 +0,0 @@ -/** - * What to change about a style, and where. - * - * ```ts - * const rules = buildStyleRules((r) => { - * r.all({ color: '#000000' }); - * r.role(LayerRole.label, { visible: false }); - * r.role(LayerRole.roadCasing, { color: '#303030' }); - * r.role(LayerRole.road, { color: '#ffffff', widthScale: 1.3 }); - * }); - * ``` - * - * Rules apply in order and override each other property by property, the way - * CSS does: the last rule to name a colour wins, and a rule that says - * nothing about width leaves the width alone. Reordering the two road rules - * above gives a different map, which is the point — only the app knows - * whether the casings should keep their own colour. - * - * ## It is JSON underneath, on purpose - * - * `json` is the real definition, not a serialisation of the builder. The - * same text is what the compiler reads on Android, iOS and the web, so a - * rule set can be written by hand, stored, shipped from a server, or diffed - * between two versions of an app — and {@link parseStyleRules} takes it - * straight back. The builder is sugar over that, there so the common case is - * checked by the compiler rather than by a typo. - * - * Nothing is validated here. A rule set is checked when it is compiled - * against a style, which is the only place that can tell whether - * `role('road')` means anything. - */ -export interface StyleRules { - /** The canonical form. */ - readonly json: string; -} - -/** No adjustments: the style as its author wrote it. */ -export const NO_STYLE_RULES: StyleRules = { json: '{"schemaVersion":1,"rules":[]}' }; - -/** - * Takes a rules document as it stands. - * - * Not checked here — a document is checked when it is compiled against a - * style, and the compiler reports then. - */ -export function parseStyleRules(json: string): StyleRules { - return { json }; -} - -/** - * The roles the built-in schema profiles assign. - * - * Open strings rather than a closed union: a style cut to a schema nobody - * here has heard of can name its own roles through `customSchema`, and - * adding a role to the built-in tables must not be a breaking change on - * three platforms. - */ -export const LayerRole = { - background: 'background', - water: 'water', - waterway: 'waterway', - land: 'land', - landuse: 'landuse', - park: 'park', - building: 'building', - road: 'road', - /** - * The wide dark line drawn under a road to give it an edge. - * - * A style draws every road twice, and "make roads white" applied to both - * halves gives a white slab rather than a road. Nothing in the tile - * distinguishes them — only the layer's name does — so this is the one - * role decided by a naming convention, and the compiler reports how many - * layers it found. - */ - roadCasing: 'road-casing', - rail: 'rail', - transit: 'transit', - boundary: 'boundary', - aeroway: 'aeroway', - label: 'label', - poi: 'poi', -} as const; - -/** A style layer's `type`. */ -export type StyleLayerKind = 'background' | 'fill' | 'line' | 'circle' | 'symbol' | 'other'; - -/** Which layers a rule reaches. */ -export type StyleSelector = - | 'all' - /** What the layer *is*, across schemas that name their sources differently. */ - | { readonly role: string } - /** The layer's `id`, as a glob: `*` for any run, `?` for one character. */ - | { readonly layerId: string } - | { readonly sourceLayer: string } - | { readonly kind: StyleLayerKind } - | { readonly anyOf: readonly StyleSelector[] } - | { readonly allOf: readonly StyleSelector[] } - | { readonly not: StyleSelector }; - -/** A function of the colour already there, for what a literal cannot express. */ -export type StyleColorFilter = - | { readonly desaturate: number } - | { readonly darken: number } - | { readonly lighten: number } - | { readonly invertLightness: true } - | { readonly mix: { readonly color: string; readonly amount?: number } }; - -/** What to change about the layers a selector matched. */ -export interface StylePatch { - /** `layout.visibility`. */ - readonly visible?: boolean; - /** - * The layer's colour, whichever property that is for its type: - * `fill-color` on a fill, `line-color` on a line, `text-color` and - * `icon-color` on a symbol, `background-color` on the background. - * - * Any CSS colour the style spec accepts. - */ - readonly color?: string; - readonly colorFilter?: StyleColorFilter; - /** `*-opacity`, 0 to 1. */ - readonly opacity?: number; - /** - * Multiplies how fat the layer is drawn: `line-width` on a line, - * `circle-radius` on a circle. - * - * A multiplier rather than a value because the width is almost always an - * expression over zoom, and replacing it with a number would throw that - * curve away. - */ - readonly widthScale?: number; - /** Replaces the layer's filter, as a MapLibre filter expression. */ - readonly filter?: unknown; - readonly minZoom?: number; - readonly maxZoom?: number; - /** - * Any style-spec property by name. The last word: applied after - * everything above, including over a `color` in the same rule. - * - * The escape hatch for what the fields above do not name — - * `text-field`, `fill-pattern`, `line-dasharray`, a `fill-extrusion` - * height. A property the SDK's own rasteriser cannot draw will show only - * on a map that renders the style itself; the compiler says so. - */ - readonly properties?: Readonly>; -} - -/** Writes the `rules` array. */ -export interface StyleRulesBuilder { - /** - * Which tile schema the style's `source-layer` names come from. - * - * Left alone it is worked out from the style, which is right for - * OpenMapTiles, Shortbread and Mapbox Streets. - */ - schema(name: string): void; - /** Teaches the compiler a schema of your own: role name to `source-layer` names. */ - customSchema(roles: Readonly>): void; - - all(patch: StylePatch): void; - role(role: string, patch: StylePatch): void; - layerId(glob: string, patch: StylePatch): void; - sourceLayer(name: string, patch: StylePatch): void; - kind(kind: StyleLayerKind, patch: StylePatch): void; - /** For a selector built by hand: `allOf`, `not` and friends. */ - where(selector: StyleSelector, patch: StylePatch): void; -} - -/** Writes a rules document with the type checker checking the shape. */ -export function buildStyleRules(block: (rules: StyleRulesBuilder) => void): StyleRules { - const written: unknown[] = []; - let schema: unknown; - - const push = (selector: StyleSelector, patch: StylePatch) => { - written.push({ selector, patch: normalise(patch) }); - }; - const builder: StyleRulesBuilder = { - schema(name) { - schema = name; - }, - customSchema(roles) { - schema = { roles }; - }, - all: (patch) => push('all', patch), - role: (role, patch) => push({ role }, patch), - layerId: (layerId, patch) => push({ layerId }, patch), - sourceLayer: (sourceLayer, patch) => push({ sourceLayer }, patch), - kind: (kind, patch) => push({ kind }, patch), - where: push, - }; - block(builder); - - // Written through `JSON.stringify` with an explicit key order rather than - // by hand: unlike Kotlin and Swift, this runtime has a JSON writer that - // is already correct about escaping, and the order below is what the - // other two platforms emit. - const document: Record = { schemaVersion: 1 }; - if (schema !== undefined) document.schema = schema; - document.rules = written; - return { json: JSON.stringify(document) }; -} - -/** Drops the keys that were left out, so an absent field is absent. */ -function normalise(patch: StylePatch): Record { - const out: Record = {}; - for (const [key, value] of Object.entries(patch)) { - if (value !== undefined) out[key] = value; - } - return out; -} diff --git a/react-vectorstyle/src/VectorStyle.ts b/react-vectorstyle/src/VectorStyle.ts deleted file mode 100644 index 5e33869..0000000 --- a/react-vectorstyle/src/VectorStyle.ts +++ /dev/null @@ -1,366 +0,0 @@ -import { - parseStyleMutations, - styleMutationProperty, - VectorStyleMutationSupportKey, - VectorStyleSupportKey, - type MapStyleHost, - type MapStyleInstallation, - type MapViewStyle, - type NativeStyleDescriptor, - type StyleMutation, -} from '@mapconductor/js-sdk-core'; -import { compileStyle, type CompiledStyle, type StyleAffects } from '../vendor/vectorstyle/dist/index.js'; - -// The compiler ships inside this package (vendor/, fetched from -// MapConductor/vectortile's release). react-vectortile compiles through these -// rather than carrying a second copy of the wasm. -export { compileStyle }; -export type { CompiledStyle, StyleAffects }; - -import { NO_STYLE_RULES, type StyleRules } from './StyleRules'; - -/** Which style the rules are applied to. */ -export type VectorStyleSource = - /** The document itself. The app already has it. */ - | { readonly text: string } - /** - * A `style.json` to fetch. - * - * Fetched by this module rather than by the map, because the rules have - * to be compiled against it before the map is given anything. - */ - | { readonly url: string; readonly headers?: Readonly> } - /** - * Whatever the map is already drawing. - * - * For adjusting a basemap the app did not supply. The module reads the - * design's style URL from the host and fetches it; a backend that has no - * such thing cannot be adjusted this way and says so. - */ - | 'currentDesign'; - -/** - * What to do about an adjustment the map would not take. - * - * `'report'` says so and leaves the rest applied — the default, because the - * alternative makes the map reload, and not reloading is the point. - * `'reload'` hands the map the adjusted document instead, which is correct - * and expensive. - */ -export type UnsupportedPolicy = 'report' | 'reload'; - -/** Draws a style the map cannot read itself. Implemented by the vector tile module. */ -export interface VectorStyleRasteriser { - install( - host: MapStyleHost, - styleJson: string, - affects: StyleAffects, - ): VectorStyleRasterisation; -} - -/** A rasteriser's work in progress. */ -export interface VectorStyleRasterisation { - /** - * Draws a different style with the same tiles. The geometry has not - * changed, only the paint over it, so this costs a re-rasterise and no - * network. - */ - restyle(styleJson: string, affects: StyleAffects): void; - dispose(): void; -} - -export interface VectorStyleOptions { - /** Which style to adjust. Defaults to whatever the map is already drawing. */ - readonly document?: VectorStyleSource; - readonly rules?: StyleRules; - /** - * Draws the style for a backend that cannot read one. - * - * `@mapconductor/react-vectortile` supplies one. Left out, a map without - * vector style support is told so in the diagnostics rather than left - * blank — there is nothing sensible this can do on its own. - */ - readonly rasteriser?: VectorStyleRasteriser; - readonly onUnsupported?: UnsupportedPolicy; - readonly onDiagnostics?: (diagnostics: readonly string[]) => void; - /** Where the compiler's `.wasm` is served from, if not the default. */ - readonly wasmUrl?: string | URL; -} - -/** - * A vector style, with adjustments, as the map's appearance. - * - * ```tsx - * - * ``` - * - * What happens underneath depends on the backend, and the app does not have - * to know: - * - * - **A map that reads vector styles** (MapLibre, Mapbox, MapTiler) is given - * the document and told the per-layer differences. Changing the rules - * later sends new differences and **reloads nothing** — which is the whole - * reason the adjustments are compiled into deltas as well as a document. - * - **A map that cannot** (Google Maps, Leaflet, Cesium, OpenLayers...) is - * handed raster tiles drawn from the adjusted document, if the app passed - * a `rasteriser`. Changing the rules re-rasterises and refetches nothing. - * - * Either way the same rules produce the same map, because both paths start - * from one compilation of one style. - * - * Quietly doing nothing is the failure this design is built against, so - * `onDiagnostics` always hears how many layers each rule matched, which - * matched none, and what this backend would not take. - */ -export function createVectorStyle(options: VectorStyleOptions = {}): MapViewStyle { - const document = options.document ?? 'currentDesign'; - const rules = options.rules ?? NO_STYLE_RULES; - const resolved: Resolved = { ...options, document, rules }; - return { - key: `${sourceKey(document)}|${rules.json}`, - install: (host) => install(host, resolved), - // How an installed style recognises its successor. The map hands - // `update` a `MapViewStyle`, which says nothing about where it came - // from; this is the one place a style can leave something for its - // own kind to read. - /** @internal */ - [VECTOR_STYLE]: resolved, - /** - * On React Native nothing above runs: the compiler is wasm and - * Hermes has no wasm, and the map is the Android or iOS SDK rather - * than a JavaScript object. The style crosses the bridge as this - * and is rebuilt by the platform's own vector style module, so the - * map a user sees comes from exactly the code a native app runs. - */ - toNativeDescriptor: (): NativeStyleDescriptor => ({ - ...(document === 'currentDesign' - ? { fromCurrentDesign: true } - : 'text' in document - ? { documentJson: document.text } - : { documentUrl: document.url, documentHeaders: document.headers }), - rulesJson: rules.json, - }), - } as MapViewStyle; -} - -/** @internal */ -const VECTOR_STYLE = Symbol.for('mapconductor.vectorstyle'); - -function sourceKey(source: VectorStyleSource): string { - if (source === 'currentDesign') return 'current'; - if ('text' in source) return `text:${source.text.length}:${source.text}`; - return `url:${source.url}`; -} - -/** Whether `next` differs from an installed style only in its adjustments. */ -function sameStyle(a: Resolved, b: Resolved): boolean { - return ( - sourceKey(a.document) === sourceKey(b.document) && - a.rasteriser === b.rasteriser && - (a.onUnsupported ?? 'report') === (b.onUnsupported ?? 'report') - ); -} - -type Resolved = VectorStyleOptions & { - readonly document: VectorStyleSource; - readonly rules: StyleRules; -}; - -/** - * One style's life on one map. - * - * Resolving the document can mean a network round trip and loading the - * compiler's wasm, so the work is started and this returns at once; - * everything after checks `disposed` before touching the map, because a view - * can be gone before its style arrives. - */ -function install(host: MapStyleHost, initial: Resolved): MapStyleInstallation { - let style = initial; - let disposed = false; - /** The style as its author wrote it, kept so later rules compile against it. */ - let base: string | null = null; - let rasterisation: VectorStyleRasterisation | null = null; - let servedDocument = false; - let styleLoaded: MapStyleInstallation | null = null; - /** Serial: two rule changes in flight would race to be the last applied. */ - let queue: Promise = Promise.resolve(); - - const report = (diagnostics: readonly string[]) => { - if (diagnostics.length === 0) return; - host.report(diagnostics); - style.onDiagnostics?.(diagnostics); - }; - - const resolve = async (source: VectorStyleSource): Promise => { - if (source !== 'currentDesign' && 'text' in source) return source.text; - const url = - source === 'currentDesign' - ? host.vectorStyleUrl ?? - raise( - 'this map is not drawing a vector style, so there is nothing to adjust; ' + - 'give `document` a style of your own', - ) - : source.url; - const headers = source !== 'currentDesign' && 'url' in source ? source.headers : undefined; - const response = await fetch(url, headers ? { headers } : undefined); - if (!response.ok) throw new Error(`HTTP ${response.status} for ${url}`); - return response.text(); - }; - - // The browser's map takes the parsed style straight, so there is no - // document to serve and nothing to take down afterwards. Android and iOS - // hand over a URL because their renderers only read one; the SDK's local - // tile server exists for them. - const serve = (json: string) => { - const vector = host.serviceRegistry.get(VectorStyleSupportKey); - if (!vector) return; - servedDocument = true; - vector.showStyle(JSON.parse(json) as object, attributionsOf(json)); - }; - - const apply = async (next: Resolved, firstTime: boolean) => { - if (disposed || base === null) return; - let compiled: CompiledStyle; - try { - compiled = await compileStyle(base, next.rules.json, { wasmUrl: next.wasmUrl }); - } catch (error) { - report([`the rules could not be applied: ${messageOf(error)}`]); - return; - } - if (disposed) return; - report(compiled.diagnostics); - - const vector = host.serviceRegistry.get(VectorStyleSupportKey); - const mutation = host.serviceRegistry.get(VectorStyleMutationSupportKey); - const mutations = parseStyleMutations(compiled.mutationsJson); - - if (vector && mutation) { - // The map draws styles itself and can be told differences: give - // it the author's document and the deltas on top. The compiled - // document is deliberately *not* what it is given — the next - // rule change produces deltas against the original, and a map - // holding an already-adjusted document would take them to mean - // something else. - if (firstTime) serve(base); - const unapplied = mutation.apply(mutations); - if (unapplied.length > 0) handleUnapplied(unapplied, compiled, next); - } else if (vector) { - // It draws styles but cannot be patched: the adjusted document - // is the only way, and every rule change reloads. - serve(JSON.stringify(compiled.style)); - } else if (next.rasteriser) { - const json = JSON.stringify(compiled.style); - if (rasterisation) { - rasterisation.restyle(json, compiled.affects); - } else { - rasterisation = next.rasteriser.install(host, json, compiled.affects); - if (disposed) { - rasterisation.dispose(); - rasterisation = null; - } - } - } else { - report([ - 'this map cannot draw a vector style, and no rasteriser was given; ' + - 'pass `rasteriser` from @mapconductor/react-vectortile', - ]); - } - - // Whatever was just applied is lost the moment the map loads a style - // again — an app switching basemap, a provider rebuilding. The - // mutation store puts its own set back. - if (firstTime && styleLoaded === null) styleLoaded = host.onStyleLoaded(() => {}); - }; - - const handleUnapplied = ( - unapplied: readonly StyleMutation[], - compiled: CompiledStyle, - next: Resolved, - ) => { - // Named by property, not by layer. A backend with no property for a - // spec key fails that key on every layer that uses it, so a list of - // layers was hundreds of names for one cause — and never said which - // property, which is the only part an app can act on. - const properties = [...new Set(unapplied.map(styleMutationProperty))].sort(); - const shown = properties.slice(0, 5); - const more = properties.length > shown.length ? ', ...' : ''; - const layers = new Set(unapplied.map((m) => ('layerId' in m ? m.layerId : ''))).size; - const message = - `${unapplied.length} adjustments were not applied: this map cannot set these ` + - `properties by name (${shown.join(', ')}${more}) across ${layers} layers`; - if ((next.onUnsupported ?? 'report') === 'reload') { - report([`${message}; handing the map the adjusted document instead`]); - host.serviceRegistry.get(VectorStyleMutationSupportKey)?.clear(); - serve(JSON.stringify(compiled.style)); - } else { - report([message]); - } - }; - - queue = (async () => { - try { - base = await resolve(style.document); - } catch (error) { - report([`the style could not be read: ${messageOf(error)}`]); - return; - } - if (disposed) return; - await apply(style, true); - })(); - - return { - dispose() { - if (disposed) return; - disposed = true; - styleLoaded?.dispose(); - styleLoaded = null; - // Order matters: the mutations have to come off while the - // document they were applied to is still the one loaded. - host.serviceRegistry.get(VectorStyleMutationSupportKey)?.clear(); - if (servedDocument) host.serviceRegistry.get(VectorStyleSupportKey)?.clearStyle(); - rasterisation?.dispose(); - rasterisation = null; - }, - update(candidate) { - const next = (candidate as unknown as Record)[VECTOR_STYLE]; - // A different document is a different style, whatever else - // matches: it has to be fetched and the map has to be told. - if (!next || !sameStyle(style, next) || base === null) return false; - style = next; - queue = queue.then(() => (disposed ? undefined : apply(next, false))); - return true; - }, - }; -} - -function raise(message: string): never { - throw new Error(message); -} - -function messageOf(error: unknown): string { - return error instanceof Error ? error.message : String(error); -} - -/** - * The credits the style's sources ask for. - * - * Carried onto the design so the map's attribution overlay shows them for as - * long as the style is up. Nothing else about this can be wrong while still - * looking right: the map draws perfectly whether or not anyone is credited - * for the data. - */ -function attributionsOf(json: string): { attribution: string }[] { - try { - const sources = (JSON.parse(json) as { sources?: Record }) - .sources; - if (!sources) return []; - const seen = new Set(); - for (const source of Object.values(sources)) { - const credit = source?.attribution; - if (typeof credit === 'string' && credit.trim() !== '') seen.add(credit); - } - return [...seen].map((attribution) => ({ attribution })); - } catch { - return []; - } -} diff --git a/react-vectorstyle/src/index.ts b/react-vectorstyle/src/index.ts deleted file mode 100644 index b5307d1..0000000 --- a/react-vectorstyle/src/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -export { - buildStyleRules, - LayerRole, - NO_STYLE_RULES, - parseStyleRules, -} from './StyleRules'; -export type { - StyleColorFilter, - StyleLayerKind, - StylePatch, - StyleRules, - StyleRulesBuilder, - StyleSelector, -} from './StyleRules'; -export { compileStyle, createVectorStyle } from './VectorStyle'; -export type { - CompiledStyle, - StyleAffects, - UnsupportedPolicy, - VectorStyleOptions, - VectorStyleRasterisation, - VectorStyleRasteriser, - VectorStyleSource, -} from './VectorStyle'; diff --git a/react-vectorstyle/tsconfig.json b/react-vectorstyle/tsconfig.json deleted file mode 100644 index e95aa4e..0000000 --- a/react-vectorstyle/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "lib": ["ES2022", "DOM"], - "jsx": "react-jsx", - "strict": true, - "declaration": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowJs": true, - "outDir": "dist" - }, - "include": ["src"] -} diff --git a/react-vectorstyle/tsup.config.ts b/react-vectorstyle/tsup.config.ts deleted file mode 100644 index de32061..0000000 --- a/react-vectorstyle/tsup.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'tsup'; - -export default defineConfig({ - entry: ['src/index.ts'], - format: ['esm'], - dts: true, - clean: true, - // vendor/ is the Rust build fetched from MapConductor/vectortile's release. - // It ships next to dist/ as it is: it finds its worker and wasm relative to - // its own files (`new URL('./worker.js', import.meta.url)`), which bundling - // would break. - external: [/\/vendor\//, '@mapconductor/js-sdk-core'], -}); diff --git a/react-vectortile/api/react-vectortile.api.d.ts b/react-vectortile/api/react-vectortile.api.d.ts index 9da00a4..5734c75 100644 --- a/react-vectortile/api/react-vectortile.api.d.ts +++ b/react-vectortile/api/react-vectortile.api.d.ts @@ -1,5 +1,5 @@ import React from 'react'; -import { StyleRules, VectorStyleRasteriser, StyleAffects, VectorStyleRasterisation } from '@mapconductor/react-vectorstyle'; +import { StyleRules, VectorStyleRasteriser, StyleAffects, VectorStyleRasterisation } from '@mapconductor/js-vectorstyle'; import { MapStyleHost } from '@mapconductor/js-sdk-core'; interface VectorTileLayerProps { diff --git a/react-vectortile/package.json b/react-vectortile/package.json index b00fdda..e48763c 100644 --- a/react-vectortile/package.json +++ b/react-vectortile/package.json @@ -37,7 +37,7 @@ "dependencies": { "@mapconductor/js-sdk-core": "^0.2.0", "@mapconductor/js-sdk-react": "^0.2.1", - "@mapconductor/react-vectorstyle": "^0.1.0" + "@mapconductor/js-vectorstyle": "^0.1.0" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0" diff --git a/react-vectortile/src/VectorTileLayer.tsx b/react-vectortile/src/VectorTileLayer.tsx index e2adef6..f89cc6d 100644 --- a/react-vectortile/src/VectorTileLayer.tsx +++ b/react-vectortile/src/VectorTileLayer.tsx @@ -10,7 +10,7 @@ import { } from '@mapconductor/js-sdk-core'; import { RasterLayer, useMapServiceRegistry } from '@mapconductor/js-sdk-react'; import { VectorTileProvider } from '../vendor/vectortile/dist/index.js'; -import { NO_STYLE_RULES, type StyleRules } from '@mapconductor/react-vectorstyle'; +import { NO_STYLE_RULES, type StyleRules } from '@mapconductor/js-vectorstyle'; export interface VectorTileLayerProps { /** A `style.json` URL, its raw text, or the parsed object. */ @@ -242,7 +242,7 @@ export function VectorTileLayer({ const document = styleRef.current; const json = rulesRef.current; if (json === NO_STYLE_RULES.json) return document; - const { compileStyle } = await import('@mapconductor/react-vectorstyle'); + const { compileStyle } = await import('@mapconductor/js-vectorstyle'); const compiled = await compileStyle(await styleText(document), json); if (compiled.diagnostics.length > 0) report?.([...compiled.diagnostics]); return compiled.style as object; diff --git a/react-vectortile/src/VectorTileRasteriser.ts b/react-vectortile/src/VectorTileRasteriser.ts index 56b1198..89a8286 100644 --- a/react-vectortile/src/VectorTileRasteriser.ts +++ b/react-vectortile/src/VectorTileRasteriser.ts @@ -8,8 +8,8 @@ import { type RasterLayerState, } from '@mapconductor/js-sdk-core'; import { VectorTileProvider } from '../vendor/vectortile/dist/index.js'; -import type { StyleAffects } from '@mapconductor/react-vectorstyle'; -import type { VectorStyleRasterisation, VectorStyleRasteriser } from '@mapconductor/react-vectorstyle'; +import type { StyleAffects } from '@mapconductor/js-vectorstyle'; +import type { VectorStyleRasterisation, VectorStyleRasteriser } from '@mapconductor/js-vectorstyle'; /** How long a burst of restyles is gathered into one redraw. */ const COALESCE_MS = 150; diff --git a/scripts/api-surface.mjs b/scripts/api-surface.mjs index 05b2fe1..074f4e5 100644 --- a/scripts/api-surface.mjs +++ b/scripts/api-surface.mjs @@ -62,7 +62,7 @@ const PACKAGES = [ "react-kml", "react-heatmap", "react-marker-clustering", - "react-vectorstyle", + "js-vectorstyle", "react-vectortile", "react-icons-jp", "react-icons-us", diff --git a/scripts/fetch-vector-assets.mjs b/scripts/fetch-vector-assets.mjs index cdee3ca..a88183f 100644 --- a/scripts/fetch-vector-assets.mjs +++ b/scripts/fetch-vector-assets.mjs @@ -1,7 +1,8 @@ #!/usr/bin/env node /** - * Puts the Rust style compiler and renderer (wasm + their JS bindings) where - * react-vectorstyle and react-vectortile import them from. + * Puts the Rust renderer (wasm + its JS bindings) where react-vectortile + * imports it from. The style compiler is fetched by js-vectorstyle itself, the + * same way, from its own copy of this script; keep the two tags in step. * * node scripts/fetch-vector-assets.mjs fetch what is missing or stale * node scripts/fetch-vector-assets.mjs --force fetch again regardless @@ -13,7 +14,7 @@ * * To try a local build of mapconductor-vectortile instead, point * MAPCONDUCTOR_VECTORTILE_DIR at that checkout (after `npm run build` in its - * bindings/js and bindings/js-style). Nothing is verified then, and the stamp + * bindings/js). Nothing is verified then, and the stamp * says so, so the next plain run fetches the pinned release again. */ import { createHash } from "node:crypto"; @@ -28,7 +29,6 @@ const PIN = JSON.parse(readFileSync(join(ROOT, "scripts", "vector-assets.json"), /** Release asset -> where it is unpacked, and where a local build keeps it. */ const TARGETS = [ - { asset: "vectorstyle-web.tgz", dest: "react-vectorstyle/vendor/vectorstyle", local: "bindings/js-style" }, { asset: "vectortile-web.tgz", dest: "react-vectortile/vendor/vectortile", local: "bindings/js" }, ]; diff --git a/scripts/vector-assets.json b/scripts/vector-assets.json index bcdd635..c624af2 100644 --- a/scripts/vector-assets.json +++ b/scripts/vector-assets.json @@ -2,7 +2,6 @@ "repository": "MapConductor/vectortile", "tag": "v0.1.0", "assets": { - "vectorstyle-web.tgz": "7d5a3bd2826937b2b2d745bdb02ba06de05238435ae70803b5aa571c8da14e14", "vectortile-web.tgz": "f87e498e36d892595ba240dbf4cdcb94914bd0088b98d66feff842a0fdc4f490" } }