@unmap/themes 0.16.0 → 0.17.0
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/README.md +5 -3
- package/dist/index.d.ts +15 -19
- package/dist/index.js +11 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,8 +32,8 @@ const doc = await decodeTheme(code) // validated ThemeDoc, or th
|
|
|
32
32
|
## What is in a theme
|
|
33
33
|
|
|
34
34
|
- `base` picks the style: `base`, `muted`, `outdoor`, `blueprint`, `blush`, `orchid`, `canopy`, `lagoon`, `tropic`, `sunset`, `bold`, `pastel`, `atlas` or `swiss`. Each of `light` and `dark` carries
|
|
35
|
-
sparse overrides on that style, so a theme with no overrides renders exactly like
|
|
36
|
-
|
|
35
|
+
sparse overrides on that style, so a theme with no overrides renders exactly like the style
|
|
36
|
+
itself at `/styles/<style>.json`.
|
|
37
37
|
- `basemap` overrides are colours on the style's recipe (land, water, vegetation, roads, labels,
|
|
38
38
|
points of interest, landcover). `marker` styles the geocoding pin (`color`, `scale` 0.5 to 2).
|
|
39
39
|
`route` styles the routing line (`color`, `width` 1 to 12, `opacity`, and a casing).
|
|
@@ -45,7 +45,9 @@ const doc = await decodeTheme(code) // validated ThemeDoc, or th
|
|
|
45
45
|
- `encodeTheme(doc)` and `decodeTheme(code)`: async, validate on both sides, throw `ThemeError`
|
|
46
46
|
with a `detail` array naming each problem. Simple themes encode as a short `u…` preset
|
|
47
47
|
(three characters and up); advanced overrides stay `ut1.` + deflate. Codes are at most 4096
|
|
48
|
-
characters.
|
|
48
|
+
characters. The `ut1` prefix is the wire version and bumps on a breaking change to the
|
|
49
|
+
document format. The short codes pack a style slot and a preset index; both tables grow only
|
|
50
|
+
at the end and keep their positions, and a retired slot is a tombstone that does not decode.
|
|
49
51
|
- `validateTheme(input)`: the synchronous validator, returns a typed `ThemeDoc`.
|
|
50
52
|
- `resolveTheme(doc, mode)`: what the gateway calls. Returns the style's flavor name, the
|
|
51
53
|
composed colour flavor, and the resolved `marker` and `route` styles with defaults filled in.
|
package/dist/index.d.ts
CHANGED
|
@@ -174,9 +174,9 @@ declare const mist: {
|
|
|
174
174
|
readonly 980: "#0D0D0D";
|
|
175
175
|
};
|
|
176
176
|
/**
|
|
177
|
-
* Jade, hue 163. The `
|
|
178
|
-
*
|
|
179
|
-
* rely on clears the floors here too. Chroma rises with lightness up to the mid steps
|
|
177
|
+
* Jade, hue 163. The emerald and mint greens of `orchid`'s woods and of the parks and woods in
|
|
178
|
+
* `tropic`, `bold` and `pastel`. Same lightness ladder as `ink`, so every label step the other
|
|
179
|
+
* styles rely on clears the floors here too. Chroma rises with lightness up to the mid steps
|
|
180
180
|
* (`0.16·L`) and eases off toward white (`0.42·(1−L)`), which is the profile of the
|
|
181
181
|
* reference's own four greens (`#142a21` → `#50a882`).
|
|
182
182
|
*/
|
|
@@ -460,15 +460,11 @@ declare const swissRelief: {
|
|
|
460
460
|
* The shipped styles. Appended, never inserted: this array's order drives the style picker in
|
|
461
461
|
* the unmap.dev builder, so inserting a style mid-array silently reorders a control people have
|
|
462
462
|
* already learned.
|
|
463
|
-
*
|
|
464
|
-
* `relief`, `street` and `decimal` were retired; they are not listed here. Short preset codes
|
|
465
|
-
* still decode those slots via `normalizeThemeBase` / the slot table in `preset.ts`. `decimal`
|
|
466
|
-
* (2026-09-09) maps onto `blueprint`: the two single-hue styles read as the same map.
|
|
467
463
|
*/
|
|
468
464
|
declare const THEME_BASES: readonly ["base", "muted", "outdoor", "blueprint", "blush", "orchid", "canopy", "lagoon", "tropic", "sunset", "bold", "pastel", "atlas", "swiss"];
|
|
469
465
|
type ThemeBase = (typeof THEME_BASES)[number];
|
|
470
|
-
/**
|
|
471
|
-
declare function
|
|
466
|
+
/** Whether `base` names a shipped style. */
|
|
467
|
+
declare function isThemeBase(base: unknown): base is ThemeBase;
|
|
472
468
|
declare const MODES: readonly ["light", "dark"];
|
|
473
469
|
type ThemeMode = (typeof MODES)[number];
|
|
474
470
|
interface RoadRamp {
|
|
@@ -707,8 +703,8 @@ declare function validateTheme(input: unknown): ThemeDoc;
|
|
|
707
703
|
* `deflate-raw`, which Node 20 — the repo floor — does not implement; the wrapper costs six
|
|
708
704
|
* bytes and buys a checksum.
|
|
709
705
|
*
|
|
710
|
-
* `ut1` is the wire version.
|
|
711
|
-
*
|
|
706
|
+
* `ut1` is the wire version. A breaking change to the document format bumps it, and the decoder
|
|
707
|
+
* reads the current prefix only.
|
|
712
708
|
*/
|
|
713
709
|
declare const THEME_CODE_PREFIX = "ut1.";
|
|
714
710
|
declare const MAX_CODE_LENGTH = 4096;
|
|
@@ -726,8 +722,7 @@ declare function decodeTheme(code: string): Promise<ThemeDoc>;
|
|
|
726
722
|
* enumerated choices that starts at three characters and grows only when the theme leaves the
|
|
727
723
|
* curated set.
|
|
728
724
|
*
|
|
729
|
-
* u00 …
|
|
730
|
-
* it decodes to `blueprint`, and `blueprint` still encodes as `u04`)
|
|
725
|
+
* u00 … u0E the style slots, in lineup order (`u03` is a tombstone and does not decode)
|
|
731
726
|
* u0W, u4e, … a named theme preset on a style (three characters for the first fifteen
|
|
732
727
|
* presets; `tamarack`, the sixteenth, is the first to take four)
|
|
733
728
|
* six to eight a style or preset with layer groups hidden or reordered
|
|
@@ -746,10 +741,10 @@ declare function decodeTheme(code: string): Promise<ThemeDoc>;
|
|
|
746
741
|
* by a 13-bit Lehmer index of the draw order (0 = stock order)
|
|
747
742
|
*
|
|
748
743
|
* Anything left above the last field is an error, so a truncated or padded code fails rather
|
|
749
|
-
* than decoding to a theme nobody asked for. Both lookup tables
|
|
750
|
-
*
|
|
751
|
-
*
|
|
752
|
-
*
|
|
744
|
+
* than decoding to a theme nobody asked for. Both lookup tables only grow at the end and never
|
|
745
|
+
* reuse a position: the index is bit-packed into every code, so removing an entry would
|
|
746
|
+
* renumber every code after it. A retired entry stays as a `null` tombstone that fails to
|
|
747
|
+
* decode. (The layout itself was re-cut on 2026-09-07.)
|
|
753
748
|
*/
|
|
754
749
|
declare const PRESET_CODE_PREFIX = "u";
|
|
755
750
|
declare const PRESET_CODE_RE: RegExp;
|
|
@@ -867,7 +862,8 @@ declare function contrastWarnings(doc: ThemeDoc): ContrastWarning[];
|
|
|
867
862
|
|
|
868
863
|
/**
|
|
869
864
|
* The shipped styles as starting-point themes: zero overrides, so each is guaranteed identical
|
|
870
|
-
* to
|
|
865
|
+
* to the style it names, served at `/styles/<style>.json` (asserted in the gateway theme tests).
|
|
866
|
+
* The builder opens on these.
|
|
871
867
|
*
|
|
872
868
|
* Named after the style itself — `base`, `muted`, `outdoor`, `blueprint`, `blush`, … — the same word the homepage, the
|
|
873
869
|
* SDK's `style` option and the gateway URL use. The theme presets (`process ink`, `boreal`, …)
|
|
@@ -956,4 +952,4 @@ interface PaletteColor {
|
|
|
956
952
|
*/
|
|
957
953
|
declare function seedsFromPalette(colors: PaletteColor[]): Required<ThemeSeeds>;
|
|
958
954
|
|
|
959
|
-
export { BUILDINGS_3D_LAYER_ID, type BasemapOverrides, type ContrastWarning, DEFAULT_LAYER_VISIBILITY, DEFAULT_MARKER, DEFAULT_ROUTE, DEFAULT_SEEDS, type DeepPartial, LABEL_PAIRS, LAYER_GROUPS, type LabelRamp, type LayerGroup, MAX_CODE_LENGTH, MODES, type MarkerTheme, type Oklch, PRESET_CODE_PREFIX, PRESET_CODE_RE, type PaletteColor, RECIPES, type RampSet, type Recipe, type ResolvedTheme, type RoadRamp, type RouteTheme, STOCK_RAMPS, STYLE_THEMES, THEME_BASES, THEME_CODE_PREFIX, THEME_PRESETS, type ThemeBase, type ThemeDoc, ThemeError, type ThemeHalf, type ThemeLayers, type ThemeMode, type ThemePreset, type ThemeSeeds, amber, applyThemeLayers, aqua, atlasGreen, atlasPaper, atlasRelief, atlasRoad, atlasWater, azure, buildRecipes, cobalt, contrast, contrastWarnings, coral, decodePreset, decodeTheme, effectiveLayerOrder, ember, encodePreset, encodeTheme, fern, generateTheme, graphite, hexToOklch, indigo, ink, isLayerVisible, isStockLayerOrder, isStockLayers, isThemePresetCode, jade, layerGroupOf, lilac, linen, makeFlavor, mergeRecipe, mist,
|
|
955
|
+
export { BUILDINGS_3D_LAYER_ID, type BasemapOverrides, type ContrastWarning, DEFAULT_LAYER_VISIBILITY, DEFAULT_MARKER, DEFAULT_ROUTE, DEFAULT_SEEDS, type DeepPartial, LABEL_PAIRS, LAYER_GROUPS, type LabelRamp, type LayerGroup, MAX_CODE_LENGTH, MODES, type MarkerTheme, type Oklch, PRESET_CODE_PREFIX, PRESET_CODE_RE, type PaletteColor, RECIPES, type RampSet, type Recipe, type ResolvedTheme, type RoadRamp, type RouteTheme, STOCK_RAMPS, STYLE_THEMES, THEME_BASES, THEME_CODE_PREFIX, THEME_PRESETS, type ThemeBase, type ThemeDoc, ThemeError, type ThemeHalf, type ThemeLayers, type ThemeMode, type ThemePreset, type ThemeSeeds, amber, applyThemeLayers, aqua, atlasGreen, atlasPaper, atlasRelief, atlasRoad, atlasWater, azure, buildRecipes, cobalt, contrast, contrastWarnings, coral, decodePreset, decodeTheme, effectiveLayerOrder, ember, encodePreset, encodeTheme, fern, generateTheme, graphite, hexToOklch, indigo, ink, isLayerVisible, isStockLayerOrder, isStockLayers, isThemeBase, isThemePresetCode, jade, layerGroupOf, lilac, linen, makeFlavor, mergeRecipe, mist, oklchToHex, paper, peach, presetId, registryThemeKey, resolveTheme, rose, sandstone, seedsFromPalette, shuffleSeeds, sky, swissGreen, swissPaper, swissRelief, swissRoad, swissWater, validateTheme, verdant, wave };
|
package/dist/index.js
CHANGED
|
@@ -366,14 +366,8 @@ var THEME_BASES = [
|
|
|
366
366
|
"atlas",
|
|
367
367
|
"swiss"
|
|
368
368
|
];
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
street: "base",
|
|
372
|
-
decimal: "blueprint"
|
|
373
|
-
};
|
|
374
|
-
function normalizeThemeBase(base) {
|
|
375
|
-
if (THEME_BASES.includes(base)) return base;
|
|
376
|
-
return RETIRED_BASES[base] ?? null;
|
|
369
|
+
function isThemeBase(base) {
|
|
370
|
+
return typeof base === "string" && THEME_BASES.includes(base);
|
|
377
371
|
}
|
|
378
372
|
var MODES = ["light", "dark"];
|
|
379
373
|
function makeFlavor(r) {
|
|
@@ -2506,8 +2500,7 @@ function validateTheme(input) {
|
|
|
2506
2500
|
if (!DOC_KEYS.includes(key)) errors.push(`${key}: unknown field`);
|
|
2507
2501
|
}
|
|
2508
2502
|
if (input.v !== 1) errors.push("v: must be 1");
|
|
2509
|
-
|
|
2510
|
-
if (!base) {
|
|
2503
|
+
if (!isThemeBase(input.base)) {
|
|
2511
2504
|
errors.push(`base: must be one of ${THEME_BASES.join(", ")}`);
|
|
2512
2505
|
}
|
|
2513
2506
|
if (input.name !== void 0) {
|
|
@@ -2546,7 +2539,6 @@ function validateTheme(input) {
|
|
|
2546
2539
|
}
|
|
2547
2540
|
}
|
|
2548
2541
|
if (errors.length > 0) throw new ThemeError("invalid theme", errors);
|
|
2549
|
-
if (base && base !== input.base) return { ...input, base };
|
|
2550
2542
|
return input;
|
|
2551
2543
|
}
|
|
2552
2544
|
|
|
@@ -3032,7 +3024,8 @@ var STYLE_SLOTS = [
|
|
|
3032
3024
|
"base",
|
|
3033
3025
|
"muted",
|
|
3034
3026
|
"outdoor",
|
|
3035
|
-
|
|
3027
|
+
null,
|
|
3028
|
+
// u03, retired 2026-09-09
|
|
3036
3029
|
"blueprint",
|
|
3037
3030
|
"blush",
|
|
3038
3031
|
"orchid",
|
|
@@ -3175,7 +3168,7 @@ function unpackLayers(bits) {
|
|
|
3175
3168
|
return layers;
|
|
3176
3169
|
}
|
|
3177
3170
|
function encodePreset(doc) {
|
|
3178
|
-
const slot = STYLE_SLOTS.indexOf(doc.base);
|
|
3171
|
+
const slot = isThemeBase(doc.base) ? STYLE_SLOTS.indexOf(doc.base) : -1;
|
|
3179
3172
|
if (slot < 0) return null;
|
|
3180
3173
|
let kind;
|
|
3181
3174
|
let payload = 0n;
|
|
@@ -3217,9 +3210,10 @@ function decodePreset(code) {
|
|
|
3217
3210
|
rest >>= bits;
|
|
3218
3211
|
return value;
|
|
3219
3212
|
};
|
|
3220
|
-
const slot =
|
|
3221
|
-
const base = slot
|
|
3222
|
-
if (
|
|
3213
|
+
const slot = Number(take(STYLE_BITS));
|
|
3214
|
+
const base = STYLE_SLOTS[slot];
|
|
3215
|
+
if (base === void 0) throw new ThemeError("invalid theme", ["preset style is out of range"]);
|
|
3216
|
+
if (base === null) throw new ThemeError("invalid theme", [`preset style slot ${slot} is retired`]);
|
|
3223
3217
|
const kind = take(KIND_BITS);
|
|
3224
3218
|
const hasLayers = take(1n) === 1n;
|
|
3225
3219
|
let doc;
|
|
@@ -3456,6 +3450,7 @@ export {
|
|
|
3456
3450
|
isLayerVisible,
|
|
3457
3451
|
isStockLayerOrder,
|
|
3458
3452
|
isStockLayers,
|
|
3453
|
+
isThemeBase,
|
|
3459
3454
|
isThemePresetCode,
|
|
3460
3455
|
jade,
|
|
3461
3456
|
layerGroupOf,
|
|
@@ -3464,7 +3459,6 @@ export {
|
|
|
3464
3459
|
makeFlavor,
|
|
3465
3460
|
mergeRecipe,
|
|
3466
3461
|
mist,
|
|
3467
|
-
normalizeThemeBase,
|
|
3468
3462
|
oklchToHex,
|
|
3469
3463
|
paper,
|
|
3470
3464
|
peach,
|