@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,247 @@
1
+ <script>
2
+ import Button from "../../ui/Button.svelte";
3
+
4
+ let {
5
+ componentNameProp = undefined,
6
+ data = undefined,
7
+ metaData = undefined,
8
+ caption = undefined,
9
+ colourScale = undefined,
10
+ } = $props();
11
+
12
+ let localCopyOfData = $state([...data]);
13
+
14
+ function hasUniqueValues(array, key) {
15
+ const seen = new Set();
16
+ for (const obj of array) {
17
+ if (seen.has(obj[key])) {
18
+ return false; // Duplicate found
19
+ }
20
+ seen.add(obj[key]);
21
+ }
22
+ return true; // All values are unique
23
+ }
24
+
25
+ // $inspect(
26
+ // localCopyOfData[0].areaName,
27
+ // "data type is",
28
+ // typeof localCopyOfData[0].areaName,
29
+ // );
30
+ // $inspect(
31
+ // localCopyOfData[0]["Household waste recycling rate"],
32
+ // "data type is",
33
+ // typeof localCopyOfData[0]["Household waste recycling rate"],
34
+ // );
35
+
36
+ let columns = [];
37
+
38
+ for (const column in localCopyOfData[0]) {
39
+ // create a variable to store whether the key is unique or not
40
+ const keyIsUnique = hasUniqueValues(localCopyOfData, column);
41
+ // get data type of each column
42
+ const columnDataType = typeof localCopyOfData[0][column];
43
+ // for each one create an object and push it into the array
44
+ const columnObject = {
45
+ key: column,
46
+ isUnique: keyIsUnique,
47
+ dataType: columnDataType,
48
+ };
49
+ columns.push(columnObject);
50
+ }
51
+
52
+ $inspect("columns array is ", columns);
53
+
54
+ const metrics = columns
55
+ .filter((column) => column.dataType === "number")
56
+ .map((column) => column.key);
57
+
58
+ // $inspect("metrics is", metrics);
59
+
60
+ let sortState = $state({ column: "sortedColumn", order: "ascending" });
61
+
62
+ function updateSortState(columnToSort, sortOrder) {
63
+ sortState.column = columnToSort;
64
+ sortState.order = sortOrder;
65
+ }
66
+
67
+ function sortFunction() {
68
+ if (typeof localCopyOfData[0][sortState["column"]] === "number") {
69
+ if (sortState.order === "ascending") {
70
+ localCopyOfData.sort(
71
+ (a, b) => a[sortState.column] - b[sortState.column],
72
+ );
73
+ } else {
74
+ localCopyOfData.sort(
75
+ (a, b) => b[sortState.column] - a[sortState.column],
76
+ );
77
+ }
78
+ }
79
+ if (typeof localCopyOfData[0][sortState["column"]] === "string") {
80
+ if (sortState.order === "ascending") {
81
+ localCopyOfData.sort((a, b) =>
82
+ a[sortState["column"]].localeCompare(b[sortState["column"]]),
83
+ );
84
+ } else {
85
+ localCopyOfData.sort((a, b) =>
86
+ b[sortState["column"]].localeCompare(a[sortState["column"]]),
87
+ );
88
+ }
89
+ }
90
+ }
91
+
92
+ $inspect(
93
+ sortState,
94
+ localCopyOfData[0],
95
+ typeof localCopyOfData[0][sortState["column"]],
96
+ );
97
+
98
+ // heat map
99
+
100
+ // calculate the min and max of each metric
101
+ const minAndMaxValues = {}; // create an empty object to store them in
102
+ for (const metric of metrics) {
103
+ // get the values
104
+ const metricValues = localCopyOfData.map((item) => item[metric]);
105
+ const min = Math.min(...metricValues);
106
+ const max = Math.max(...metricValues);
107
+ // store them
108
+ minAndMaxValues[metric] = { min, max };
109
+ }
110
+
111
+ localCopyOfData = localCopyOfData.map((row) => {
112
+ const rowWithNorms = { ...row };
113
+
114
+ for (const metric of metrics) {
115
+ const { min, max } = minAndMaxValues[metric];
116
+ const value = row[metric];
117
+ const normalisedValue = (value - min) / (max - min);
118
+
119
+ rowWithNorms[`${metric}__normalised`] = normalisedValue;
120
+ }
121
+
122
+ return rowWithNorms;
123
+ });
124
+
125
+ function normToColor(norm) {
126
+ const hue = 120 * norm;
127
+ return `hsl(${hue}, 100%, 80%)`;
128
+ }
129
+
130
+ function normToColorReverse(norm) {
131
+ const hue = 120 * (1 - norm);
132
+ return `hsl(${hue}, 100%, 80%)`;
133
+ }
134
+
135
+ const colorKey = Object.entries({ Good: 1, Ok: 0.5, Bad: 0 });
136
+
137
+ // $inspect("the first column key is", columns[0].key);
138
+ </script>
139
+
140
+ <div class="p-4">
141
+ {#if colourScale === "On"}
142
+ <div class="legend">
143
+ <div>Colour key:</div>
144
+ {#each colorKey as key}
145
+ <div class="color-keys" style="background-color: {normToColor(key[1])}">
146
+ {key[0]}
147
+ </div>
148
+ {/each}
149
+ </div>
150
+ {/if}
151
+
152
+ <div class="table-container">
153
+ <table class="govuk-table" data-module="moj-sortable-table">
154
+ <caption class="govuk-table__caption">{caption}</caption>
155
+ <thead class="govuk-table__head"
156
+ ><tr class="govuk-table__row">
157
+ {#each columns as column}
158
+ <th
159
+ scope="col"
160
+ class={`govuk-table__header ${column.dataType === "number" ? "govuk-table__header--numeric" : ""}`}
161
+ title={metaData[column.key].explainer}
162
+ aria-sort="none"
163
+ >
164
+ <div class="header">
165
+ <Button
166
+ textContent={metaData[column.key].shortLabel}
167
+ buttonType={"table header"}
168
+ onClickFunction={() => {
169
+ const newDirection =
170
+ sortState.column === column.key &&
171
+ sortState.order === "ascending"
172
+ ? "descending"
173
+ : "ascending";
174
+
175
+ updateSortState(column.key, newDirection);
176
+ sortFunction();
177
+ }}
178
+ ></Button>
179
+ </div></th
180
+ >
181
+ {/each}
182
+ </tr></thead
183
+ >
184
+ <tbody class="govuk-table__body">
185
+ {#each localCopyOfData as row}
186
+ <tr class="govuk-table__row">
187
+ {#each columns as column}
188
+ {#if column.dataType === "number"}
189
+ {#if colourScale === "On"}
190
+ {#if metaData[column.key].direction === "Higher is better"}
191
+ <td
192
+ class="govuk-table__cell govuk-table__cell--numeric"
193
+ style="background-color: {normToColor(
194
+ row[column.key + '__normalised'],
195
+ )}"
196
+ data-sort-value="42">{row[column.key]}</td
197
+ >
198
+ {:else}
199
+ <td
200
+ class="govuk-table__cell govuk-table__cell--numeric"
201
+ style="background-color: {normToColorReverse(
202
+ row[column.key + '__normalised'],
203
+ )}"
204
+ data-sort-value="42">{row[column.key]}</td
205
+ >
206
+ {/if}
207
+ {:else}
208
+ <td
209
+ class="govuk-table__cell govuk-table__cell--numeric"
210
+ data-sort-value="42">{row[column.key]}</td
211
+ >
212
+ {/if}
213
+ {:else}
214
+ <td class="govuk-table__cell">{row[column.key]}</td>
215
+ {/if}
216
+ {/each}
217
+ </tr>
218
+ {/each}
219
+ </tbody>
220
+ </table>
221
+ </div>
222
+ </div>
223
+
224
+ <style>
225
+ .table-container {
226
+ max-height: 80vh;
227
+ overflow-y: auto;
228
+ }
229
+
230
+ th {
231
+ position: sticky;
232
+ top: 0;
233
+ z-index: 1;
234
+ background-color: white;
235
+ }
236
+
237
+ .legend {
238
+ display: flex;
239
+ justify-content: center;
240
+ gap: 20px;
241
+ margin: 10px;
242
+ }
243
+ .color-keys {
244
+ border-radius: 10%;
245
+ padding: 6px;
246
+ }
247
+ </style>
@@ -0,0 +1,19 @@
1
+ export default Table;
2
+ type Table = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Table: import("svelte").Component<{
7
+ componentNameProp?: any;
8
+ data?: any;
9
+ metaData?: any;
10
+ caption?: any;
11
+ colourScale?: any;
12
+ }, {}, "">;
13
+ type $$ComponentProps = {
14
+ componentNameProp?: any;
15
+ data?: any;
16
+ metaData?: any;
17
+ caption?: any;
18
+ colourScale?: any;
19
+ };
@@ -0,0 +1,191 @@
1
+ <script lang="ts">
2
+ import { onMount } from "svelte";
3
+ import { page } from "$app/state";
4
+
5
+ /**
6
+ * Breadcrumbs component
7
+ *
8
+ * Use this component to display a navigation path to the current page.
9
+ *
10
+ * Features:
11
+ * - Automatically generates breadcrumbs based on the current route
12
+ * - Set `collapseOnMobile` to true to show only the first and last items on mobile devices
13
+ * - Set `inverse` to true to show white links on dark backgrounds (ensure contrast ratio of 4.5:1)
14
+ * - Optionally provide custom items array to override automatic breadcrumb generation
15
+ */
16
+
17
+ // Define the BreadcrumbItem type
18
+ export type BreadcrumbItem = {
19
+ text: string;
20
+ href: string;
21
+ };
22
+
23
+ // Component props
24
+ let {
25
+ items = undefined,
26
+ collapseOnMobile = false,
27
+ inverse = false,
28
+ ariaLabel = "Breadcrumb",
29
+ } = $props<{
30
+ items?: BreadcrumbItem[];
31
+ collapseOnMobile?: boolean;
32
+ inverse?: boolean;
33
+ ariaLabel?: string;
34
+ }>();
35
+
36
+ // Load all page modules for route detection
37
+ const routeModules = $state<Record<string, any>>({});
38
+
39
+ onMount(async () => {
40
+ try {
41
+ // Use Vite's glob import to get all page components
42
+ const modules = import.meta.glob("/src/routes/**/+page.svelte", {
43
+ eager: true,
44
+ });
45
+ Object.assign(routeModules, modules);
46
+ } catch (error) {
47
+ console.warn("Failed to load route modules:", error);
48
+ }
49
+ });
50
+
51
+ // State variable to hold the current breadcrumb items
52
+ let breadcrumbItems = $state<BreadcrumbItem[]>([]);
53
+
54
+ // Effect to update breadcrumb items when dependencies change
55
+ $effect(() => {
56
+ breadcrumbItems = items || generateBreadcrumbItems(page, routeModules);
57
+ });
58
+
59
+ // Generate breadcrumb items from the current route
60
+ function generateBreadcrumbItems(page, modules): BreadcrumbItem[] {
61
+ const path = page.url.pathname;
62
+ const pathSegments = path.split("/").filter((segment) => segment !== "");
63
+
64
+ // Always include home page
65
+ const items: BreadcrumbItem[] = [{ text: "Home", href: "/" }];
66
+
67
+ // Build up paths for each breadcrumb
68
+ let currentPath = "";
69
+
70
+ for (let i = 0; i < pathSegments.length; i++) {
71
+ currentPath += `/${pathSegments[i]}`;
72
+
73
+ // Check if this path has a corresponding +page.svelte file
74
+ const isValidRoute = isPathValid(currentPath, modules);
75
+
76
+ // Add breadcrumb if it's a valid route or the current page
77
+ if (isValidRoute || i === pathSegments.length - 1) {
78
+ // Try to get custom title from module exports
79
+ const customTitle = getCustomTitle(currentPath, modules, page.data);
80
+
81
+ // Format text (convert slug to readable text)
82
+ const text = customTitle || formatBreadcrumbText(pathSegments[i]);
83
+
84
+ items.push({
85
+ text: text,
86
+ href: currentPath,
87
+ });
88
+ }
89
+ }
90
+
91
+ return items;
92
+ }
93
+
94
+ // Check if a path has a corresponding page component
95
+ function isPathValid(path: string, modules: Record<string, any>): boolean {
96
+ // For the root path
97
+ if (path === "/") return true;
98
+
99
+ // Normalize the path to check against module paths
100
+ const modulePath = `/src/routes${path}/+page.svelte`;
101
+ const dynamicModulePaths = Object.keys(modules).filter((m) => {
102
+ // Convert dynamic route patterns like [id] to regex pattern that matches :id or actual values
103
+ const pattern = m.replace(/\[([^\]]+)\]/g, "([^/]+)");
104
+ const regex = new RegExp(
105
+ `^${pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`,
106
+ );
107
+ return regex.test(modulePath);
108
+ });
109
+
110
+ return dynamicModulePaths.length > 0;
111
+ }
112
+
113
+ // Try to get custom title from module exports
114
+ function getCustomTitle(
115
+ path: string,
116
+ modules: Record<string, any>,
117
+ pageData: any,
118
+ ): string | null {
119
+ const modulePath = `/src/routes${path}/+page.svelte`;
120
+
121
+ // Check for exact match first
122
+ if (modules[modulePath]) {
123
+ // Check if module exports pageTitle
124
+ if (modules[modulePath].pageTitle) {
125
+ return modules[modulePath].pageTitle;
126
+ }
127
+
128
+ // Check if module exports getPageTitle function
129
+ if (typeof modules[modulePath].getPageTitle === "function") {
130
+ return modules[modulePath].getPageTitle(pageData);
131
+ }
132
+ }
133
+
134
+ // Check for dynamic routes
135
+ const dynamicModulePath = Object.keys(modules).find((m) => {
136
+ const pattern = m.replace(/\[([^\]]+)\]/g, "([^/]+)");
137
+ const regex = new RegExp(
138
+ `^${pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`,
139
+ );
140
+ return regex.test(modulePath);
141
+ });
142
+
143
+ if (dynamicModulePath && modules[dynamicModulePath]) {
144
+ if (modules[dynamicModulePath].pageTitle) {
145
+ return modules[dynamicModulePath].pageTitle;
146
+ }
147
+
148
+ if (typeof modules[dynamicModulePath].getPageTitle === "function") {
149
+ return modules[dynamicModulePath].getPageTitle(pageData);
150
+ }
151
+ }
152
+
153
+ return null;
154
+ }
155
+
156
+ /**
157
+ * Converts route segments to human-readable text
158
+ */
159
+ function formatBreadcrumbText(text: string): string {
160
+ // Handle special cases
161
+ if (text === "ui") return "UI Components";
162
+ if (text === "data-vis") return "Data Visualization";
163
+ if (text === "content") return "Content Components";
164
+ if (text === "layout") return "Layout Components";
165
+ if (text === "user-guide") return "User Guide";
166
+ if (text === "playground") return "Playground";
167
+ if (text === "components") return "Components";
168
+ if (text === "local-lib") return "Local Library";
169
+
170
+ // Default: capitalize and replace hyphens with spaces
171
+ return text
172
+ .split("-")
173
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
174
+ .join(" ");
175
+ }
176
+ </script>
177
+
178
+ <nav
179
+ class="govuk-breadcrumbs
180
+ {collapseOnMobile ? 'govuk-breadcrumbs--collapse-on-mobile' : ''}
181
+ {inverse ? 'govuk-breadcrumbs--inverse' : ''}"
182
+ aria-label={ariaLabel}
183
+ >
184
+ <ol class="govuk-breadcrumbs__list">
185
+ {#each breadcrumbItems as item}
186
+ <li class="govuk-breadcrumbs__list-item">
187
+ <a class="govuk-breadcrumbs__link" href={item.href}>{item.text}</a>
188
+ </li>
189
+ {/each}
190
+ </ol>
191
+ </nav>
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Breadcrumbs component
3
+ *
4
+ * Use this component to display a navigation path to the current page.
5
+ *
6
+ * Features:
7
+ * - Automatically generates breadcrumbs based on the current route
8
+ * - Set `collapseOnMobile` to true to show only the first and last items on mobile devices
9
+ * - Set `inverse` to true to show white links on dark backgrounds (ensure contrast ratio of 4.5:1)
10
+ * - Optionally provide custom items array to override automatic breadcrumb generation
11
+ */
12
+ export type BreadcrumbItem = {
13
+ text: string;
14
+ href: string;
15
+ };
16
+ type $$ComponentProps = {
17
+ items?: BreadcrumbItem[];
18
+ collapseOnMobile?: boolean;
19
+ inverse?: boolean;
20
+ ariaLabel?: string;
21
+ };
22
+ declare const Breadcrumbs: import("svelte").Component<$$ComponentProps, {}, "">;
23
+ type Breadcrumbs = ReturnType<typeof Breadcrumbs>;
24
+ export default Breadcrumbs;
@@ -0,0 +1,171 @@
1
+ <script lang="ts">
2
+ // Define component props with default values
3
+ // sections: array of footer navigation sections
4
+ // inlineLinks: array of inline footer links
5
+ // metaCustomContent: custom HTML content for meta section
6
+ // containerWidth: width class for the container
7
+ // showLicence: toggle for OGL license display
8
+ // showCopyright: toggle for crown copyright display
9
+ // copyrightLogoUrl: URL for the crown copyright logo background image (overrides the default CSS background-image)
10
+ // copyrightText: Text to display for the crown copyright notice
11
+ // crownSvgPath: SVG path data for the crown logo used in the license section
12
+ // licenceHref: URL for the Open Government Licence link
13
+ // licenceLinkText: Text for the Open Government Licence link
14
+ // licenceTextBefore: Text to display before the licence link
15
+ // licenceTextAfter: Text to display after the licence link
16
+ // copyrightHref: URL for the crown copyright link
17
+
18
+ // Define types for component props
19
+ interface FooterItem {
20
+ href: string;
21
+ label: string;
22
+ lang?: string;
23
+ hrefLang?: string;
24
+ }
25
+
26
+ interface FooterSection {
27
+ title: string;
28
+ columns?: number;
29
+ items: FooterItem[];
30
+ }
31
+
32
+ // Define component props with types and default values
33
+ let {
34
+ sections = [] as FooterSection[],
35
+ inlineLinks = [] as FooterItem[],
36
+ metaCustomContent = "",
37
+ containerWidth = "govuk-width-container",
38
+ showLicence = true,
39
+ showCopyright = true,
40
+ copyrightLogoUrl = "/assets/images/govuk-crest.svg",
41
+ copyrightText = "© Crown copyright",
42
+ crownSvgPath = "M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145",
43
+ licenceHref = "https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/",
44
+ licenceLinkText = "Open Government Licence v3.0",
45
+ licenceTextBefore = "All content is available under the ",
46
+ licenceTextAfter = ", except where otherwise stated",
47
+ copyrightHref = "https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/",
48
+ } = $props<{
49
+ sections?: FooterSection[];
50
+ inlineLinks?: FooterItem[];
51
+ metaCustomContent?: string;
52
+ containerWidth?: string;
53
+ showLicence?: boolean;
54
+ showCopyright?: boolean;
55
+ copyrightLogoUrl?: string;
56
+ copyrightText?: string;
57
+ crownSvgPath?: string;
58
+ licenceHref?: string;
59
+ licenceLinkText?: string;
60
+ licenceTextBefore?: string;
61
+ licenceTextAfter?: string;
62
+ copyrightHref?: string;
63
+ }>();
64
+ </script>
65
+
66
+ <!-- Main footer container -->
67
+ <footer class="govuk-footer">
68
+ <div class={containerWidth}>
69
+ <!-- Navigation sections (optional) -->
70
+ {#if sections.length > 0}
71
+ <div class="govuk-footer__navigation">
72
+ <!-- Iterate through each footer section -->
73
+ {#each sections as section}
74
+ <div
75
+ class="govuk-footer__section {section.columns === 2
76
+ ? 'govuk-grid-column-two-thirds'
77
+ : 'govuk-grid-column-one-third'}"
78
+ >
79
+ <h2 class="govuk-footer__heading govuk-heading-m">
80
+ {section.title}
81
+ </h2>
82
+ <ul
83
+ class="govuk-footer__list {section.columns === 2
84
+ ? 'govuk-footer__list--columns-2'
85
+ : ''}"
86
+ >
87
+ {#each section.items as item}
88
+ <li class="govuk-footer__list-item">
89
+ <a
90
+ class="govuk-footer__link"
91
+ href={item.href}
92
+ lang={item.lang}
93
+ hreflang={item.hrefLang}
94
+ >
95
+ {item.label}
96
+ </a>
97
+ </li>
98
+ {/each}
99
+ </ul>
100
+ </div>
101
+ {/each}
102
+ </div>
103
+ <hr class="govuk-footer__section-break" />
104
+ {/if}
105
+
106
+ <!-- Footer meta section -->
107
+ <div class="govuk-footer__meta">
108
+ <div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
109
+ <!-- Inline links section (optional) -->
110
+ {#if inlineLinks.length > 0}
111
+ <h2 class="govuk-visually-hidden">Support links</h2>
112
+ <ul class="govuk-footer__inline-list">
113
+ {#each inlineLinks as link}
114
+ <li class="govuk-footer__inline-list-item">
115
+ <a
116
+ class="govuk-footer__link"
117
+ href={link.href}
118
+ lang={link.lang}
119
+ hreflang={link.hrefLang}
120
+ >
121
+ {link.label}
122
+ </a>
123
+ </li>
124
+ {/each}
125
+ </ul>
126
+ {/if}
127
+
128
+ <!-- Custom meta content (optional) -->
129
+ {#if metaCustomContent}
130
+ <div class="govuk-footer__meta-custom">
131
+ {@html metaCustomContent}
132
+ </div>
133
+ {/if}
134
+
135
+ <!-- Open Government License section (optional) -->
136
+ {#if showLicence}
137
+ <svg
138
+ aria-hidden="true"
139
+ focusable="false"
140
+ class="govuk-footer__licence-logo"
141
+ xmlns="http://www.w3.org/2000/svg"
142
+ viewBox="0 0 483.2 195.7"
143
+ height="17"
144
+ width="41"
145
+ >
146
+ <path fill="currentColor" d={crownSvgPath}></path>
147
+ </svg>
148
+ <span class="govuk-footer__licence-description">
149
+ {licenceTextBefore}
150
+ <a class="govuk-footer__link" href={licenceHref} rel="license"
151
+ >{licenceLinkText}</a
152
+ >{licenceTextAfter}
153
+ </span>
154
+ {/if}
155
+ </div>
156
+
157
+ <!-- Crown copyright section (optional) -->
158
+ {#if showCopyright}
159
+ <div class="govuk-footer__meta-item">
160
+ <a
161
+ class="govuk-footer__link govuk-footer__copyright-logo"
162
+ href={copyrightHref}
163
+ style="background-image: url({copyrightLogoUrl});"
164
+ >
165
+ {copyrightText}
166
+ </a>
167
+ </div>
168
+ {/if}
169
+ </div>
170
+ </div>
171
+ </footer>
@@ -0,0 +1,30 @@
1
+ interface FooterItem {
2
+ href: string;
3
+ label: string;
4
+ lang?: string;
5
+ hrefLang?: string;
6
+ }
7
+ interface FooterSection {
8
+ title: string;
9
+ columns?: number;
10
+ items: FooterItem[];
11
+ }
12
+ type $$ComponentProps = {
13
+ sections?: FooterSection[];
14
+ inlineLinks?: FooterItem[];
15
+ metaCustomContent?: string;
16
+ containerWidth?: string;
17
+ showLicence?: boolean;
18
+ showCopyright?: boolean;
19
+ copyrightLogoUrl?: string;
20
+ copyrightText?: string;
21
+ crownSvgPath?: string;
22
+ licenceHref?: string;
23
+ licenceLinkText?: string;
24
+ licenceTextBefore?: string;
25
+ licenceTextAfter?: string;
26
+ copyrightHref?: string;
27
+ };
28
+ declare const Footer: import("svelte").Component<$$ComponentProps, {}, "">;
29
+ type Footer = ReturnType<typeof Footer>;
30
+ export default Footer;