@rcpch/imd-map 0.1.2 → 0.2.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/CHANGELOG.md CHANGED
@@ -8,6 +8,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.2.0] — 2026-04-26
12
+
13
+ ### Changed
14
+
15
+ - Switched local authority boundary overlay to zoom-tiered pg_tileserv tables (`public.la_tiles_z0_4`, `public.la_tiles_z5_7`, `public.la_tiles_z8_10`, `public.la_tiles_z11_14`) with tier-matched layer zoom windows.
16
+ - Switched health boundary overlays to zoom-tiered pg_tileserv tables for NHS England regions (`public.nhser_tiles_2021_*`), ICBs (`public.icb_tiles_2023_*`), and Welsh LHBs (`public.lhb_tiles_2022_*`).
17
+ - Corrected overlay `source-layer` usage to match pg_tileserv behavior (table name without `public.` schema prefix).
18
+ - Updated overlay visibility handling so hide/show applies across all zoom-tier boundary layers.
19
+
20
+ ### Added
21
+
22
+ - Unit tests covering tiered overlay source/layer creation, source-layer naming, and overlay hide behavior across tiers.
23
+
11
24
  ## [0.1.0] — 2026-04-20
12
25
 
13
26
  ### Added
package/dist/index.esm.js CHANGED
@@ -884,53 +884,69 @@ function normalizeLeadCentreInput(data) {
884
884
  }
885
885
  var LOCAL_AUTHORITY_SOURCE_ID = "rcpch-imd-la-overlay";
886
886
  var LOCAL_AUTHORITY_LAYER_ID = "rcpch-imd-la-overlay-line";
887
- var LOCAL_AUTHORITY_FULL_TABLE_NAME = "public.la_tiles";
888
- var LOCAL_AUTHORITY_SOURCE_LAYER = "public.la_tiles";
887
+ var LOCAL_AUTHORITY_TABLE_PREFIX = "la_tiles";
888
+ function localAuthoritySourceId(tier) {
889
+ return `${LOCAL_AUTHORITY_SOURCE_ID}-${tier}`;
890
+ }
891
+ function localAuthorityLayerId(tier) {
892
+ return `${LOCAL_AUTHORITY_LAYER_ID}-${tier}`;
893
+ }
889
894
  function addOrUpdateLocalAuthorityOverlay(map, tilesBaseUrl, style) {
890
- const tileUrl = buildTileUrl(tilesBaseUrl, LOCAL_AUTHORITY_FULL_TABLE_NAME);
891
- const existing = map.getSource(LOCAL_AUTHORITY_SOURCE_ID);
892
- if (existing instanceof VectorTileSource) {
893
- existing.setTiles([tileUrl]);
894
- } else {
895
- if (existing) map.removeSource(LOCAL_AUTHORITY_SOURCE_ID);
896
- map.addSource(LOCAL_AUTHORITY_SOURCE_ID, {
897
- type: "vector",
898
- tiles: [tileUrl],
899
- minzoom: 0,
900
- maxzoom: 14
895
+ for (const { tier, minzoom, maxzoom } of ZOOM_TIERS) {
896
+ const sourceId = localAuthoritySourceId(tier);
897
+ const layerId = localAuthorityLayerId(tier);
898
+ const fullTableName = `public.${LOCAL_AUTHORITY_TABLE_PREFIX}_${tier}`;
899
+ const sourceLayer = `${LOCAL_AUTHORITY_TABLE_PREFIX}_${tier}`;
900
+ const tileUrl = buildTileUrl(tilesBaseUrl, fullTableName);
901
+ const existing = map.getSource(sourceId);
902
+ if (existing instanceof VectorTileSource) {
903
+ existing.setTiles([tileUrl]);
904
+ } else {
905
+ if (existing) map.removeSource(sourceId);
906
+ map.addSource(sourceId, {
907
+ type: "vector",
908
+ tiles: [tileUrl],
909
+ minzoom: 0,
910
+ maxzoom: 14
911
+ });
912
+ }
913
+ if (map.getLayer(layerId)) {
914
+ map.setPaintProperty(
915
+ layerId,
916
+ "line-color",
917
+ style.boundaries.localAuthorityColor ?? "#0d0d58"
918
+ );
919
+ map.setPaintProperty(
920
+ layerId,
921
+ "line-width",
922
+ style.boundaries.localAuthorityWidth ?? 1
923
+ );
924
+ map.setLayoutProperty(layerId, "visibility", "visible");
925
+ continue;
926
+ }
927
+ map.addLayer({
928
+ id: layerId,
929
+ type: "line",
930
+ source: sourceId,
931
+ "source-layer": sourceLayer,
932
+ minzoom,
933
+ maxzoom,
934
+ paint: {
935
+ "line-color": style.boundaries.localAuthorityColor ?? "#0d0d58",
936
+ "line-width": style.boundaries.localAuthorityWidth ?? 1
937
+ },
938
+ layout: {
939
+ visibility: "visible"
940
+ }
901
941
  });
902
942
  }
903
- if (map.getLayer(LOCAL_AUTHORITY_LAYER_ID)) {
904
- map.setPaintProperty(
905
- LOCAL_AUTHORITY_LAYER_ID,
906
- "line-color",
907
- style.boundaries.localAuthorityColor ?? "#0d0d58"
908
- );
909
- map.setPaintProperty(
910
- LOCAL_AUTHORITY_LAYER_ID,
911
- "line-width",
912
- style.boundaries.localAuthorityWidth ?? 1
913
- );
914
- map.setLayoutProperty(LOCAL_AUTHORITY_LAYER_ID, "visibility", "visible");
915
- return;
916
- }
917
- map.addLayer({
918
- id: LOCAL_AUTHORITY_LAYER_ID,
919
- type: "line",
920
- source: LOCAL_AUTHORITY_SOURCE_ID,
921
- "source-layer": LOCAL_AUTHORITY_SOURCE_LAYER,
922
- paint: {
923
- "line-color": style.boundaries.localAuthorityColor ?? "#0d0d58",
924
- "line-width": style.boundaries.localAuthorityWidth ?? 1
925
- },
926
- layout: {
927
- visibility: "visible"
928
- }
929
- });
930
943
  }
931
944
  function hideLocalAuthorityOverlay(map) {
932
- if (map.getLayer(LOCAL_AUTHORITY_LAYER_ID)) {
933
- map.setLayoutProperty(LOCAL_AUTHORITY_LAYER_ID, "visibility", "none");
945
+ for (const { tier } of ZOOM_TIERS) {
946
+ const layerId = localAuthorityLayerId(tier);
947
+ if (map.getLayer(layerId)) {
948
+ map.setLayoutProperty(layerId, "visibility", "none");
949
+ }
934
950
  }
935
951
  }
936
952
  var NHSER_SOURCE_ID = "rcpch-imd-nhser-overlay";
@@ -939,52 +955,62 @@ var ICB_SOURCE_ID = "rcpch-imd-icb-overlay";
939
955
  var ICB_LAYER_ID = "rcpch-imd-icb-overlay-line";
940
956
  var LHB_SOURCE_ID = "rcpch-imd-lhb-overlay";
941
957
  var LHB_LAYER_ID = "rcpch-imd-lhb-overlay-line";
942
- var NHSER_FULL_TABLE_NAME = "public.nhser_tiles_2021";
943
- var NHSER_SOURCE_LAYER = "public.nhser_tiles_2021";
944
- var ICB_FULL_TABLE_NAME = "public.icb_tiles_2023";
945
- var ICB_SOURCE_LAYER = "public.icb_tiles_2023";
946
- var LHB_FULL_TABLE_NAME = "public.lhb_tiles_2022";
947
- var LHB_SOURCE_LAYER = "public.lhb_tiles_2022";
958
+ var NHSER_TABLE_PREFIX = "nhser_tiles_2021";
959
+ var ICB_TABLE_PREFIX = "icb_tiles_2023";
960
+ var LHB_TABLE_PREFIX = "lhb_tiles_2022";
961
+ function overlaySourceId(baseSourceId, tier) {
962
+ return `${baseSourceId}-${tier}`;
963
+ }
964
+ function overlayLayerId(baseLayerId, tier) {
965
+ return `${baseLayerId}-${tier}`;
966
+ }
948
967
  function addOrUpdateBoundaryOverlay(map, tilesBaseUrl, input) {
949
- const tileUrl = buildTileUrl(tilesBaseUrl, input.fullTableName);
950
- const existing = map.getSource(input.sourceId);
951
- if (existing instanceof VectorTileSource) {
952
- existing.setTiles([tileUrl]);
953
- } else {
954
- if (existing) map.removeSource(input.sourceId);
955
- map.addSource(input.sourceId, {
956
- type: "vector",
957
- tiles: [tileUrl],
958
- minzoom: 0,
959
- maxzoom: 14
968
+ for (const { tier, minzoom, maxzoom } of ZOOM_TIERS) {
969
+ const sourceId = overlaySourceId(input.sourceId, tier);
970
+ const layerId = overlayLayerId(input.layerId, tier);
971
+ const fullTableName = `public.${input.tablePrefix}_${tier}`;
972
+ const sourceLayer = `${input.tablePrefix}_${tier}`;
973
+ const tileUrl = buildTileUrl(tilesBaseUrl, fullTableName);
974
+ const existing = map.getSource(sourceId);
975
+ if (existing instanceof VectorTileSource) {
976
+ existing.setTiles([tileUrl]);
977
+ } else {
978
+ if (existing) map.removeSource(sourceId);
979
+ map.addSource(sourceId, {
980
+ type: "vector",
981
+ tiles: [tileUrl],
982
+ minzoom: 0,
983
+ maxzoom: 14
984
+ });
985
+ }
986
+ if (map.getLayer(layerId)) {
987
+ map.setPaintProperty(layerId, "line-color", input.lineColor);
988
+ map.setPaintProperty(layerId, "line-width", input.lineWidth);
989
+ map.setLayoutProperty(layerId, "visibility", "visible");
990
+ continue;
991
+ }
992
+ map.addLayer({
993
+ id: layerId,
994
+ type: "line",
995
+ source: sourceId,
996
+ "source-layer": sourceLayer,
997
+ minzoom,
998
+ maxzoom,
999
+ paint: {
1000
+ "line-color": input.lineColor,
1001
+ "line-width": input.lineWidth
1002
+ },
1003
+ layout: {
1004
+ visibility: "visible"
1005
+ }
960
1006
  });
961
1007
  }
962
- if (map.getLayer(input.layerId)) {
963
- map.setPaintProperty(input.layerId, "line-color", input.lineColor);
964
- map.setPaintProperty(input.layerId, "line-width", input.lineWidth);
965
- map.setLayoutProperty(input.layerId, "visibility", "visible");
966
- return;
967
- }
968
- map.addLayer({
969
- id: input.layerId,
970
- type: "line",
971
- source: input.sourceId,
972
- "source-layer": input.sourceLayer,
973
- paint: {
974
- "line-color": input.lineColor,
975
- "line-width": input.lineWidth
976
- },
977
- layout: {
978
- visibility: "visible"
979
- }
980
- });
981
1008
  }
982
1009
  function addOrUpdateNhserOverlay(map, tilesBaseUrl, style) {
983
1010
  addOrUpdateBoundaryOverlay(map, tilesBaseUrl, {
984
1011
  sourceId: NHSER_SOURCE_ID,
985
1012
  layerId: NHSER_LAYER_ID,
986
- fullTableName: NHSER_FULL_TABLE_NAME,
987
- sourceLayer: NHSER_SOURCE_LAYER,
1013
+ tablePrefix: NHSER_TABLE_PREFIX,
988
1014
  lineColor: style.boundaries.nhserColor ?? "#e00087",
989
1015
  lineWidth: style.boundaries.nhserWidth ?? 1.5
990
1016
  });
@@ -993,8 +1019,7 @@ function addOrUpdateIcbOverlay(map, tilesBaseUrl, style) {
993
1019
  addOrUpdateBoundaryOverlay(map, tilesBaseUrl, {
994
1020
  sourceId: ICB_SOURCE_ID,
995
1021
  layerId: ICB_LAYER_ID,
996
- fullTableName: ICB_FULL_TABLE_NAME,
997
- sourceLayer: ICB_SOURCE_LAYER,
1022
+ tablePrefix: ICB_TABLE_PREFIX,
998
1023
  lineColor: style.boundaries.icbColor ?? "#57c7f2",
999
1024
  lineWidth: style.boundaries.icbWidth ?? 1
1000
1025
  });
@@ -1003,15 +1028,17 @@ function addOrUpdateLhbOverlay(map, tilesBaseUrl, style) {
1003
1028
  addOrUpdateBoundaryOverlay(map, tilesBaseUrl, {
1004
1029
  sourceId: LHB_SOURCE_ID,
1005
1030
  layerId: LHB_LAYER_ID,
1006
- fullTableName: LHB_FULL_TABLE_NAME,
1007
- sourceLayer: LHB_SOURCE_LAYER,
1031
+ tablePrefix: LHB_TABLE_PREFIX,
1008
1032
  lineColor: style.boundaries.lhbColor ?? "#57c7f2",
1009
1033
  lineWidth: style.boundaries.lhbWidth ?? 1
1010
1034
  });
1011
1035
  }
1012
1036
  function hideOverlay(map, layerId) {
1013
- if (map.getLayer(layerId)) {
1014
- map.setLayoutProperty(layerId, "visibility", "none");
1037
+ for (const { tier } of ZOOM_TIERS) {
1038
+ const tierLayerId = overlayLayerId(layerId, tier);
1039
+ if (map.getLayer(tierLayerId)) {
1040
+ map.setLayoutProperty(tierLayerId, "visibility", "none");
1041
+ }
1015
1042
  }
1016
1043
  }
1017
1044
  function hideNhserOverlay(map) {