@unmap/themes 0.2.0 → 0.3.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 +2 -2
- package/dist/index.d.ts +151 -6
- package/dist/index.js +886 -50
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ import { encodeTheme, decodeTheme, validateTheme, ThemeError } from '@unmap/them
|
|
|
20
20
|
const code = await encodeTheme({
|
|
21
21
|
v: 1,
|
|
22
22
|
name: 'copper',
|
|
23
|
-
base: 'outdoor', // base | muted | outdoor | decimal | blueprint
|
|
23
|
+
base: 'outdoor', // base | muted | outdoor | decimal | blueprint | blush | orchid | canopy | lagoon
|
|
24
24
|
light: { basemap: { water: '#9CCFD2' }, route: { color: '#B85C00', width: 4 } },
|
|
25
25
|
dark: { basemap: { water: '#12303A' }, route: { color: '#FFA24D', width: 4 } },
|
|
26
26
|
})
|
|
@@ -31,7 +31,7 @@ const doc = await decodeTheme(code) // validated ThemeDoc, or th
|
|
|
31
31
|
|
|
32
32
|
## What is in a theme
|
|
33
33
|
|
|
34
|
-
- `base` picks the style: `base`, `muted`, `outdoor`, `decimal` or `
|
|
34
|
+
- `base` picks the style: `base`, `muted`, `outdoor`, `decimal`, `blueprint`, `blush`, `orchid`, `canopy` or `lagoon`. Each of `light` and `dark` carries
|
|
35
35
|
sparse overrides on that style, so a theme with no overrides renders exactly like its
|
|
36
36
|
`flavor=` twin.
|
|
37
37
|
- `basemap` overrides are colours on the style's recipe (land, water, vegetation, roads, labels,
|
package/dist/index.d.ts
CHANGED
|
@@ -199,6 +199,65 @@ declare const cobalt: {
|
|
|
199
199
|
readonly 950: "#0F1629";
|
|
200
200
|
readonly 1000: "#080B15";
|
|
201
201
|
};
|
|
202
|
+
/**
|
|
203
|
+
* Rose, hue 20. The `blush` pair's land, buildings and labels: a pink that stays a field at the
|
|
204
|
+
* light steps and becomes a wine at the dark ones. Same lightness ladder as `ink`; chroma rises
|
|
205
|
+
* with lightness to the mid steps and eases off toward white.
|
|
206
|
+
*/
|
|
207
|
+
declare const rose: {
|
|
208
|
+
readonly 25: "#FFF3F3";
|
|
209
|
+
readonly 50: "#FFEBEA";
|
|
210
|
+
readonly 100: "#FFDFDE";
|
|
211
|
+
readonly 200: "#FECFCE";
|
|
212
|
+
readonly 300: "#FCBDBC";
|
|
213
|
+
readonly 400: "#F8A4A4";
|
|
214
|
+
readonly 500: "#E48687";
|
|
215
|
+
readonly 600: "#BA6D6D";
|
|
216
|
+
readonly 700: "#8D5151";
|
|
217
|
+
readonly 800: "#643838";
|
|
218
|
+
readonly 850: "#4B2929";
|
|
219
|
+
readonly 900: "#351B1B";
|
|
220
|
+
readonly 950: "#241111";
|
|
221
|
+
readonly 1000: "#150808";
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Lilac, hue 300, low chroma. The `orchid` pair's land, buildings and labels — a lavender grey
|
|
225
|
+
* rather than a purple, so the vivid teal parks and sky water are what carry the colour. Chroma
|
|
226
|
+
* grows a little toward the dark steps so the labels read as violet rather than as grey.
|
|
227
|
+
*/
|
|
228
|
+
declare const lilac: {
|
|
229
|
+
readonly 25: "#F8F5FF";
|
|
230
|
+
readonly 50: "#F2EDFF";
|
|
231
|
+
readonly 100: "#EAE4F9";
|
|
232
|
+
readonly 200: "#DFD8EE";
|
|
233
|
+
readonly 300: "#D2CBE1";
|
|
234
|
+
readonly 400: "#C1BACF";
|
|
235
|
+
readonly 500: "#A7A1B5";
|
|
236
|
+
readonly 600: "#888296";
|
|
237
|
+
readonly 700: "#676174";
|
|
238
|
+
readonly 800: "#4A415A";
|
|
239
|
+
readonly 850: "#382E4A";
|
|
240
|
+
readonly 900: "#281C3C";
|
|
241
|
+
readonly 950: "#1C0E30";
|
|
242
|
+
readonly 1000: "#110225";
|
|
243
|
+
};
|
|
244
|
+
/**
|
|
245
|
+
* Aqua, hue 205. Vivid teal on the `wave` ladder for `orchid`'s and `lagoon`'s parks — the
|
|
246
|
+
* only park colour on the map that is not a green. Chroma peaks at the mid steps.
|
|
247
|
+
*/
|
|
248
|
+
declare const aqua: {
|
|
249
|
+
readonly 100: "#C7F1F5";
|
|
250
|
+
readonly 200: "#ACE3E9";
|
|
251
|
+
readonly 300: "#89D2DB";
|
|
252
|
+
readonly 400: "#57BEC9";
|
|
253
|
+
readonly 500: "#00A6B3";
|
|
254
|
+
readonly 600: "#00858F";
|
|
255
|
+
readonly 700: "#00636B";
|
|
256
|
+
readonly 800: "#004349";
|
|
257
|
+
readonly 900: "#05292D";
|
|
258
|
+
readonly 950: "#081B1D";
|
|
259
|
+
readonly 980: "#060E0F";
|
|
260
|
+
};
|
|
202
261
|
|
|
203
262
|
/**
|
|
204
263
|
* The unmap cartography authoring surface, moved here from apps/gateway/src/flavors.ts so the
|
|
@@ -217,7 +276,7 @@ declare const cobalt: {
|
|
|
217
276
|
* `relief` and `street` were retired; they are not listed here. Short preset codes still
|
|
218
277
|
* decode those slots via `normalizeThemeBase` / the slot table in `preset.ts`.
|
|
219
278
|
*/
|
|
220
|
-
declare const THEME_BASES: readonly ["base", "muted", "outdoor", "decimal", "blueprint"];
|
|
279
|
+
declare const THEME_BASES: readonly ["base", "muted", "outdoor", "decimal", "blueprint", "blush", "orchid", "canopy", "lagoon"];
|
|
221
280
|
type ThemeBase = (typeof THEME_BASES)[number];
|
|
222
281
|
/** Map a theme `base` — living or retired — onto a shipped style. `null` if unknown. */
|
|
223
282
|
declare function normalizeThemeBase(base: string): ThemeBase | null;
|
|
@@ -317,6 +376,9 @@ interface RampSet {
|
|
|
317
376
|
mist: typeof mist;
|
|
318
377
|
jade: typeof jade;
|
|
319
378
|
cobalt: typeof cobalt;
|
|
379
|
+
rose: typeof rose;
|
|
380
|
+
lilac: typeof lilac;
|
|
381
|
+
aqua: typeof aqua;
|
|
320
382
|
ember: typeof ember;
|
|
321
383
|
}
|
|
322
384
|
declare const STOCK_RAMPS: RampSet;
|
|
@@ -378,12 +440,41 @@ interface ThemeSeeds {
|
|
|
378
440
|
/** Marker + route accent. Defaults to the interface magenta. */
|
|
379
441
|
accent?: string;
|
|
380
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* The major layer groups a theme can hide or reorder, in their stock bottom-to-top draw order.
|
|
445
|
+
* Every layer the cartography draws belongs to exactly one of these (see `layerGroupOf`) except
|
|
446
|
+
* the background, which always stays underneath. `buildings3d` is the one group that is off by
|
|
447
|
+
* default: it draws building extrusions from the tiles' `height` property on top of the roads.
|
|
448
|
+
*
|
|
449
|
+
* Append only, like `THEME_BASES`: the names are on the wire in every `ut1.` code.
|
|
450
|
+
*/
|
|
451
|
+
declare const LAYER_GROUPS: readonly ["land", "water", "buildings", "roads", "boundaries", "buildings3d", "labels"];
|
|
452
|
+
type LayerGroup = (typeof LAYER_GROUPS)[number];
|
|
453
|
+
/**
|
|
454
|
+
* Structural overrides on the layer groups. Doc-level, not per half: which layers draw, and in
|
|
455
|
+
* what order, is one decision for both modes — colour is the only thing that differs between
|
|
456
|
+
* light and dark. Sparse like the halves: an absent field means stock.
|
|
457
|
+
*/
|
|
458
|
+
interface ThemeLayers {
|
|
459
|
+
/**
|
|
460
|
+
* Per-group visibility; a missing key means the group's default (every group on except
|
|
461
|
+
* `buildings3d`). Hidden groups are dropped from the style entirely.
|
|
462
|
+
*/
|
|
463
|
+
visible?: Partial<Record<LayerGroup, boolean>>;
|
|
464
|
+
/**
|
|
465
|
+
* Bottom-to-top draw order, always the full set of groups exactly once. Absent means the
|
|
466
|
+
* stock cartography order, in which the groups interleave (tunnels under buildings, bridges
|
|
467
|
+
* over boundaries); an explicit order regroups every layer under its group.
|
|
468
|
+
*/
|
|
469
|
+
order?: LayerGroup[];
|
|
470
|
+
}
|
|
381
471
|
interface ThemeDoc {
|
|
382
472
|
v: 1;
|
|
383
473
|
/** Display name, ≤ 40 chars. */
|
|
384
474
|
name?: string;
|
|
385
475
|
base: ThemeBase;
|
|
386
476
|
seeds?: ThemeSeeds;
|
|
477
|
+
layers?: ThemeLayers;
|
|
387
478
|
light?: ThemeHalf;
|
|
388
479
|
dark?: ThemeHalf;
|
|
389
480
|
}
|
|
@@ -429,9 +520,10 @@ declare function decodeTheme(code: string): Promise<ThemeDoc>;
|
|
|
429
520
|
*
|
|
430
521
|
* u00, u01, u04 living styles from the original lineup (base, muted, outdoor)
|
|
431
522
|
* u02, u03 retired styles (relief → outdoor, street → base)
|
|
432
|
-
* u05, u06
|
|
523
|
+
* u05, u06 the second wave (decimal, blueprint)
|
|
524
|
+
* u5K, u5N, … the third wave (blush, orchid, canopy, lagoon) and any style after them
|
|
433
525
|
* u08… named theme preset on one of the original style slots
|
|
434
|
-
*
|
|
526
|
+
* u5L… named theme preset on a later style
|
|
435
527
|
* longer custom seed colours (4× RGB) on any style
|
|
436
528
|
*
|
|
437
529
|
* Advanced overrides — anything `generateTheme` would not emit — still use the `ut1.` deflate
|
|
@@ -485,6 +577,58 @@ declare function mergeRecipe(base: Recipe, overrides?: BasemapOverrides): Recipe
|
|
|
485
577
|
*/
|
|
486
578
|
declare function resolveTheme(doc: ThemeDoc, mode: ThemeMode): ResolvedTheme;
|
|
487
579
|
|
|
580
|
+
/**
|
|
581
|
+
* Layer groups: the structural half of a theme. A theme can hide any of the seven major groups
|
|
582
|
+
* and redraw them in another order, the way kepler.gl's base-map panel does. This module owns
|
|
583
|
+
* the mapping from the expanded Protomaps layer list onto those groups and applies a document's
|
|
584
|
+
* `layers` field to a style's layer array.
|
|
585
|
+
*
|
|
586
|
+
* It works on the expanded layers rather than the Flavor because the groups are about what
|
|
587
|
+
* draws, not what colour it draws in — the Recipe stays the colour surface, this is the only
|
|
588
|
+
* structural one, and both are still data (booleans and one enum list on the wire).
|
|
589
|
+
*/
|
|
590
|
+
/** Stock visibility: every group draws except the extrusions, which are opt-in. */
|
|
591
|
+
declare const DEFAULT_LAYER_VISIBILITY: Readonly<Record<LayerGroup, boolean>>;
|
|
592
|
+
/** The id of the synthetic extrusion layer `buildings3d` draws. */
|
|
593
|
+
declare const BUILDINGS_3D_LAYER_ID = "buildings_3d";
|
|
594
|
+
/**
|
|
595
|
+
* Which group an expanded Protomaps layer belongs to, or `null` for the background, which is
|
|
596
|
+
* never hidden or moved: with land off it is what you see. Symbol layers are labels regardless
|
|
597
|
+
* of their source, so the POI icons, shields and one-way arrows hide with the text.
|
|
598
|
+
*
|
|
599
|
+
* The contract test asserts every stock layer lands in a group, so an upstream layer this
|
|
600
|
+
* cannot place fails loudly rather than becoming an unmovable, unhideable stray.
|
|
601
|
+
*/
|
|
602
|
+
declare function layerGroupOf(layer: {
|
|
603
|
+
id: string;
|
|
604
|
+
type: string;
|
|
605
|
+
}): LayerGroup | null;
|
|
606
|
+
/** Whether a group draws under this `layers` field (absent field means stock). */
|
|
607
|
+
declare function isLayerVisible(layers: ThemeLayers | undefined, group: LayerGroup): boolean;
|
|
608
|
+
/** The bottom-to-top group order this `layers` field asks for; stock when it names none. */
|
|
609
|
+
declare function effectiveLayerOrder(layers: ThemeLayers | undefined): readonly LayerGroup[];
|
|
610
|
+
/** True when `order` is the stock order (or absent), so nothing needs regrouping. */
|
|
611
|
+
declare function isStockLayerOrder(order: readonly LayerGroup[] | undefined): boolean;
|
|
612
|
+
/** True when the field changes nothing — the builder strips such a field back to absent. */
|
|
613
|
+
declare function isStockLayers(layers: ThemeLayers | undefined): boolean;
|
|
614
|
+
/**
|
|
615
|
+
* Apply a theme's `layers` field to an expanded style layer array. Returns the input untouched
|
|
616
|
+
* when the field changes nothing, so a zero-override theme stays byte-identical to its flavor.
|
|
617
|
+
*
|
|
618
|
+
* Hidden groups are removed outright rather than set to `visibility: none` — a smaller style,
|
|
619
|
+
* and nothing left for a client to accidentally switch back on. With the stock order the
|
|
620
|
+
* remaining layers keep their stock positions (and the extrusions, if on, slot in just under
|
|
621
|
+
* the labels). With a custom order every group's layers are gathered under it, in stock
|
|
622
|
+
* relative order within the group; the background and any layer outside every group stay
|
|
623
|
+
* first, in their stock order.
|
|
624
|
+
*
|
|
625
|
+
* `buildingsColor` paints the extrusions: the resolved theme's `buildings` slot.
|
|
626
|
+
*/
|
|
627
|
+
declare function applyThemeLayers<T extends {
|
|
628
|
+
id: string;
|
|
629
|
+
type: string;
|
|
630
|
+
}>(styleLayers: T[], layers: ThemeLayers | undefined, buildingsColor: string): T[];
|
|
631
|
+
|
|
488
632
|
/** WCAG contrast ratio between two hex colours (1–21). */
|
|
489
633
|
declare function contrast(a: string, b: string): number;
|
|
490
634
|
/** Every enforced pair with its floor — the generator's contrast-clamp iterates these. */
|
|
@@ -506,7 +650,7 @@ declare function contrastWarnings(doc: ThemeDoc): ContrastWarning[];
|
|
|
506
650
|
* The shipped styles as starting-point themes: zero overrides, so each is guaranteed identical
|
|
507
651
|
* to its `flavor=` twin (asserted in the gateway theme tests). The builder opens on these.
|
|
508
652
|
*
|
|
509
|
-
* Named after the style itself — `base`, `muted`, `outdoor`, `decimal`, `blueprint` — the same word the homepage, the
|
|
653
|
+
* Named after the style itself — `base`, `muted`, `outdoor`, `decimal`, `blueprint`, `blush`, … — the same word the homepage, the
|
|
510
654
|
* SDK's `style` option and the gateway URL use. The theme presets (`process ink`, `boreal`, …)
|
|
511
655
|
* are a separate set layered on a style; a style never borrows one's name.
|
|
512
656
|
*/
|
|
@@ -547,7 +691,8 @@ declare const DEFAULT_SEEDS: Required<ThemeSeeds>;
|
|
|
547
691
|
* Family mapping: `land` recolours the land spines — `ink`, `base`'s `paper`, `muted`'s
|
|
548
692
|
* `graphite` at a whisper of chroma (that style exists to vanish under data), and the
|
|
549
693
|
* single-hue families of `decimal` (`jade`) and `blueprint` (`cobalt`) at full chroma, so a
|
|
550
|
-
* seed can carry them to any hue
|
|
694
|
+
* seed can carry them to any hue, plus `blush`'s `rose` and `orchid`'s `lilac`. `nature`
|
|
695
|
+
* recolours `verdant` and the teal `aqua` of `orchid` and `lagoon`. `water` recolours the wave, sky, and mist ramps (`mist` is
|
|
551
696
|
* greyscale in stock `muted` and takes the water seed's hue outright), `nature` the verdant
|
|
552
697
|
* ramp. Warm landcover (sandstone), POI accents and white road fills stay stock: they
|
|
553
698
|
* are tuned relationships, not identity. `accent` styles the marker and route overlays only —
|
|
@@ -576,4 +721,4 @@ declare const THEME_PRESETS: ThemePreset[];
|
|
|
576
721
|
*/
|
|
577
722
|
declare function shuffleSeeds(rng?: () => number): Required<ThemeSeeds>;
|
|
578
723
|
|
|
579
|
-
export { type BasemapOverrides, type ContrastWarning, DEFAULT_MARKER, DEFAULT_ROUTE, DEFAULT_SEEDS, type DeepPartial, LABEL_PAIRS, type LabelRamp, MAX_CODE_LENGTH, MODES, type MarkerTheme, type Oklch, PRESET_CODE_PREFIX, PRESET_CODE_RE, 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 ThemeMode, type ThemePreset, type ThemeSeeds, buildRecipes, cobalt, contrast, contrastWarnings, decodePreset, decodeTheme, ember, encodePreset, encodeTheme, generateTheme, graphite, hexToOklch, ink, isThemePresetCode, jade, makeFlavor, mergeRecipe, mist, normalizeThemeBase, oklchToHex, paper, presetId, registryThemeKey, resolveTheme, sandstone, shuffleSeeds, sky, validateTheme, verdant, wave };
|
|
724
|
+
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, 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, applyThemeLayers, aqua, buildRecipes, cobalt, contrast, contrastWarnings, decodePreset, decodeTheme, effectiveLayerOrder, ember, encodePreset, encodeTheme, generateTheme, graphite, hexToOklch, ink, isLayerVisible, isStockLayerOrder, isStockLayers, isThemePresetCode, jade, layerGroupOf, lilac, makeFlavor, mergeRecipe, mist, normalizeThemeBase, oklchToHex, paper, presetId, registryThemeKey, resolveTheme, rose, sandstone, shuffleSeeds, sky, validateTheme, verdant, wave };
|