@communitiesuk/svelte-component-library 0.1.19-beta.17 → 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.
Files changed (39) hide show
  1. package/README.md +7 -0
  2. package/dist/components/data-vis/Histogram.svelte +241 -0
  3. package/dist/components/data-vis/{histogram/Histogram.svelte.d.ts → Histogram.svelte.d.ts} +31 -15
  4. package/dist/components/data-vis/axis/Axis.svelte +34 -42
  5. package/dist/components/data-vis/axis/Axis.svelte.d.ts +9 -5
  6. package/dist/components/data-vis/axis/Ticks.svelte +91 -97
  7. package/dist/components/data-vis/axis/Ticks.svelte.d.ts +10 -9
  8. package/dist/components/data-vis/line-chart/LineChart.svelte +51 -21
  9. package/dist/components/data-vis/line-chart/LineChart.svelte.d.ts +15 -7
  10. package/dist/components/data-vis/line-chart/ValueLabel.svelte +10 -21
  11. package/dist/components/data-vis/line-chart/ValueLabel.svelte.d.ts +0 -2
  12. package/dist/components/data-vis/position-chart/PositionChart.svelte +400 -1017
  13. package/dist/components/data-vis/position-chart/PositionChart.svelte.d.ts +21 -35
  14. package/dist/components/data-vis/position-chart/PositionChartAxis.svelte +22 -42
  15. package/dist/components/data-vis/position-chart/PositionChartAxis.svelte.d.ts +0 -2
  16. package/dist/components/ui/BasicMultiSelect.svelte +185 -0
  17. package/dist/components/ui/BasicMultiSelect.svelte.d.ts +8 -0
  18. package/dist/components/ui/Card.svelte +2 -7
  19. package/dist/components/ui/CardHeader.svelte +8 -5
  20. package/dist/components/ui/CardHeader.svelte.d.ts +2 -0
  21. package/dist/components/ui/ChartExporter.svelte +142 -0
  22. package/dist/components/ui/ChartExporter.svelte.d.ts +16 -0
  23. package/dist/components/ui/CheckBox.svelte +1 -2
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.js +3 -1
  26. package/package.json +3 -2
  27. package/dist/components/data-vis/histogram/Histogram.svelte +0 -335
  28. package/dist/components/data-vis/position-chart/assignBinColors.d.ts +0 -1
  29. package/dist/components/data-vis/position-chart/assignBinColors.js +0 -13
  30. package/dist/components/data-vis/position-chart/createEqualWidthBins.d.ts +0 -12
  31. package/dist/components/data-vis/position-chart/createEqualWidthBins.js +0 -42
  32. package/dist/components/data-vis/position-chart/getColorsForValues.d.ts +0 -1
  33. package/dist/components/data-vis/position-chart/getColorsForValues.js +0 -16
  34. package/dist/components/data-vis/position-chart/interpolateColors.d.ts +0 -1
  35. package/dist/components/data-vis/position-chart/interpolateColors.js +0 -68
  36. package/dist/components/data-vis/position-chart/splitGroupsAndAverages.d.ts +0 -4
  37. package/dist/components/data-vis/position-chart/splitGroupsAndAverages.js +0 -20
  38. package/dist/server/lastUpdated.d.ts +0 -1
  39. package/dist/server/lastUpdated.js +0 -10
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,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>
@@ -4,46 +4,62 @@ type Histogram = {
4
4
  $set?(props: Partial<$$ComponentProps>): void;
5
5
  };
6
6
  declare const Histogram: import("svelte").Component<{
7
- min?: any;
8
- max?: any;
9
- dist?: any[];
10
- color?: string;
11
- highlightColor?: string;
12
- highlightValue?: any;
7
+ averageValue?: any;
8
+ distribution?: any[];
9
+ minX?: number;
10
+ maxX?: number;
11
+ minY?: number;
12
+ maxY?: number;
13
13
  showXAxis?: boolean;
14
14
  showYAxis?: boolean;
15
15
  showArrows?: boolean;
16
16
  midColor?: string;
17
17
  startColor?: string;
18
18
  endColor?: string;
19
- thresholds?: number;
20
19
  floor?: any;
21
20
  ceiling?: any;
21
+ nBins?: number;
22
22
  padding?: number;
23
23
  height?: number;
24
24
  polarity?: string;
25
+ annotationValue?: number;
25
26
  annotationText?: string;
26
27
  labelFormatter?: Function;
27
- }, {}, "">;
28
+ containerWidth?: number;
29
+ numberOfTicks: any;
30
+ customColorScale?: any;
31
+ skew?: boolean;
32
+ showGridlines?: boolean;
33
+ showTickMarks?: boolean;
34
+ strokeWidth?: number;
35
+ }, {}, "containerWidth">;
28
36
  type $$ComponentProps = {
29
- min?: any;
30
- max?: any;
31
- dist?: any[];
32
- color?: string;
33
- highlightColor?: string;
34
- highlightValue?: any;
37
+ averageValue?: any;
38
+ distribution?: any[];
39
+ minX?: number;
40
+ maxX?: number;
41
+ minY?: number;
42
+ maxY?: number;
35
43
  showXAxis?: boolean;
36
44
  showYAxis?: boolean;
37
45
  showArrows?: boolean;
38
46
  midColor?: string;
39
47
  startColor?: string;
40
48
  endColor?: string;
41
- thresholds?: number;
42
49
  floor?: any;
43
50
  ceiling?: any;
51
+ nBins?: number;
44
52
  padding?: number;
45
53
  height?: number;
46
54
  polarity?: string;
55
+ annotationValue?: number;
47
56
  annotationText?: string;
48
57
  labelFormatter?: Function;
58
+ containerWidth?: number;
59
+ numberOfTicks: any;
60
+ customColorScale?: any;
61
+ skew?: boolean;
62
+ showGridlines?: boolean;
63
+ showTickMarks?: boolean;
64
+ strokeWidth?: number;
49
65
  };
@@ -7,41 +7,34 @@
7
7
  import Ticks from "./Ticks.svelte";
8
8
 
9
9
  type AxisName = "x" | "y";
10
- type Polarity = "standard" | "reverse";
11
-
12
10
  type AxisPosition = "bottom" | "top" | "left" | "right";
13
11
  type Orientation = { axis: AxisName; position: AxisPosition };
14
12
  type AxisProjector = (value: number) => number;
15
- type LabelFormatter = (
16
- tick: number,
17
- index: number,
18
- numberOfTicks: number,
19
- values: number[],
20
- ) => string | number;
13
+ type LabelFormatter = (tick: number, index: number) => string | number;
14
+ type Polarity = "standard" | "reverse";
21
15
 
22
16
  let {
23
17
  chartHeight = 100,
24
18
  chartWidth = $bindable<number>(200),
25
19
 
26
- numberOfTicks = 2,
20
+ numberOfTicks = undefined as number | undefined,
27
21
 
28
22
  // Bindable, but avoid binding undefined – initialize as [] for safety
29
23
  ticksArray = $bindable<number[]>([]),
30
24
 
31
25
  // Values to derive ticks/domain from if ticksArray not provided
32
- values = undefined as number[] | undefined,
26
+ min = undefined as number | undefined,
27
+ max = undefined as number | undefined,
33
28
 
34
29
  orientation = { axis: "x", position: "bottom" } as Orientation,
35
30
 
36
- floor = null,
37
- ceiling = null,
31
+ floor = undefined as number | undefined,
32
+ ceiling = undefined as number | undefined,
38
33
 
39
34
  paddingTop = 100,
40
35
  paddingBottom = 100,
41
36
  paddingLeft = 0,
42
37
  paddingRight = 0,
43
- tickStrokeWidth = 2,
44
- axisStrokeWidth = 2,
45
38
 
46
39
  labelFormatter = undefined as LabelFormatter | undefined,
47
40
 
@@ -54,17 +47,21 @@
54
47
  domain = undefined as [number, number] | undefined,
55
48
  range = undefined as [number, number] | undefined,
56
49
  fontSize = 19,
57
- polarity = "standard" as Polarity,
58
- gridlines = false,
50
+ polarity = "standard",
51
+ showGridlines = false,
52
+ showTickMarks = false,
53
+ strokeWidth = 2,
59
54
  }: {
60
55
  chartHeight?: number;
61
56
  chartWidth?: number;
62
57
  numberOfTicks?: number;
63
58
  ticksArray?: number[];
64
- values?: number[];
59
+ min?: number;
60
+ max?: number;
61
+
65
62
  orientation?: Orientation;
66
- floor?: number | null;
67
- ceiling?: number | null;
63
+ floor?: number;
64
+ ceiling?: number;
68
65
  paddingTop?: number;
69
66
  paddingBottom?: number;
70
67
  paddingLeft?: number;
@@ -78,6 +75,9 @@
78
75
  fontSize?: number;
79
76
  polarity?: Polarity;
80
77
  gridlines?: Boolean;
78
+ strokeWidth?: Number;
79
+ showGridlines?: Boolean;
80
+ showTickMarks?: Boolean;
81
81
  } = $props();
82
82
 
83
83
  // --- Helpers to compute default domain/range when not supplied ---
@@ -85,7 +85,8 @@
85
85
  const innerHeight = $derived(Math.max(0, chartHeight));
86
86
 
87
87
  function computeDefaultDomain(): [number, number] {
88
- const arr = (ticksArray && ticksArray.length ? ticksArray : values) ?? [];
88
+ const arr =
89
+ (ticksArray && ticksArray.length ? ticksArray : [min, max]) ?? [];
89
90
  const dMin =
90
91
  floor ?? (arr.length ? arr.reduce((a, b) => (a < b ? a : b)) : 0);
91
92
  const dMax =
@@ -109,23 +110,12 @@
109
110
  const useDomain = domain ?? computeDefaultDomain();
110
111
  base.domain(useDomain);
111
112
 
112
- let useRange = range ?? computeDefaultRange(innerWidth, innerHeight);
113
- if (polarity === "reverse") {
114
- useRange = [...useRange].reverse();
115
- }
116
- base.range([...useRange]);
113
+ const useRange = range ?? computeDefaultRange(innerWidth, innerHeight);
114
+ base.range(useRange);
117
115
 
118
116
  return base;
119
117
  });
120
-
121
- const axisFunction: AxisProjector = (v) => {
122
- const s = resolvedScale();
123
- const r = s.range();
124
- const lo = Math.min(r[0], r[1]);
125
- const hi = Math.max(r[0], r[1]);
126
- const px = s(v);
127
- return Math.max(lo, Math.min(hi, px));
128
- };
118
+ const axisFunction: AxisProjector = $derived((v: number) => resolvedScale(v));
129
119
  </script>
130
120
 
131
121
  <g
@@ -135,21 +125,22 @@
135
125
  : chartWidth},{orientation.position === 'bottom' ? chartHeight : 0})"
136
126
  >
137
127
  <line
138
- x1={0}
128
+ x1={range[0]}
139
129
  y1="0"
140
- x2={orientation.axis === "x" ? chartWidth : 0}
130
+ x2={orientation.axis === "x" ? range[1] : 0}
141
131
  y2={orientation.axis === "y" ? chartHeight : 0}
142
- stroke="darkgrey"
143
- stroke-width={axisStrokeWidth}
132
+ stroke="grey"
133
+ stroke-width="2px"
144
134
  ></line>
145
- {#if values}
135
+ {#if ticksArray || (min && max)}
146
136
  {#key numberOfTicks}
147
137
  <Ticks
148
138
  bind:ticksArray
149
139
  {chartWidth}
150
140
  {chartHeight}
151
141
  {axisFunction}
152
- {values}
142
+ {min}
143
+ {max}
153
144
  {numberOfTicks}
154
145
  {orientation}
155
146
  {floor}
@@ -157,8 +148,9 @@
157
148
  {labelFormatter}
158
149
  {fontSize}
159
150
  {polarity}
160
- {tickStrokeWidth}
161
- {gridlines}
151
+ {showGridlines}
152
+ {showTickMarks}
153
+ {strokeWidth}
162
154
  />
163
155
  {/key}
164
156
  {/if}
@@ -1,21 +1,22 @@
1
1
  import { type ScaleContinuousNumeric } from "d3-scale";
2
2
  type AxisName = "x" | "y";
3
- type Polarity = "standard" | "reverse";
4
3
  type AxisPosition = "bottom" | "top" | "left" | "right";
5
4
  type Orientation = {
6
5
  axis: AxisName;
7
6
  position: AxisPosition;
8
7
  };
9
- type LabelFormatter = (tick: number, index: number, numberOfTicks: number, values: number[]) => string | number;
8
+ type LabelFormatter = (tick: number, index: number) => string | number;
9
+ type Polarity = "standard" | "reverse";
10
10
  type $$ComponentProps = {
11
11
  chartHeight?: number;
12
12
  chartWidth?: number;
13
13
  numberOfTicks?: number;
14
14
  ticksArray?: number[];
15
- values?: number[];
15
+ min?: number;
16
+ max?: number;
16
17
  orientation?: Orientation;
17
- floor?: number | null;
18
- ceiling?: number | null;
18
+ floor?: number;
19
+ ceiling?: number;
19
20
  paddingTop?: number;
20
21
  paddingBottom?: number;
21
22
  paddingLeft?: number;
@@ -27,6 +28,9 @@ type $$ComponentProps = {
27
28
  fontSize?: number;
28
29
  polarity?: Polarity;
29
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>;