@communitiesuk/svelte-component-library 0.1.19-beta.18 → 0.1.19-beta.19

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.
@@ -0,0 +1,241 @@
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
+ nBins = 10,
23
+ padding = 0,
24
+ height = 50,
25
+ polarity = "standard",
26
+ annotationValue = 0,
27
+ annotationText = "",
28
+ labelFormatter = (tick, index, numberOfTicks, values) => {
29
+ return tick;
30
+ },
31
+ containerWidth = $bindable(100),
32
+ numberOfTicks,
33
+ customColorScale = undefined,
34
+ skew = true,
35
+ showGridlines = true,
36
+ showTickMarks = false,
37
+ strokeWidth = 0.25,
38
+ } = $props();
39
+
40
+ let xTicks = $state([]);
41
+ let yTicks = $state([]);
42
+
43
+ let xTickFirst = $derived(xTicks.length ? xTicks[0] : 0);
44
+ let xTickLast = $derived(xTicks.length ? xTicks.at(-1) : 1);
45
+
46
+ let domainXMin = $derived(Math.min(xTickFirst, xTickLast));
47
+ let domainXMax = $derived(Math.max(xTickFirst, xTickLast));
48
+
49
+ let yTickFirst = $derived(yTicks.length ? yTicks[0] : 0);
50
+ let yTickLast = $derived(yTicks.length ? yTicks.at(-1) : 1);
51
+
52
+ let domainYMin = $derived(Math.min(yTickFirst, yTickLast));
53
+ let domainYMax = $derived(Math.max(yTickFirst, yTickLast));
54
+
55
+ let useRange = $derived(
56
+ polarity === "standard"
57
+ ? [0, containerWidth - padding]
58
+ : [containerWidth - padding, 0],
59
+ );
60
+
61
+ let xScale = $derived(
62
+ scaleLinear().domain([domainXMin, domainXMax]).range(useRange),
63
+ );
64
+
65
+ const segmentScale = $derived(
66
+ scaleLinear().domain([0, nBins]).range([domainXMin, domainXMax]),
67
+ );
68
+
69
+ const binThresholds = $derived(d3range(1, nBins).map(segmentScale));
70
+
71
+ const binner = $derived(
72
+ bin().domain([domainXMin, domainXMax]).thresholds(binThresholds),
73
+ );
74
+
75
+ const bins = $derived(
76
+ polarity === "reverse"
77
+ ? binner(distribution).toReversed()
78
+ : binner(distribution),
79
+ );
80
+
81
+ const proportionsInBins = $derived(
82
+ bins.map((b) => b.length / distribution.length),
83
+ );
84
+
85
+ let proportionInExtremeBins = $derived([
86
+ proportionsInBins[0],
87
+ proportionsInBins.at(-1),
88
+ ]);
89
+
90
+ let yScale = $derived(
91
+ scaleLinear()
92
+ .domain([0, Math.max(...bins.map((b) => b.length))])
93
+ .range([0, height]),
94
+ );
95
+
96
+ function interpolateColors(
97
+ startColor,
98
+ endColor,
99
+ nSegments,
100
+ midColor = null,
101
+ skew,
102
+ ) {
103
+ const colorArray = [startColor, midColor, endColor].filter(Boolean);
104
+
105
+ if (!skew) {
106
+ return chroma.scale(colorArray).colors(nSegments);
107
+ } else {
108
+ const extremeColors = chroma
109
+ .scale([startColor, midColor, endColor])
110
+ .padding([
111
+ proportionInExtremeBins[0] / 2,
112
+ proportionInExtremeBins[1] / 2,
113
+ ])
114
+ .colors(2);
115
+
116
+ const averageNormalised =
117
+ (averageValue - xTickFirst) / (xTickLast - xTickFirst);
118
+
119
+ const binColors = chroma
120
+ .scale([extremeColors[0], midColor, extremeColors[1]])
121
+ .domain([
122
+ 0,
123
+ polarity === "reverse" ? 1 - averageNormalised : averageNormalised,
124
+ 1,
125
+ ])
126
+ .colors(10);
127
+
128
+ return binColors;
129
+ }
130
+ }
131
+
132
+ let colorScale = $derived(
133
+ customColorScale ??
134
+ interpolateColors(startColor, endColor, nBins, midColor, skew),
135
+ );
136
+
137
+ $inspect({ colorScale });
138
+ </script>
139
+
140
+ {#key containerWidth}
141
+ <div class="scale-container" bind:clientWidth={containerWidth}>
142
+ <svg
143
+ width={containerWidth}
144
+ height={height + 20 + (annotationText ? 25 : 0) + (showXAxis ? 25 : 0)}
145
+ style="overflow: visible;"
146
+ >
147
+ <g transform="translate({padding / 2},0)">
148
+ <g transform="translate(0,{annotationText ? 25 : 20})">
149
+ <text dx={-2} dy={-4} fill="#666" font-size="0.75em"
150
+ >Number of areas</text
151
+ ></g
152
+ >
153
+
154
+ {#if annotationText}
155
+ <g transform="translate({xScale(annotationValue)},0)">
156
+ <text
157
+ fill="#555555"
158
+ font-size="0.8em"
159
+ text-anchor="middle"
160
+ dominant-baseline="hanging"
161
+ >
162
+ <tspan x="0" dy="0">{annotationText}</tspan>
163
+ <tspan x="0" dy="12">▼</tspan>
164
+ </text>
165
+ </g>
166
+ {/if}
167
+
168
+ <g transform="translate(0,{annotationText ? 25 : 20})">
169
+ <g>
170
+ {#if showXAxis}
171
+ <Axis
172
+ bind:ticksArray={xTicks}
173
+ chartHeight={height}
174
+ chartWidth={containerWidth - padding}
175
+ orientation={{ axis: "x", position: "bottom" }}
176
+ domain={[xTickFirst, xTickLast]}
177
+ min={minX}
178
+ max={maxX}
179
+ range={useRange}
180
+ fontSize={13}
181
+ {floor}
182
+ {ceiling}
183
+ {labelFormatter}
184
+ {numberOfTicks}
185
+ ></Axis>
186
+ {/if}
187
+ {#if showYAxis}
188
+ <Axis
189
+ bind:ticksArray={yTicks}
190
+ chartHeight={height}
191
+ chartWidth={containerWidth - padding}
192
+ orientation={{ axis: "y", position: "left" }}
193
+ min={minY}
194
+ max={maxY}
195
+ domain={[0, yTickLast]}
196
+ range={[0, height]}
197
+ fontSize={0}
198
+ numberOfTicks={4}
199
+ {showGridlines}
200
+ {showTickMarks}
201
+ strokeWidth={0.25}
202
+ ></Axis>
203
+ {/if}
204
+ </g>
205
+ {#each bins as bin, i}
206
+ {#key bin.x0}
207
+ <rect
208
+ x={polarity === "reverse" ? xScale(bin.x1) : xScale(bin.x0)}
209
+ y={height - yScale(bin.length)}
210
+ width={Math.abs(xScale(bin.x1) - xScale(bin.x0))}
211
+ height={yScale(bin.length)}
212
+ fill={colorScale[i]}
213
+ stroke-width={0}
214
+ ></rect>
215
+ {/key}
216
+ {/each}
217
+ </g>
218
+ </g>
219
+ </svg>
220
+ </div>
221
+ {/key}
222
+
223
+ <div style="content-visibility: hidden;">
224
+ {#if !showXAxis}
225
+ <Axis
226
+ bind:ticksArray={xTicks}
227
+ chartHeight={height}
228
+ chartWidth={containerWidth - padding}
229
+ orientation={{ axis: "x", position: "bottom" }}
230
+ domain={[xTickFirst, xTickLast]}
231
+ min={minX}
232
+ max={maxX}
233
+ range={useRange}
234
+ fontSize={13}
235
+ {floor}
236
+ {ceiling}
237
+ {labelFormatter}
238
+ {numberOfTicks}
239
+ ></Axis>
240
+ {/if}
241
+ </div>
@@ -0,0 +1,65 @@
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
+ nBins?: number;
22
+ padding?: number;
23
+ height?: number;
24
+ polarity?: string;
25
+ annotationValue?: number;
26
+ annotationText?: string;
27
+ labelFormatter?: Function;
28
+ containerWidth?: number;
29
+ numberOfTicks: any;
30
+ customColorScale?: any;
31
+ skew?: boolean;
32
+ showGridlines?: boolean;
33
+ showTickMarks?: boolean;
34
+ strokeWidth?: number;
35
+ }, {}, "containerWidth">;
36
+ type $$ComponentProps = {
37
+ averageValue?: any;
38
+ distribution?: any[];
39
+ minX?: number;
40
+ maxX?: number;
41
+ minY?: number;
42
+ maxY?: number;
43
+ showXAxis?: boolean;
44
+ showYAxis?: boolean;
45
+ showArrows?: boolean;
46
+ midColor?: string;
47
+ startColor?: string;
48
+ endColor?: string;
49
+ floor?: any;
50
+ ceiling?: any;
51
+ nBins?: number;
52
+ padding?: number;
53
+ height?: number;
54
+ polarity?: string;
55
+ annotationValue?: number;
56
+ annotationText?: string;
57
+ labelFormatter?: Function;
58
+ containerWidth?: number;
59
+ numberOfTicks: any;
60
+ customColorScale?: any;
61
+ skew?: boolean;
62
+ showGridlines?: boolean;
63
+ showTickMarks?: boolean;
64
+ strokeWidth?: number;
65
+ };
@@ -48,6 +48,9 @@
48
48
  range = undefined as [number, number] | undefined,
49
49
  fontSize = 19,
50
50
  polarity = "standard",
51
+ showGridlines = false,
52
+ showTickMarks = false,
53
+ strokeWidth = 2,
51
54
  }: {
52
55
  chartHeight?: number;
53
56
  chartWidth?: number;
@@ -71,6 +74,10 @@
71
74
  range?: [number, number];
72
75
  fontSize?: number;
73
76
  polarity?: Polarity;
77
+ gridlines?: Boolean;
78
+ strokeWidth?: Number;
79
+ showGridlines?: Boolean;
80
+ showTickMarks?: Boolean;
74
81
  } = $props();
75
82
 
76
83
  // --- Helpers to compute default domain/range when not supplied ---
@@ -141,6 +148,9 @@
141
148
  {labelFormatter}
142
149
  {fontSize}
143
150
  {polarity}
151
+ {showGridlines}
152
+ {showTickMarks}
153
+ {strokeWidth}
144
154
  />
145
155
  {/key}
146
156
  {/if}
@@ -27,6 +27,10 @@ type $$ComponentProps = {
27
27
  range?: [number, number];
28
28
  fontSize?: number;
29
29
  polarity?: Polarity;
30
+ gridlines?: Boolean;
31
+ strokeWidth?: Number;
32
+ showGridlines?: Boolean;
33
+ showTickMarks?: Boolean;
30
34
  };
31
35
  declare const Axis: import("svelte").Component<$$ComponentProps, {}, "ticksArray" | "chartWidth">;
32
36
  type Axis = ReturnType<typeof Axis>;
@@ -26,6 +26,10 @@
26
26
  labelFormatter,
27
27
  fontSize = 19,
28
28
  polarity = "standard",
29
+ showGridlines = false,
30
+ showTickMarks = false,
31
+
32
+ strokeWidth = 2,
29
33
  }: {
30
34
  ticksArray?: number[]; // bindable
31
35
  chartWidth: number;
@@ -40,6 +44,10 @@
40
44
  labelFormatter?: (tick: number, index: number) => string;
41
45
  fontSize?: number;
42
46
  polarity?: Polarity;
47
+ showGridlines?: Boolean;
48
+ showTickMarks?: Boolean;
49
+
50
+ strokeWidth?: number;
43
51
  } = $props();
44
52
  function axisValue(fn: any, tick: number): number {
45
53
  // Try single-call first: axisFunction(tick)
@@ -146,17 +154,32 @@
146
154
  {orientation.axis === 'y' ? axisValue(axisFunction, tick) : 0}
147
155
  )"
148
156
  >
149
- <path
150
- d={orientation.axis === "y"
151
- ? orientation.position === "left"
152
- ? "M0 -1 l-8 0"
153
- : "M0 -1 l8 0"
154
- : orientation.position === "top"
155
- ? "M0 -1 l0 -8"
156
- : "M0 -1 l0 8"}
157
- stroke="grey"
158
- stroke-width="2px"
159
- ></path>
157
+ {#if showTickMarks}
158
+ <path
159
+ d={orientation.axis === "y"
160
+ ? orientation.position === "left"
161
+ ? `M1 0 l-8 0`
162
+ : `M1 0 l8 0`
163
+ : orientation.position === "top"
164
+ ? "M0 -1 l0 -8"
165
+ : "M0 -1 l0 8"}
166
+ stroke="grey"
167
+ stroke-width={strokeWidth}
168
+ ></path>
169
+ {/if}
170
+ {#if showGridlines}
171
+ <path
172
+ d={orientation.axis === "y"
173
+ ? orientation.position === "left"
174
+ ? `M0 0 l${chartWidth} 0`
175
+ : `M0 0 l-${chartWidth} 0`
176
+ : orientation.position === "top"
177
+ ? `M0 0 l0 ${chartHeight}`
178
+ : `M0 0 l0 -${chartHeight}`}
179
+ stroke="grey"
180
+ stroke-width={strokeWidth}
181
+ ></path>
182
+ {/if}
160
183
  <text
161
184
  transform="translate(
162
185
  {orientation.axis === 'x'
@@ -19,6 +19,9 @@ type $$ComponentProps = {
19
19
  labelFormatter?: (tick: number, index: number) => string;
20
20
  fontSize?: number;
21
21
  polarity?: Polarity;
22
+ showGridlines?: Boolean;
23
+ showTickMarks?: Boolean;
24
+ strokeWidth?: number;
22
25
  };
23
26
  declare const Ticks: import("svelte").Component<$$ComponentProps, {}, "ticksArray">;
24
27
  type Ticks = ReturnType<typeof Ticks>;
@@ -91,12 +91,12 @@
91
91
  averageValue = undefined,
92
92
  polarity = "standard",
93
93
  skew = false,
94
+ showTickMarks = true,
95
+ showGridlines = false,
94
96
  } = $props();
95
97
 
96
98
  let xTicks = $state([]);
97
99
 
98
- $inspect({ xTicks });
99
-
100
100
  let xTickFirst = $derived(xTicks.length ? xTicks[0] : 0);
101
101
  let xTickLast = $derived(xTicks.length ? xTicks.at(-1) : 1);
102
102
 
@@ -470,6 +470,8 @@
470
470
  {ceiling}
471
471
  {numberOfTicks}
472
472
  {polarity}
473
+ {showTickMarks}
474
+ {showGridlines}
473
475
  ></Axis>
474
476
  {/if}
475
477
  {#if showAverage}
@@ -51,6 +51,8 @@ declare const PositionChart: import("svelte").Component<{
51
51
  averageValue?: any;
52
52
  polarity?: string;
53
53
  skew?: boolean;
54
+ showTickMarks?: boolean;
55
+ showGridlines?: boolean;
54
56
  }, {}, "chartWidth">;
55
57
  type $$ComponentProps = {
56
58
  value?: any;
@@ -100,4 +102,6 @@ type $$ComponentProps = {
100
102
  averageValue?: any;
101
103
  polarity?: string;
102
104
  skew?: boolean;
105
+ showTickMarks?: boolean;
106
+ showGridlines?: boolean;
103
107
  };
@@ -58,7 +58,7 @@
58
58
  .left-label,
59
59
  .right-label {
60
60
  display: flex;
61
- width: 45%;
61
+ max-width: 120px;
62
62
  }
63
63
 
64
64
  .left-label {
@@ -20,6 +20,7 @@
20
20
  selectedValue = $bindable(),
21
21
  display = "flex",
22
22
  gridPosition = undefined,
23
+ subtitle = undefined,
23
24
  } = $props();
24
25
  </script>
25
26
 
@@ -36,6 +37,7 @@
36
37
  textColor={headerTextColor}
37
38
  backgroundColor={headerBackgroundColor}
38
39
  {href}
40
+ {subtitle}
39
41
  ></CardHeader>
40
42
  {:else}
41
43
  {@render headerSnippet?.()}
@@ -65,6 +67,7 @@
65
67
  <style>
66
68
  .card {
67
69
  flex-direction: column;
70
+ min-width: 0;
68
71
  }
69
72
 
70
73
  .header-div {
@@ -22,6 +22,7 @@ declare const Card: import("svelte").Component<{
22
22
  selectedValue?: any;
23
23
  display?: string;
24
24
  gridPosition?: any;
25
+ subtitle?: any;
25
26
  }, {}, "selectedValue">;
26
27
  type $$ComponentProps = {
27
28
  headerIsLink?: boolean;
@@ -42,4 +43,5 @@ type $$ComponentProps = {
42
43
  selectedValue?: any;
43
44
  display?: string;
44
45
  gridPosition?: any;
46
+ subtitle?: any;
45
47
  };
@@ -5,13 +5,15 @@
5
5
  textColor = "#1D70B8",
6
6
  backgroundColor = "white",
7
7
  href = undefined,
8
+ subtitle = undefined,
8
9
  } = $props();
9
10
  </script>
10
11
 
11
12
  <a
12
13
  class="link govuk-heading-m"
13
14
  {href}
14
- style="font-size: {textSize}; color: {textColor}; background-color: {backgroundColor}"
15
+ style="font-size: {textSize}; color: {textColor}; background-color: {backgroundColor}; margin: {subtitle ??
16
+ 0}"
15
17
  >
16
18
  {text}
17
19
  <svg
@@ -27,12 +29,10 @@
27
29
  ></path>
28
30
  </svg>
29
31
  </a>
32
+ {#if subtitle !== undefined}
33
+ <p>{subtitle}</p>{/if}
30
34
 
31
35
  <style>
32
- * {
33
- margin: 0; /* this removes the margin applied by govuk-heading-m */
34
- }
35
-
36
36
  .link {
37
37
  display: flex;
38
38
  justify-content: space-between;
@@ -40,4 +40,7 @@
40
40
  width: 100%;
41
41
  gap: 0.5rem;
42
42
  }
43
+ p {
44
+ color: #666;
45
+ }
43
46
  </style>
@@ -9,6 +9,7 @@ declare const CardHeader: import("svelte").Component<{
9
9
  textColor?: string;
10
10
  backgroundColor?: string;
11
11
  href?: any;
12
+ subtitle?: any;
12
13
  }, {}, "">;
13
14
  type $$ComponentProps = {
14
15
  text?: string;
@@ -16,4 +17,5 @@ type $$ComponentProps = {
16
17
  textColor?: string;
17
18
  backgroundColor?: string;
18
19
  href?: any;
20
+ subtitle?: any;
19
21
  };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import "./main.css";
2
2
  export { default as InsetText } from './components/content/InsetText.svelte';
3
3
  export { default as WarningText } from './components/content/WarningText.svelte';
4
+ export { default as Histogram } from './components/data-vis/Histogram.svelte';
4
5
  export { default as Axis } from './components/data-vis/axis/Axis.svelte';
5
6
  export { default as Ticks } from './components/data-vis/axis/Ticks.svelte';
6
7
  export { default as Line } from './components/data-vis/line-chart/Line.svelte';
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import "./main.css";
3
3
  export { default as InsetText } from './components/content/InsetText.svelte';
4
4
  export { default as WarningText } from './components/content/WarningText.svelte';
5
+ export { default as Histogram } from './components/data-vis/Histogram.svelte';
5
6
  export { default as Axis } from './components/data-vis/axis/Axis.svelte';
6
7
  export { default as Ticks } from './components/data-vis/axis/Ticks.svelte';
7
8
  export { default as Line } from './components/data-vis/line-chart/Line.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@communitiesuk/svelte-component-library",
3
- "version": "0.1.19-beta.18",
3
+ "version": "0.1.19-beta.19",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/communitiesuk/mhclg_svelte_component_library.git"