ixmaps-gl 0.2.14 → 0.2.15

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.
Files changed (3) hide show
  1. package/README.md +25 -0
  2. package/ixmaps-gl.js +183 -48
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -101,6 +101,31 @@ an id wins, a polygon's position is flat's shape center (the vertex mean in Merc
101
101
  `chartlower` (else `layerupper`/`layerlower`) hide a theme outside their scales; `.filter()` takes
102
102
  flat's grammar (`WHERE a > 5 AND b NOT x`, `LIKE`, `IN`, `BETWEEN`, `$field$`, or a plain regex).
103
103
 
104
+ ### Handle API
105
+
106
+ The main interface is flat's handle chain: `ixmaps.map()` — or `ixmaps.map("name")` for the map
107
+ with that `name` in its `Map()` options, so several maps on one page can be addressed separately
108
+ (no name: the last built map, as in flat). From the map handle, `map("name").theme("themename")`
109
+ returns the theme handle (flat's `themeApi`):
110
+
111
+ ```js
112
+ ixmaps.map("map1").theme("mytheme").changeStyle("scale:1.2", "factor");
113
+ ixmaps.map().theme("mytheme").show(); // also hide(), toggle(), remove(),
114
+ // replace(theme), markClass(n), unmarkClass(n)
115
+ ```
116
+
117
+ The historic global forms remain as compatibility wrappers and dispatch on arity: the canonical
118
+ theme-first `ixmaps.changeThemeStyle(themeId, "style:value", "set")` and `ixmaps.removeTheme(id)`
119
+ (htmlgui.js), the handle method `map().changeThemeStyle(theme, style, flag)`, and the older
120
+ map-first pages calling `ixmaps.changeThemeStyle(null|mapName, themeId, style, flag)` /
121
+ `ixmaps.removeTheme(null|mapName, id)` / `ixmaps.setBasemapOpacity(null|mapName, opacity, mode)`
122
+ — where a registered map name targets that map and a null or unknown name the last built one.
123
+ The `ixmaps.Map(div, opts, callback)` callback receives the builder for its own
124
+ `.options().view().layer()` chain, which also carries flat's mapApi handle methods
125
+ (`setView`, `replace`, `show`, `getThemes`, … — htmlgui_flat.js), each delegated to the handle
126
+ of that map's options name — so a page that keeps the callback object as its map handle,
127
+ as flat pages do, works unmodified.
128
+
104
129
  ### Zoom levels
105
130
 
106
131
  Zoom numbers in the ixmaps API are ixmaps-flat's, i.e. Leaflet's (256px tiles):
package/ixmaps-gl.js CHANGED
@@ -82,7 +82,7 @@
82
82
  // ---------------------------------------------------------------
83
83
  // this engine's release (= package.json "version", checked by
84
84
  // test/unit/version.test.mjs); ixmaps.glVersion, and logged once at start
85
- const IXMAPS_GL_VERSION = '0.2.14';
85
+ const IXMAPS_GL_VERSION = '0.2.15';
86
86
 
87
87
  const LIB_URLS = {
88
88
  // Bumped 3.6.2 -> 5.x (2026-09-21, globe-projection compat fix): native
@@ -1951,6 +1951,10 @@
1951
1951
  // per-map handle — most real pages only ever build one map anyway. Set
1952
1952
  // once per successful build(), just before it returns engineApi below.
1953
1953
  let _lastMapApi = null;
1954
+ // flat's map instance registry (htmlgui_flat.js 2416): the built maps by
1955
+ // their Map() options name — ixmaps.map("name") is the handle of THAT
1956
+ // map, ixmaps.map() stays the last built one
1957
+ const _mapApis = Object.create(null);
1954
1958
  // resolves with the first built map's API: ixmaps.map() calls a page
1955
1959
  // makes while the map is still building wait for it
1956
1960
  let _resolveMapReady;
@@ -3063,10 +3067,12 @@
3063
3067
  function mount() {
3064
3068
  map.on('move', updatePinnedTooltipPosition);
3065
3069
  watchHoverTooltip();
3066
- if (el.parentElement) {
3067
- el.parentElement.style.position = el.parentElement.style.position || 'relative';
3068
- el.parentElement.appendChild(pinnedTooltipEl);
3069
- }
3070
+ // anchor inside the map container: map.project() gives container-
3071
+ // relative pixels, and styling the page's own body (relative) breaks
3072
+ // any page element absolutely positioned against it (AirBnB's
3073
+ // #onmap-buttons on a zero-height all-float body flew off-screen)
3074
+ el.style.position = el.style.position || 'relative';
3075
+ el.appendChild(pinnedTooltipEl);
3070
3076
  }
3071
3077
  return { getTooltip, onClick, mount };
3072
3078
  }
@@ -3080,7 +3086,7 @@
3080
3086
  // layoutLegends().
3081
3087
  // ---------------------------------------------------------------
3082
3088
  function createLegend(ctx) {
3083
- const { builder, map, el, overlay, runtimes, engineApi, built, refresh, scheduleRefresh, notifyRedraw } = ctx;
3089
+ const { builder, map, el, overlay, runtimes, engineApi, built, refresh, scheduleRefresh, notifyRedraw, quietRefresh } = ctx;
3084
3090
  let addLegendPanel = () => {};
3085
3091
  let setLegendOption = () => {};
3086
3092
  let updateSubTheme = () => {};
@@ -3228,15 +3234,28 @@
3228
3234
  legendStack = document.createElement('div');
3229
3235
  legendStack.className = 'ix-legend-stack';
3230
3236
  legendStack.style.cssText = 'position:absolute;' + legendAlignCss + 'z-index:6;width:280px;'
3231
- + 'display:flex;flex-direction:column;max-height:calc(100% - 24px);overflow-y:auto;'
3237
+ + 'display:flex;flex-direction:column;max-height:66.6%;overflow-y:auto;'
3232
3238
  + 'border-radius:6px;box-shadow:' + shadow + ';pointer-events:auto;';
3233
3239
  if (!document.getElementById('ix-legend-stack-css')) {
3234
3240
  const css = document.createElement('style');
3235
3241
  css.id = 'ix-legend-stack-css';
3236
- css.textContent = '.ix-legend-stack>.ix-native-legend:not([data-ixoff])~.ix-native-legend:not([data-ixoff]){border-top:1px solid rgba(128,128,128,.35)}';
3242
+ // the slider rules are flat's own legend.css .slider block
3243
+ // (355-411) — its two duplicate blocks resolved to what the
3244
+ // cascade actually shows: a 5px rounded grey track at 0.7
3245
+ // opacity (1 on hover) and a green thumb
3246
+ css.textContent = '.ix-legend-stack>.ix-native-legend:not([data-ixoff])~.ix-native-legend:not([data-ixoff]){border-top:1px solid rgba(128,128,128,.35)}'
3247
+ + '.ix-legend-stack input[type=range]{-webkit-appearance:none;appearance:none;height:5px;border-radius:10px;background:rgba(155,155,155,0.3);border:solid #888 0px;outline:none;opacity:0.7;transition:opacity .2s;}'
3248
+ + '.ix-legend-stack input[type=range]:hover{opacity:1;}'
3249
+ + '.ix-legend-stack input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:14px;height:14px;border-radius:0.5em;background:#4CAF50;cursor:pointer;}'
3250
+ + '.ix-legend-stack input[type=range]::-moz-range-thumb{width:25px;height:25px;border-radius:50%;background:#4CAF50;cursor:pointer;}';
3237
3251
  document.head.appendChild(css);
3238
3252
  }
3239
- el.parentElement.appendChild(legendStack);
3253
+ // flat anchors its legend inside the map div (#map-legend), so the
3254
+ // panel's max-height resolves against the MAP's height — the stack's
3255
+ // former parent anchor collapsed it to 0 on pages whose body has
3256
+ // only floated children (height 0)
3257
+ el.style.position = el.style.position || 'relative';
3258
+ el.appendChild(legendStack);
3240
3259
  return legendStack;
3241
3260
  };
3242
3261
  // map.setLegend(value): the `legend` map option at runtime, same values as
@@ -3281,7 +3300,7 @@
3281
3300
  rt._triggerRedraw = () => { refresh(); };
3282
3301
  if (subThemeCapable(rt)) rt._onMarksChanged = () => updateSubTheme(rt);
3283
3302
  if (!legendOn || !el.parentElement || !legendApplies(rt)) return;
3284
- el.parentElement.style.position = el.parentElement.style.position || 'relative';
3303
+ el.style.position = el.style.position || 'relative';
3285
3304
  {
3286
3305
  // .type("...|NOLEGEND") — the fourth real legend-related type()
3287
3306
  // token: opts a theme OUT of the legend entirely (real engine's
@@ -3328,23 +3347,22 @@
3328
3347
  // would hand the dark look a light bg here: its dark branch never
3329
3348
  // ran for this map, its light bg would clash with dark rows/text)
3330
3349
  if (!rt.style.legendtheme) legendColors.bg = looksDark ? '#111' : flatLook.bg;
3331
- // max-height:66% resolves against el.parentElement's own
3332
- // height (the map container, which always has a definite
3333
- // height for the map itself to render into) since this panel
3334
- // is absolutely positioned inside it — a plain percentage on
3335
- // an absolutely-positioned element's height IS legal CSS as
3336
- // long as its containing block has a definite height, which
3337
- // this one does. display:flex column + min-height:0 on the
3338
- // ROWS wrapper below (not this outer panel) is what makes
3339
- // only the row list scroll while the header/description/
3340
- // slider stay fixed in place — a flex child won't actually
3341
- // shrink to fit and scroll internally without min-height:0,
3342
- // it just overflows its flex parent instead.
3350
+ // max-height:66.6% resolves against el's own height (the map
3351
+ // container, which always has a definite height for the map
3352
+ // itself to render into) since this panel sits in the stack,
3353
+ // absolutely positioned inside el. flex:0 1 auto + min-height:0
3354
+ // lets the panel SHRINK to the stack's 2/3 cap so the ROWS
3355
+ // wrapper (its own flex:1 1 auto + min-height:0 below) scrolls
3356
+ // internally while the header/description/slider stay fixed —
3357
+ // with flex:0 0 auto the panel grew past the cap and the whole
3358
+ // stack scrolled instead. text-align:left: the page body may
3359
+ // centre everything (the AirBnB port does), the legend is left
3360
+ // aligned chrome.
3343
3361
  // one box for every theme, as flat's #map-legend (legend.js
3344
3362
  // 2200-2460): the panels stack in the legend stack in theme
3345
3363
  // order, a line between them (see layoutLegends)
3346
- panel.style.cssText = 'position:relative;flex:0 0 auto;'
3347
- + 'display:flex;flex-direction:column;'
3364
+ panel.style.cssText = 'position:relative;flex:0 1 auto;min-height:0;overflow:hidden;'
3365
+ + 'display:flex;flex-direction:column;text-align:left;'
3348
3366
  + 'background:' + legendColors.bg + ';color:' + legendColors.fg + ';font:12px/1.4 -apple-system,Arial,sans-serif;'
3349
3367
  + 'padding:10px 12px 12px;pointer-events:auto;';
3350
3368
  const stack = legendStackEl(legendColors.shadow);
@@ -3783,12 +3801,12 @@
3783
3801
  slider.min = isOpacitySlider ? '0' : '25';
3784
3802
  slider.max = isOpacitySlider ? '100' : '200';
3785
3803
  slider.value = String(initialPct);
3786
- slider.style.cssText = 'width:100%;margin-top:2px;';
3804
+ slider.style.cssText = 'width:50%;margin-top:0.4em;'; // flat's own inline slider style (legend.js 2392)
3787
3805
  slider.addEventListener('input', () => {
3788
3806
  const pct = parseInt(slider.value, 10);
3789
3807
  sliderRow.querySelector('.ix-legend-scale-val').textContent = pct;
3790
3808
  rt.setStyle(isOpacitySlider ? { fillopacity: pct / 100 } : { scale: pct / 100 });
3791
- refresh();
3809
+ quietRefresh();
3792
3810
  });
3793
3811
  bodyEl.appendChild(slider);
3794
3812
  }
@@ -4179,12 +4197,14 @@
4179
4197
  attributionBox.set(this._attributionText != null ? this._attributionText : this.mapOptions.attribution);
4180
4198
  this._setAttribution = text => attributionBox.set(text);
4181
4199
 
4182
- if (this._legendHtml && el.parentElement) {
4200
+ if (this._legendHtml) {
4183
4201
  const legendEl = document.createElement('div');
4184
4202
  legendEl.style.cssText = 'position:absolute;top:0;left:0;z-index:5;pointer-events:none';
4185
4203
  legendEl.innerHTML = this._legendHtml;
4186
- el.parentElement.style.position = el.parentElement.style.position || 'relative';
4187
- el.parentElement.appendChild(legendEl);
4204
+ // inside the map container, never the page's body (see the pinned
4205
+ // tooltip mount) — styling body breaks page-positioned elements
4206
+ el.style.position = el.style.position || 'relative';
4207
+ el.appendChild(legendEl);
4188
4208
  }
4189
4209
 
4190
4210
  // themes are addressed by either the layer()'s own name (e.g. "AREU")
@@ -5228,9 +5248,18 @@
5228
5248
  // the native legend: createLegend (its four hooks are what the rest
5229
5249
  // of the map calls — panels, the legend option, sub-themes, layout)
5230
5250
  ({ addLegendPanel, setLegendOption, updateSubTheme, layoutLegends } =
5231
- createLegend({ builder, map, el, overlay, runtimes, engineApi, built, refresh, scheduleRefresh, notifyRedraw }));
5251
+ createLegend({ builder, map, el, overlay, runtimes, engineApi, built, refresh, scheduleRefresh, notifyRedraw,
5252
+ // flat's legend slider (legend.js 2839-2854) patches the style and
5253
+ // calls redrawTheme — a per-theme redraw that does NOT fire
5254
+ // htmlgui_onDrawTheme, so a page's own onDrawTheme hook (this
5255
+ // port's hookStatistics re-applying its own slider's scale)
5256
+ // only reasserts on the next full redraw (pan/zoom). refresh()
5257
+ // here would notify synchronously and clobber the new scale in
5258
+ // the same tick — this quiet variant is that flat behavior.
5259
+ quietRefresh: () => { refreshLayers(); } }));
5232
5260
 
5233
5261
  _lastMapApi = engineApi;
5262
+ if (this.mapOptions && this.mapOptions.name) _mapApis[this.mapOptions.name] = engineApi;
5234
5263
  // ?ixgl-debug: ixmaps.__glDebug.check() reports, for the moment it is
5235
5264
  // called, every theme's geometry problems (invalid or mixed-dimension
5236
5265
  // coordinates, a shape far larger than the theme's others) and what
@@ -5296,6 +5325,27 @@
5296
5325
  }
5297
5326
  }
5298
5327
 
5328
+ // GL-PORT COMPAT: flat's ixmaps.Map(div, opts, cb) hands the callback a
5329
+ // mapApi HANDLE (htmlgui_flat.js 904-935) — a real page keeps it and
5330
+ // calls its methods on it (__map.setView(...), __map.replace(...) —
5331
+ // AirBnB's city selector). This engine hands the callback the BUILDER
5332
+ // for its own .options().view().layer() chain; the builder here also
5333
+ // carries flat's handle methods, delegated to the map handle of THIS
5334
+ // map's options name (calls before the map exists wait for it, exactly
5335
+ // as ixmaps.map() does). The builder's own methods with different
5336
+ // semantics — layer, view, options, require, attribution, on — keep
5337
+ // theirs and are not overridden.
5338
+ for (const m of ['replace', 'add', 'remove', 'removeTheme', 'replaceTheme', 'changeThemeStyle', 'setThemeStyle',
5339
+ 'refreshTheme', 'redrawTheme', 'setBasemapOpacity', 'setMapType', 'setMapTypeId', 'mapType', 'resize',
5340
+ 'loadProject', 'project', 'setThemeVisible', 'setThemeTimeFrame', 'show', 'hide', 'getZoom', 'getThemeObj',
5341
+ 'getThemes', 'theme', 'setView']) {
5342
+ if (!MapBuilder.prototype[m]) {
5343
+ MapBuilder.prototype[m] = function (...args) {
5344
+ return mapHandle(this.mapOptions && this.mapOptions.name)[m](...args);
5345
+ };
5346
+ }
5347
+ }
5348
+
5299
5349
  // named createMap (not Map) so it doesn't shadow the built-in ES6 Map
5300
5350
  // class used throughout this file — a real bug caught during testing
5301
5351
  // (every `new Map()` below silently resolved to *this* function instead)
@@ -11423,22 +11473,73 @@
11423
11473
  try { hook.call(global.ixmaps, themeIdOf(rt)); } catch (e) { console.error('[ixmaps-gl] htmlgui_onNewTheme:', e); }
11424
11474
  }
11425
11475
 
11426
- // flat's ixmaps.map() — the running map's handle (htmlgui.js 173ff,
11427
- // htmlgui_flat.js). Its methods act on the last built map; called while
11428
- // the map is still building, they run once it is ready.
11476
+ // flat's ixmaps.themeApi (htmlgui_flat.js 1112-1196): the theme handle a
11477
+ // page gets from map().theme(name) — changeStyle is flat's canonical
11478
+ // global changeThemeStyle(szThemeName, szStyle, szFlag) (htmlgui.js 2050)
11479
+ // in handle form; show / hide / toggle are setThemeVisible, remove the map
11480
+ // handle's. flat's own markClass delegates 3-arg — a stale call against
11481
+ // htmlgui.js's 2-arg markThemeClass (2196) — the canonical form is used
11482
+ // here. Theme ids are global (the registry), so the map binding only
11483
+ // matters for replace.
11484
+ function themeApi(szMap, szTheme) {
11485
+ this.szMap = szMap || null;
11486
+ this.szTheme = szTheme || null;
11487
+ }
11488
+ themeApi.prototype = {
11489
+ changeStyle(szStyle, szFlag) { compatChangeThemeStyle(this.szTheme, szStyle, szFlag); return this; },
11490
+ markClass(nClass) { markThemeClass(this.szTheme, nClass); return this; },
11491
+ unmarkClass(nClass) { unmarkThemeClass(this.szTheme, nClass); return this; },
11492
+ show() { mapHandle(this.szMap).setThemeVisible(this.szTheme, true); return this; },
11493
+ hide() { mapHandle(this.szMap).setThemeVisible(this.szTheme, false); return this; },
11494
+ toggle() {
11495
+ const rt = _globalThemeRegistry.get(this.szTheme);
11496
+ mapHandle(this.szMap).setThemeVisible(this.szTheme, rt ? !!rt._hidden : false);
11497
+ return this;
11498
+ },
11499
+ remove() { mapHandle(this.szMap).remove(this.szTheme); return this; },
11500
+ replace(theme, flag) { mapHandle(this.szMap).replaceTheme(this.szTheme, theme, flag); return this; }
11501
+ };
11502
+
11503
+ // flat's ixmaps.map() / ixmaps.api(szMap) — the running map's handle
11504
+ // (htmlgui.js 173ff, htmlgui_flat.js mapApi 1283). Its methods act on the
11505
+ // map named by szMap (its Map() options name) or, without a name, the
11506
+ // last built map; called while the map is still building, they run once
11507
+ // it is ready.
11429
11508
  const MAP_HANDLE_METHODS = ['replace', 'add', 'remove', 'removeTheme', 'replaceTheme', 'changeThemeStyle', 'setThemeStyle',
11430
11509
  'refreshTheme', 'setBasemapOpacity', 'setMapType', 'setMapTypeId', 'mapType', 'resize', 'view', 'options', 'layer', 'loadProject', 'require', 'setThemeVisible', 'setThemeTimeFrame', 'attribution'];
11431
- const _mapHandle = {};
11432
- for (const m of MAP_HANDLE_METHODS) {
11433
- _mapHandle[m] = (...args) => {
11434
- if (_lastMapApi) { const r = _lastMapApi[m](...args); return r === _lastMapApi ? _mapHandle : r; }
11435
- _mapReady.then(api => api[m](...args));
11436
- return _mapHandle;
11437
- };
11510
+ const _mapHandles = Object.create(null);
11511
+ function makeMapHandle(szMap) {
11512
+ const h = {};
11513
+ const api = () => (szMap && _mapApis[szMap]) || _lastMapApi;
11514
+ for (const m of MAP_HANDLE_METHODS) {
11515
+ h[m] = (...args) => {
11516
+ const a = api();
11517
+ if (a) { const r = a[m](...args); return r === a ? h : r; }
11518
+ _mapReady.then(ready => ready[m](...args));
11519
+ return h;
11520
+ };
11521
+ }
11522
+ h.getZoom = () => { const a = api(); return a ? a.getZoom() : undefined; };
11523
+ h.getThemeObj = id => getThemeObj(id);
11524
+ // flat's mapApi.theme(szTheme) (htmlgui_flat.js 1571): the theme handle
11525
+ h.theme = szTheme => new themeApi(szMap, szTheme);
11526
+ // flat's mapApi aliases (htmlgui_flat.js 1286+): show/hide a theme,
11527
+ // redrawTheme (refreshTheme here), project (loadProject), getThemes(),
11528
+ // setView (view, both flat's object form and (array, zoom))
11529
+ h.show = id => h.setThemeVisible(id, true);
11530
+ h.hide = id => h.setThemeVisible(id, false);
11531
+ h.redrawTheme = id => h.refreshTheme(id);
11532
+ h.project = (...a) => h.loadProject(...a);
11533
+ h.setView = (...a) => h.view(...a);
11534
+ h.getThemes = () => [...new Set(_globalThemeRegistry.values())].map(rt => getThemeObj(themeIdOf(rt))).filter(Boolean);
11535
+ return h;
11536
+ }
11537
+ const _mapHandle = makeMapHandle(null);
11538
+ function mapHandle(szMap) {
11539
+ if (!szMap) return _mapHandle;
11540
+ if (!_mapHandles[szMap]) _mapHandles[szMap] = makeMapHandle(szMap);
11541
+ return _mapHandles[szMap];
11438
11542
  }
11439
- _mapHandle.getZoom = () => (_lastMapApi ? _lastMapApi.getZoom() : undefined);
11440
- _mapHandle.getThemeObj = id => getThemeObj(id);
11441
- function mapHandle() { return _mapHandle; }
11442
11543
 
11443
11544
  // flat's ixmaps.formatValue(value, precision, flag) (ui/js/tools/format.js),
11444
11545
  // which user chart scripts call: thousands separated by "." (BLANK: a
@@ -12013,10 +12114,44 @@
12013
12114
  return _lastMapApi.loadProject(src, flags);
12014
12115
  }
12015
12116
 
12117
+ // flat's global compat forms come in two arities: the canonical
12118
+ // theme-first signatures — changeThemeStyle(szThemeName, szStyle, szFlag)
12119
+ // (htmlgui.js 2050, with its duplicate-leading shift, 2052),
12120
+ // removeTheme(szThemeId) (1884), setBasemapOpacity(nOpacity, szMode)
12121
+ // (1409) — and the older map-first pages calling
12122
+ // (null|szMap, szId, ...) — PNRR passes an explicit null. Arity tells
12123
+ // them apart; theme ids are global (the registry), so the leading map
12124
+ // argument only matters for setBasemapOpacity, where a registered map
12125
+ // name targets that map and null or an unknown name the last built one.
12126
+ function themeStyleArgs(a) {
12127
+ if (a.length >= 4) a = a.slice(1);
12128
+ else if (a[0] === a[1]) a = a.slice(1);
12129
+ return a;
12130
+ }
12131
+ function compatChangeThemeStyle(...a) {
12132
+ const [szId, szStyle, szFlag] = themeStyleArgs(a);
12133
+ return _mapHandle.changeThemeStyle(szId, szStyle, szFlag);
12134
+ }
12135
+ function compatRemoveTheme(...a) {
12136
+ return _mapHandle.remove(a.length >= 2 ? a[1] : a[0]);
12137
+ }
12138
+ function compatSetBasemapOpacity(...a) {
12139
+ if (a.length >= 3) {
12140
+ const api = (a[0] && _mapApis[a[0]]) || _lastMapApi;
12141
+ if (api) api.setBasemapOpacity(a[1], a[2]);
12142
+ return;
12143
+ }
12144
+ return _mapHandle.setBasemapOpacity(a[0], a[1]);
12145
+ }
12146
+
12016
12147
  global.ixmaps = {
12017
12148
  layer, Layer: layer, Map: createMap, setExternalData: setExternalDataBridge, getThemeObj, data: ixmapsData,
12018
12149
  szResourceBase: ixmapsSzResourceBase, getProjectString, setProjectJSON, loadProject,
12019
12150
  markThemeClass, unmarkThemeClass, getBoundingBox, setTitle, setTitleBox, refreshTheme, formatValue: flatFormatValue,
12151
+ // flat's ixmaps.__formatValue (ui/js/tools/legend.js 451-553) — pages call
12152
+ // it for statistics/legend values; legend's own variant differs from
12153
+ // format.js's only in the SPACE flag, which flatFormatValue covers too
12154
+ __formatValue: flatFormatValue,
12020
12155
  map: mapHandle, getZoom, getThemeDefinitionObj, embeddedSVG,
12021
12156
  // flat's theme list: the theme objects of every theme
12022
12157
  getThemes: () => [...new Set(_globalThemeRegistry.values())].map(rt => getThemeObj(themeIdOf(rt))).filter(Boolean),
@@ -12033,11 +12168,11 @@
12033
12168
  setAttribution: (text) => { if (_lastMapApi && _lastMapApi.setAttribution) _lastMapApi.setAttribution(text); },
12034
12169
  htmlgui_setAttributionString: (text) => { if (_lastMapApi && _lastMapApi.setAttribution) _lastMapApi.setAttribution(text); },
12035
12170
  htmlgui_getAttributionString: () => (_lastMapApi && _lastMapApi.getAttribution ? _lastMapApi.getAttribution() : ''),
12036
- changeThemeStyle: (szMap, szId, szStyle, szFlag) => _mapHandle.changeThemeStyle(szId, szStyle, szFlag),
12037
- removeTheme: (szMap, szId) => _mapHandle.remove(szId),
12171
+ changeThemeStyle: compatChangeThemeStyle,
12172
+ removeTheme: compatRemoveTheme,
12038
12173
  // flat's time slider: show the records of a theme (null = all themes) whose timefield lies in [min, max)
12039
12174
  setThemeTimeFrame: (szId, nMin, nMax) => _mapHandle.setThemeTimeFrame(szId, nMin, nMax),
12040
- setBasemapOpacity: (szMap, nOpacity, szMode) => _mapHandle.setBasemapOpacity(nOpacity, szMode),
12175
+ setBasemapOpacity: compatSetBasemapOpacity,
12041
12176
  // this engine's version (flat's own ixmaps.version numbers flat)
12042
12177
  glVersion: IXMAPS_GL_VERSION,
12043
12178
  // flat always has this page hook (its layer legend tool defines it,
@@ -12062,7 +12197,7 @@
12062
12197
  // engine runs in a Node vm there); deliberately NOT on the ixmaps object
12063
12198
  global.__ixmapsGlInternals = {
12064
12199
  IXMAPS_GL_VERSION, youtubeClickToPlay, symbolsFlagCompat, tooltipTable, legendRowLabels, scaleDenom, cssColorAlpha, aggregatedCategoricalClass, dominantDopacityAlpha, isAggregatedCategoricalChoropleth, computeBubblePackLayout, isolatedBubblePackLayout, sequenceLayout, multiQuadOffsets, pixelOffsetLngLat,
12065
- normalizeTheme, projectThemeToDefinition, withoutProjectCode, groupRecordCount, resolveBasemapStyleUrl, resolveMapTypeColor, LayerBuilder, LayerRuntime, typeStyleNumbers, styleNum,
12200
+ normalizeTheme, projectThemeToDefinition, withoutProjectCode, groupRecordCount, resolveBasemapStyleUrl, resolveMapTypeColor, LayerBuilder, LayerRuntime, MapBuilder, typeStyleNumbers, styleNum,
12066
12201
  resolveScriptUrl, isTrustedScriptUrl, loadProcessingScript, loadBrokerData, applyBrokerThemePatch, makeBrokerTheme,
12067
12202
  equalIntervalBreaks, quantileBreaks, naturalBreaks, evenStrideSample, jenksBreakValues, partsFromBreakValues, resolvePartsClass,
12068
12203
  computeAlphaStats, computeMultiFieldClasses, computeDominantStats, resolveDominantClass, computeComposeColorStats,
@@ -12071,7 +12206,7 @@
12071
12206
  flatToMapLibreZoom, mapLibreToFlatZoom, scaleDenominatorAt, resolveZoomReference, resolveAggregationPx, valuesHiddenByScale,
12072
12207
  fetchLayerData, parseCsvText, dataTableRows, geometryRowsToFeatureCollection, filterFlatValues, applyField100, field100Binding, rangeClassLegendTotals, resolveAggregateValue, classValueSeparate, cellAggregatedValues, oneHot, groupCoLocated, aggregateOnGrid, GridAggregateIndex, flatRangeParts, aggregateField100, valueRadius, itemPlotGeometry, itemAnchor, objectZoomFactor, resolveZoomReference, defaultNormalSizeValue,
12073
12208
  applyWhereFilter, joinChartPositions, flatLookupKey, flatShapeCenter, chartHiddenByScale, glowHiddenByScale, isSymbolChart, flatChartAlignOffset, flatChartBranch, flatValueText, categoryValueRecord, flatDerivateRgb, flatChartTextRgb, flatGroupedValue, flatNoBreaks, featuresHiddenByScale, boxHiddenByScale, flatShadowOn, snapToAggregationGrid,
12074
- flatFormatValue,
12209
+ flatFormatValue, themeStyleArgs,
12075
12210
  dataCacheKey, dataCacheDisabled, cachedLayerData, featuresBounds, wantsZoomToExtent, legendIsOn,
12076
12211
  };
12077
12212
  global.__setFilter = __setFilter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ixmaps-gl",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "MapLibre GL + deck.gl reimplementation of the ixmaps-flat declarative mapping engine",
5
5
  "main": "ixmaps-gl.js",
6
6
  "browser": "ixmaps-gl.js",