map-sprite
v0.1.1
Published
Framework-independent TypeScript utilities for generating MapLibre and Mapbox sprite assets from SVG icons.
Maintainers
Readme
map-sprite
Framework-independent TypeScript utilities for generating MapLibre / Mapbox sprite assets from SVG icons.
The package includes a small React example, but the core library does not depend on React.
Features
- Parse SVG text into icon inputs.
- Normalize SVG file names into map icon IDs.
- Pack icons with
maxrects-packer. - Generate MapLibre / Mapbox-compatible
sprite.json. - Render transparent
sprite.pngin the browser. - Export
map-sprite.zipcontents with both normal and retina assets:sprite.pngsprite.json[email protected][email protected]
Install
npm install map-spriteBasic Usage
import { createSprite, exportSpriteZip, parseSvgText } from "map-sprite";
const svgText = '<svg width="32" height="32" viewBox="0 0 32 32"></svg>';
const icon = parseSvgText(svgText, "Gas Valve.svg");
const sprite = createSprite([icon]);
console.log(sprite.json);
const zipBlob = await exportSpriteZip(sprite);DOM Editor Usage
The package also exposes a DOM-mounted editor, similar to map SDK initialization:
import { MapSpriteEditor } from "map-sprite";
const editor = new MapSpriteEditor({
container: document.getElementById("sprite-editor")!,
logic: "max-edge",
padding: 2,
preserveOrder: true,
themeColor: "#3fb572",
onChange({ sprite }) {
console.log(sprite.json);
}
});
editor.setThemeColor("#2f9e6a");
// Later, when unmounting:
editor.destroy();The editor owns its UI and supports SVG upload, drag-and-drop import, icon order reordering, icon rotation, layout strategy switching, gap configuration, theme color switching, transparent checkerboard preview, JSON preview, and ZIP export.
Editor layout modes:
max-edgeandmax-areausemaxrects-packer; icon dragging is disabled because positions are generated by the packer. ToggleKeep orderto preserve import order or let the packer search compact layout candidates.customfreezes the current positions and enables dragging. Dropping one icon on another swaps those two icons in the order, then recalculates custom positions with the configured gap without usingmaxrects-packer.
Switch packing logic when creating a sprite:
createSprite(icons, { logic: "max-edge" }); // default
createSprite(icons, { logic: "max-area" });Set spacing between SVG icons:
createSprite(icons, { padding: 4 });Rotate an icon in 90-degree steps before packing:
const rotatedIcon = {
...icon,
rotation: 90
} as const;
const sprite = createSprite([rotatedIcon]);
console.log(sprite.json[rotatedIcon.name].width); // uses the rotated bounding boxPreserve the caller-provided icon order instead of letting addArray sort inputs first:
createSprite(icons, { preserveOrder: true });exportSpriteZip includes normal and @2x assets by default. To export only one form:
await exportSpriteZip(sprite, { includeNormal: true, includeRetina: false });
await exportSpriteZip(sprite, { includeNormal: false, includeRetina: true });Core API
normalizeIconName(fileName: string): string
parseSvgText(svgText: string, fileName: string): SvgIconInput
createSprite(icons: SvgIconInput[], options?: SpriteOptions): SpriteResult
renderSpritePng(sprite: SpriteResult, options?: RenderSpriteOptions): Promise<Blob>
exportSpriteZip(sprite: SpriteResult, options?: ExportSpriteZipOptions): Promise<Blob>Default packing options:
{
maxWidth: 1024,
maxHeight: 1024,
padding: 2,
border: 1,
smart: true,
pot: false,
square: false,
allowRotation: false,
logic: "max-edge",
preserveOrder: false
}Packer-level rotation is always disabled because automatic rectangle rotation would desynchronize the rendered icon from downstream map usage. Per-icon rotation is supported in 90-degree steps and is reflected in the rendered PNG and generated JSON bounds.
Packing logic options:
"max-edge": sorts by longest edge and picks tighter edge fits. This is the default."max-area": sorts by area and picks lower wasted-area fits.
When preserveOrder is false, packing tries multiple deterministic order and width candidates, then keeps the single-sprite result with the smallest area.
React Example
Run the included example:
npm install
npm run devThe example supports SVG upload, drag-and-drop import, layout mode switching, gap changes, theme color changes, transparent checkerboard canvas preview, click selection, custom-mode reorder dragging, rotation, deletion, JSON preview, and ZIP export.
Development
npm run format:check
npm run format
npm test
npm run typecheck
npm run buildThe ZIP export test uses an injected PNG renderer so core ZIP behavior can be verified in Node without a real browser canvas.
