@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.
- package/README.md +188 -0
- package/dist/assets/css/govuk-frontend.min.css +2 -0
- package/dist/assets/css/govuk-frontend.min.css.map +1 -0
- package/dist/assets/fonts/bold-affa96571d-v2.woff +0 -0
- package/dist/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
- package/dist/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
- package/dist/assets/fonts/light-f591b13f7d-v2.woff +0 -0
- package/dist/assets/govuk_publishing_components/images/icon-autocomplete-search-suggestion.svg +4 -0
- package/dist/assets/govuk_publishing_components/images/icon-close.svg +1 -0
- package/dist/assets/images/favicon.ico +0 -0
- package/dist/assets/images/favicon.svg +1 -0
- package/dist/assets/images/govuk-crest-2x.png +0 -0
- package/dist/assets/images/govuk-crest.png +0 -0
- package/dist/assets/images/govuk-crest.svg +1 -0
- package/dist/assets/images/govuk-icon-180.png +0 -0
- package/dist/assets/images/govuk-icon-192.png +0 -0
- package/dist/assets/images/govuk-icon-512.png +0 -0
- package/dist/assets/images/govuk-icon-mask.svg +1 -0
- package/dist/assets/images/govuk-opengraph-image.png +0 -0
- package/dist/assets/images/homepage-illustration.svg +1 -0
- package/dist/assets/images/homepage.svg +44 -0
- package/dist/assets/images/masthead-illustration.svg +123 -0
- package/dist/assets/images/oflog_crest_black.png +0 -0
- package/dist/assets/images/oflog_crest_white.png +0 -0
- package/dist/assets/images/undraw_approved-wireframe_odf4.svg +1 -0
- package/dist/assets/images/undraw_collaborators_rgw4.svg +1 -0
- package/dist/assets/images/undraw_content-creator_vuqg.svg +1 -0
- package/dist/assets/images/undraw_online-media_opxh.svg +1 -0
- package/dist/assets/images/undraw_pull-request_zlsu.svg +1 -0
- package/dist/assets/images/undraw_reviewed-docs_g0cg.svg +1 -0
- package/dist/components/FilterPanel/codeBlocks.d.ts +3 -0
- package/dist/components/FilterPanel/codeBlocks.js +418 -0
- package/dist/components/content/InsetText.svelte +21 -0
- package/dist/components/content/InsetText.svelte.d.ts +7 -0
- package/dist/components/content/WarningText.svelte +27 -0
- package/dist/components/content/WarningText.svelte.d.ts +8 -0
- package/dist/components/data-vis/axis/Axis.svelte +51 -0
- package/dist/components/data-vis/axis/Axis.svelte.d.ts +33 -0
- package/dist/components/data-vis/axis/Ticks.svelte +113 -0
- package/dist/components/data-vis/axis/Ticks.svelte.d.ts +33 -0
- package/dist/components/data-vis/line-chart/Line.svelte +150 -0
- package/dist/components/data-vis/line-chart/Line.svelte.d.ts +85 -0
- package/dist/components/data-vis/line-chart/LineChart.svelte +249 -0
- package/dist/components/data-vis/line-chart/LineChart.svelte.d.ts +73 -0
- package/dist/components/data-vis/line-chart/Lines.svelte +138 -0
- package/dist/components/data-vis/line-chart/Lines.svelte.d.ts +57 -0
- package/dist/components/data-vis/line-chart/Marker.svelte +61 -0
- package/dist/components/data-vis/line-chart/Marker.svelte.d.ts +37 -0
- package/dist/components/data-vis/line-chart/SeriesLabel.svelte +67 -0
- package/dist/components/data-vis/line-chart/SeriesLabel.svelte.d.ts +43 -0
- package/dist/components/data-vis/line-chart/ValueLabel.svelte +50 -0
- package/dist/components/data-vis/line-chart/ValueLabel.svelte.d.ts +25 -0
- package/dist/components/data-vis/map/Map.svelte +392 -0
- package/dist/components/data-vis/map/Map.svelte.d.ts +47 -0
- package/dist/components/data-vis/map/MapLegend.svelte +41 -0
- package/dist/components/data-vis/map/MapLegend.svelte.d.ts +15 -0
- package/dist/components/data-vis/map/NonStandardControls.svelte +42 -0
- package/dist/components/data-vis/map/NonStandardControls.svelte.d.ts +13 -0
- package/dist/components/data-vis/map/Tooltip.svelte +41 -0
- package/dist/components/data-vis/map/Tooltip.svelte.d.ts +19 -0
- package/dist/components/data-vis/map/colorbrewer.d.ts +337 -0
- package/dist/components/data-vis/map/colorbrewer.js +1523 -0
- package/dist/components/data-vis/map/colors.d.ts +13 -0
- package/dist/components/data-vis/map/colors.js +65 -0
- package/dist/components/data-vis/map/dataJoin.d.ts +2 -0
- package/dist/components/data-vis/map/dataJoin.js +27 -0
- package/dist/components/data-vis/map/fullTopo.json +1 -0
- package/dist/components/data-vis/map/jenks.d.ts +1 -0
- package/dist/components/data-vis/map/jenks.js +51 -0
- package/dist/components/data-vis/map/lad2023.json +1 -0
- package/dist/components/data-vis/map/mapUtils.d.ts +5 -0
- package/dist/components/data-vis/map/mapUtils.js +86 -0
- package/dist/components/data-vis/map/topo.json +1 -0
- package/dist/components/data-vis/table/Table.svelte +247 -0
- package/dist/components/data-vis/table/Table.svelte.d.ts +19 -0
- package/dist/components/layout/Breadcrumbs.svelte +191 -0
- package/dist/components/layout/Breadcrumbs.svelte.d.ts +24 -0
- package/dist/components/layout/Footer.svelte +171 -0
- package/dist/components/layout/Footer.svelte.d.ts +30 -0
- package/dist/components/layout/Header.svelte +43 -0
- package/dist/components/layout/Header.svelte.d.ts +7 -0
- package/dist/components/layout/InternalHeader.svelte +628 -0
- package/dist/components/layout/InternalHeader.svelte.d.ts +15 -0
- package/dist/components/layout/PhaseBanner.svelte +28 -0
- package/dist/components/layout/PhaseBanner.svelte.d.ts +9 -0
- package/dist/components/layout/ServiceNavigation.svelte +143 -0
- package/dist/components/layout/ServiceNavigation.svelte.d.ts +13 -0
- package/dist/components/layout/SideNavigation.svelte +345 -0
- package/dist/components/layout/SideNavigation.svelte.d.ts +25 -0
- package/dist/components/layout/service-navigation-nested-mobile/HeaderNav.svelte +91 -0
- package/dist/components/layout/service-navigation-nested-mobile/HeaderNav.svelte.d.ts +15 -0
- package/dist/components/layout/service-navigation-nested-mobile/MobileNav.svelte +233 -0
- package/dist/components/layout/service-navigation-nested-mobile/MobileNav.svelte.d.ts +27 -0
- package/dist/components/layout/service-navigation-nested-mobile/ServiceNavigationNestedMobile.svelte +70 -0
- package/dist/components/layout/service-navigation-nested-mobile/ServiceNavigationNestedMobile.svelte.d.ts +11 -0
- package/dist/components/layout/service-navigation-nested-mobile/SideNav.svelte +276 -0
- package/dist/components/layout/service-navigation-nested-mobile/SideNav.svelte.d.ts +22 -0
- package/dist/components/ui/Accordion.svelte +244 -0
- package/dist/components/ui/Accordion.svelte.d.ts +23 -0
- package/dist/components/ui/Breadcrumbs.svelte +198 -0
- package/dist/components/ui/Breadcrumbs.svelte.d.ts +24 -0
- package/dist/components/ui/Button.svelte +96 -0
- package/dist/components/ui/Button.svelte.d.ts +17 -0
- package/dist/components/ui/CheckBox.svelte +198 -0
- package/dist/components/ui/CheckBox.svelte.d.ts +27 -0
- package/dist/components/ui/ContentsList.svelte +1117 -0
- package/dist/components/ui/ContentsList.svelte.d.ts +25 -0
- package/dist/components/ui/DateInput.svelte +255 -0
- package/dist/components/ui/DateInput.svelte.d.ts +59 -0
- package/dist/components/ui/Details.svelte +12 -0
- package/dist/components/ui/Details.svelte.d.ts +13 -0
- package/dist/components/ui/FilterPanel.svelte +588 -0
- package/dist/components/ui/FilterPanel.svelte.d.ts +74 -0
- package/dist/components/ui/Footer.svelte +171 -0
- package/dist/components/ui/Footer.svelte.d.ts +30 -0
- package/dist/components/ui/Header.svelte +43 -0
- package/dist/components/ui/Header.svelte.d.ts +7 -0
- package/dist/components/ui/Masthead.svelte +267 -0
- package/dist/components/ui/Masthead.svelte.d.ts +12 -0
- package/dist/components/ui/NavigationExample.svelte +117 -0
- package/dist/components/ui/NavigationExample.svelte.d.ts +3 -0
- package/dist/components/ui/NotificationBanner.svelte +93 -0
- package/dist/components/ui/NotificationBanner.svelte.d.ts +15 -0
- package/dist/components/ui/Radios.svelte +176 -0
- package/dist/components/ui/Radios.svelte.d.ts +28 -0
- package/dist/components/ui/RelatedContent.svelte +596 -0
- package/dist/components/ui/RelatedContent.svelte.d.ts +29 -0
- package/dist/components/ui/Search.svelte +499 -0
- package/dist/components/ui/Search.svelte.d.ts +32 -0
- package/dist/components/ui/SearchAutocomplete.svelte +655 -0
- package/dist/components/ui/SearchAutocomplete.svelte.d.ts +37 -0
- package/dist/components/ui/Select.svelte +116 -0
- package/dist/components/ui/Select.svelte.d.ts +22 -0
- package/dist/components/ui/ServiceNavigation.svelte +143 -0
- package/dist/components/ui/ServiceNavigation.svelte.d.ts +13 -0
- package/dist/components/ui/SideNavigation.svelte +346 -0
- package/dist/components/ui/SideNavigation.svelte.d.ts +25 -0
- package/dist/components/ui/Tabs.svelte +306 -0
- package/dist/components/ui/Tabs.svelte.d.ts +18 -0
- package/dist/components/ui/WhatsNew.svelte +155 -0
- package/dist/components/ui/WhatsNew.svelte.d.ts +29 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.js +44 -0
- package/dist/icons/DoubleChevronButton.svelte +62 -0
- package/dist/icons/DoubleChevronButton.svelte.d.ts +13 -0
- package/dist/icons/IconSearch.svelte +42 -0
- package/dist/icons/IconSearch.svelte.d.ts +6 -0
- package/dist/icons/SingleChevronButtonWithLabel.svelte +132 -0
- package/dist/icons/SingleChevronButtonWithLabel.svelte.d.ts +19 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +45 -0
- package/dist/main.css +1 -0
- package/dist/package-wrapping/BaseInformation.svelte +82 -0
- package/dist/package-wrapping/BaseInformation.svelte.d.ts +15 -0
- package/dist/package-wrapping/BaseNameAndStatus.svelte +108 -0
- package/dist/package-wrapping/BaseNameAndStatus.svelte.d.ts +10 -0
- package/dist/package-wrapping/CodeBlock.svelte +62 -0
- package/dist/package-wrapping/CodeBlock.svelte.d.ts +12 -0
- package/dist/package-wrapping/ComponentDemo.svelte +114 -0
- package/dist/package-wrapping/ComponentDemo.svelte.d.ts +25 -0
- package/dist/package-wrapping/ComponentDemoTEMP.svelte +305 -0
- package/dist/package-wrapping/ComponentDemoTEMP.svelte.d.ts +21 -0
- package/dist/package-wrapping/ComponentDetails.svelte +123 -0
- package/dist/package-wrapping/ComponentDetails.svelte.d.ts +13 -0
- package/dist/package-wrapping/DividerLine.svelte +21 -0
- package/dist/package-wrapping/DividerLine.svelte.d.ts +17 -0
- package/dist/package-wrapping/InputForParameter.svelte +205 -0
- package/dist/package-wrapping/InputForParameter.svelte.d.ts +13 -0
- package/dist/package-wrapping/InputForParameterUpdated.svelte +222 -0
- package/dist/package-wrapping/InputForParameterUpdated.svelte.d.ts +17 -0
- package/dist/package-wrapping/InputForParameterUpdatedTEMP.svelte +203 -0
- package/dist/package-wrapping/InputForParameterUpdatedTEMP.svelte.d.ts +17 -0
- package/dist/package-wrapping/ListOfComponentStatuses.svelte +19 -0
- package/dist/package-wrapping/ListOfComponentStatuses.svelte.d.ts +11 -0
- package/dist/package-wrapping/OverlayAndComponentContainer.svelte +426 -0
- package/dist/package-wrapping/OverlayAndComponentContainer.svelte.d.ts +33 -0
- package/dist/package-wrapping/ParametersSection.svelte +235 -0
- package/dist/package-wrapping/ParametersSection.svelte.d.ts +19 -0
- package/dist/package-wrapping/ParsingErrorToastsContainer.svelte +50 -0
- package/dist/package-wrapping/ParsingErrorToastsContainer.svelte.d.ts +15 -0
- package/dist/package-wrapping/Pill.svelte +54 -0
- package/dist/package-wrapping/Pill.svelte.d.ts +25 -0
- package/dist/package-wrapping/PlaygroundDetails.svelte +106 -0
- package/dist/package-wrapping/PlaygroundDetails.svelte.d.ts +13 -0
- package/dist/package-wrapping/ScreenSizeRadio.svelte +24 -0
- package/dist/package-wrapping/ScreenSizeRadio.svelte.d.ts +11 -0
- package/dist/package-wrapping/ScreenSizeRadioUpdated.svelte +23 -0
- package/dist/package-wrapping/ScreenSizeRadioUpdated.svelte.d.ts +11 -0
- package/dist/package-wrapping/SidebarContainer.svelte +103 -0
- package/dist/package-wrapping/SidebarContainer.svelte.d.ts +23 -0
- package/dist/package-wrapping/WrapperDetailsUpdate.svelte +40 -0
- package/dist/package-wrapping/WrapperDetailsUpdate.svelte.d.ts +15 -0
- package/dist/package-wrapping/templates/Template.svelte +100 -0
- package/dist/package-wrapping/templates/Template.svelte.d.ts +25 -0
- package/dist/templates/ComponentPageTemplate.svelte +1 -0
- package/dist/templates/ComponentPageTemplate.svelte.d.ts +26 -0
- package/dist/utils/data-transformations/convertCSV.d.ts +2 -0
- package/dist/utils/data-transformations/convertCSV.js +22 -0
- package/dist/utils/data-transformations/getValueFromParametersArray.d.ts +1 -0
- package/dist/utils/data-transformations/getValueFromParametersArray.js +9 -0
- package/dist/utils/layoutNavHelpers.d.ts +70 -0
- package/dist/utils/layoutNavHelpers.js +129 -0
- package/dist/utils/package-wrapping-specific/addIndexAndInitialValue.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/addIndexAndInitialValue.js +21 -0
- package/dist/utils/package-wrapping-specific/createBindableParametersValuesArray.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/createBindableParametersValuesArray.js +12 -0
- package/dist/utils/package-wrapping-specific/createParametersObject.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/createParametersObject.js +29 -0
- package/dist/utils/package-wrapping-specific/defineDefaultEventHandler.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/defineDefaultEventHandler.js +14 -0
- package/dist/utils/package-wrapping-specific/trackVisibleParameters.d.ts +1 -0
- package/dist/utils/package-wrapping-specific/trackVisibleParameters.js +29 -0
- package/dist/utils/syntax-highlighting/shikiHighlight.d.ts +7 -0
- package/dist/utils/syntax-highlighting/shikiHighlight.js +76 -0
- package/dist/utils/text-string-conversion/textStringConversion.d.ts +9 -0
- package/dist/utils/text-string-conversion/textStringConversion.js +86 -0
- package/package.json +113 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
export const serverFormExampleCode = `// ... see previous examples for FilterPanel setup ...
|
|
2
|
+
|
|
3
|
+
<script lang="ts">
|
|
4
|
+
import FilterPanel from './FilterPanel.svelte';
|
|
5
|
+
import type { Section, FilteredResult } from './types';
|
|
6
|
+
import Accordion from '../Accordion/Accordion.svelte';
|
|
7
|
+
import CodeBlock from '../CodeBlock/CodeBlock.svelte';
|
|
8
|
+
import { serverFormExampleCode } from './codeBlocks.js'; // Assuming this file is aliased
|
|
9
|
+
|
|
10
|
+
export let form: {
|
|
11
|
+
data?: FilteredResult[];
|
|
12
|
+
error?: string;
|
|
13
|
+
message?: string;
|
|
14
|
+
} | null = null;
|
|
15
|
+
|
|
16
|
+
const sectionsData: Section[] = [
|
|
17
|
+
{
|
|
18
|
+
type: "checkboxes" as "checkboxes",
|
|
19
|
+
title: "Select Metrics (Server)",
|
|
20
|
+
name: "metrics",
|
|
21
|
+
options: [
|
|
22
|
+
{ label: "Household waste recycling rates", value: "Household waste recycling rates" },
|
|
23
|
+
{ label: "Percentage of household waste sent to landfill", value: "Percentage of household waste sent to landfill" },
|
|
24
|
+
{ label: "Total fly-tipping incidents", value: "Total fly-tipping incidents" },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: "radio" as "radio",
|
|
29
|
+
title: "Select Year (Server)",
|
|
30
|
+
name: "year",
|
|
31
|
+
options: [
|
|
32
|
+
{ label: "2019/20", value: "2019/20" },
|
|
33
|
+
{ label: "2020/21", value: "2020/21" },
|
|
34
|
+
{ label: "2021/22", value: "2021/22" },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "select" as "select",
|
|
39
|
+
title: "Select Area Type (Server)",
|
|
40
|
+
name: "areaType",
|
|
41
|
+
options: [
|
|
42
|
+
{ label: "District", value: "District" },
|
|
43
|
+
{ label: "Unitary Authority", value: "Unitary Authority" },
|
|
44
|
+
{ label: "County Council", value: "County Council" },
|
|
45
|
+
{ label: "Region", value: "Region" },
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
];
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<Accordion single>
|
|
52
|
+
<div class="accordion-item py-4" data-title="Example 3: Server Form Submission">
|
|
53
|
+
<p class="text-sm text-surface-500 mb-4">
|
|
54
|
+
This example demonstrates a form that submits data to a server action.
|
|
55
|
+
The filtering logic is handled on the server-side in <code>+page.server.ts</code>.
|
|
56
|
+
The results are then returned and displayed.
|
|
57
|
+
</p>
|
|
58
|
+
<FilterPanel
|
|
59
|
+
formClasses="p-4 border rounded-lg"
|
|
60
|
+
fieldSetClasses="mb-4 p-2 border-t"
|
|
61
|
+
legendClasses="text-lg font-semibold"
|
|
62
|
+
showSubmitButton={true}
|
|
63
|
+
submitButtonText="Filter on Server"
|
|
64
|
+
target="?/serverFilter"
|
|
65
|
+
{sectionsData}
|
|
66
|
+
resultsHeaderText="Server Form Submission Results (Filtered in +page.server.ts)"
|
|
67
|
+
>
|
|
68
|
+
<svelte:fragment slot="results">
|
|
69
|
+
{#if form?.data}
|
|
70
|
+
<div class="mt-4 p-4 border rounded-lg bg-surface-100 dark:bg-surface-800">
|
|
71
|
+
<h3 class="text-xl font-semibold mb-2">Results</h3>
|
|
72
|
+
<p class="text-sm text-surface-600 dark:text-surface-300">
|
|
73
|
+
Displaying {form.data.length} results. Filtered by the server.
|
|
74
|
+
</p>
|
|
75
|
+
<div class="overflow-x-auto mt-2">
|
|
76
|
+
<table class="table table-compact w-full">
|
|
77
|
+
<thead>
|
|
78
|
+
<tr>
|
|
79
|
+
<th>Metric</th>
|
|
80
|
+
<th>Area</th>
|
|
81
|
+
<th>Years (X)</th>
|
|
82
|
+
<th>Values (Y)</th>
|
|
83
|
+
</tr>
|
|
84
|
+
</thead>
|
|
85
|
+
<tbody>
|
|
86
|
+
{#each form.data as result}
|
|
87
|
+
<tr>
|
|
88
|
+
<td>{result.metricName}</td>
|
|
89
|
+
<td>{result.areaName}</td>
|
|
90
|
+
<td>{result.data.map(d => d.x).join(', ')}</td>
|
|
91
|
+
<td>{result.data.map(d => d.y).join(', ')}</td>
|
|
92
|
+
</tr>
|
|
93
|
+
{/each}
|
|
94
|
+
</tbody>
|
|
95
|
+
</table>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
{:else if form?.error}
|
|
99
|
+
<div class="mt-4 p-4 border rounded-lg bg-error-100 dark:bg-error-800 text-error-700 dark:text-error-200">
|
|
100
|
+
<h3 class="text-xl font-semibold mb-2">Error</h3>
|
|
101
|
+
<p>{form.error}</p>
|
|
102
|
+
</div>
|
|
103
|
+
{:else if form?.message}
|
|
104
|
+
<div class="mt-4 p-4 border rounded-lg bg-warning-100 dark:bg-warning-800 text-warning-700 dark:text-warning-200">
|
|
105
|
+
<h3 class="text-xl font-semibold mb-2">Info</h3>
|
|
106
|
+
<p>{form.message}</p>
|
|
107
|
+
</div>
|
|
108
|
+
{/if}
|
|
109
|
+
</svelte:fragment>
|
|
110
|
+
</FilterPanel>
|
|
111
|
+
<h4 class="text-lg font-semibold mt-6 mb-2">Code:</h4>
|
|
112
|
+
<CodeBlock language="svelte" code={serverFormExampleCode} />
|
|
113
|
+
</div>
|
|
114
|
+
</Accordion>
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
export const enhancedFormExampleCode = `// ... see previous examples for FilterPanel setup ...
|
|
118
|
+
|
|
119
|
+
<script lang="ts">
|
|
120
|
+
import FilterPanel from './FilterPanel.svelte';
|
|
121
|
+
import type { Section, FilterPanelData, FilteredResult } from './types';
|
|
122
|
+
import Accordion from '../Accordion/Accordion.svelte';
|
|
123
|
+
import CodeBlock from '../CodeBlock/CodeBlock.svelte';
|
|
124
|
+
import { enhancedFormExampleCode } from './codeBlocks.js';
|
|
125
|
+
import { page } from '$app/state';
|
|
126
|
+
import { enhance } from '$app/forms';
|
|
127
|
+
|
|
128
|
+
// Reactive state for results
|
|
129
|
+
let clientFilteredResults: FilteredResult[] = $state([]);
|
|
130
|
+
let formMessage: string | undefined = $state(undefined);
|
|
131
|
+
let formError: string | undefined = $state(undefined);
|
|
132
|
+
|
|
133
|
+
// Data for the line chart from +page.ts load function
|
|
134
|
+
const allDataForChart: FilteredResult[] = $page.data.dataInFormatForLineChart || [];
|
|
135
|
+
|
|
136
|
+
const sectionsData: Section[] = [
|
|
137
|
+
// ... same sectionsData as client-side filtering example ...
|
|
138
|
+
{
|
|
139
|
+
type: "checkboxes" as "checkboxes",
|
|
140
|
+
title: "Select Metrics (Client - Enhanced)",
|
|
141
|
+
name: "metrics",
|
|
142
|
+
options: [
|
|
143
|
+
{ label: "Household waste recycling rates", value: "Household waste recycling rates" },
|
|
144
|
+
{ label: "Percentage of household waste sent to landfill", value: "Percentage of household waste sent to landfill" },
|
|
145
|
+
{ label: "Total fly-tipping incidents", value: "Total fly-tipping incidents" },
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
type: "radio" as "radio",
|
|
150
|
+
title: "Select Year (Client - Enhanced)",
|
|
151
|
+
name: "year",
|
|
152
|
+
options: [
|
|
153
|
+
{ label: "2019/20", value: "2019/20" },
|
|
154
|
+
{ label: "2020/21", value: "2020/21" },
|
|
155
|
+
{ label: "2021/22", value: "2021/22" },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
type: "select" as "select",
|
|
160
|
+
title: "Select Area Type (Client - Enhanced)",
|
|
161
|
+
name: "areaType",
|
|
162
|
+
options: [
|
|
163
|
+
{ label: "District", value: "District" },
|
|
164
|
+
{ label: "Unitary Authority", value: "Unitary Authority" },
|
|
165
|
+
{ label: "County Council", value: "County Council" },
|
|
166
|
+
{ label: "Region", value: "Region" },
|
|
167
|
+
],
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
function filterData(allChartData: FilteredResult[], formData: FilterPanelData): FilteredResult[] {
|
|
172
|
+
const selectedMetrics = formData.metrics as string[] | string | undefined;
|
|
173
|
+
const selectedYear = formData.year as string | undefined;
|
|
174
|
+
const selectedAreaType = formData.areaType as string | undefined;
|
|
175
|
+
|
|
176
|
+
let results = allChartData;
|
|
177
|
+
|
|
178
|
+
if (selectedMetrics && selectedMetrics.length > 0) {
|
|
179
|
+
const metricsArray = Array.isArray(selectedMetrics) ? selectedMetrics : [selectedMetrics];
|
|
180
|
+
results = results.filter(item => metricsArray.includes(item.metricName));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (selectedAreaType) {
|
|
184
|
+
results = results.filter(item => item.areaType === selectedAreaType);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (selectedYear) {
|
|
188
|
+
results = results.map(metricEntry => {
|
|
189
|
+
const filteredDataPoints = metricEntry.data.filter(dp => dp.x === selectedYear);
|
|
190
|
+
return { ...metricEntry, data: filteredDataPoints };
|
|
191
|
+
}).filter(metricEntry => metricEntry.data.length > 0);
|
|
192
|
+
}
|
|
193
|
+
return results;
|
|
194
|
+
}
|
|
195
|
+
</script>
|
|
196
|
+
|
|
197
|
+
<Accordion single>
|
|
198
|
+
<div class="accordion-item py-4" data-title="Example 4: Progressive Enhancement (Client-Side Filtering from Server Action)">
|
|
199
|
+
<p class="text-sm text-surface-500 mb-4">
|
|
200
|
+
This example uses <code>use:enhance</code> for progressive enhancement. The form submits to a server action
|
|
201
|
+
(<code>?/enhancedFilter</code>), which currently just echoes back the form data.
|
|
202
|
+
The client-side JavaScript then takes this echoed data and performs filtering using
|
|
203
|
+
the same <code>allDataForChart</code> data source as the pure client-side example.
|
|
204
|
+
This demonstrates handling server responses and updating the UI on the client.
|
|
205
|
+
</p>
|
|
206
|
+
<form
|
|
207
|
+
method="POST"
|
|
208
|
+
action="?/enhancedFilter"
|
|
209
|
+
use:enhance={({ form, data, action, cancel, submitter }) => {
|
|
210
|
+
return async ({ result, update }) => {
|
|
211
|
+
formMessage = undefined;
|
|
212
|
+
formError = undefined;
|
|
213
|
+
clientFilteredResults = [];
|
|
214
|
+
|
|
215
|
+
if (result.type === 'success' && result.data?.formData) {
|
|
216
|
+
const rawFormData = result.data.formData as Record<string, FormDataEntryValue>;
|
|
217
|
+
const processedFormData: FilterPanelData = {};
|
|
218
|
+
for (const key in rawFormData) {
|
|
219
|
+
// Handling array values for checkboxes
|
|
220
|
+
if (data.getAll(key).length > 1) {
|
|
221
|
+
processedFormData[key] = data.getAll(key).map(val => val.toString());
|
|
222
|
+
} else {
|
|
223
|
+
processedFormData[key] = rawFormData[key]?.toString();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
clientFilteredResults = filterData(allDataForChart, processedFormData);
|
|
227
|
+
if (clientFilteredResults.length === 0) {
|
|
228
|
+
formMessage = "No results found for your selection (client-filtered).";
|
|
229
|
+
}
|
|
230
|
+
} else if (result.type === 'failure') {
|
|
231
|
+
formError = result.data?.message || 'Filtering failed on the server.';
|
|
232
|
+
} else if (result.type === 'error') {
|
|
233
|
+
formError = result.error?.message || 'An unexpected error occurred.';
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}}
|
|
237
|
+
>
|
|
238
|
+
<FilterPanel
|
|
239
|
+
formClasses="p-4 border rounded-lg"
|
|
240
|
+
fieldSetClasses="mb-4 p-2 border-t"
|
|
241
|
+
legendClasses="text-lg font-semibold"
|
|
242
|
+
showSubmitButton={true}
|
|
243
|
+
submitButtonText="Filter with Enhancement"
|
|
244
|
+
{sectionsData}
|
|
245
|
+
resultsHeaderText="Client-Filtered Results (from Enhanced Server Action)"
|
|
246
|
+
>
|
|
247
|
+
<svelte:fragment slot="results">
|
|
248
|
+
{#if clientFilteredResults.length > 0}
|
|
249
|
+
<div class="mt-4 p-4 border rounded-lg bg-surface-100 dark:bg-surface-800">
|
|
250
|
+
<h3 class="text-xl font-semibold mb-2">Results</h3>
|
|
251
|
+
<p class="text-sm text-surface-600 dark:text-surface-300">
|
|
252
|
+
Displaying {clientFilteredResults.length} results. Filtered by client after server echo.
|
|
253
|
+
</p>
|
|
254
|
+
<div class="overflow-x-auto mt-2">
|
|
255
|
+
<table class="table table-compact w-full">
|
|
256
|
+
<thead>
|
|
257
|
+
<tr>
|
|
258
|
+
<th>Metric</th>
|
|
259
|
+
<th>Area</th>
|
|
260
|
+
<th>Years (X)</th>
|
|
261
|
+
<th>Values (Y)</th>
|
|
262
|
+
</tr>
|
|
263
|
+
</thead>
|
|
264
|
+
<tbody>
|
|
265
|
+
{#each clientFilteredResults as result}
|
|
266
|
+
<tr>
|
|
267
|
+
<td>{result.metricName}</td>
|
|
268
|
+
<td>{result.areaName}</td>
|
|
269
|
+
<td>{result.data.map(d => d.x).join(', ')}</td>
|
|
270
|
+
<td>{result.data.map(d => d.y).join(', ')}</td>
|
|
271
|
+
</tr>
|
|
272
|
+
{/each}
|
|
273
|
+
</tbody>
|
|
274
|
+
</table>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
{:else if formError}
|
|
278
|
+
<div class="mt-4 p-4 border rounded-lg bg-error-100 dark:bg-error-800 text-error-700 dark:text-error-200">
|
|
279
|
+
<h3 class="text-xl font-semibold mb-2">Error</h3>
|
|
280
|
+
<p>{formError}</p>
|
|
281
|
+
</div>
|
|
282
|
+
{:else if formMessage}
|
|
283
|
+
<div class="mt-4 p-4 border rounded-lg bg-warning-100 dark:bg-warning-800 text-warning-700 dark:text-warning-200">
|
|
284
|
+
<h3 class="text-xl font-semibold mb-2">Info</h3>
|
|
285
|
+
<p>{formMessage}</p>
|
|
286
|
+
</div>
|
|
287
|
+
{/if}
|
|
288
|
+
</svelte:fragment>
|
|
289
|
+
</FilterPanel>
|
|
290
|
+
</form>
|
|
291
|
+
<h4 class="text-lg font-semibold mt-6 mb-2">Code:</h4>
|
|
292
|
+
<CodeBlock language="svelte" code={enhancedFormExampleCode} />
|
|
293
|
+
</div>
|
|
294
|
+
</Accordion>
|
|
295
|
+
`;
|
|
296
|
+
|
|
297
|
+
export const serverFormWithBasicEnhanceExampleCode = `// Basic progressive enhancement with use:enhance
|
|
298
|
+
// This form submits to the same '/serverFilter' action as Example 3.
|
|
299
|
+
// SvelteKit will automatically handle the form submission via fetch,
|
|
300
|
+
// update the 'form' prop, and invalidate data if the action is successful.
|
|
301
|
+
|
|
302
|
+
<script lang="ts">
|
|
303
|
+
import FilterPanel from './FilterPanel.svelte';
|
|
304
|
+
import type { Section, FilteredResult } from './types';
|
|
305
|
+
import Accordion from '../Accordion/Accordion.svelte';
|
|
306
|
+
import CodeBlock from '../CodeBlock/CodeBlock.svelte';
|
|
307
|
+
import { serverFormWithBasicEnhanceExampleCode } from './codeBlocks.js';
|
|
308
|
+
import { enhance } from '$app/forms'; // Import enhance
|
|
309
|
+
|
|
310
|
+
// 'form' prop will be populated by SvelteKit after action completes
|
|
311
|
+
export let form: {
|
|
312
|
+
data?: FilteredResult[];
|
|
313
|
+
error?: string;
|
|
314
|
+
message?: string;
|
|
315
|
+
} | null = null;
|
|
316
|
+
|
|
317
|
+
const sectionsData: Section[] = [
|
|
318
|
+
{
|
|
319
|
+
type: "checkboxes" as "checkboxes",
|
|
320
|
+
title: "Select Metrics (Server - Basic Enhance)",
|
|
321
|
+
name: "metrics",
|
|
322
|
+
options: [
|
|
323
|
+
{ label: "Household waste recycling rates", value: "Household waste recycling rates" },
|
|
324
|
+
{ label: "Percentage of household waste sent to landfill", value: "Percentage of household waste sent to landfill" },
|
|
325
|
+
{ label: "Total fly-tipping incidents", value: "Total fly-tipping incidents" },
|
|
326
|
+
],
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
type: "radio" as "radio",
|
|
330
|
+
title: "Select Year (Server - Basic Enhance)",
|
|
331
|
+
name: "year",
|
|
332
|
+
options: [
|
|
333
|
+
{ label: "2019/20", value: "2019/20" },
|
|
334
|
+
{ label: "2020/21", value: "2020/21" },
|
|
335
|
+
{ label: "2021/22", value: "2021/22" },
|
|
336
|
+
],
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
type: "select" as "select",
|
|
340
|
+
title: "Select Area Type (Server - Basic Enhance)",
|
|
341
|
+
name: "areaType",
|
|
342
|
+
options: [
|
|
343
|
+
{ label: "District", value: "District" },
|
|
344
|
+
{ label: "Unitary Authority", value: "Unitary Authority" },
|
|
345
|
+
{ label: "County Council", value: "County Council" },
|
|
346
|
+
{ label: "Region", value: "Region" },
|
|
347
|
+
],
|
|
348
|
+
}
|
|
349
|
+
];
|
|
350
|
+
</script>
|
|
351
|
+
|
|
352
|
+
<Accordion single>
|
|
353
|
+
<div class="accordion-item py-4" data-title="Example 5: Server Form with Basic Progressive Enhancement">
|
|
354
|
+
<p class="text-sm text-surface-500 mb-4">
|
|
355
|
+
This example is identical to Example 3 (Server Form Submission) but adds <code>use:enhance</code>
|
|
356
|
+
to the form tag. SvelteKit handles the form submission client-side by default,
|
|
357
|
+
updating the <code>form</code> prop automatically upon completion of the server action.
|
|
358
|
+
No custom client-side filtering or result handling is needed beyond what SvelteKit provides.
|
|
359
|
+
</p>
|
|
360
|
+
<form method="POST" action="?/serverFilter" use:enhance> {/* Added use:enhance here */}
|
|
361
|
+
<FilterPanel
|
|
362
|
+
formClasses="p-4 border rounded-lg"
|
|
363
|
+
fieldSetClasses="mb-4 p-2 border-t"
|
|
364
|
+
legendClasses="text-lg font-semibold"
|
|
365
|
+
showSubmitButton={true}
|
|
366
|
+
submitButtonText="Filter (Basic Enhance)"
|
|
367
|
+
{sectionsData} /* No target needed as form action is used */
|
|
368
|
+
resultsHeaderText="Server Form Results (via Basic Enhance)"
|
|
369
|
+
>
|
|
370
|
+
<svelte:fragment slot="results">
|
|
371
|
+
{#if form?.data}
|
|
372
|
+
<div class="mt-4 p-4 border rounded-lg bg-surface-100 dark:bg-surface-800">
|
|
373
|
+
<h3 class="text-xl font-semibold mb-2">Results</h3>
|
|
374
|
+
<p class="text-sm text-surface-600 dark:text-surface-300">
|
|
375
|
+
Displaying {form.data.length} results. Filtered by server, handled by <code>use:enhance</code>.
|
|
376
|
+
</p>
|
|
377
|
+
<div class="overflow-x-auto mt-2">
|
|
378
|
+
<table class="table table-compact w-full">
|
|
379
|
+
<thead>
|
|
380
|
+
<tr>
|
|
381
|
+
<th>Metric</th>
|
|
382
|
+
<th>Area</th>
|
|
383
|
+
<th>Years (X)</th>
|
|
384
|
+
<th>Values (Y)</th>
|
|
385
|
+
</tr>
|
|
386
|
+
</thead>
|
|
387
|
+
<tbody>
|
|
388
|
+
{#each form.data as result}
|
|
389
|
+
<tr>
|
|
390
|
+
<td>{result.metricName}</td>
|
|
391
|
+
<td>{result.areaName}</td>
|
|
392
|
+
<td>{result.data.map(d => d.x).join(', ')}</td>
|
|
393
|
+
<td>{result.data.map(d => d.y).join(', ')}</td>
|
|
394
|
+
</tr>
|
|
395
|
+
{/each}
|
|
396
|
+
</tbody>
|
|
397
|
+
</table>
|
|
398
|
+
</div>
|
|
399
|
+
</div>
|
|
400
|
+
{:else if form?.error}
|
|
401
|
+
<div class="mt-4 p-4 border rounded-lg bg-error-100 dark:bg-error-800 text-error-700 dark:text-error-200">
|
|
402
|
+
<h3 class="text-xl font-semibold mb-2">Error</h3>
|
|
403
|
+
<p>{form.error}</p>
|
|
404
|
+
</div>
|
|
405
|
+
{:else if form?.message}
|
|
406
|
+
<div class="mt-4 p-4 border rounded-lg bg-warning-100 dark:bg-warning-800 text-warning-700 dark:text-warning-200">
|
|
407
|
+
<h3 class="text-xl font-semibold mb-2">Info</h3>
|
|
408
|
+
<p>{form.message}</p>
|
|
409
|
+
</div>
|
|
410
|
+
{/if}
|
|
411
|
+
</svelte:fragment>
|
|
412
|
+
</FilterPanel>
|
|
413
|
+
</form>
|
|
414
|
+
<h4 class="text-lg font-semibold mt-6 mb-2">Code:</h4>
|
|
415
|
+
<CodeBlock language="svelte" code={serverFormWithBasicEnhanceExampleCode} />
|
|
416
|
+
</div>
|
|
417
|
+
</Accordion>
|
|
418
|
+
`;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
// Define component props with types and default values
|
|
5
|
+
let {
|
|
6
|
+
content = "It can take up to 8 weeks to register a lasting power of attorney if there are no mistakes in the application.",
|
|
7
|
+
} = $props<{
|
|
8
|
+
content?: string | Snippet;
|
|
9
|
+
}>();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div class="govuk-inset-text">
|
|
13
|
+
{#if typeof content === "string"}
|
|
14
|
+
{content}
|
|
15
|
+
{:else if content}
|
|
16
|
+
{@render content()}
|
|
17
|
+
{/if}
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
|
|
4
|
+
// Define component props with types and default values
|
|
5
|
+
let {
|
|
6
|
+
assistiveText = "Warning",
|
|
7
|
+
text = "You can be fined up to £5,000 if you do not register.",
|
|
8
|
+
} = $props<{
|
|
9
|
+
assistiveText?: string;
|
|
10
|
+
text?: string | Snippet;
|
|
11
|
+
}>();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div class="govuk-warning-text">
|
|
15
|
+
<span class="govuk-warning-text__icon" aria-hidden="true">!</span>
|
|
16
|
+
<strong class="govuk-warning-text__text">
|
|
17
|
+
<span class="govuk-visually-hidden">{assistiveText}</span>
|
|
18
|
+
{#if typeof text === "string"}
|
|
19
|
+
{text}
|
|
20
|
+
{:else if text}
|
|
21
|
+
{@render text()}
|
|
22
|
+
{/if}
|
|
23
|
+
</strong>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<style>
|
|
27
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
assistiveText?: string;
|
|
4
|
+
text?: string | Snippet;
|
|
5
|
+
};
|
|
6
|
+
declare const WarningText: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
7
|
+
type WarningText = ReturnType<typeof WarningText>;
|
|
8
|
+
export default WarningText;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { FolderArrowRightSolid } from "flowbite-svelte-icons";
|
|
3
|
+
import Ticks from "./Ticks.svelte";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
chartHeight,
|
|
7
|
+
chartWidth,
|
|
8
|
+
numberOfTicks,
|
|
9
|
+
ticksArray = $bindable(),
|
|
10
|
+
axisFunction,
|
|
11
|
+
values,
|
|
12
|
+
orientation,
|
|
13
|
+
prefix,
|
|
14
|
+
suffix,
|
|
15
|
+
floor,
|
|
16
|
+
ceiling,
|
|
17
|
+
yearsInput,
|
|
18
|
+
} = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<g
|
|
22
|
+
data-role="{orientation.axis}-axis"
|
|
23
|
+
transform="translate({orientation.position != 'right'
|
|
24
|
+
? 0
|
|
25
|
+
: chartWidth},{orientation.position === 'bottom' ? chartHeight : 0})"
|
|
26
|
+
>
|
|
27
|
+
<line
|
|
28
|
+
x1="0"
|
|
29
|
+
y1="0"
|
|
30
|
+
x2={orientation.axis === "x" ? chartWidth : 0}
|
|
31
|
+
y2={orientation.axis === "y" ? chartHeight : 0}
|
|
32
|
+
stroke="black"
|
|
33
|
+
stroke-width="2px"
|
|
34
|
+
></line>
|
|
35
|
+
{#key numberOfTicks}
|
|
36
|
+
<Ticks
|
|
37
|
+
bind:ticksArray
|
|
38
|
+
{chartWidth}
|
|
39
|
+
{chartHeight}
|
|
40
|
+
{axisFunction}
|
|
41
|
+
{values}
|
|
42
|
+
{numberOfTicks}
|
|
43
|
+
{orientation}
|
|
44
|
+
{floor}
|
|
45
|
+
{ceiling}
|
|
46
|
+
{yearsInput}
|
|
47
|
+
{suffix}
|
|
48
|
+
{prefix}
|
|
49
|
+
></Ticks>
|
|
50
|
+
{/key}
|
|
51
|
+
</g>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default Axis;
|
|
2
|
+
type Axis = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const Axis: import("svelte").Component<{
|
|
7
|
+
chartHeight: any;
|
|
8
|
+
chartWidth: any;
|
|
9
|
+
numberOfTicks: any;
|
|
10
|
+
ticksArray?: any;
|
|
11
|
+
axisFunction: any;
|
|
12
|
+
values: any;
|
|
13
|
+
orientation: any;
|
|
14
|
+
prefix: any;
|
|
15
|
+
suffix: any;
|
|
16
|
+
floor: any;
|
|
17
|
+
ceiling: any;
|
|
18
|
+
yearsInput: any;
|
|
19
|
+
}, {}, "ticksArray">;
|
|
20
|
+
type $$ComponentProps = {
|
|
21
|
+
chartHeight: any;
|
|
22
|
+
chartWidth: any;
|
|
23
|
+
numberOfTicks: any;
|
|
24
|
+
ticksArray?: any;
|
|
25
|
+
axisFunction: any;
|
|
26
|
+
values: any;
|
|
27
|
+
orientation: any;
|
|
28
|
+
prefix: any;
|
|
29
|
+
suffix: any;
|
|
30
|
+
floor: any;
|
|
31
|
+
ceiling: any;
|
|
32
|
+
yearsInput: any;
|
|
33
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import Decimal from "decimal.js";
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
ticksArray = $bindable(),
|
|
6
|
+
prefix,
|
|
7
|
+
suffix,
|
|
8
|
+
chartWidth,
|
|
9
|
+
chartHeight,
|
|
10
|
+
axisFunction,
|
|
11
|
+
values,
|
|
12
|
+
numberOfTicks,
|
|
13
|
+
floor,
|
|
14
|
+
ceiling,
|
|
15
|
+
orientation,
|
|
16
|
+
yearsInput,
|
|
17
|
+
} = $props();
|
|
18
|
+
|
|
19
|
+
$inspect(ticksArray);
|
|
20
|
+
|
|
21
|
+
function generateTicks(data, numTicks, floor, ceiling) {
|
|
22
|
+
let minValueFromData = Decimal.min(...data);
|
|
23
|
+
|
|
24
|
+
let minVal = floor
|
|
25
|
+
? Decimal.max(floor, minValueFromData)
|
|
26
|
+
: minValueFromData;
|
|
27
|
+
|
|
28
|
+
let maxValueFromData = Decimal.max(...data);
|
|
29
|
+
|
|
30
|
+
let maxVal = ceiling
|
|
31
|
+
? Decimal.min(ceiling, maxValueFromData)
|
|
32
|
+
: maxValueFromData;
|
|
33
|
+
|
|
34
|
+
let rangeVal = maxVal.minus(minVal);
|
|
35
|
+
|
|
36
|
+
let roughStep = rangeVal.div(numTicks - 1);
|
|
37
|
+
let normalizedSteps = [1, 2, 5, 10];
|
|
38
|
+
|
|
39
|
+
let stepPower = Decimal.pow(
|
|
40
|
+
10,
|
|
41
|
+
-Math.floor(Math.log10(roughStep.toNumber())),
|
|
42
|
+
);
|
|
43
|
+
let normalizedStep = roughStep.mul(stepPower);
|
|
44
|
+
let optimalStep = new Decimal(
|
|
45
|
+
normalizedSteps.find((step) => step >= normalizedStep.toNumber()),
|
|
46
|
+
).div(stepPower);
|
|
47
|
+
|
|
48
|
+
let scaleMin = minVal.div(optimalStep).floor().mul(optimalStep);
|
|
49
|
+
let scaleMax = maxVal.div(optimalStep).ceil().mul(optimalStep);
|
|
50
|
+
|
|
51
|
+
let ticks = [];
|
|
52
|
+
for (let i = scaleMin; i.lte(scaleMax); i = i.plus(optimalStep)) {
|
|
53
|
+
ticks.push(i.toNumber());
|
|
54
|
+
}
|
|
55
|
+
return ticks;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function tickCount(chartWidth, chartHeight) {
|
|
59
|
+
let tickNum = orientation.axis === "y" ? chartHeight / 50 : chartWidth / 50;
|
|
60
|
+
return tickNum;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function yearsFormat(ticks) {
|
|
64
|
+
return ticks.map((tick) => `FY ${tick % 100}-${(tick % 100) + 1}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
numberOfTicks = tickCount(chartWidth, chartHeight);
|
|
68
|
+
|
|
69
|
+
ticksArray = generateTicks(values, numberOfTicks, floor, ceiling);
|
|
70
|
+
let yearTicks = yearsInput ? yearsFormat(ticksArray) : [];
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
{#if axisFunction && ticksArray && orientation.axis && orientation.position}
|
|
74
|
+
{#each ticksArray as tick, index}
|
|
75
|
+
<g
|
|
76
|
+
transform="translate({orientation.axis === 'x'
|
|
77
|
+
? axisFunction(tick)
|
|
78
|
+
: 0},{orientation.axis === 'y' ? axisFunction(tick) : 0})"
|
|
79
|
+
>
|
|
80
|
+
<path
|
|
81
|
+
d={orientation.axis === "y"
|
|
82
|
+
? orientation.position === "left"
|
|
83
|
+
? "M0 0 l-8 0"
|
|
84
|
+
: "M0 0 l8 0"
|
|
85
|
+
: orientation.position === "top"
|
|
86
|
+
? "M0 0 l0 -8"
|
|
87
|
+
: "M0 0 l0 8"}
|
|
88
|
+
stroke="black"
|
|
89
|
+
stroke-width="2px"
|
|
90
|
+
></path>
|
|
91
|
+
<text
|
|
92
|
+
transform="translate({orientation.axis === 'x'
|
|
93
|
+
? 0
|
|
94
|
+
: orientation.position === 'left'
|
|
95
|
+
? -10
|
|
96
|
+
: 10}, {orientation.axis === 'y'
|
|
97
|
+
? 5
|
|
98
|
+
: orientation.position === 'top'
|
|
99
|
+
? -10
|
|
100
|
+
: 23})"
|
|
101
|
+
font-size="19"
|
|
102
|
+
text-anchor={orientation.axis === "x"
|
|
103
|
+
? "middle"
|
|
104
|
+
: orientation.position === "left"
|
|
105
|
+
? "end"
|
|
106
|
+
: "start"}
|
|
107
|
+
fill="black"
|
|
108
|
+
>
|
|
109
|
+
{yearsInput ? yearTicks[index] : prefix + tick + suffix}
|
|
110
|
+
</text>
|
|
111
|
+
</g>
|
|
112
|
+
{/each}
|
|
113
|
+
{/if}
|