@communitiesuk/svelte-component-library 0.1.17

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 (217) hide show
  1. package/README.md +188 -0
  2. package/dist/assets/css/govuk-frontend.min.css +2 -0
  3. package/dist/assets/css/govuk-frontend.min.css.map +1 -0
  4. package/dist/assets/fonts/bold-affa96571d-v2.woff +0 -0
  5. package/dist/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
  6. package/dist/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
  7. package/dist/assets/fonts/light-f591b13f7d-v2.woff +0 -0
  8. package/dist/assets/govuk_publishing_components/images/icon-autocomplete-search-suggestion.svg +4 -0
  9. package/dist/assets/govuk_publishing_components/images/icon-close.svg +1 -0
  10. package/dist/assets/images/favicon.ico +0 -0
  11. package/dist/assets/images/favicon.svg +1 -0
  12. package/dist/assets/images/govuk-crest-2x.png +0 -0
  13. package/dist/assets/images/govuk-crest.png +0 -0
  14. package/dist/assets/images/govuk-crest.svg +1 -0
  15. package/dist/assets/images/govuk-icon-180.png +0 -0
  16. package/dist/assets/images/govuk-icon-192.png +0 -0
  17. package/dist/assets/images/govuk-icon-512.png +0 -0
  18. package/dist/assets/images/govuk-icon-mask.svg +1 -0
  19. package/dist/assets/images/govuk-opengraph-image.png +0 -0
  20. package/dist/assets/images/homepage-illustration.svg +1 -0
  21. package/dist/assets/images/homepage.svg +44 -0
  22. package/dist/assets/images/masthead-illustration.svg +123 -0
  23. package/dist/assets/images/oflog_crest_black.png +0 -0
  24. package/dist/assets/images/oflog_crest_white.png +0 -0
  25. package/dist/assets/images/undraw_approved-wireframe_odf4.svg +1 -0
  26. package/dist/assets/images/undraw_collaborators_rgw4.svg +1 -0
  27. package/dist/assets/images/undraw_content-creator_vuqg.svg +1 -0
  28. package/dist/assets/images/undraw_online-media_opxh.svg +1 -0
  29. package/dist/assets/images/undraw_pull-request_zlsu.svg +1 -0
  30. package/dist/assets/images/undraw_reviewed-docs_g0cg.svg +1 -0
  31. package/dist/components/FilterPanel/codeBlocks.d.ts +3 -0
  32. package/dist/components/FilterPanel/codeBlocks.js +418 -0
  33. package/dist/components/content/InsetText.svelte +21 -0
  34. package/dist/components/content/InsetText.svelte.d.ts +7 -0
  35. package/dist/components/content/WarningText.svelte +27 -0
  36. package/dist/components/content/WarningText.svelte.d.ts +8 -0
  37. package/dist/components/data-vis/axis/Axis.svelte +51 -0
  38. package/dist/components/data-vis/axis/Axis.svelte.d.ts +33 -0
  39. package/dist/components/data-vis/axis/Ticks.svelte +113 -0
  40. package/dist/components/data-vis/axis/Ticks.svelte.d.ts +33 -0
  41. package/dist/components/data-vis/line-chart/Line.svelte +150 -0
  42. package/dist/components/data-vis/line-chart/Line.svelte.d.ts +85 -0
  43. package/dist/components/data-vis/line-chart/LineChart.svelte +249 -0
  44. package/dist/components/data-vis/line-chart/LineChart.svelte.d.ts +73 -0
  45. package/dist/components/data-vis/line-chart/Lines.svelte +138 -0
  46. package/dist/components/data-vis/line-chart/Lines.svelte.d.ts +57 -0
  47. package/dist/components/data-vis/line-chart/Marker.svelte +61 -0
  48. package/dist/components/data-vis/line-chart/Marker.svelte.d.ts +37 -0
  49. package/dist/components/data-vis/line-chart/SeriesLabel.svelte +67 -0
  50. package/dist/components/data-vis/line-chart/SeriesLabel.svelte.d.ts +43 -0
  51. package/dist/components/data-vis/line-chart/ValueLabel.svelte +50 -0
  52. package/dist/components/data-vis/line-chart/ValueLabel.svelte.d.ts +25 -0
  53. package/dist/components/data-vis/map/Map.svelte +392 -0
  54. package/dist/components/data-vis/map/Map.svelte.d.ts +47 -0
  55. package/dist/components/data-vis/map/MapLegend.svelte +41 -0
  56. package/dist/components/data-vis/map/MapLegend.svelte.d.ts +15 -0
  57. package/dist/components/data-vis/map/NonStandardControls.svelte +42 -0
  58. package/dist/components/data-vis/map/NonStandardControls.svelte.d.ts +13 -0
  59. package/dist/components/data-vis/map/Tooltip.svelte +41 -0
  60. package/dist/components/data-vis/map/Tooltip.svelte.d.ts +19 -0
  61. package/dist/components/data-vis/map/colorbrewer.d.ts +337 -0
  62. package/dist/components/data-vis/map/colorbrewer.js +1523 -0
  63. package/dist/components/data-vis/map/colors.d.ts +13 -0
  64. package/dist/components/data-vis/map/colors.js +65 -0
  65. package/dist/components/data-vis/map/dataJoin.d.ts +2 -0
  66. package/dist/components/data-vis/map/dataJoin.js +27 -0
  67. package/dist/components/data-vis/map/fullTopo.json +1 -0
  68. package/dist/components/data-vis/map/jenks.d.ts +1 -0
  69. package/dist/components/data-vis/map/jenks.js +51 -0
  70. package/dist/components/data-vis/map/lad2023.json +1 -0
  71. package/dist/components/data-vis/map/mapUtils.d.ts +5 -0
  72. package/dist/components/data-vis/map/mapUtils.js +86 -0
  73. package/dist/components/data-vis/map/topo.json +1 -0
  74. package/dist/components/data-vis/table/Table.svelte +247 -0
  75. package/dist/components/data-vis/table/Table.svelte.d.ts +19 -0
  76. package/dist/components/layout/Breadcrumbs.svelte +191 -0
  77. package/dist/components/layout/Breadcrumbs.svelte.d.ts +24 -0
  78. package/dist/components/layout/Footer.svelte +171 -0
  79. package/dist/components/layout/Footer.svelte.d.ts +30 -0
  80. package/dist/components/layout/Header.svelte +43 -0
  81. package/dist/components/layout/Header.svelte.d.ts +7 -0
  82. package/dist/components/layout/InternalHeader.svelte +628 -0
  83. package/dist/components/layout/InternalHeader.svelte.d.ts +15 -0
  84. package/dist/components/layout/PhaseBanner.svelte +28 -0
  85. package/dist/components/layout/PhaseBanner.svelte.d.ts +9 -0
  86. package/dist/components/layout/ServiceNavigation.svelte +143 -0
  87. package/dist/components/layout/ServiceNavigation.svelte.d.ts +13 -0
  88. package/dist/components/layout/SideNavigation.svelte +345 -0
  89. package/dist/components/layout/SideNavigation.svelte.d.ts +25 -0
  90. package/dist/components/layout/service-navigation-nested-mobile/HeaderNav.svelte +91 -0
  91. package/dist/components/layout/service-navigation-nested-mobile/HeaderNav.svelte.d.ts +15 -0
  92. package/dist/components/layout/service-navigation-nested-mobile/MobileNav.svelte +233 -0
  93. package/dist/components/layout/service-navigation-nested-mobile/MobileNav.svelte.d.ts +27 -0
  94. package/dist/components/layout/service-navigation-nested-mobile/ServiceNavigationNestedMobile.svelte +70 -0
  95. package/dist/components/layout/service-navigation-nested-mobile/ServiceNavigationNestedMobile.svelte.d.ts +11 -0
  96. package/dist/components/layout/service-navigation-nested-mobile/SideNav.svelte +276 -0
  97. package/dist/components/layout/service-navigation-nested-mobile/SideNav.svelte.d.ts +22 -0
  98. package/dist/components/ui/Accordion.svelte +244 -0
  99. package/dist/components/ui/Accordion.svelte.d.ts +23 -0
  100. package/dist/components/ui/Breadcrumbs.svelte +198 -0
  101. package/dist/components/ui/Breadcrumbs.svelte.d.ts +24 -0
  102. package/dist/components/ui/Button.svelte +96 -0
  103. package/dist/components/ui/Button.svelte.d.ts +17 -0
  104. package/dist/components/ui/CheckBox.svelte +198 -0
  105. package/dist/components/ui/CheckBox.svelte.d.ts +27 -0
  106. package/dist/components/ui/ContentsList.svelte +1117 -0
  107. package/dist/components/ui/ContentsList.svelte.d.ts +25 -0
  108. package/dist/components/ui/DateInput.svelte +255 -0
  109. package/dist/components/ui/DateInput.svelte.d.ts +59 -0
  110. package/dist/components/ui/Details.svelte +12 -0
  111. package/dist/components/ui/Details.svelte.d.ts +13 -0
  112. package/dist/components/ui/FilterPanel.svelte +588 -0
  113. package/dist/components/ui/FilterPanel.svelte.d.ts +74 -0
  114. package/dist/components/ui/Footer.svelte +171 -0
  115. package/dist/components/ui/Footer.svelte.d.ts +30 -0
  116. package/dist/components/ui/Header.svelte +43 -0
  117. package/dist/components/ui/Header.svelte.d.ts +7 -0
  118. package/dist/components/ui/Masthead.svelte +267 -0
  119. package/dist/components/ui/Masthead.svelte.d.ts +12 -0
  120. package/dist/components/ui/NavigationExample.svelte +117 -0
  121. package/dist/components/ui/NavigationExample.svelte.d.ts +3 -0
  122. package/dist/components/ui/NotificationBanner.svelte +93 -0
  123. package/dist/components/ui/NotificationBanner.svelte.d.ts +15 -0
  124. package/dist/components/ui/Radios.svelte +176 -0
  125. package/dist/components/ui/Radios.svelte.d.ts +28 -0
  126. package/dist/components/ui/RelatedContent.svelte +596 -0
  127. package/dist/components/ui/RelatedContent.svelte.d.ts +29 -0
  128. package/dist/components/ui/Search.svelte +499 -0
  129. package/dist/components/ui/Search.svelte.d.ts +32 -0
  130. package/dist/components/ui/SearchAutocomplete.svelte +655 -0
  131. package/dist/components/ui/SearchAutocomplete.svelte.d.ts +37 -0
  132. package/dist/components/ui/Select.svelte +116 -0
  133. package/dist/components/ui/Select.svelte.d.ts +22 -0
  134. package/dist/components/ui/ServiceNavigation.svelte +143 -0
  135. package/dist/components/ui/ServiceNavigation.svelte.d.ts +13 -0
  136. package/dist/components/ui/SideNavigation.svelte +346 -0
  137. package/dist/components/ui/SideNavigation.svelte.d.ts +25 -0
  138. package/dist/components/ui/Tabs.svelte +306 -0
  139. package/dist/components/ui/Tabs.svelte.d.ts +18 -0
  140. package/dist/components/ui/WhatsNew.svelte +155 -0
  141. package/dist/components/ui/WhatsNew.svelte.d.ts +29 -0
  142. package/dist/config.d.ts +51 -0
  143. package/dist/config.js +44 -0
  144. package/dist/icons/DoubleChevronButton.svelte +62 -0
  145. package/dist/icons/DoubleChevronButton.svelte.d.ts +13 -0
  146. package/dist/icons/IconSearch.svelte +42 -0
  147. package/dist/icons/IconSearch.svelte.d.ts +6 -0
  148. package/dist/icons/SingleChevronButtonWithLabel.svelte +132 -0
  149. package/dist/icons/SingleChevronButtonWithLabel.svelte.d.ts +19 -0
  150. package/dist/index.d.ts +44 -0
  151. package/dist/index.js +45 -0
  152. package/dist/main.css +1 -0
  153. package/dist/package-wrapping/BaseInformation.svelte +82 -0
  154. package/dist/package-wrapping/BaseInformation.svelte.d.ts +15 -0
  155. package/dist/package-wrapping/BaseNameAndStatus.svelte +108 -0
  156. package/dist/package-wrapping/BaseNameAndStatus.svelte.d.ts +10 -0
  157. package/dist/package-wrapping/CodeBlock.svelte +62 -0
  158. package/dist/package-wrapping/CodeBlock.svelte.d.ts +12 -0
  159. package/dist/package-wrapping/ComponentDemo.svelte +114 -0
  160. package/dist/package-wrapping/ComponentDemo.svelte.d.ts +25 -0
  161. package/dist/package-wrapping/ComponentDemoTEMP.svelte +305 -0
  162. package/dist/package-wrapping/ComponentDemoTEMP.svelte.d.ts +21 -0
  163. package/dist/package-wrapping/ComponentDetails.svelte +123 -0
  164. package/dist/package-wrapping/ComponentDetails.svelte.d.ts +13 -0
  165. package/dist/package-wrapping/DividerLine.svelte +21 -0
  166. package/dist/package-wrapping/DividerLine.svelte.d.ts +17 -0
  167. package/dist/package-wrapping/InputForParameter.svelte +205 -0
  168. package/dist/package-wrapping/InputForParameter.svelte.d.ts +13 -0
  169. package/dist/package-wrapping/InputForParameterUpdated.svelte +222 -0
  170. package/dist/package-wrapping/InputForParameterUpdated.svelte.d.ts +17 -0
  171. package/dist/package-wrapping/InputForParameterUpdatedTEMP.svelte +203 -0
  172. package/dist/package-wrapping/InputForParameterUpdatedTEMP.svelte.d.ts +17 -0
  173. package/dist/package-wrapping/ListOfComponentStatuses.svelte +19 -0
  174. package/dist/package-wrapping/ListOfComponentStatuses.svelte.d.ts +11 -0
  175. package/dist/package-wrapping/OverlayAndComponentContainer.svelte +426 -0
  176. package/dist/package-wrapping/OverlayAndComponentContainer.svelte.d.ts +33 -0
  177. package/dist/package-wrapping/ParametersSection.svelte +235 -0
  178. package/dist/package-wrapping/ParametersSection.svelte.d.ts +19 -0
  179. package/dist/package-wrapping/ParsingErrorToastsContainer.svelte +50 -0
  180. package/dist/package-wrapping/ParsingErrorToastsContainer.svelte.d.ts +15 -0
  181. package/dist/package-wrapping/Pill.svelte +54 -0
  182. package/dist/package-wrapping/Pill.svelte.d.ts +25 -0
  183. package/dist/package-wrapping/PlaygroundDetails.svelte +106 -0
  184. package/dist/package-wrapping/PlaygroundDetails.svelte.d.ts +13 -0
  185. package/dist/package-wrapping/ScreenSizeRadio.svelte +24 -0
  186. package/dist/package-wrapping/ScreenSizeRadio.svelte.d.ts +11 -0
  187. package/dist/package-wrapping/ScreenSizeRadioUpdated.svelte +23 -0
  188. package/dist/package-wrapping/ScreenSizeRadioUpdated.svelte.d.ts +11 -0
  189. package/dist/package-wrapping/SidebarContainer.svelte +103 -0
  190. package/dist/package-wrapping/SidebarContainer.svelte.d.ts +23 -0
  191. package/dist/package-wrapping/WrapperDetailsUpdate.svelte +40 -0
  192. package/dist/package-wrapping/WrapperDetailsUpdate.svelte.d.ts +15 -0
  193. package/dist/package-wrapping/templates/Template.svelte +100 -0
  194. package/dist/package-wrapping/templates/Template.svelte.d.ts +25 -0
  195. package/dist/templates/ComponentPageTemplate.svelte +1 -0
  196. package/dist/templates/ComponentPageTemplate.svelte.d.ts +26 -0
  197. package/dist/utils/data-transformations/convertCSV.d.ts +2 -0
  198. package/dist/utils/data-transformations/convertCSV.js +22 -0
  199. package/dist/utils/data-transformations/getValueFromParametersArray.d.ts +1 -0
  200. package/dist/utils/data-transformations/getValueFromParametersArray.js +9 -0
  201. package/dist/utils/layoutNavHelpers.d.ts +70 -0
  202. package/dist/utils/layoutNavHelpers.js +129 -0
  203. package/dist/utils/package-wrapping-specific/addIndexAndInitialValue.d.ts +1 -0
  204. package/dist/utils/package-wrapping-specific/addIndexAndInitialValue.js +21 -0
  205. package/dist/utils/package-wrapping-specific/createBindableParametersValuesArray.d.ts +1 -0
  206. package/dist/utils/package-wrapping-specific/createBindableParametersValuesArray.js +12 -0
  207. package/dist/utils/package-wrapping-specific/createParametersObject.d.ts +1 -0
  208. package/dist/utils/package-wrapping-specific/createParametersObject.js +29 -0
  209. package/dist/utils/package-wrapping-specific/defineDefaultEventHandler.d.ts +1 -0
  210. package/dist/utils/package-wrapping-specific/defineDefaultEventHandler.js +14 -0
  211. package/dist/utils/package-wrapping-specific/trackVisibleParameters.d.ts +1 -0
  212. package/dist/utils/package-wrapping-specific/trackVisibleParameters.js +29 -0
  213. package/dist/utils/syntax-highlighting/shikiHighlight.d.ts +7 -0
  214. package/dist/utils/syntax-highlighting/shikiHighlight.js +76 -0
  215. package/dist/utils/text-string-conversion/textStringConversion.d.ts +9 -0
  216. package/dist/utils/text-string-conversion/textStringConversion.js +86 -0
  217. package/package.json +113 -0
@@ -0,0 +1,392 @@
1
+ <script lang="ts">
2
+ import {
3
+ MapLibre,
4
+ GeoJSON,
5
+ FillLayer,
6
+ LineLayer,
7
+ zoomTransition,
8
+ Control,
9
+ ControlButton,
10
+ ControlGroup,
11
+ } from "svelte-maplibre";
12
+ import { contrastingColor } from "./colors.js";
13
+ import { colorbrewer } from "./colorbrewer.js";
14
+ import { hoverStateFilter } from "svelte-maplibre/filters.js";
15
+ import type { LngLatLike } from "maplibre-gl";
16
+ import type { FeatureCollection } from "geojson";
17
+ import fullTopo from "./fullTopo.json";
18
+ import * as topojson from "topojson-client";
19
+ import Tooltip from "./Tooltip.svelte";
20
+ import {
21
+ getColor,
22
+ filterGeo,
23
+ jenksBreaks,
24
+ quantileBreaks,
25
+ } from "./mapUtils.js";
26
+ import NonStandardControls from "./NonStandardControls.svelte";
27
+ import { replaceState } from "$app/navigation";
28
+ import { page } from "$app/state";
29
+ import { joinData } from "./dataJoin.js";
30
+
31
+ import maplibregl from "maplibre-gl";
32
+ const { LngLatBounds } = maplibregl;
33
+
34
+ import type { LngLatBoundsLike } from "maplibre-gl";
35
+ let {
36
+ data,
37
+ customPallet,
38
+ setCustomPallet,
39
+ interactive,
40
+ cooperativeGestures = true,
41
+ standardControls = true,
42
+ navigationControl,
43
+ navigationControlPosition = "top-left",
44
+ geolocateControl,
45
+ geolocateControlPosition = "top-left",
46
+ fullscreenControl,
47
+ fullscreenControlPosition = "top-left",
48
+ scaleControl,
49
+ scaleControlPosition = "bottom-left",
50
+ scaleControlUnit = "metric",
51
+ styleSheet = "Carto-light",
52
+ colorPalette = "YlGnBu",
53
+ showBorder = false,
54
+ maxBorderWidth = 1.5,
55
+ tooltip,
56
+ clickToZoom = true,
57
+ geoType,
58
+ year,
59
+ metric,
60
+ breaksType = "quantile",
61
+ customBreaks,
62
+ numberOfBreaks = 5,
63
+ fillOpacity = 0.5,
64
+ changeOpacityOnHover = true,
65
+ hoverOpacity = 0.8,
66
+ center = [-2.5, 53],
67
+ zoom = 5,
68
+ minZoom,
69
+ maxZoom,
70
+ maxBoundsCoords,
71
+ hash = false,
72
+ updateHash = (u) => {
73
+ replaceState(u, page.state);
74
+ },
75
+ useInitialHash = true,
76
+ mapHeight = 200,
77
+ setMaxBounds,
78
+ }: {
79
+ data: object[];
80
+ customPallet: object[] | undefined;
81
+ cooperativeGestures?: boolean;
82
+ standardControls?: boolean;
83
+ navigationControl?: boolean;
84
+ navigationControlPosition?: string;
85
+ geolocateControl?: boolean;
86
+ geolocateControlPosition?: string;
87
+ fullscreenControl?: boolean;
88
+ fullscreenControlPosition?: string;
89
+ scaleControl?: boolean;
90
+ scaleControlPosition?: string;
91
+ scaleControlUnit?: string;
92
+ styleSheet?: string | URL | object;
93
+ colorPalette?: string;
94
+ showBorder?: boolean;
95
+ maxBorderWidth?: number;
96
+ tooltip?: boolean;
97
+ clickToZoom?: boolean;
98
+ geoType?: string;
99
+ year?: string | number;
100
+ metric?: string;
101
+ breaksType?: string;
102
+ numberOfBreaks?: number;
103
+ fillOpacity?: number;
104
+ changeOpacityOnHover: boolean;
105
+ hoverOpacity?: number;
106
+ center?: LngLatLike | undefined;
107
+ zoom?: number;
108
+ minZoom?: number | undefined;
109
+ maxZoom?: number | undefined;
110
+ maxBoundsCoords?: LngLatBoundsLike;
111
+ setMaxBounds?: boolean;
112
+ hash?: boolean;
113
+ updateHash?: (URL) => void;
114
+ useInitialHash?: boolean;
115
+ mapHeight?: number;
116
+ setCustomPallet?: boolean;
117
+ customBreaks?: number[];
118
+ interactive: boolean;
119
+ } = $props();
120
+
121
+ let styleLookup = {
122
+ "Carto-light":
123
+ "https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",
124
+ "Carto-dark":
125
+ "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
126
+ };
127
+ let style = $derived(styleLookup[styleSheet] ?? styleSheet);
128
+
129
+ let breakCount = $derived(
130
+ breaksType == "custom" ? customBreaks.length : numberOfBreaks,
131
+ );
132
+
133
+ let mapData = $derived(data?.filter((d) => d["year"] == year)[0]?.data);
134
+
135
+ let filteredMapData = $derived(
136
+ mapData.map((el) => ({
137
+ areaCode: el.areaCode,
138
+ areaName: el.areaName,
139
+ metric: +el.data[metric],
140
+ })),
141
+ );
142
+
143
+ const geojsonData: FeatureCollection = $derived(
144
+ topojson.feature(fullTopo, fullTopo.objects[geoType]),
145
+ );
146
+
147
+ let filteredGeoJsonData = $derived(filterGeo(geojsonData, year));
148
+
149
+ let fillColors: string[] = $derived(
150
+ setCustomPallet == true
151
+ ? customPallet
152
+ : colorbrewer[colorPalette][breakCount],
153
+ );
154
+
155
+ let borderColor = "#003300";
156
+
157
+ let map: maplibregl.Map | undefined = $state();
158
+
159
+ let loaded = $state(false);
160
+ let textLayers: maplibregl.LayerSpecification[] = $derived(
161
+ map && loaded && styleSheet
162
+ ? map.getStyle().layers.filter((layer) => {
163
+ return layer.type === "symbol" && layer["source-layer"] === "place";
164
+ })
165
+ : [],
166
+ );
167
+
168
+ let colors = $derived(fillColors.map((d) => contrastingColor(d)));
169
+ $effect(() => {
170
+ //Things can get out of sync when changing source
171
+ //this section makes sure that the geojson layers end up below the text layers
172
+ let geoJsonLayerIds = map
173
+ ?.getStyle()
174
+ ?.layers.filter((layer) => {
175
+ return layer.source == "areas";
176
+ })
177
+ .map((d) => d.id);
178
+ const labelLayerId = map
179
+ ?.getStyle()
180
+ ?.layers.find(
181
+ (layer) => layer.type === "symbol" && layer["source-layer"] === "place",
182
+ )?.id;
183
+ if (geoJsonLayerIds && labelLayerId) {
184
+ for (let layer of geoJsonLayerIds) {
185
+ map?.moveLayer(layer, labelLayerId);
186
+ }
187
+ }
188
+
189
+ for (let layer of textLayers) {
190
+ //Hard coded to first color for testing
191
+ map?.setPaintProperty(layer.id, "text-color", colors[0].textColor);
192
+ map?.setPaintProperty(
193
+ layer.id,
194
+ "text-halo-color",
195
+ colors[0].textOutlineColor,
196
+ );
197
+ }
198
+
199
+ if (cooperativeGestures) {
200
+ map?.cooperativeGestures.enable();
201
+ } else {
202
+ map?.cooperativeGestures.disable();
203
+ }
204
+
205
+ map?.setMaxBounds(bounds);
206
+ });
207
+
208
+ let vals = $derived(
209
+ filteredMapData.map((d) => d.metric).sort((a, b) => a - b),
210
+ );
211
+
212
+ let breaks = $derived(
213
+ breaksType == "jenks"
214
+ ? jenksBreaks(vals, breakCount)
215
+ : breaksType == "quantile"
216
+ ? quantileBreaks(vals, breakCount)
217
+ : customBreaks,
218
+ );
219
+
220
+ let dataWithColor = $derived(
221
+ filteredMapData.map((d) => {
222
+ return {
223
+ ...d,
224
+ color: getColor(d.metric, breaks, fillColors),
225
+ };
226
+ }),
227
+ );
228
+
229
+ let merged = $derived(joinData(filteredGeoJsonData, dataWithColor));
230
+
231
+ let hoveredArea = $state();
232
+ let hoveredAreaData = $state();
233
+ let currentMousePosition = $state();
234
+
235
+ function convertToLngLatBounds(coords: LngLatBoundsLike): LngLatBoundsLike {
236
+ const bounds = new LngLatBounds(coords[0], coords[0]);
237
+
238
+ for (let i = 1; i < coords.length; i++) {
239
+ bounds.extend(coords[i]);
240
+ }
241
+
242
+ return bounds;
243
+ }
244
+
245
+ function zoomToArea(e) {
246
+ if (clickToZoom) {
247
+ let coordArray =
248
+ e.features[0].geometry.coordinates.length === 1
249
+ ? e.features[0].geometry.coordinates[0]
250
+ : //Do some extra processing to get the data in the right shape if the area has non-contiguous areas
251
+ e.features[0].geometry.coordinates.flat(2);
252
+
253
+ let minValues = [
254
+ Math.min(...coordArray.map((d) => +d[0])),
255
+ Math.max(...coordArray.map((d) => +d[0])),
256
+ ];
257
+
258
+ let maxValues = [
259
+ Math.min(...coordArray.map((d) => +d[1])),
260
+ Math.max(...coordArray.map((d) => +d[1])),
261
+ ];
262
+
263
+ map?.fitBounds([
264
+ [minValues[0], maxValues[0]],
265
+ [minValues[1], maxValues[1]],
266
+ ]);
267
+ }
268
+ }
269
+ //When useInitialHash is true, even if hash is false, if the page is loaded with a location hash use that as the initial settings, rather than the values passed to the component
270
+ const initialLocationHash = page.url.hash.replace("#", "").split("/");
271
+ const useLocationHash = initialLocationHash.length >= 3 ? true : false;
272
+
273
+ center = useInitialHash
274
+ ? useLocationHash
275
+ ? [+initialLocationHash[2], +initialLocationHash[1]]
276
+ : center
277
+ : center;
278
+
279
+ zoom = useInitialHash
280
+ ? useLocationHash
281
+ ? +initialLocationHash[0]
282
+ : zoom
283
+ : zoom;
284
+
285
+ let bounds = $derived(
286
+ setMaxBounds ? convertToLngLatBounds(maxBoundsCoords) : undefined,
287
+ );
288
+ </script>
289
+
290
+ <div style="height: {mapHeight}px;">
291
+ <MapLibre
292
+ bind:map
293
+ bind:loaded
294
+ {style}
295
+ {center}
296
+ {zoom}
297
+ {maxZoom}
298
+ {minZoom}
299
+ standardControls={interactive && standardControls}
300
+ {hash}
301
+ {updateHash}
302
+ {interactive}
303
+ class="map"
304
+ >
305
+ {#if interactive && !standardControls}
306
+ <NonStandardControls
307
+ {navigationControl}
308
+ {navigationControlPosition}
309
+ {geolocateControl}
310
+ {geolocateControlPosition}
311
+ {fullscreenControl}
312
+ {fullscreenControlPosition}
313
+ {scaleControl}
314
+ {scaleControlPosition}
315
+ {scaleControlUnit}
316
+ />
317
+ <Control>
318
+ <ControlGroup>
319
+ <button
320
+ class="reset-button"
321
+ onclick={() => {
322
+ map.flyTo({
323
+ center: center,
324
+ zoom: zoom,
325
+ });
326
+ }}
327
+ >
328
+ Reset view
329
+ </button>
330
+ </ControlGroup>
331
+ </Control>
332
+ {/if}
333
+
334
+ <GeoJSON id="areas" data={merged} promoteId="areanm">
335
+ <FillLayer
336
+ paint={{
337
+ "fill-color": ["coalesce", ["get", "color"], "lightgrey"],
338
+ "fill-opacity": changeOpacityOnHover
339
+ ? hoverStateFilter(fillOpacity, hoverOpacity)
340
+ : fillOpacity,
341
+ }}
342
+ beforeLayerType="symbol"
343
+ manageHoverState={interactive}
344
+ onclick={interactive ? (e) => zoomToArea(e) : null}
345
+ onmousemove={interactive
346
+ ? (e) => {
347
+ hoveredArea = e.features[0].id;
348
+ hoveredAreaData = e.features[0].properties.metric;
349
+ currentMousePosition = e.event.point;
350
+ }
351
+ : null}
352
+ onmouseleave={interactive
353
+ ? () => {
354
+ hoveredArea = null;
355
+ hoveredAreaData = null;
356
+ }
357
+ : null}
358
+ />
359
+ {#if showBorder}
360
+ <LineLayer
361
+ layout={{ "line-cap": "round", "line-join": "round" }}
362
+ paint={{
363
+ "line-color": hoverStateFilter(borderColor, "orange"),
364
+ "line-width": zoomTransition(3, 0, 12, maxBorderWidth),
365
+ }}
366
+ beforeLayerType="symbol"
367
+ />
368
+ {/if}
369
+ </GeoJSON>
370
+
371
+ {#if interactive && tooltip}
372
+ <Tooltip
373
+ {currentMousePosition}
374
+ {hoveredArea}
375
+ {hoveredAreaData}
376
+ {year}
377
+ {metric}
378
+ />
379
+ {/if}
380
+ </MapLibre>
381
+ </div>
382
+
383
+ <style>
384
+ :global(.maplibregl-ctrl-group button.reset-button) {
385
+ /* margin: 10px; */
386
+ width: -moz-fit-content;
387
+ width: fit-content;
388
+ padding: 0px 10px;
389
+ font-size: 16px;
390
+ height: 100%;
391
+ }
392
+ </style>
@@ -0,0 +1,47 @@
1
+ import type { LngLatLike } from "maplibre-gl";
2
+ import type { LngLatBoundsLike } from "maplibre-gl";
3
+ type $$ComponentProps = {
4
+ data: object[];
5
+ customPallet: object[] | undefined;
6
+ cooperativeGestures?: boolean;
7
+ standardControls?: boolean;
8
+ navigationControl?: boolean;
9
+ navigationControlPosition?: string;
10
+ geolocateControl?: boolean;
11
+ geolocateControlPosition?: string;
12
+ fullscreenControl?: boolean;
13
+ fullscreenControlPosition?: string;
14
+ scaleControl?: boolean;
15
+ scaleControlPosition?: string;
16
+ scaleControlUnit?: string;
17
+ styleSheet?: string | URL | object;
18
+ colorPalette?: string;
19
+ showBorder?: boolean;
20
+ maxBorderWidth?: number;
21
+ tooltip?: boolean;
22
+ clickToZoom?: boolean;
23
+ geoType?: string;
24
+ year?: string | number;
25
+ metric?: string;
26
+ breaksType?: string;
27
+ numberOfBreaks?: number;
28
+ fillOpacity?: number;
29
+ changeOpacityOnHover: boolean;
30
+ hoverOpacity?: number;
31
+ center?: LngLatLike | undefined;
32
+ zoom?: number;
33
+ minZoom?: number | undefined;
34
+ maxZoom?: number | undefined;
35
+ maxBoundsCoords?: LngLatBoundsLike;
36
+ setMaxBounds?: boolean;
37
+ hash?: boolean;
38
+ updateHash?: (URL: any) => void;
39
+ useInitialHash?: boolean;
40
+ mapHeight?: number;
41
+ setCustomPallet?: boolean;
42
+ customBreaks?: number[];
43
+ interactive: boolean;
44
+ };
45
+ declare const Map: import("svelte").Component<$$ComponentProps, {}, "">;
46
+ type Map = ReturnType<typeof Map>;
47
+ export default Map;
@@ -0,0 +1,41 @@
1
+ <script>
2
+ let { fillColor, canvasWidth, hoveredAreaProperties } = $props();
3
+ // $inspect(hoveredAreaProperties);
4
+
5
+ let legendWidth = $derived(0.8 * canvasWidth);
6
+ </script>
7
+
8
+ <svg style="width: {legendWidth}; left: {0.1 * canvasWidth}">
9
+ {#each fillColor as color, i}
10
+ {@const barWidth = legendWidth / fillColor.length}
11
+ {@const hovered = color == hoveredAreaProperties?.color}
12
+ <rect
13
+ width={barWidth}
14
+ height="10"
15
+ x={i * barWidth}
16
+ y="10"
17
+ fill={color}
18
+ stroke={hovered ? "black" : ""}
19
+ stroke-width={hovered ? "3px" : "1px"}
20
+ opacity="0.8"
21
+ ></rect>
22
+ {#if hovered}
23
+ <text x={i * barWidth} y="40" font-size="16px"
24
+ >{hoveredAreaProperties?.LAD23NM}</text
25
+ >
26
+ <text x={i * barWidth} y="55">£{hoveredAreaProperties?.salary}</text>
27
+ {/if}
28
+ {/each}
29
+ </svg>
30
+
31
+ <style>
32
+ svg {
33
+ z-index: 1;
34
+ position: absolute;
35
+ bottom: 100px;
36
+ /* left: 100px; */
37
+ background-color: whitesmoke;
38
+ height: 80px;
39
+ opacity: 0.9;
40
+ }
41
+ </style>
@@ -0,0 +1,15 @@
1
+ export default MapLegend;
2
+ type MapLegend = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const MapLegend: import("svelte").Component<{
7
+ fillColor: any;
8
+ canvasWidth: any;
9
+ hoveredAreaProperties: any;
10
+ }, {}, "">;
11
+ type $$ComponentProps = {
12
+ fillColor: any;
13
+ canvasWidth: any;
14
+ hoveredAreaProperties: any;
15
+ };
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ //@ts-nocheck
3
+ import {
4
+ FullscreenControl,
5
+ GeolocateControl,
6
+ NavigationControl,
7
+ ScaleControl,
8
+ } from "svelte-maplibre";
9
+
10
+ let {
11
+ navigationControl,
12
+ navigationControlPosition = "top-left",
13
+ geolocateControl,
14
+ geolocateControlPosition = "top-left",
15
+ fullscreenControl,
16
+ fullscreenControlPosition = "top-left",
17
+ scaleControl,
18
+ scaleControlPosition = "bottom-left",
19
+ scaleControlUnit = "metric",
20
+ } = $props();
21
+ </script>
22
+
23
+ {#if navigationControl}
24
+ {#key navigationControlPosition}
25
+ <NavigationControl position={navigationControlPosition} />
26
+ {/key}
27
+ {/if}
28
+ {#if geolocateControl}
29
+ {#key geolocateControlPosition}
30
+ <GeolocateControl position={geolocateControlPosition} />
31
+ {/key}
32
+ {/if}
33
+ {#if fullscreenControl}
34
+ {#key fullscreenControlPosition}
35
+ <FullscreenControl position={fullscreenControlPosition} />
36
+ {/key}
37
+ {/if}
38
+ {#if scaleControl}
39
+ {#key { scaleControlPosition, scaleControlUnit }}
40
+ <ScaleControl position={scaleControlPosition} unit={scaleControlUnit} />
41
+ {/key}
42
+ {/if}
@@ -0,0 +1,13 @@
1
+ declare const NonStandardControls: import("svelte").Component<{
2
+ navigationControl: any;
3
+ navigationControlPosition?: string;
4
+ geolocateControl: any;
5
+ geolocateControlPosition?: string;
6
+ fullscreenControl: any;
7
+ fullscreenControlPosition?: string;
8
+ scaleControl: any;
9
+ scaleControlPosition?: string;
10
+ scaleControlUnit?: string;
11
+ }, {}, "">;
12
+ type NonStandardControls = ReturnType<typeof NonStandardControls>;
13
+ export default NonStandardControls;
@@ -0,0 +1,41 @@
1
+ <script>
2
+ let { currentMousePosition, hoveredArea, hoveredAreaData, year, metric } =
3
+ $props();
4
+ let tooltipHeight = $state();
5
+ let tooltipWidth = $state();
6
+ // $inspect(tooltipHeight, tooltipWidth, currentMousePosition);
7
+ </script>
8
+
9
+ {#if hoveredArea}
10
+ <div
11
+ class="tooltip"
12
+ style="top: {currentMousePosition?.y}px; left: {currentMousePosition?.x}px"
13
+ bind:clientHeight={tooltipHeight}
14
+ bind:clientWidth={tooltipWidth}
15
+ >
16
+ <p>{hoveredArea}</p>
17
+ <p class="detail">
18
+ {year}
19
+ {metric}: {isNaN(hoveredAreaData) ? "No data" : hoveredAreaData}
20
+ </p>
21
+ </div>
22
+ {/if}
23
+
24
+ <style>
25
+ .tooltip {
26
+ z-index: 1;
27
+ position: absolute;
28
+ /* top: 100px;
29
+ left: 100px; */
30
+ font-weight: 700;
31
+ font-size: 24px;
32
+ pointer-events: none;
33
+ background-color: aliceblue;
34
+ padding: 5px;
35
+ border-radius: 5px;
36
+ }
37
+ .detail {
38
+ font-weight: 400;
39
+ font-size: 16px;
40
+ }
41
+ </style>
@@ -0,0 +1,19 @@
1
+ export default Tooltip;
2
+ type Tooltip = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Tooltip: import("svelte").Component<{
7
+ currentMousePosition: any;
8
+ hoveredArea: any;
9
+ hoveredAreaData: any;
10
+ year: any;
11
+ metric: any;
12
+ }, {}, "">;
13
+ type $$ComponentProps = {
14
+ currentMousePosition: any;
15
+ hoveredArea: any;
16
+ hoveredAreaData: any;
17
+ year: any;
18
+ metric: any;
19
+ };