@neshan-maps-platform/maplibre-sdk 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026, Neshan Maps Platform
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,158 @@
1
+ # @neshan-maps-platform/maplibre-sdk
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@neshan-maps-platform/maplibre-sdk.svg)](https://www.npmjs.com/package/@neshan-maps-platform/maplibre-sdk)
4
+ [![license](https://img.shields.io/npm/l/@neshan-maps-platform/maplibre-sdk.svg)](./LICENSE)
5
+
6
+ > **Status: alpha.** The package is versioned `1.0.0-alpha` — the public API
7
+ > described below is expected to be stable, but breaking changes may still
8
+ > land before `1.0.0`.
9
+
10
+ A drop-in wrapper around [MapLibre GL JS](https://maplibre.org/) that
11
+ transparently decodes the platform's encoded, gzip-compressed vector tiles,
12
+ injects a client API key on every tile request, enables RTL text, and applies
13
+ custom branding — while being used **exactly like plain `maplibre-gl`**.
14
+ MapLibre is bundled into the package, so consumers install one thing.
15
+
16
+ ## Contents
17
+
18
+ - [Install & quick start](#neshan-maps-platformmaplibre-sdk)
19
+ - [How it works](#how-it-works)
20
+ - [API key](#api-key)
21
+ - [Custom branding](#custom-branding)
22
+ - [RTL text](#rtl-text-on-by-default)
23
+ - [Projection override](#projection-override)
24
+ - [Minimum zoom](#minimum-zoom)
25
+ - [Styles](#styles)
26
+ - [Browser support](#browser-support)
27
+ - [Package contents](#package-contents)
28
+ - [License](#license)
29
+
30
+ ```bash
31
+ npm install @neshan-maps-platform/maplibre-sdk
32
+ ```
33
+
34
+ ```js
35
+ import maplibregl from "@neshan-maps-platform/maplibre-sdk";
36
+ import "@neshan-maps-platform/maplibre-sdk/style.css";
37
+
38
+ const map = new maplibregl.Map({
39
+ container: "map",
40
+ style: "https://static.neshan.org/sdk/maplibre/styles/light.json",
41
+ center: [59.6, 36.3],
42
+ zoom: 12,
43
+ apiKey: "YOUR_API_KEY",
44
+ });
45
+ ```
46
+
47
+ That's the whole API. No protocol registration, no key handling, no
48
+ decompression, no control wiring — the subclass does all of it.
49
+
50
+ ## How it works
51
+
52
+ ### API key
53
+
54
+ Get an API key from [platform.neshan.org](https://platform.neshan.org/), then
55
+ pass it as `apiKey` to `new Map(...)`. It is appended as a `key` query
56
+ parameter to every tile request. It is your access/quota credential — not
57
+ secret in any meaningful sense, and enforced server-side.
58
+
59
+ `apiKey` is required — constructing a `Map` without one throws immediately.
60
+
61
+ ### Custom branding
62
+
63
+ The logo and copyright are added at the bottom of the map. The user can
64
+ change the location of the logo and copyright, but they are not allowed to
65
+ remove or hide them.
66
+
67
+ Placement is configurable via `NeshanMapOptions` — note that, despite the
68
+ names, `logoPosition` places the attribution control and `copyRightPosition`
69
+ places the brand logo:
70
+
71
+ ```js
72
+ new maplibregl.Map({
73
+ /* ... */
74
+ logoPosition: "bottom-left",
75
+ copyRightPosition: "bottom-right",
76
+ });
77
+ ```
78
+
79
+ Both accept MapLibre's `ControlPosition` (`'top-left'`, `'top-right'`,
80
+ `'bottom-left'`, `'bottom-right'`). `logoPosition` defaults to `'bottom-left'`;
81
+ `copyRightPosition` defaults to `'bottom-right'`.
82
+
83
+ ### RTL text (on by default)
84
+
85
+ Arabic/Persian/Hebrew labels need MapLibre's `mapbox-gl-rtl-text` plugin. The
86
+ SDK registers it **automatically** — RTL shaping is on by default with no
87
+ consumer action. The plugin is bundled locally, so there's no separate file to
88
+ host and no CDN dependency.
89
+
90
+ To customize or opt out per map:
91
+
92
+ ```js
93
+ new maplibregl.Map({ /* ... */, rtl: false }); // disable
94
+ new maplibregl.Map({ /* ... */, rtl: { lazy: false } }); // evaluate eagerly
95
+ new maplibregl.Map({ /* ... */, rtl: { url: '/rtl.js' }}); // self-hosted URL instead of inlined
96
+ ```
97
+
98
+ Registration is global and idempotent, shared across all maps on the page.
99
+
100
+ ### Projection override
101
+
102
+ Pass `projection` to force a projection regardless of what the loaded style
103
+ specifies, without editing the style JSON. It's re-applied on every
104
+ `style.load`, so it survives `setStyle` swaps too:
105
+
106
+ ```js
107
+ new maplibregl.Map({ /* ... */, projection: { type: "mercator" } });
108
+ new maplibregl.Map({ /* ... */, projection: { type: "globe" } });
109
+ ```
110
+
111
+ - `mercator` — the classic flat, 2D cylindrical map projection. Predictable
112
+ and familiar, but distorts area and shape at high latitudes.
113
+ - `globe` — renders the map as a 3D sphere that reveals its curvature at low
114
+ zoom levels, then blends into standard Mercator tiles as you zoom in.
115
+ More visually engaging for whole-world or low-zoom views.
116
+
117
+ ### Minimum zoom
118
+
119
+ `minZoom` is accepted as usual, but the SDK enforces a floor of `1.5` — if you
120
+ pass a lower value (or omit it), it's clamped up to `1.5`.
121
+
122
+ ### Styles
123
+
124
+ `style` is passed straight through to MapLibre, same as plain `maplibre-gl` —
125
+ point it at a style JSON URL. Five ready-made styles are hosted at
126
+ `https://static.neshan.org/sdk/maplibre/styles/`:
127
+
128
+ | Style | File | URL |
129
+ | ----------------------- | ----------------------- | --------------------------------------------------------------------- |
130
+ | Light | `light.json` | `https://static.neshan.org/sdk/maplibre/styles/light.json` |
131
+ | Dark | `dark.json` | `https://static.neshan.org/sdk/maplibre/styles/dark.json` |
132
+ | Neshan Monochrome Light | `monochrome_light.json` | `https://static.neshan.org/sdk/maplibre/styles/monochrome_light.json` |
133
+ | Neshan Monochrome Dark | `monochrome_dark.json` | `https://static.neshan.org/sdk/maplibre/styles/monochrome_dark.json` |
134
+ | Pastel | `pastel.json` | `https://static.neshan.org/sdk/maplibre/styles/pastel.json` |
135
+
136
+ ```js
137
+ new maplibregl.Map({
138
+ /* ... */
139
+ style: "https://static.neshan.org/sdk/maplibre/styles/dark.json",
140
+ });
141
+ ```
142
+
143
+ ## Browser support
144
+
145
+ Tile decoding uses the standard [`DecompressionStream`](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream)
146
+ API, so it needs Chrome 80+, Firefox 113+, or Safari 16.4+ (same floor as
147
+ `maplibre-gl` itself already requires). There is no fallback for older
148
+ browsers — tile requests will fail on them.
149
+
150
+ ## Package contents
151
+
152
+ | File | Format |
153
+ | --------------------------------- | ------------------------------------------------- |
154
+ | `dist/neshan-maplibre-sdk.js` | ESM |
155
+ | `dist/neshan-maplibre-sdk.cjs` | CJS |
156
+ | `dist/neshan-maplibre-sdk.umd.js` | UMD (global `maplibregl`) |
157
+ | `dist/neshan-maplibre-sdk.css` | extracted MapLibre CSS |
158
+ | `dist/index.d.ts` | rolled-up type declarations (public surface only) |
@@ -0,0 +1,75 @@
1
+ import { ControlPosition } from 'maplibre-gl';
2
+ import { default as default_2 } from 'maplibre-gl';
3
+ import { MapOptions } from 'maplibre-gl';
4
+ import { ProjectionSpecification } from 'maplibre-gl';
5
+
6
+ /**
7
+ * Drop-in replacement for maplibregl.Map. On construction it:
8
+ * - registers the nsh:// protocol (once per page, shared by all maps)
9
+ * - stores the consumer's `apiKey` for the protocol handler
10
+ * - disables the stock attribution and adds one carrying the brand entry
11
+ * - hides MapLibre's default logo and adds the custom brand logo control
12
+ *
13
+ * Consumers use it exactly like plain maplibre-gl plus one extra option:
14
+ *
15
+ * const map = new maplibregl.Map({
16
+ * container: 'map', style, center, zoom,
17
+ * apiKey: 'YOUR_API_KEY',
18
+ * });
19
+ */
20
+ declare class Map_2 extends default_2.Map {
21
+ constructor(options: NeshanMapOptions);
22
+ }
23
+ export { Map_2 as Map }
24
+
25
+ export declare interface NeshanMapOptions extends MapOptions {
26
+ /**
27
+ * Client-facing API key. NOT the tile decode key. Appended automatically
28
+ * as `?key=...` to every nsh:// tile request.
29
+ */
30
+ apiKey?: string;
31
+ /**
32
+ * RTL text shaping (Arabic/Persian/Hebrew). Enabled by default.
33
+ * Pass `false` to disable, or an options object to customize.
34
+ */
35
+ rtl?: boolean | RtlOptions;
36
+ logoPosition?: ControlPosition;
37
+ copyRightPosition?: ControlPosition;
38
+ /**
39
+ * Overrides the style's `projection`. Pass e.g. `{ type: 'mercator' }` to
40
+ * force mercator regardless of what the loaded style specifies, without
41
+ * editing the style JSON.
42
+ */
43
+ projection?: ProjectionSpecification;
44
+ }
45
+
46
+ /**
47
+ * RTL (right-to-left) text shaping for Arabic/Persian/Hebrew labels.
48
+ *
49
+ * MapLibre needs the mapbox-gl-rtl-text plugin registered once, globally,
50
+ * before it renders RTL glyphs. We inline the vendored plugin as a string and
51
+ * hand MapLibre a Blob URL, so it's fully self-contained.
52
+ *
53
+ * The SDK's Map subclass calls ensureRtlTextPlugin() automatically, so RTL is
54
+ * on by default. Exported for manual/advanced use as well.
55
+ */
56
+ export declare interface RtlOptions {
57
+ /**
58
+ * Defer downloading/evaluating the plugin until RTL text is first
59
+ * encountered. Default true. For a mostly-RTL basemap you can pass false to
60
+ * evaluate eagerly.
61
+ */
62
+ lazy?: boolean;
63
+ /**
64
+ * Override the plugin URL instead of using the inlined vendored file (e.g.
65
+ * point at a self-hosted copy). When set, the inlined file is ignored.
66
+ */
67
+ url?: string;
68
+ }
69
+
70
+ declare const sdk: Omit<typeof default_2, "Map"> & {
71
+ Map: typeof Map_2;
72
+ };
73
+ export default sdk;
74
+
75
+ export { }