diff --git a/types/jsvectormap/.npmignore b/types/jsvectormap/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/jsvectormap/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/jsvectormap/index.d.ts b/types/jsvectormap/index.d.ts new file mode 100644 index 00000000000000..1b650a3920d58b --- /dev/null +++ b/types/jsvectormap/index.d.ts @@ -0,0 +1,688 @@ +// Type definitions for jsvectormap 1.7.0 +// Project: https://github.com/themustafaomar/jsvectormap +// Definitions authored by strictly analyzing the library source (TypeScript 5). +// +// Usage: +// import jsVectorMap from 'jsvectormap' +// const map = new jsVectorMap({ selector: '#map', map: 'world' }) + +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export = jsVectorMap; +export as namespace jsVectorMap; + +declare class jsVectorMap { + /** + * Creates a new map instance. + * + * Note: at runtime the constructor returns an internal `Map` instance, + * therefore every public member documented below is available on the + * value returned by `new jsVectorMap(...)`. + * + * @throws If `options.selector` is not provided. + * @throws If `options.map` refers to a map that was not registered via {@link jsVectorMap.addMap}. + */ + constructor(options: jsVectorMap.MapOptions); + + // ------------------------------------------------------------------ + // Public state + // ------------------------------------------------------------------ + + /** The merged options (defaults deep-merged with the user options). */ + params: Required & jsVectorMap.MapOptions; + + /** Registered regions keyed by region code (e.g. `US`, `FR`). */ + regions: Record; + + /** The root container element the map is rendered into. */ + container: HTMLElement; + + /** The SVG canvas wrapper. */ + canvas: jsVectorMap.SVGCanvasElement; + + /** Current zoom scale. */ + scale: number; + + /** Current horizontal translation. */ + transX: number; + + /** Current vertical translation. */ + transY: number; + + /** Series (data legends) grouped by target, created when `series` option is used. */ + series?: { + markers: jsVectorMap.Series[]; + regions: jsVectorMap.Series[]; + }; + + /** Horizontal legend container, present only when `series` is used. */ + legendHorizontal?: HTMLElement | null; + + /** Vertical legend container, present only when `series` is used. */ + legendVertical?: HTMLElement | null; + + /** Choropleth data visualization instance, present only when `visualizeData` is used. */ + dataVisualization?: jsVectorMap.DataVisualization; + + // ------------------------------------------------------------------ + // Public methods — general + // ------------------------------------------------------------------ + + /** Sets the background color of the map container. */ + setBackgroundColor(color: string): void; + + /** + * Registers a custom instance method on the map prototype. + * @throws If a method with the given name already exists. + */ + extend(name: string, callback: (this: jsVectorMap, ...args: any[]) => any): void; + + /** Resets the map: clears series/legends, selections, markers and viewport. */ + reset(): void; + + /** + * Destroys the map, flushing all event listeners and the tooltip. + * @param destroyInstance When `true` (default), deletes all own properties of the instance. + */ + destroy(destroyInstance?: boolean): void; + + // ------------------------------------------------------------------ + // Public methods — regions + // ------------------------------------------------------------------ + + /** Returns the codes of the currently selected regions. */ + getSelectedRegions(): string[]; + + /** + * Clears the selection of the given regions, or of all selected regions + * when no argument is provided. + */ + clearSelectedRegions(regions?: string | string[]): void; + + /** Replaces the current region selection with the given region code(s). */ + setSelectedRegions(regions: string | string[]): void; + + // ------------------------------------------------------------------ + // Public methods — markers + // ------------------------------------------------------------------ + + /** Returns the indexes of the currently selected markers. */ + getSelectedMarkers(): string[]; + + /** Clears the selection of all selected markers. */ + clearSelectedMarkers(): void; + + /** Selects markers by their index key(s). */ + setSelectedMarkers(markers: Array): void; + + /** Adds one or more markers to the map. */ + addMarkers(config: jsVectorMap.MarkerConfig | jsVectorMap.MarkerConfig[]): void; + + /** + * Removes the given markers by index. When no argument is provided, + * all markers are removed. + */ + removeMarkers(markers?: Array): void; + + // ------------------------------------------------------------------ + // Public methods — lines + // ------------------------------------------------------------------ + + /** + * @deprecated Use {@link addLines} instead. + */ + addLine(from: string, to: string, style?: jsVectorMap.LineStyle): void; + + /** Adds one or more lines connecting existing markers (by their `name`). */ + addLines(config: jsVectorMap.LineConfig | jsVectorMap.LineConfig[]): void; + + /** + * Removes the given lines, or all lines when no argument is provided. + */ + removeLines(lines?: Array>): void; + + /** + * @deprecated Use {@link removeLines} instead. + */ + removeLine(from: string, to: string): void; + + // ------------------------------------------------------------------ + // Public methods — viewport / geometry (core mixin) + // ------------------------------------------------------------------ + + /** Focuses the map on region(s) or geographic coordinates. */ + setFocus(config: jsVectorMap.FocusConfig): void; + + /** Recomputes the container size and re-applies the transform. */ + updateSize(): void; + + /** + * Converts geographic coordinates to a point on the map. + * Returns `false` when the coordinates fall outside every inset. + */ + coordsToPoint(lat: number, lng: number): jsVectorMap.Point | false; + + /** Returns the inset that contains the given SVG point, if any. */ + getInsetForPoint(x: number, y: number): jsVectorMap.MapDataInset | undefined; + + /** Returns the on-screen position of a marker given its config. */ + getMarkerPosition(config: Pick): jsVectorMap.Point | false; + + // ------------------------------------------------------------------ + // Static + // ------------------------------------------------------------------ + + /** Registers a map dataset under the given name. */ + static addMap(name: string, map: jsVectorMap.MapData): void; +} + +declare namespace jsVectorMap { + // ------------------------------------------------------------------ + // Primitive helpers + // ------------------------------------------------------------------ + + /** A point in the SVG coordinate space. */ + interface Point { + x: number; + y: number; + } + + /** A `[latitude, longitude]` pair. */ + type Coords = [number, number]; + + /** A `[x, y]` pixel offset. */ + type Offset = [number, number]; + + /** An image value used by marker/legend styles. */ + interface ImageStyle { + url: string; + offset?: Offset; + } + + /** Accepted value for a single SVG presentation attribute. */ + type StyleValue = string | number | boolean | ImageStyle | undefined; + + /** + * A flat set of SVG presentation attributes (camelCase keys are hyphenated + * automatically, e.g. `fillOpacity` -> `fill-opacity`). + */ + interface StyleAttributes { + fill?: string; + fillOpacity?: number; + stroke?: string; + strokeWidth?: number | string; + strokeOpacity?: number; + strokeLinecap?: string; + strokeDasharray?: string | number; + r?: number; + cursor?: string; + fontFamily?: string; + fontSize?: number | string; + fontWeight?: number | string; + /** Renders the marker as an image instead of a circle. */ + image?: string | ImageStyle; + [attr: string]: StyleValue; + } + + /** A component style with the four interaction states. */ + interface ElementStyle { + initial?: StyleAttributes; + hover?: StyleAttributes; + selected?: StyleAttributes; + selectedHover?: StyleAttributes; + } + + /** Style for lines (a flat attribute set plus an optional curvature). */ + interface LineStyle extends StyleAttributes { + /** Bends the line; `0` draws a straight line. */ + curvature?: number; + } + + // ------------------------------------------------------------------ + // Labels + // ------------------------------------------------------------------ + + /** Configuration for region/marker labels. */ + interface LabelOptions { + /** + * Returns the label text. + * - For regions the callback receives `(code)`. + * - For markers the callback receives `(config, index)`. + */ + render?: (...args: any[]) => string | undefined | null; + /** + * Positional offsets. Either an array indexed by key, + * or a function returning `[x, y]` for a given key. + */ + offsets?: Offset[] | ((key: string | number) => Offset); + } + + interface Labels { + markers?: LabelOptions; + regions?: LabelOptions; + } + + // ------------------------------------------------------------------ + // Markers & lines + // ------------------------------------------------------------------ + + interface MarkerConfig { + /** Marker geographic (or plain xy) coordinates. */ + coords: Coords; + /** Marker name, used to link lines via `from`/`to`. */ + name?: string; + /** Per-marker style overrides. */ + style?: ElementStyle; + /** Explicit label offsets for this marker. */ + offsets?: Offset; + /** Arbitrary data forwarded to label `render`. */ + [key: string]: any; + } + + interface LineConfig { + /** Name of the origin marker. */ + from: string; + /** Name of the destination marker. */ + to: string; + /** Per-line style overrides. */ + style?: LineStyle; + } + + // ------------------------------------------------------------------ + // Series / legend / data visualization + // ------------------------------------------------------------------ + + interface LegendOptions { + /** Overrides the legend element's CSS class. */ + cssClass?: string; + /** Renders the legend into the vertical container. */ + vertical?: boolean; + /** Optional legend title. */ + title?: string; + /** Transforms each tick label before rendering. */ + labelRender?: (label: string) => string; + } + + interface SeriesConfig { + /** The SVG attribute driven by this series (defaults to `fill`). */ + attribute?: string; + /** Values keyed by region code / marker index. */ + values?: Record; + /** Static attributes applied immediately. */ + attributes?: Record; + /** Ordinal scale mapping a value to an attribute value (e.g. a color). */ + scale?: Record; + /** Legend configuration for this series. */ + legend?: LegendOptions; + } + + interface SeriesOptions { + markers?: SeriesConfig[]; + regions?: SeriesConfig[]; + } + + /** Choropleth (`visualizeData`) options. */ + interface VisualizeDataOptions { + /** `[fromColor, toColor]` gradient endpoints as hex strings. */ + scale: [string, string]; + /** Numeric values keyed by region code. */ + values: Record; + } + + // ------------------------------------------------------------------ + // Focus + // ------------------------------------------------------------------ + + interface FocusConfig { + /** Focus a single region by code. */ + region?: string; + /** Focus multiple regions by code. */ + regions?: string[]; + /** Focus a geographic point `[lat, lng]`. */ + coords?: Coords; + /** Target scale (used together with `coords`). */ + scale?: number; + /** Animate the transition. */ + animate?: boolean; + } + + // ------------------------------------------------------------------ + // Event callbacks (invoked with `this` bound to the map instance) + // ------------------------------------------------------------------ + + interface EventHandlers { + /** Fired once the map has finished initializing. */ + onLoaded?: (this: jsVectorMap, map: jsVectorMap) => void; + /** Fired whenever the viewport (scale/translation) changes. */ + onViewportChange?: (this: jsVectorMap, scale: number, transX: number, transY: number) => void; + /** Fired when a region is clicked. */ + onRegionClick?: (this: jsVectorMap, event: MouseEvent, code: string) => void; + /** Fired when a marker is clicked. */ + onMarkerClick?: (this: jsVectorMap, event: MouseEvent, index: string) => void; + /** Fired when a region selection state changes. */ + onRegionSelected?: ( + this: jsVectorMap, + code: string, + isSelected: boolean, + selectedRegions: string[], + ) => void; + /** Fired when a marker selection state changes. */ + onMarkerSelected?: ( + this: jsVectorMap, + index: string, + isSelected: boolean, + selectedMarkers: string[], + ) => void; + /** Fired before a region tooltip is shown; call `event.preventDefault()` to suppress it. */ + onRegionTooltipShow?: ( + this: jsVectorMap, + event: MouseEvent, + tooltip: Tooltip, + code: string, + ) => void; + /** Fired before a marker tooltip is shown; call `event.preventDefault()` to suppress it. */ + onMarkerTooltipShow?: ( + this: jsVectorMap, + event: MouseEvent, + tooltip: Tooltip, + index: string, + ) => void; + /** Fired when the map is destroyed. */ + onDestroyed?: (this: jsVectorMap) => void; + } + + // ------------------------------------------------------------------ + // Options + // ------------------------------------------------------------------ + + interface MapOptions extends EventHandlers { + /** Target element or CSS selector the map is rendered into. Required. */ + selector: string | HTMLElement; + + /** Name of a registered map dataset (default: `'world'`). */ + map?: string; + + /** Container background color (default: `'transparent'`). */ + backgroundColor?: string; + + /** Enables panning by dragging (default: `true`). */ + draggable?: boolean; + + /** Renders the built-in zoom buttons (default: `true`). */ + zoomButtons?: boolean; + + /** Custom zoom-in button element or selector. */ + zoomInButton?: string | HTMLElement; + + /** Custom zoom-out button element or selector. */ + zoomOutButton?: string | HTMLElement; + + /** Enables zooming with the mouse wheel (default: `true`). */ + zoomOnScroll?: boolean; + + /** Wheel zoom sensitivity (default: `3`). */ + zoomOnScrollSpeed?: number; + + /** Maximum zoom multiplier (default: `12`). */ + zoomMax?: number; + + /** Minimum zoom multiplier (default: `1`). */ + zoomMin?: number; + + /** Animate button/programmatic zooming (default: `true`). */ + zoomAnimate?: boolean; + + /** Zoom multiplier per zoom step (default: `1.5`). */ + zoomStep?: number; + + /** Shows tooltips on hover (default: `true`). */ + showTooltip?: boolean; + + /** Binds touch (pan/pinch) events on touch devices (default: `true`). */ + bindTouchEvents?: boolean; + + /** Default style applied to lines. */ + lineStyle?: LineStyle; + + /** Allow markers to be selected (default: `false`). */ + markersSelectable?: boolean; + + /** Restrict marker selection to one at a time (default: `false`). */ + markersSelectableOne?: boolean; + + /** Marker style across interaction states. */ + markerStyle?: ElementStyle; + + /** Marker label style across interaction states. */ + markerLabelStyle?: ElementStyle; + + /** Allow regions to be selected (default: `false`). */ + regionsSelectable?: boolean; + + /** Restrict region selection to one at a time (default: `false`). */ + regionsSelectableOne?: boolean; + + /** Region style across interaction states. */ + regionStyle?: ElementStyle; + + /** Region label style across interaction states. */ + regionLabelStyle?: ElementStyle; + + /** Markers to render on load. */ + markers?: MarkerConfig[]; + + /** Lines to render on load. */ + lines?: LineConfig[]; + + /** Region/marker label configuration. */ + labels?: Labels; + + /** Data series (with optional legends). */ + series?: SeriesOptions; + + /** Choropleth data visualization. */ + visualizeData?: VisualizeDataOptions; + + /** Region codes selected on load. */ + selectedRegions?: string[]; + + /** Marker index keys selected on load. */ + selectedMarkers?: Array; + + /** Focus configuration applied on load. */ + focusOn?: FocusConfig; + } + + // ------------------------------------------------------------------ + // Map dataset + // ------------------------------------------------------------------ + + type ProjectionType = "mill" | "merc" | "aea" | "lcc"; + + interface MapProjection { + type: ProjectionType; + centralMeridian: number; + } + + interface MapDataInset { + width: number; + height: number; + top: number; + left: number; + /** `[topLeft, bottomRight]` bounding box in projection space. */ + bbox: [Point, Point]; + } + + interface MapPath { + /** SVG path `d` attribute for the region. */ + path: string; + /** Human-readable region name (used as default tooltip text). */ + name?: string; + } + + interface MapData { + width: number; + height: number; + /** Region paths keyed by region code. */ + paths: Record; + /** Detached areas (e.g. Alaska, Hawaii). */ + insets?: MapDataInset[]; + /** Projection used for coordinate conversion. */ + projection?: MapProjection; + } + + // ------------------------------------------------------------------ + // Registry entries + // ------------------------------------------------------------------ + + interface RegionEntry { + config: MapPath; + element: Region; + } + + interface MarkerEntry { + _uid: string; + config: MarkerConfig; + element: Marker; + } + + // ------------------------------------------------------------------ + // SVG element wrappers + // ------------------------------------------------------------------ + + /** Base wrapper around a raw SVG DOM node. */ + interface SVGElement { + node: globalThis.SVGElement; + addClass(className: string): void; + getBBox(): DOMRect; + set(property: Record): void; + set(property: string, value: StyleValue): void; + get(property: string): StyleValue; + applyAttr(property: string, value: StyleValue): void; + remove(): void; + } + + /** A styled, stateful SVG shape (path/circle/line/text/image). */ + interface SVGShapeElement extends SVGElement { + isHovered: boolean; + isSelected: boolean; + style: ElementStyle & { current: StyleAttributes }; + setStyle(property: StyleAttributes): void; + setStyle(property: string, value: StyleValue): void; + updateStyle(): void; + } + + /** A `` element; accepts an extra `text` attribute in `set`/`applyAttr`. */ + type SVGTextElement = SVGShapeElement; + + interface SVGImageElement extends SVGShapeElement { + width?: number; + height?: number; + offset?: Offset; + cx?: number; + cy?: number; + } + + /** A group `` element wrapper. */ + interface SVGGroupElement extends SVGElement { + canvas?: SVGCanvasElement; + } + + /** The SVG canvas holding the whole map. */ + interface SVGCanvasElement extends SVGElement { + node: SVGSVGElement; + setSize(width: number, height: number): void; + applyTransformParams(scale: number, transX: number, transY: number): void; + createPath(config: Record, style?: ElementStyle, group?: SVGElement): SVGShapeElement; + createCircle(config: Record, style?: ElementStyle, group?: SVGElement): SVGShapeElement; + createLine(config: Record, style?: ElementStyle, group?: SVGElement): SVGShapeElement; + createText(config: Record, style?: ElementStyle, group?: SVGElement): SVGTextElement; + createImage(config: Record, style?: ElementStyle, group?: SVGElement): SVGImageElement; + createGroup(id?: string): SVGGroupElement; + } + + // ------------------------------------------------------------------ + // Components + // ------------------------------------------------------------------ + + /** Shared behaviour for interactive components (regions & markers). */ + interface Interactable { + shape: SVGShapeElement; + label?: SVGTextElement; + isHovered?: boolean; + isSelected?: boolean; + getLabelText(key: string | number, label?: LabelOptions): string | undefined; + getLabelOffsets(key: string | number, label?: LabelOptions): Offset; + setStyle(property: string, value: StyleValue): void; + remove(): void; + hover(state: boolean): void; + select(state: boolean): void; + } + + interface BaseComponent { + dispose(): void; + } + + interface Region extends BaseComponent, Interactable { + labelX?: number; + labelY?: number; + updateLabelPosition(): void; + } + + interface Marker extends BaseComponent, Interactable { + getConfig(): MarkerConfig; + updateLabelPosition(): void; + } + + interface Line extends BaseComponent { + shape: SVGShapeElement; + getConfig(): LineConfig; + setStyle(property: StyleAttributes): void; + setStyle(property: string, value: StyleValue): void; + } + + /** The shared tooltip element. */ + interface Tooltip extends BaseComponent { + getElement(): HTMLElement; + show(): void; + hide(): void; + /** Gets the current text when called without arguments, otherwise sets it. */ + text(): string; + text(value: string, html?: boolean): void; + css(css: Partial | Record): this; + } + + // ------------------------------------------------------------------ + // Scales & data visualization + // ------------------------------------------------------------------ + + interface OrdinalScale { + getValue(value: string | number): string | ImageStyle; + getTicks(): Array<{ label: string; value: string | ImageStyle }>; + } + + interface Series { + config: SeriesConfig & { attribute: string }; + scale: OrdinalScale; + legend?: unknown; + setValues(values: Record): void; + setAttributes(attrs: Record): void; + clear(): void; + } + + interface DataVisualization { + min: number; + max: number; + setMinMaxValues(values: Record): void; + visualize(): void; + setAttributes(attrs: Record): void; + getValue(value: number): string; + hexToRgb(hex: string): [number, number, number]; + } +} + +declare global { + interface Window { + jsVectorMap: typeof jsVectorMap; + } +} diff --git a/types/jsvectormap/jsvectormap-tests.ts b/types/jsvectormap/jsvectormap-tests.ts new file mode 100644 index 00000000000000..acf4a2577b84ab --- /dev/null +++ b/types/jsvectormap/jsvectormap-tests.ts @@ -0,0 +1,373 @@ +import jsVectorMap = require("jsvectormap"); + +const container = document.getElementById("map")!; + +//////////////////////////////////////////////////////////////////////////////////////// +// Construction + +// The library also registers itself as a browser global. +new window.jsVectorMap({ + selector: container, +}); + +new jsVectorMap({ selector: "#map" }); // $ExpectType jsVectorMap +new jsVectorMap({ selector: container, map: "world" }); // $ExpectType jsVectorMap +// @ts-expect-error +new jsVectorMap({}); +// @ts-expect-error +new jsVectorMap({ selector: "#map", notAnOption: true }); +// @ts-expect-error +new jsVectorMap({ selector: 1 }); +// The selection options only accept arrays. +// @ts-expect-error +new jsVectorMap({ selector: "#map", selectedRegions: "US" }); +// @ts-expect-error +new jsVectorMap({ selector: "#map", selectedMarkers: "0" }); + +const map = new jsVectorMap({ + selector: "#map", + map: "world", + backgroundColor: "#1f2937", + draggable: true, + zoomButtons: true, + zoomInButton: "#zoom-in", + zoomOutButton: container, + zoomOnScroll: true, + zoomOnScrollSpeed: 3, + zoomMax: 12, + zoomMin: 1, + zoomAnimate: true, + zoomStep: 1.5, + showTooltip: true, + bindTouchEvents: true, + regionsSelectable: true, + regionsSelectableOne: false, + markersSelectable: true, + markersSelectableOne: false, + selectedRegions: ["US", "FR"], + selectedMarkers: [0, "1"], + regionStyle: { + initial: { fill: "#d1d5db", fillOpacity: 1, stroke: "none" }, + hover: { fillOpacity: 0.7, cursor: "pointer" }, + selected: { fill: "#2563eb" }, + selectedHover: { fill: "#1d4ed8" }, + }, + regionLabelStyle: { + initial: { fontFamily: "Verdana", fontSize: 12, fontWeight: 500, fill: "#35373e" }, + }, + markerStyle: { + initial: { r: 6, fill: "#374151", stroke: "#fff", strokeWidth: 5, strokeOpacity: 0.5 }, + hover: { fill: "#111827" }, + }, + markerLabelStyle: { + initial: { fontFamily: "Verdana", fontSize: 13 }, + }, + lineStyle: { + stroke: "#808080", + strokeWidth: 1, + strokeLinecap: "round", + strokeDasharray: "6 3 6", + curvature: 0.5, + // Unknown SVG presentation attributes are allowed. + animation: true, + }, + markers: [ + { name: "Egypt", coords: [26.8206, 30.8025] }, + { name: "Russia", coords: [61.524, 105.3188], style: { initial: { fill: "#f97316" } } }, + ], + lines: [ + { from: "Egypt", to: "Russia" }, + { from: "Russia", to: "Egypt", style: { stroke: "#3b82f6", curvature: 0 } }, + ], + labels: { + regions: { + render: (code: string) => code, + }, + markers: { + render: (marker: jsVectorMap.MarkerConfig) => marker.name, + offsets: (key) => (key === 0 ? [0, -8] : [0, -12]), + }, + }, + focusOn: { + regions: ["EG", "RU"], + animate: true, + }, + onLoaded(instance) { + instance; // $ExpectType jsVectorMap + this.setBackgroundColor("#fff"); + }, + onViewportChange(scale, transX, transY) { + scale; // $ExpectType number + transX; // $ExpectType number + transY; // $ExpectType number + }, + onRegionClick(event, code) { + event; // $ExpectType MouseEvent + code; // $ExpectType string + this.setSelectedRegions(code); + }, + onRegionSelected(code, isSelected, selectedRegions) { + code; // $ExpectType string + isSelected; // $ExpectType boolean + selectedRegions; // $ExpectType string[] + }, + onMarkerClick(event, index) { + event.preventDefault(); + index; // $ExpectType string + }, + onMarkerSelected(index, isSelected, selectedMarkers) { + index; // $ExpectType string + isSelected; // $ExpectType boolean + selectedMarkers; // $ExpectType string[] + }, + onRegionTooltipShow(event, tooltip, code) { + tooltip; // $ExpectType Tooltip + tooltip.text(`${code}`, true); + if (code === "RU") { + event.preventDefault(); + } + }, + onMarkerTooltipShow(event, tooltip, index) { + event; // $ExpectType MouseEvent + tooltip.css({ backgroundColor: "#fff" }); // $ExpectType Tooltip + tooltip.text(index); + }, + onDestroyed() { + this.container; // $ExpectType HTMLElement + }, +}); + +//////////////////////////////////////////////////////////////////////////////////////// +// Instance state + +map.container; // $ExpectType HTMLElement +map.canvas; // $ExpectType SVGCanvasElement +map.scale; // $ExpectType number +map.transX; // $ExpectType number +map.transY; // $ExpectType number +map.params.zoomMax.toFixed(1); +map.regions["US"]; // $ExpectType RegionEntry +map.regions["US"].config.name; // $ExpectType string | undefined +map.regions["US"].element.select(true); // $ExpectType void + +//////////////////////////////////////////////////////////////////////////////////////// +// General + +map.setBackgroundColor("#fff"); // $ExpectType void +// $ExpectType void +map.extend("focusOnRegion", function(code: string) { + this.setFocus({ region: code, animate: true }); +}); +map.reset(); // $ExpectType void +// @ts-expect-error +map.setBackgroundColor(); + +//////////////////////////////////////////////////////////////////////////////////////// +// Regions + +map.getSelectedRegions(); // $ExpectType string[] +map.setSelectedRegions("US"); // $ExpectType void +map.setSelectedRegions(["US", "FR"]); // $ExpectType void +map.clearSelectedRegions(); // $ExpectType void +map.clearSelectedRegions("US"); // $ExpectType void +map.clearSelectedRegions(["US", "FR"]); // $ExpectType void +// @ts-expect-error +map.setSelectedRegions(); +// @ts-expect-error +map.setSelectedRegions(1); + +//////////////////////////////////////////////////////////////////////////////////////// +// Markers + +map.getSelectedMarkers(); // $ExpectType string[] +map.setSelectedMarkers(["0", "1"]); // $ExpectType void +map.setSelectedMarkers([0, "1"]); // $ExpectType void +map.clearSelectedMarkers(); // $ExpectType void +map.addMarkers({ name: "Cairo", coords: [30.0444, 31.2357] }); // $ExpectType void +// $ExpectType void +map.addMarkers([ + { coords: [26.8206, 30.8025], offsets: [0, -8] }, + { coords: [61.524, 105.3188], style: { initial: { image: "/pin.png" } } }, + { coords: [51.5074, -0.1278], style: { initial: { image: { url: "/pin.png", offset: [0, -8] } } } }, + // Extra properties are forwarded to the label `render` callback. + { coords: [48.8566, 2.3522], population: 2_140_000 }, +]); +map.removeMarkers(); // $ExpectType void +map.removeMarkers([0, "1"]); // $ExpectType void +// A bare index key is not accepted, only an array of them. +// @ts-expect-error +map.setSelectedMarkers("0"); +// @ts-expect-error +map.addMarkers({ name: "Cairo" }); +// @ts-expect-error +map.addMarkers({ coords: [1, 2, 3] }); + +//////////////////////////////////////////////////////////////////////////////////////// +// Lines + +map.addLines({ from: "Egypt", to: "Russia" }); // $ExpectType void +// $ExpectType void +map.addLines([ + { from: "Egypt", to: "Russia" }, + { from: "Russia", to: "Egypt", style: { stroke: "#3b82f6", strokeWidth: 2, curvature: 0 } }, +]); +map.removeLines([{ from: "Egypt", to: "Russia" }]); // $ExpectType void +map.removeLines(); // $ExpectType void +// @ts-expect-error +map.addLines({ from: "Egypt" }); + +// Deprecated single-line helpers. +map.addLine("Egypt", "Russia", { stroke: "#000" }); // $ExpectType void +map.removeLine("Egypt", "Russia"); // $ExpectType void + +//////////////////////////////////////////////////////////////////////////////////////// +// Viewport & geometry + +map.setFocus({ region: "US" }); // $ExpectType void +map.setFocus({ regions: ["US", "FR"], animate: true }); // $ExpectType void +map.setFocus({ coords: [26.8206, 30.8025], scale: 5, animate: false }); // $ExpectType void +map.updateSize(); // $ExpectType void +map.coordsToPoint(26.8206, 30.8025); // $ExpectType false | Point +map.getInsetForPoint(120, 240); // $ExpectType MapDataInset | undefined +map.getMarkerPosition({ coords: [26.8206, 30.8025] }); // $ExpectType false | Point +// @ts-expect-error +map.setFocus({ region: ["US"] }); + +//////////////////////////////////////////////////////////////////////////////////////// +// SVG canvas + +const group = map.canvas.createGroup("markers-group"); // $ExpectType SVGGroupElement +const circle = map.canvas.createCircle({ cx: 10, cy: 20, r: 5 }, { initial: { fill: "#f00" } }, group); +circle; // $ExpectType SVGShapeElement +circle.isHovered; // $ExpectType boolean +circle.isSelected; // $ExpectType boolean +circle.setStyle("fill", "#00f"); // $ExpectType void +circle.setStyle({ fill: "#00f", strokeWidth: 2 }); // $ExpectType void +circle.updateStyle(); // $ExpectType void +circle.addClass("jvm-marker"); // $ExpectType void +circle.set("fill", "#0f0"); // $ExpectType void +circle.set({ fill: "#0f0", r: 8 }); // $ExpectType void +circle.get("fill"); // $ExpectType StyleValue +circle.applyAttr("fill", "#0f0"); // $ExpectType void +circle.getBBox(); // $ExpectType DOMRect +circle.remove(); // $ExpectType void + +map.canvas.createPath({ d: "M0,0L10,10Z" }); // $ExpectType SVGShapeElement +map.canvas.createLine({ x1: 0, y1: 0, x2: 10, y2: 10 }); // $ExpectType SVGShapeElement +map.canvas.createImage({ x: 0, y: 0 }); // $ExpectType SVGImageElement +map.canvas.setSize(600, 400); // $ExpectType void +map.canvas.applyTransformParams(2, 10, 10); // $ExpectType void +map.canvas.node; // $ExpectType SVGSVGElement + +// `SVGTextElement` is an alias of `SVGShapeElement`. +const text: jsVectorMap.SVGTextElement = map.canvas.createText({ x: 0, y: 0, text: "Cairo" }); +text.setStyle("fontSize", 12); // $ExpectType void + +const image = map.canvas.createImage({ x: 0, y: 0 }, { initial: { image: "/pin.png" } }); +image.offset; // $ExpectType Offset | undefined +image.width; // $ExpectType number | undefined + +//////////////////////////////////////////////////////////////////////////////////////// +// Series, legends & data visualization + +const seriesMap = new jsVectorMap({ + selector: "#series-map", + series: { + regions: [{ + attribute: "fill", + values: { US: 100, FR: "50" }, + scale: { 100: "#4f46e5", 50: "#a5b4fc" }, + legend: { + vertical: true, + title: "GDP", + cssClass: "jvm-legend", + labelRender: (label) => label.toUpperCase(), + }, + }], + markers: [{ + attribute: "fill", + values: { 0: 25 }, + attributes: { fill: "#111827" }, + }], + }, + visualizeData: { + scale: ["#c8eeff", "#0071a4"], + values: { US: 100, FR: 50 }, + }, +}); + +seriesMap.series?.regions[0].setValues({ US: 20 }); // $ExpectType void | undefined +seriesMap.series?.markers[0].clear(); // $ExpectType void | undefined +seriesMap.series?.regions[0].scale.getValue(20); // $ExpectType string | ImageStyle | undefined +seriesMap.legendHorizontal; // $ExpectType HTMLElement | null | undefined +seriesMap.legendVertical; // $ExpectType HTMLElement | null | undefined +seriesMap.dataVisualization?.getValue(50); // $ExpectType string | undefined +seriesMap.dataVisualization?.hexToRgb("#0071a4"); // $ExpectType [number, number, number] | undefined +seriesMap.dataVisualization?.min; // $ExpectType number | undefined +seriesMap.dataVisualization?.visualize(); // $ExpectType void | undefined + +//////////////////////////////////////////////////////////////////////////////////////// +// Statics + +// $ExpectType void +jsVectorMap.addMap("egypt", { + width: 900, + height: 440, + paths: { + EG: { path: "M0,0L10,10Z", name: "Egypt" }, + }, + insets: [{ + width: 900, + height: 440, + top: 0, + left: 0, + bbox: [{ x: 0, y: 0 }, { x: 900, y: 440 }], + }], + projection: { type: "merc", centralMeridian: 11.5 }, +}); +// @ts-expect-error +jsVectorMap.addMap("egypt", { width: 900, height: 440, paths: {}, projection: { type: "utm", centralMeridian: 0 } }); + +//////////////////////////////////////////////////////////////////////////////////////// +// Standalone type usage + +const markers: jsVectorMap.MarkerConfig[] = [{ name: "Cairo", coords: [30.0444, 31.2357] }]; +const lineStyle: jsVectorMap.LineStyle = { stroke: "#000", strokeWidth: 1, curvature: 0.3 }; +const focus: jsVectorMap.FocusConfig = { coords: [30.0444, 31.2357], scale: 4 }; +const projection: jsVectorMap.MapProjection = { type: "mill", centralMeridian: 0 }; + +map.addMarkers(markers); +map.addLine("Cairo", "Cairo", lineStyle); +map.setFocus(focus); +projection.type; // $ExpectType ProjectionType + +// The components are structural interfaces: they can be referenced as types, +// but the library does not expose their constructors. +declare const region: jsVectorMap.Region; +region.shape.isSelected; // $ExpectType boolean +region.labelX; // $ExpectType number | undefined +region.getLabelText("US"); // $ExpectType string | undefined +region.getLabelOffsets("US"); // $ExpectType Offset +region.hover(true); // $ExpectType void +region.dispose(); // $ExpectType void + +declare const entry: jsVectorMap.MarkerEntry; +entry._uid; // $ExpectType string +entry.element.getConfig(); // $ExpectType MarkerConfig +entry.element.updateLabelPosition(); // $ExpectType void + +declare const line: jsVectorMap.Line; +line.getConfig(); // $ExpectType LineConfig +line.setStyle({ stroke: "#000" }); // $ExpectType void +line.setStyle("stroke", "#000"); // $ExpectType void + +declare const scale: jsVectorMap.OrdinalScale; +scale.getValue("50"); // $ExpectType string | ImageStyle +scale.getTicks(); // $ExpectType { label: string; value: string | ImageStyle; }[] + +//////////////////////////////////////////////////////////////////////////////////////// +// Teardown + +map.destroy(); // $ExpectType void +map.destroy(false); // $ExpectType void +seriesMap.destroy(true); // $ExpectType void diff --git a/types/jsvectormap/package.json b/types/jsvectormap/package.json new file mode 100644 index 00000000000000..241069f8d62fbb --- /dev/null +++ b/types/jsvectormap/package.json @@ -0,0 +1,25 @@ +{ + "private": true, + "name": "@types/jsvectormap", + "version": "1.7.9999", + "projects": [ + "https://github.com/themustafaomar/jsvectormap" + ], + "exports": { + ".": { + "types": { + "import": "./index.d.ts", + "require": "./index.d.ts" + } + } + }, + "devDependencies": { + "@types/jsvectormap": "workspace:." + }, + "owners": [ + { + "name": "one_222333", + "githubUsername": "bt-23" + } + ] +} diff --git a/types/jsvectormap/tsconfig.json b/types/jsvectormap/tsconfig.json new file mode 100644 index 00000000000000..13efb31ee7b6e9 --- /dev/null +++ b/types/jsvectormap/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "jsvectormap-tests.ts" + ] +} diff --git a/types/n3/index.d.ts b/types/n3/index.d.ts index b3e38f368499c7..1170d1a67b3902 100644 --- a/types/n3/index.d.ts +++ b/types/n3/index.d.ts @@ -394,4 +394,4 @@ export namespace Util { } export function termToId(term: Term): string; -export function termFromId(id: string, factory: RDF.DataFactory): Term; +export function termFromId(id: string, factory?: RDF.DataFactory): Term; diff --git a/types/n3/n3-tests.ts b/types/n3/n3-tests.ts index c4ccec659a5804..9778b20b31b90d 100644 --- a/types/n3/n3-tests.ts +++ b/types/n3/n3-tests.ts @@ -628,5 +628,10 @@ function test_base_iri_constructor() { const relative1: string = baseIri.toRelative("http://example.org/path/resource"); } +function test_term_from_id_optional_factory() { + // factory defaults to N3's own DataFactory + const t1: N3.Term = N3.termFromId("http://example.org/"); +} + export const namedNode: ReturnType = N3.DataFactory.namedNode("hello world"); export const df: RDF.DataFactory = N3.DataFactory;