@communitiesuk/svelte-component-library 0.1.19-beta.2 → 0.1.19-beta.20

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 (43) hide show
  1. package/README.md +7 -0
  2. package/dist/components/data-vis/Histogram.svelte +245 -0
  3. package/dist/components/data-vis/Histogram.svelte.d.ts +71 -0
  4. package/dist/components/data-vis/axis/Axis.svelte +140 -34
  5. package/dist/components/data-vis/axis/Axis.svelte.d.ts +34 -30
  6. package/dist/components/data-vis/axis/Ticks.svelte +155 -60
  7. package/dist/components/data-vis/axis/Ticks.svelte.d.ts +25 -30
  8. package/dist/components/data-vis/line-chart/LineChart.svelte +51 -21
  9. package/dist/components/data-vis/line-chart/LineChart.svelte.d.ts +14 -6
  10. package/dist/components/data-vis/position-chart/PositionChart.svelte +220 -112
  11. package/dist/components/data-vis/position-chart/PositionChart.svelte.d.ts +26 -4
  12. package/dist/components/data-vis/position-chart/PositionChartAxis.svelte +38 -34
  13. package/dist/components/data-vis/position-chart/PositionChartAxis.svelte.d.ts +6 -2
  14. package/dist/components/layout/Footer.svelte +9 -0
  15. package/dist/components/layout/Footer.svelte.d.ts +1 -0
  16. package/dist/components/layout/PhaseBanner.svelte +10 -1
  17. package/dist/components/layout/PhaseBanner.svelte.d.ts +1 -0
  18. package/dist/components/layout/ServiceNavigation.svelte +19 -1
  19. package/dist/components/layout/ServiceNavigation.svelte.d.ts +2 -0
  20. package/dist/components/ui/BasicMultiSelect.svelte +185 -0
  21. package/dist/components/ui/BasicMultiSelect.svelte.d.ts +8 -0
  22. package/dist/components/ui/Button.svelte +1 -0
  23. package/dist/components/ui/Card.svelte +48 -60
  24. package/dist/components/ui/Card.svelte.d.ts +26 -12
  25. package/dist/components/ui/CardHeader.svelte +46 -0
  26. package/dist/components/ui/CardHeader.svelte.d.ts +21 -0
  27. package/dist/components/ui/ChartExporter.svelte +142 -0
  28. package/dist/components/ui/ChartExporter.svelte.d.ts +16 -0
  29. package/dist/components/ui/Details.svelte +10 -2
  30. package/dist/components/ui/Details.svelte.d.ts +2 -0
  31. package/dist/components/ui/Masthead.svelte +36 -6
  32. package/dist/components/ui/Masthead.svelte.d.ts +4 -0
  33. package/dist/components/ui/PostcodeOrAreaSearch.svelte +12 -0
  34. package/dist/components/ui/PostcodeOrAreaSearch.svelte.d.ts +4 -0
  35. package/dist/components/ui/RelatedContent.svelte +4 -1
  36. package/dist/components/ui/RelatedContent.svelte.d.ts +1 -0
  37. package/dist/components/ui/SearchAutocomplete.svelte +185 -34
  38. package/dist/components/ui/SearchAutocomplete.svelte.d.ts +5 -0
  39. package/dist/components/ui/Tabs.svelte +190 -18
  40. package/dist/components/ui/Tabs.svelte.d.ts +1 -0
  41. package/dist/index.d.ts +4 -0
  42. package/dist/index.js +4 -0
  43. package/package.json +4 -1
package/README.md CHANGED
@@ -103,6 +103,13 @@ Make sure you are on your main development branch you want to release (e.g., `ma
103
103
 
104
104
  Use the `npm version` command to update `package.json` and `package-lock.json`, create a commit, and create an annotated Git tag. Choose **one** of the following based on [Semantic Versioning (SemVer)](https://semver.org/):
105
105
 
106
+
107
+ - **Pre-Release:**
108
+
109
+ ```bash
110
+ npm version prerelease --preid=alpha
111
+ ```
112
+
106
113
  - **Patch Release (Bug fixes, tiny changes - e.g., 1.0.0 → 1.0.1):**
107
114
 
108
115
  ```bash
@@ -0,0 +1,245 @@
1
+ <script>
2
+ import { scaleLinear } from "d3-scale";
3
+ import { bin, range as d3range } from "d3-array";
4
+ import Axis from "./axis/Axis.svelte";
5
+ import chroma from "chroma-js";
6
+
7
+ let {
8
+ averageValue = undefined,
9
+ distribution = [],
10
+ minX = 0,
11
+ maxX = 1,
12
+ minY = 0,
13
+ maxY = 100,
14
+ showXAxis = true,
15
+ showYAxis = true,
16
+ showArrows = true,
17
+ midColor = "#DDDDDD",
18
+ startColor = "#B70000",
19
+ endColor = "#2D6644",
20
+ floor = undefined,
21
+ ceiling = undefined,
22
+ fill = "grey",
23
+ nBins = 10,
24
+ padding = 0,
25
+ height = 50,
26
+ polarity = "standard",
27
+ annotationValue = 0,
28
+ annotationText = "",
29
+ labelFormatter = (tick, index, numberOfTicks, values) => {
30
+ return tick;
31
+ },
32
+ containerWidth = $bindable(100),
33
+ numberOfTicks,
34
+ customColorScale = undefined,
35
+ skew = true,
36
+ showGridlines = true,
37
+ showTickMarks = false,
38
+ tickStrokeWidth = 0.25,
39
+ barStrokeWidth = 0,
40
+ barStrokeColor = "white",
41
+ } = $props();
42
+
43
+ let xTicks = $state([]);
44
+ let yTicks = $state([]);
45
+
46
+ let xTickFirst = $derived(xTicks.length ? xTicks[0] : 0);
47
+ let xTickLast = $derived(xTicks.length ? xTicks.at(-1) : 1);
48
+
49
+ let domainXMin = $derived(Math.min(xTickFirst, xTickLast));
50
+ let domainXMax = $derived(Math.max(xTickFirst, xTickLast));
51
+
52
+ let yTickFirst = $derived(yTicks.length ? yTicks[0] : 0);
53
+ let yTickLast = $derived(yTicks.length ? yTicks.at(-1) : 1);
54
+
55
+ let domainYMin = $derived(Math.min(yTickFirst, yTickLast));
56
+ let domainYMax = $derived(Math.max(yTickFirst, yTickLast));
57
+
58
+ let useRange = $derived(
59
+ polarity === "standard"
60
+ ? [0, containerWidth - padding]
61
+ : [containerWidth - padding, 0],
62
+ );
63
+
64
+ let xScale = $derived(
65
+ scaleLinear().domain([domainXMin, domainXMax]).range(useRange),
66
+ );
67
+
68
+ const segmentScale = $derived(
69
+ scaleLinear().domain([0, nBins]).range([domainXMin, domainXMax]),
70
+ );
71
+
72
+ const binThresholds = $derived(d3range(1, nBins).map(segmentScale));
73
+
74
+ const binner = $derived(
75
+ bin().domain([domainXMin, domainXMax]).thresholds(binThresholds),
76
+ );
77
+
78
+ const bins = $derived(
79
+ polarity === "reverse"
80
+ ? binner(distribution).toReversed()
81
+ : binner(distribution),
82
+ );
83
+
84
+ const proportionsInBins = $derived(
85
+ bins.map((b) => b.length / distribution.length),
86
+ );
87
+
88
+ let proportionInExtremeBins = $derived([
89
+ proportionsInBins[0],
90
+ proportionsInBins.at(-1),
91
+ ]);
92
+
93
+ let yScale = $derived(
94
+ scaleLinear()
95
+ .domain([0, Math.max(...bins.map((b) => b.length))])
96
+ .range([0, height]),
97
+ );
98
+
99
+ function interpolateColors(
100
+ startColor,
101
+ endColor,
102
+ nSegments,
103
+ midColor = null,
104
+ skew,
105
+ ) {
106
+ const colorArray = [startColor, midColor, endColor].filter(Boolean);
107
+
108
+ if (!skew) {
109
+ return chroma.scale(colorArray).colors(nSegments);
110
+ } else {
111
+ const extremeColors = chroma
112
+ .scale([startColor, midColor, endColor])
113
+ .padding([
114
+ proportionInExtremeBins[0] / 2,
115
+ proportionInExtremeBins[1] / 2,
116
+ ])
117
+ .colors(2);
118
+
119
+ const averageNormalised =
120
+ (averageValue - xTickFirst) / (xTickLast - xTickFirst);
121
+
122
+ const binColors = chroma
123
+ .scale([extremeColors[0], midColor, extremeColors[1]])
124
+ .domain([
125
+ 0,
126
+ polarity === "reverse" ? 1 - averageNormalised : averageNormalised,
127
+ 1,
128
+ ])
129
+ .colors(10);
130
+
131
+ return binColors;
132
+ }
133
+ }
134
+
135
+ let colorScale = $derived(
136
+ customColorScale ??
137
+ interpolateColors(startColor, endColor, nBins, midColor, skew),
138
+ );
139
+
140
+ $inspect({ colorScale });
141
+ </script>
142
+
143
+ {#key containerWidth}
144
+ <div class="scale-container" bind:clientWidth={containerWidth}>
145
+ <svg
146
+ width={containerWidth}
147
+ height={height + 20 + (annotationText ? 25 : 0) + (showXAxis ? 25 : 0)}
148
+ style="overflow: visible;"
149
+ >
150
+ <g transform="translate({padding / 2},0)">
151
+ <g transform="translate(0,{annotationText ? 25 : 20})">
152
+ <text dx={-2} dy={-4} fill="#666" font-size="0.75em"
153
+ >Number of areas</text
154
+ ></g
155
+ >
156
+
157
+ {#if annotationText}
158
+ <g transform="translate({xScale(annotationValue)},0)">
159
+ <text
160
+ fill="#555555"
161
+ font-size="0.8em"
162
+ text-anchor="middle"
163
+ dominant-baseline="hanging"
164
+ >
165
+ <tspan x="0" dy="0">{annotationText}</tspan>
166
+ <tspan x="0" dy="12">▼</tspan>
167
+ </text>
168
+ </g>
169
+ {/if}
170
+
171
+ <g transform="translate(0,{annotationText ? 25 : 20})">
172
+ <g>
173
+ {#if showXAxis}
174
+ <Axis
175
+ bind:ticksArray={xTicks}
176
+ chartHeight={height}
177
+ chartWidth={containerWidth - padding}
178
+ orientation={{ axis: "x", position: "bottom" }}
179
+ domain={[xTickFirst, xTickLast]}
180
+ min={minX}
181
+ max={maxX}
182
+ range={useRange}
183
+ fontSize={13}
184
+ {floor}
185
+ {ceiling}
186
+ {labelFormatter}
187
+ {numberOfTicks}
188
+ ></Axis>
189
+ {/if}
190
+ {#if showYAxis}
191
+ <Axis
192
+ bind:ticksArray={yTicks}
193
+ chartHeight={height}
194
+ chartWidth={containerWidth - padding}
195
+ orientation={{ axis: "y", position: "left" }}
196
+ min={minY}
197
+ max={maxY}
198
+ domain={[0, yTickLast]}
199
+ range={[0, height]}
200
+ fontSize={0}
201
+ numberOfTicks={4}
202
+ {showGridlines}
203
+ {showTickMarks}
204
+ strokeWidth={tickStrokeWidth}
205
+ ></Axis>
206
+ {/if}
207
+ </g>
208
+ {#each bins as bin, i}
209
+ {#key bin.x0}
210
+ <rect
211
+ x={polarity === "reverse" ? xScale(bin.x1) : xScale(bin.x0)}
212
+ y={height - yScale(bin.length)}
213
+ width={Math.abs(xScale(bin.x1) - xScale(bin.x0))}
214
+ height={yScale(bin.length)}
215
+ fill={fill ?? colorScale[i]}
216
+ stroke-width={barStrokeWidth}
217
+ stroke={barStrokeColor}
218
+ ></rect>
219
+ {/key}
220
+ {/each}
221
+ </g>
222
+ </g>
223
+ </svg>
224
+ </div>
225
+ {/key}
226
+
227
+ <div style="content-visibility: hidden;">
228
+ {#if !showXAxis}
229
+ <Axis
230
+ bind:ticksArray={xTicks}
231
+ chartHeight={height}
232
+ chartWidth={containerWidth - padding}
233
+ orientation={{ axis: "x", position: "bottom" }}
234
+ domain={[xTickFirst, xTickLast]}
235
+ min={minX}
236
+ max={maxX}
237
+ range={useRange}
238
+ fontSize={13}
239
+ {floor}
240
+ {ceiling}
241
+ {labelFormatter}
242
+ {numberOfTicks}
243
+ ></Axis>
244
+ {/if}
245
+ </div>
@@ -0,0 +1,71 @@
1
+ export default Histogram;
2
+ type Histogram = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const Histogram: import("svelte").Component<{
7
+ averageValue?: any;
8
+ distribution?: any[];
9
+ minX?: number;
10
+ maxX?: number;
11
+ minY?: number;
12
+ maxY?: number;
13
+ showXAxis?: boolean;
14
+ showYAxis?: boolean;
15
+ showArrows?: boolean;
16
+ midColor?: string;
17
+ startColor?: string;
18
+ endColor?: string;
19
+ floor?: any;
20
+ ceiling?: any;
21
+ fill?: string;
22
+ nBins?: number;
23
+ padding?: number;
24
+ height?: number;
25
+ polarity?: string;
26
+ annotationValue?: number;
27
+ annotationText?: string;
28
+ labelFormatter?: Function;
29
+ containerWidth?: number;
30
+ numberOfTicks: any;
31
+ customColorScale?: any;
32
+ skew?: boolean;
33
+ showGridlines?: boolean;
34
+ showTickMarks?: boolean;
35
+ tickStrokeWidth?: number;
36
+ barStrokeWidth?: number;
37
+ barStrokeColor?: string;
38
+ }, {}, "containerWidth">;
39
+ type $$ComponentProps = {
40
+ averageValue?: any;
41
+ distribution?: any[];
42
+ minX?: number;
43
+ maxX?: number;
44
+ minY?: number;
45
+ maxY?: number;
46
+ showXAxis?: boolean;
47
+ showYAxis?: boolean;
48
+ showArrows?: boolean;
49
+ midColor?: string;
50
+ startColor?: string;
51
+ endColor?: string;
52
+ floor?: any;
53
+ ceiling?: any;
54
+ fill?: string;
55
+ nBins?: number;
56
+ padding?: number;
57
+ height?: number;
58
+ polarity?: string;
59
+ annotationValue?: number;
60
+ annotationText?: string;
61
+ labelFormatter?: Function;
62
+ containerWidth?: number;
63
+ numberOfTicks: any;
64
+ customColorScale?: any;
65
+ skew?: boolean;
66
+ showGridlines?: boolean;
67
+ showTickMarks?: boolean;
68
+ tickStrokeWidth?: number;
69
+ barStrokeWidth?: number;
70
+ barStrokeColor?: string;
71
+ };
@@ -1,51 +1,157 @@
1
- <script>
2
- import { FolderArrowRightSolid } from "flowbite-svelte-icons";
1
+ <script lang="ts">
2
+ import {
3
+ scaleLinear,
4
+ type ScaleContinuousNumeric,
5
+ type ScaleLinear,
6
+ } from "d3-scale";
3
7
  import Ticks from "./Ticks.svelte";
4
8
 
9
+ type AxisName = "x" | "y";
10
+ type AxisPosition = "bottom" | "top" | "left" | "right";
11
+ type Orientation = { axis: AxisName; position: AxisPosition };
12
+ type AxisProjector = (value: number) => number;
13
+ type LabelFormatter = (tick: number, index: number) => string | number;
14
+ type Polarity = "standard" | "reverse";
15
+
5
16
  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,
17
+ chartHeight = 100,
18
+ chartWidth = $bindable<number>(200),
19
+
20
+ numberOfTicks = undefined as number | undefined,
21
+
22
+ // Bindable, but avoid binding undefined – initialize as [] for safety
23
+ ticksArray = $bindable<number[]>([]),
24
+
25
+ // Values to derive ticks/domain from if ticksArray not provided
26
+ min = undefined as number | undefined,
27
+ max = undefined as number | undefined,
28
+
29
+ orientation = { axis: "x", position: "bottom" } as Orientation,
30
+
31
+ floor = undefined as number | undefined,
32
+ ceiling = undefined as number | undefined,
33
+
34
+ paddingTop = 100,
35
+ paddingBottom = 100,
36
+ paddingLeft = 0,
37
+ paddingRight = 0,
38
+
39
+ labelFormatter = undefined as LabelFormatter | undefined,
40
+
41
+ // --- New inputs for D3 scale + optional overrides ---
42
+ // A ready-made D3 continuous scale (linear/log/time, etc.)
43
+ // For this component we use numeric-only; time scales also implement numeric mapping.
44
+ scale = undefined as ScaleContinuousNumeric<number, number> | undefined,
45
+
46
+ // Optional overrides for domain/range applied to a COPY of the provided scale
47
+ domain = undefined as [number, number] | undefined,
48
+ range = undefined as [number, number] | undefined,
49
+ fontSize = 19,
50
+ polarity = "standard",
51
+ showGridlines = false,
52
+ showTickMarks = false,
53
+ strokeWidth = 2,
54
+ }: {
55
+ chartHeight?: number;
56
+ chartWidth?: number;
57
+ numberOfTicks?: number;
58
+ ticksArray?: number[];
59
+ min?: number;
60
+ max?: number;
61
+
62
+ orientation?: Orientation;
63
+ floor?: number;
64
+ ceiling?: number;
65
+ paddingTop?: number;
66
+ paddingBottom?: number;
67
+ paddingLeft?: number;
68
+ paddingRight?: number;
69
+ labelFormatter?: LabelFormatter;
70
+
71
+ // New
72
+ scale?: ScaleContinuousNumeric<number, number>;
73
+ domain?: [number, number];
74
+ range?: [number, number];
75
+ fontSize?: number;
76
+ polarity?: Polarity;
77
+ gridlines?: Boolean;
78
+ strokeWidth?: Number;
79
+ showGridlines?: Boolean;
80
+ showTickMarks?: Boolean;
18
81
  } = $props();
82
+
83
+ // --- Helpers to compute default domain/range when not supplied ---
84
+ const innerWidth = $derived(Math.max(0, chartWidth));
85
+ const innerHeight = $derived(Math.max(0, chartHeight));
86
+
87
+ function computeDefaultDomain(): [number, number] {
88
+ const arr =
89
+ (ticksArray && ticksArray.length ? ticksArray : [min, max]) ?? [];
90
+ const dMin =
91
+ floor ?? (arr.length ? arr.reduce((a, b) => (a < b ? a : b)) : 0);
92
+ const dMax =
93
+ ceiling ?? (arr.length ? arr.reduce((a, b) => (a > b ? a : b)) : 1);
94
+ return [dMin, dMax];
95
+ }
96
+
97
+ function computeDefaultRange(innerWidth, innerHeight): [number, number] {
98
+ if (orientation.axis === "x") {
99
+ return [0, innerWidth];
100
+ } else {
101
+ return [innerHeight, 0];
102
+ }
103
+ }
104
+ //Returns d3 scale function
105
+ const resolvedScale = $derived(() => {
106
+ const base: ScaleContinuousNumeric<number, number> = scale
107
+ ? scale.copy()
108
+ : scaleLinear<number, number>();
109
+
110
+ const useDomain = domain ?? computeDefaultDomain();
111
+ base.domain(useDomain);
112
+
113
+ const useRange = range ?? computeDefaultRange(innerWidth, innerHeight);
114
+ base.range(useRange);
115
+
116
+ return base;
117
+ });
118
+ const axisFunction: AxisProjector = $derived((v: number) => resolvedScale(v));
19
119
  </script>
20
120
 
21
121
  <g
22
122
  data-role="{orientation.axis}-axis"
23
- transform="translate({orientation.position != 'right'
123
+ transform="translate({orientation.position !== 'right'
24
124
  ? 0
25
125
  : chartWidth},{orientation.position === 'bottom' ? chartHeight : 0})"
26
126
  >
27
127
  <line
28
- x1="0"
128
+ x1={range[0]}
29
129
  y1="0"
30
- x2={orientation.axis === "x" ? chartWidth : 0}
130
+ x2={orientation.axis === "x" ? range[1] : 0}
31
131
  y2={orientation.axis === "y" ? chartHeight : 0}
32
- stroke="black"
132
+ stroke="grey"
33
133
  stroke-width="2px"
34
134
  ></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}
135
+ {#if ticksArray || (min && max)}
136
+ {#key numberOfTicks}
137
+ <Ticks
138
+ bind:ticksArray
139
+ {chartWidth}
140
+ {chartHeight}
141
+ {axisFunction}
142
+ {min}
143
+ {max}
144
+ {numberOfTicks}
145
+ {orientation}
146
+ {floor}
147
+ {ceiling}
148
+ {labelFormatter}
149
+ {fontSize}
150
+ {polarity}
151
+ {showGridlines}
152
+ {showTickMarks}
153
+ {strokeWidth}
154
+ />
155
+ {/key}
156
+ {/if}
51
157
  </g>
@@ -1,33 +1,37 @@
1
- export default Axis;
2
- type Axis = {
3
- $on?(type: string, callback: (e: any) => void): () => void;
4
- $set?(props: Partial<$$ComponentProps>): void;
1
+ import { type ScaleContinuousNumeric } from "d3-scale";
2
+ type AxisName = "x" | "y";
3
+ type AxisPosition = "bottom" | "top" | "left" | "right";
4
+ type Orientation = {
5
+ axis: AxisName;
6
+ position: AxisPosition;
5
7
  };
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">;
8
+ type LabelFormatter = (tick: number, index: number) => string | number;
9
+ type Polarity = "standard" | "reverse";
20
10
  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;
11
+ chartHeight?: number;
12
+ chartWidth?: number;
13
+ numberOfTicks?: number;
14
+ ticksArray?: number[];
15
+ min?: number;
16
+ max?: number;
17
+ orientation?: Orientation;
18
+ floor?: number;
19
+ ceiling?: number;
20
+ paddingTop?: number;
21
+ paddingBottom?: number;
22
+ paddingLeft?: number;
23
+ paddingRight?: number;
24
+ labelFormatter?: LabelFormatter;
25
+ scale?: ScaleContinuousNumeric<number, number>;
26
+ domain?: [number, number];
27
+ range?: [number, number];
28
+ fontSize?: number;
29
+ polarity?: Polarity;
30
+ gridlines?: Boolean;
31
+ strokeWidth?: Number;
32
+ showGridlines?: Boolean;
33
+ showTickMarks?: Boolean;
33
34
  };
35
+ declare const Axis: import("svelte").Component<$$ComponentProps, {}, "ticksArray" | "chartWidth">;
36
+ type Axis = ReturnType<typeof Axis>;
37
+ export default Axis;