panelui-native 0.22.6 → 0.28.1
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 +1 -0
- package/lib/module/components/accordion/index.js +8 -8
- package/lib/module/components/accordion/index.js.map +1 -1
- package/lib/module/components/alert/index.js +2 -2
- package/lib/module/components/alert/index.js.map +1 -1
- package/lib/module/components/area-chart/index.js +958 -0
- package/lib/module/components/area-chart/index.js.map +1 -0
- package/lib/module/components/attachment/index.js +2 -1
- package/lib/module/components/attachment/index.js.map +1 -1
- package/lib/module/components/avatar/index.js +4 -4
- package/lib/module/components/avatar/index.js.map +1 -1
- package/lib/module/components/badge/index.js +4 -4
- package/lib/module/components/badge/index.js.map +1 -1
- package/lib/module/components/bar-chart/index.js +994 -0
- package/lib/module/components/bar-chart/index.js.map +1 -0
- package/lib/module/components/bottom-sheet/index.js +213 -24
- package/lib/module/components/bottom-sheet/index.js.map +1 -1
- package/lib/module/components/breadcrumb/index.js +275 -0
- package/lib/module/components/breadcrumb/index.js.map +1 -0
- package/lib/module/components/button/index.js +11 -6
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/calendar/index.js +557 -0
- package/lib/module/components/calendar/index.js.map +1 -0
- package/lib/module/components/carousel/index.js +680 -0
- package/lib/module/components/carousel/index.js.map +1 -0
- package/lib/module/components/chip/index.js +6 -6
- package/lib/module/components/chip/index.js.map +1 -1
- package/lib/module/components/date-picker/index.js +158 -0
- package/lib/module/components/date-picker/index.js.map +1 -0
- package/lib/module/components/dialog/index.js +7 -2
- package/lib/module/components/dialog/index.js.map +1 -1
- package/lib/module/components/direction/index.js +15 -20
- package/lib/module/components/direction/index.js.map +1 -1
- package/lib/module/components/empty-state/index.js +2 -2
- package/lib/module/components/empty-state/index.js.map +1 -1
- package/lib/module/components/field/index.js +5 -5
- package/lib/module/components/field/index.js.map +1 -1
- package/lib/module/components/flow/index.js +3 -3
- package/lib/module/components/flow/index.js.map +1 -1
- package/lib/module/components/frame/index.js +22 -5
- package/lib/module/components/frame/index.js.map +1 -1
- package/lib/module/components/heatmap-chart/index.js +28 -8
- package/lib/module/components/heatmap-chart/index.js.map +1 -1
- package/lib/module/components/input-group/index.js +5 -4
- package/lib/module/components/input-group/index.js.map +1 -1
- package/lib/module/components/item/index.js +9 -9
- package/lib/module/components/item/index.js.map +1 -1
- package/lib/module/components/label/index.js +4 -4
- package/lib/module/components/label/index.js.map +1 -1
- package/lib/module/components/line-chart/index.js +165 -184
- package/lib/module/components/line-chart/index.js.map +1 -1
- package/lib/module/components/loader/index.js +758 -0
- package/lib/module/components/loader/index.js.map +1 -0
- package/lib/module/components/map/basemap.js +265 -0
- package/lib/module/components/map/basemap.js.map +1 -0
- package/lib/module/components/map/index.js +850 -0
- package/lib/module/components/map/index.js.map +1 -0
- package/lib/module/components/map/maplibre.js +87 -0
- package/lib/module/components/map/maplibre.js.map +1 -0
- package/lib/module/components/marker/index.js +3 -3
- package/lib/module/components/marker/index.js.map +1 -1
- package/lib/module/components/message/index.js +15 -14
- package/lib/module/components/message/index.js.map +1 -1
- package/lib/module/components/message-scroller/index.js +5 -4
- package/lib/module/components/message-scroller/index.js.map +1 -1
- package/lib/module/components/otp-input/index.js +2 -2
- package/lib/module/components/popover/index.js +39 -7
- package/lib/module/components/popover/index.js.map +1 -1
- package/lib/module/components/progress/index.js +8 -2
- package/lib/module/components/progress/index.js.map +1 -1
- package/lib/module/components/radio-group/index.js +2 -2
- package/lib/module/components/radio-group/index.js.map +1 -1
- package/lib/module/components/ring-chart/index.js +423 -0
- package/lib/module/components/ring-chart/index.js.map +1 -0
- package/lib/module/components/section-rail/index.js +6 -6
- package/lib/module/components/section-rail/index.js.map +1 -1
- package/lib/module/components/select/index.js +10 -4
- package/lib/module/components/select/index.js.map +1 -1
- package/lib/module/components/separator/index.js +76 -22
- package/lib/module/components/separator/index.js.map +1 -1
- package/lib/module/components/shimmer/index.js +10 -1
- package/lib/module/components/shimmer/index.js.map +1 -1
- package/lib/module/components/slider/index.js +19 -5
- package/lib/module/components/slider/index.js.map +1 -1
- package/lib/module/components/steps/index.js +5 -5
- package/lib/module/components/steps/index.js.map +1 -1
- package/lib/module/components/switch/index.js +6 -1
- package/lib/module/components/switch/index.js.map +1 -1
- package/lib/module/components/tabs/index.js +7 -7
- package/lib/module/components/tabs/index.js.map +1 -1
- package/lib/module/components/timeline/index.js +4 -4
- package/lib/module/components/timeline/index.js.map +1 -1
- package/lib/module/components/toast/index.js +2 -2
- package/lib/module/components/toast/index.js.map +1 -1
- package/lib/module/components/toggle-button/index.js +5 -5
- package/lib/module/components/toggle-button/index.js.map +1 -1
- package/lib/module/components/tooltip/index.js +492 -0
- package/lib/module/components/tooltip/index.js.map +1 -0
- package/lib/module/components/typography/index.js +7 -2
- package/lib/module/components/typography/index.js.map +1 -1
- package/lib/module/hooks/index.js +1 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/use-back-handler.js +37 -0
- package/lib/module/hooks/use-back-handler.js.map +1 -0
- package/lib/module/hooks/use-direction.js +43 -0
- package/lib/module/hooks/use-direction.js.map +1 -0
- package/lib/module/icons/index.js +180 -2
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +12 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/primitives/keyboard-avoider.js +2 -1
- package/lib/module/primitives/keyboard-avoider.js.map +1 -1
- package/lib/module/primitives/text.js +55 -11
- package/lib/module/primitives/text.js.map +1 -1
- package/lib/module/utils/chart.js +279 -0
- package/lib/module/utils/chart.js.map +1 -0
- package/lib/module/utils/date.js +386 -0
- package/lib/module/utils/date.js.map +1 -0
- package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
- package/lib/typescript/src/components/alert/index.d.ts.map +1 -1
- package/lib/typescript/src/components/area-chart/index.d.ts +237 -0
- package/lib/typescript/src/components/area-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/attachment/index.d.ts.map +1 -1
- package/lib/typescript/src/components/bar-chart/index.d.ts +270 -0
- package/lib/typescript/src/components/bar-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/bottom-sheet/index.d.ts +75 -4
- package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/src/components/breadcrumb/index.d.ts +100 -0
- package/lib/typescript/src/components/breadcrumb/index.d.ts.map +1 -0
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/calendar/index.d.ts +108 -0
- package/lib/typescript/src/components/calendar/index.d.ts.map +1 -0
- package/lib/typescript/src/components/carousel/index.d.ts +179 -0
- package/lib/typescript/src/components/carousel/index.d.ts.map +1 -0
- package/lib/typescript/src/components/chip/index.d.ts.map +1 -1
- package/lib/typescript/src/components/date-picker/index.d.ts +91 -0
- package/lib/typescript/src/components/date-picker/index.d.ts.map +1 -0
- package/lib/typescript/src/components/dialog/index.d.ts.map +1 -1
- package/lib/typescript/src/components/direction/index.d.ts +11 -10
- package/lib/typescript/src/components/direction/index.d.ts.map +1 -1
- package/lib/typescript/src/components/empty-state/index.d.ts.map +1 -1
- package/lib/typescript/src/components/field/index.d.ts.map +1 -1
- package/lib/typescript/src/components/frame/index.d.ts +17 -0
- package/lib/typescript/src/components/frame/index.d.ts.map +1 -1
- package/lib/typescript/src/components/heatmap-chart/index.d.ts +22 -3
- package/lib/typescript/src/components/heatmap-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/item/index.d.ts.map +1 -1
- package/lib/typescript/src/components/label/index.d.ts.map +1 -1
- package/lib/typescript/src/components/line-chart/index.d.ts +42 -2
- package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -1
- package/lib/typescript/src/components/loader/index.d.ts +38 -0
- package/lib/typescript/src/components/loader/index.d.ts.map +1 -0
- package/lib/typescript/src/components/map/basemap.d.ts +76 -0
- package/lib/typescript/src/components/map/basemap.d.ts.map +1 -0
- package/lib/typescript/src/components/map/index.d.ts +367 -0
- package/lib/typescript/src/components/map/index.d.ts.map +1 -0
- package/lib/typescript/src/components/map/maplibre.d.ts +193 -0
- package/lib/typescript/src/components/map/maplibre.d.ts.map +1 -0
- package/lib/typescript/src/components/marker/index.d.ts.map +1 -1
- package/lib/typescript/src/components/message/index.d.ts.map +1 -1
- package/lib/typescript/src/components/message-scroller/index.d.ts.map +1 -1
- package/lib/typescript/src/components/popover/index.d.ts.map +1 -1
- package/lib/typescript/src/components/progress/index.d.ts.map +1 -1
- package/lib/typescript/src/components/ring-chart/index.d.ts +156 -0
- package/lib/typescript/src/components/ring-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/select/index.d.ts.map +1 -1
- package/lib/typescript/src/components/separator/index.d.ts +36 -1
- package/lib/typescript/src/components/separator/index.d.ts.map +1 -1
- package/lib/typescript/src/components/shimmer/index.d.ts.map +1 -1
- package/lib/typescript/src/components/slider/index.d.ts.map +1 -1
- package/lib/typescript/src/components/steps/index.d.ts.map +1 -1
- package/lib/typescript/src/components/switch/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/src/components/timeline/index.d.ts.map +1 -1
- package/lib/typescript/src/components/toast/index.d.ts.map +1 -1
- package/lib/typescript/src/components/toggle-button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tooltip/index.d.ts +125 -0
- package/lib/typescript/src/components/tooltip/index.d.ts.map +1 -0
- package/lib/typescript/src/components/typography/index.d.ts +6 -0
- package/lib/typescript/src/components/typography/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/index.d.ts +1 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-back-handler.d.ts +19 -0
- package/lib/typescript/src/hooks/use-back-handler.d.ts.map +1 -0
- package/lib/typescript/src/hooks/use-direction.d.ts +20 -0
- package/lib/typescript/src/hooks/use-direction.d.ts.map +1 -0
- package/lib/typescript/src/icons/index.d.ts +8 -0
- package/lib/typescript/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +14 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/primitives/keyboard-avoider.d.ts.map +1 -1
- package/lib/typescript/src/primitives/text.d.ts +20 -0
- package/lib/typescript/src/primitives/text.d.ts.map +1 -1
- package/lib/typescript/src/utils/chart.d.ts +96 -0
- package/lib/typescript/src/utils/chart.d.ts.map +1 -0
- package/lib/typescript/src/utils/date.d.ts +116 -0
- package/lib/typescript/src/utils/date.d.ts.map +1 -0
- package/package.json +9 -1
- package/src/components/accordion/index.tsx +8 -12
- package/src/components/alert/index.tsx +2 -2
- package/src/components/area-chart/index.tsx +1147 -0
- package/src/components/attachment/index.tsx +2 -2
- package/src/components/avatar/index.tsx +4 -4
- package/src/components/badge/index.tsx +6 -6
- package/src/components/bar-chart/index.tsx +1208 -0
- package/src/components/bottom-sheet/index.tsx +282 -21
- package/src/components/breadcrumb/index.tsx +363 -0
- package/src/components/button/index.tsx +12 -8
- package/src/components/calendar/index.tsx +703 -0
- package/src/components/carousel/index.tsx +788 -0
- package/src/components/chip/index.tsx +6 -8
- package/src/components/date-picker/index.tsx +237 -0
- package/src/components/dialog/index.tsx +7 -2
- package/src/components/direction/index.tsx +22 -22
- package/src/components/empty-state/index.tsx +2 -2
- package/src/components/field/index.tsx +3 -5
- package/src/components/flow/index.tsx +3 -3
- package/src/components/frame/index.tsx +22 -7
- package/src/components/heatmap-chart/index.tsx +58 -11
- package/src/components/input-group/index.tsx +5 -4
- package/src/components/item/index.tsx +9 -9
- package/src/components/label/index.tsx +2 -2
- package/src/components/line-chart/index.tsx +194 -223
- package/src/components/loader/index.tsx +812 -0
- package/src/components/map/basemap.ts +304 -0
- package/src/components/map/index.tsx +1116 -0
- package/src/components/map/maplibre.ts +201 -0
- package/src/components/marker/index.tsx +3 -3
- package/src/components/message/index.tsx +15 -14
- package/src/components/message-scroller/index.tsx +5 -4
- package/src/components/otp-input/index.tsx +2 -2
- package/src/components/popover/index.tsx +43 -7
- package/src/components/progress/index.tsx +10 -2
- package/src/components/radio-group/index.tsx +2 -2
- package/src/components/ring-chart/index.tsx +543 -0
- package/src/components/section-rail/index.tsx +6 -6
- package/src/components/select/index.tsx +10 -4
- package/src/components/separator/index.tsx +77 -19
- package/src/components/shimmer/index.tsx +10 -1
- package/src/components/slider/index.tsx +20 -5
- package/src/components/steps/index.tsx +5 -5
- package/src/components/switch/index.tsx +6 -1
- package/src/components/tabs/index.tsx +7 -9
- package/src/components/timeline/index.tsx +4 -4
- package/src/components/toast/index.tsx +2 -2
- package/src/components/toggle-button/index.tsx +5 -7
- package/src/components/tooltip/index.tsx +610 -0
- package/src/components/typography/index.tsx +7 -2
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-back-handler.ts +37 -0
- package/src/hooks/use-direction.ts +45 -0
- package/src/icons/index.tsx +111 -0
- package/src/index.ts +129 -0
- package/src/primitives/keyboard-avoider.tsx +2 -1
- package/src/primitives/text.tsx +53 -8
- package/src/utils/chart.ts +355 -0
- package/src/utils/date.ts +446 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The maths every chart shares.
|
|
5
|
+
*
|
|
6
|
+
* Scales, monotone tangents and path building, in one place because four
|
|
7
|
+
* charts need them and a copy per chart is four chances for two charts to
|
|
8
|
+
* disagree about where a point goes. A line and an area drawn from different
|
|
9
|
+
* code do not lie on top of each other, and that is exactly the pair most
|
|
10
|
+
* often drawn together.
|
|
11
|
+
*
|
|
12
|
+
* Everything here is a worklet. The paths are rebuilt on the UI thread on
|
|
13
|
+
* every frame a domain is tweening, so none of it can be allowed to need the
|
|
14
|
+
* JS thread — which also rules out reaching for a charting dependency, since
|
|
15
|
+
* that is the one thing none of them are written to survive.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { useCSSVariable } from 'uniwind';
|
|
19
|
+
|
|
20
|
+
/** Only reached if the theme CSS was never imported. */
|
|
21
|
+
const FALLBACK_SERIES = ['#3b82f6', '#10b981', '#f59e0b', '#8b5cf6', '#ec4899'];
|
|
22
|
+
|
|
23
|
+
/** Which of the five chart tokens a series takes. */
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A series' colour: an explicit one, else the `--color-chart-*` token.
|
|
27
|
+
*
|
|
28
|
+
* Shared so every chart draws its first series in the same colour. Two charts
|
|
29
|
+
* on one screen disagreeing about what "series one" looks like is the kind of
|
|
30
|
+
* thing nobody reports and everybody notices.
|
|
31
|
+
*/
|
|
32
|
+
export function useSeriesColor(explicit, index) {
|
|
33
|
+
const token = useCSSVariable(`--color-chart-${index}`);
|
|
34
|
+
return explicit ?? (typeof token === 'string' ? token : FALLBACK_SERIES[index - 1]);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** `12.4k` rather than `12400` — a readout has one line to say it in. */
|
|
38
|
+
export function compactNumber(value) {
|
|
39
|
+
const abs = Math.abs(value);
|
|
40
|
+
if (abs >= 1_000_000) return `${(value / 1_000_000).toFixed(1)}M`;
|
|
41
|
+
if (abs >= 1_000) return `${(value / 1_000).toFixed(1)}k`;
|
|
42
|
+
return Number.isInteger(value) ? String(value) : value.toFixed(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The drawable box inside a chart, after its padding is taken off. */
|
|
46
|
+
|
|
47
|
+
/** A point's x, spreading `total` of them evenly across the plot. */
|
|
48
|
+
export function xOf(index, total, plot) {
|
|
49
|
+
'worklet';
|
|
50
|
+
|
|
51
|
+
if (total <= 1) return plot.left + plot.width / 2;
|
|
52
|
+
return plot.left + plot.width * index / (total - 1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** A value's y, with `min` at the bottom of the plot and `max` at the top. */
|
|
56
|
+
export function yOf(value, plot, min, max) {
|
|
57
|
+
'worklet';
|
|
58
|
+
|
|
59
|
+
const span = max - min || 1;
|
|
60
|
+
return plot.top + plot.height - (value - min) / span * plot.height;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The centre of the `index`th of `total` bands, as used for bars and columns. */
|
|
64
|
+
export function bandOf(index, total, plot) {
|
|
65
|
+
'worklet';
|
|
66
|
+
|
|
67
|
+
if (total <= 0) return plot.left + plot.width / 2;
|
|
68
|
+
const width = plot.width / total;
|
|
69
|
+
return plot.left + width * (index + 0.5);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Monotone cubic tangents.
|
|
74
|
+
*
|
|
75
|
+
* Written out rather than taken from a charting dependency, because it is forty
|
|
76
|
+
* lines and it has to run inside a worklet.
|
|
77
|
+
*
|
|
78
|
+
* Monotone is the right default for a time series. A plain cubic spline
|
|
79
|
+
* overshoots between points, so a series that never goes below zero draws a dip
|
|
80
|
+
* under the axis between two low values — a shape that is not in the data. This
|
|
81
|
+
* one cannot, because the tangent at each point is clamped against the slopes
|
|
82
|
+
* either side of it, and a local peak or trough is given a flat one.
|
|
83
|
+
*/
|
|
84
|
+
export function tangents(xs, ys) {
|
|
85
|
+
'worklet';
|
|
86
|
+
|
|
87
|
+
const n = xs.length;
|
|
88
|
+
const slopes = [];
|
|
89
|
+
for (let i = 0; i < n - 1; i += 1) {
|
|
90
|
+
slopes.push((ys[i + 1] - ys[i]) / (xs[i + 1] - xs[i] || 1));
|
|
91
|
+
}
|
|
92
|
+
const result = new Array(n).fill(0);
|
|
93
|
+
result[0] = slopes[0] ?? 0;
|
|
94
|
+
result[n - 1] = slopes[n - 2] ?? 0;
|
|
95
|
+
for (let i = 1; i < n - 1; i += 1) {
|
|
96
|
+
const previous = slopes[i - 1];
|
|
97
|
+
const next = slopes[i];
|
|
98
|
+
result[i] = previous * next <= 0 ? 0 : (previous + next) / 2;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Fritsch–Carlson: pull any tangent back inside the circle of radius 3, which
|
|
102
|
+
// is the condition for the segment to stay monotone.
|
|
103
|
+
for (let i = 0; i < n - 1; i += 1) {
|
|
104
|
+
const slope = slopes[i];
|
|
105
|
+
if (slope === 0) {
|
|
106
|
+
result[i] = 0;
|
|
107
|
+
result[i + 1] = 0;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const a = result[i] / slope;
|
|
111
|
+
const b = result[i + 1] / slope;
|
|
112
|
+
const magnitude = Math.sqrt(a * a + b * b);
|
|
113
|
+
if (magnitude > 3) {
|
|
114
|
+
result[i] = 3 / magnitude * a * slope;
|
|
115
|
+
result[i + 1] = 3 / magnitude * b * slope;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** How a series is joined between its points. */
|
|
122
|
+
|
|
123
|
+
/** Points, split at the gaps — a null breaks the series rather than crossing it. */
|
|
124
|
+
export function runsOf(values, plot, min, max, /** Baselines to stack each point on top of, for a stacked area. */
|
|
125
|
+
baselines) {
|
|
126
|
+
'worklet';
|
|
127
|
+
|
|
128
|
+
const runs = [];
|
|
129
|
+
let run = [];
|
|
130
|
+
for (let i = 0; i < values.length; i += 1) {
|
|
131
|
+
const value = values[i];
|
|
132
|
+
if (value === null || value === undefined) {
|
|
133
|
+
if (run.length) runs.push(run);
|
|
134
|
+
run = [];
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const stacked = value + (baselines?.[i] ?? 0);
|
|
138
|
+
run.push({
|
|
139
|
+
x: xOf(i, values.length, plot),
|
|
140
|
+
y: yOf(stacked, plot, min, max)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
if (run.length) runs.push(run);
|
|
144
|
+
return runs;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** One unbroken run of points as a path, curved or straight. */
|
|
148
|
+
export function segment(points, curve) {
|
|
149
|
+
'worklet';
|
|
150
|
+
|
|
151
|
+
if (!points.length) return '';
|
|
152
|
+
if (points.length < 3 || curve === 'linear') {
|
|
153
|
+
return points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');
|
|
154
|
+
}
|
|
155
|
+
const xs = points.map(p => p.x);
|
|
156
|
+
const ys = points.map(p => p.y);
|
|
157
|
+
const ms = tangents(xs, ys);
|
|
158
|
+
let d = `M${xs[0]},${ys[0]}`;
|
|
159
|
+
for (let i = 0; i < points.length - 1; i += 1) {
|
|
160
|
+
const dx = (xs[i + 1] - xs[i]) / 3;
|
|
161
|
+
d += ` C${xs[i] + dx},${ys[i] + ms[i] * dx} ${xs[i + 1] - dx},${ys[i + 1] - ms[i + 1] * dx} ${xs[i + 1]},${ys[i + 1]}`;
|
|
162
|
+
}
|
|
163
|
+
return d;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** A series as a stroked line. Flat down the middle while it is still loading. */
|
|
167
|
+
export function linePath(values, plot, min, max, curve, loading, baselines) {
|
|
168
|
+
'worklet';
|
|
169
|
+
|
|
170
|
+
if (loading || plot.width <= 0) {
|
|
171
|
+
// Flat down the middle: the shape the skeleton holds, and the shape the
|
|
172
|
+
// real series grows out of once the data arrives.
|
|
173
|
+
const y = plot.top + plot.height / 2;
|
|
174
|
+
return `M${plot.left},${y} L${plot.left + plot.width},${y}`;
|
|
175
|
+
}
|
|
176
|
+
return runsOf(values, plot, min, max, baselines).map(run => segment(run, curve)).join(' ');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* A series as a filled area.
|
|
181
|
+
*
|
|
182
|
+
* `floors` is what makes a stack: without it every run is closed against the
|
|
183
|
+
* bottom of the plot, and with it each run is closed against the series below,
|
|
184
|
+
* so the bands sit on each other rather than overlapping. The floor is walked
|
|
185
|
+
* backwards because the fill has to trace its underside right to left to close.
|
|
186
|
+
*/
|
|
187
|
+
export function areaPath(values, plot, min, max, curve, loading, baselines) {
|
|
188
|
+
'worklet';
|
|
189
|
+
|
|
190
|
+
if (loading || plot.width <= 0) return '';
|
|
191
|
+
const bottom = plot.top + plot.height;
|
|
192
|
+
const runs = runsOf(values, plot, min, max, baselines);
|
|
193
|
+
if (!baselines) {
|
|
194
|
+
return runs.map(run => {
|
|
195
|
+
const top = segment(run, curve);
|
|
196
|
+
if (!top) return '';
|
|
197
|
+
const first = run[0];
|
|
198
|
+
const last = run[run.length - 1];
|
|
199
|
+
return `${top} L${last.x},${bottom} L${first.x},${bottom} Z`;
|
|
200
|
+
}).join(' ');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Stacked: the underside is the baseline itself, drawn as its own curve so
|
|
204
|
+
// the two edges of a band meet cleanly at both ends.
|
|
205
|
+
const floors = runsOf(values.map(value => value === null || value === undefined ? null : 0), plot, min, max, baselines);
|
|
206
|
+
return runs.map((run, index) => {
|
|
207
|
+
const top = segment(run, curve);
|
|
208
|
+
const floor = floors[index];
|
|
209
|
+
if (!top || !floor?.length) return '';
|
|
210
|
+
const under = segment([...floor].reverse(), curve).replace('M', 'L');
|
|
211
|
+
return `${top} ${under} Z`;
|
|
212
|
+
}).join(' ');
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* A rounded rectangle, built as a path rather than drawn as a `Rect`.
|
|
217
|
+
*
|
|
218
|
+
* A bar is rounded on the end it grows towards and square on the end it grows
|
|
219
|
+
* from, so it reads as sitting on the axis rather than floating above it —
|
|
220
|
+
* which `rx` cannot express, since it rounds all four corners or none.
|
|
221
|
+
*/
|
|
222
|
+
export function barPath(x, y, width, height, radius, /** Which end is the growing one. */
|
|
223
|
+
towards) {
|
|
224
|
+
'worklet';
|
|
225
|
+
|
|
226
|
+
if (width <= 0 || height <= 0) return '';
|
|
227
|
+
const r = Math.max(0, Math.min(radius, width / 2, height / 2));
|
|
228
|
+
const right = x + width;
|
|
229
|
+
const bottom = y + height;
|
|
230
|
+
if (towards === 'up') {
|
|
231
|
+
return `M${x},${bottom}L${x},${y + r}Q${x},${y} ${x + r},${y}` + `L${right - r},${y}Q${right},${y} ${right},${y + r}L${right},${bottom}Z`;
|
|
232
|
+
}
|
|
233
|
+
if (towards === 'down') {
|
|
234
|
+
return `M${x},${y}L${x},${bottom - r}Q${x},${bottom} ${x + r},${bottom}` + `L${right - r},${bottom}Q${right},${bottom} ${right},${bottom - r}L${right},${y}Z`;
|
|
235
|
+
}
|
|
236
|
+
if (towards === 'right') {
|
|
237
|
+
return `M${x},${y}L${right - r},${y}Q${right},${y} ${right},${y + r}` + `L${right},${bottom - r}Q${right},${bottom} ${right - r},${bottom}L${x},${bottom}Z`;
|
|
238
|
+
}
|
|
239
|
+
return `M${right},${y}L${x + r},${y}Q${x},${y} ${x},${y + r}` + `L${x},${bottom - r}Q${x},${bottom} ${x + r},${bottom}L${right},${bottom}Z`;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* An arc of a circle, as a path.
|
|
244
|
+
*
|
|
245
|
+
* Angles are in turns from twelve o'clock, clockwise, because that is how a
|
|
246
|
+
* ring chart is described — "sixty percent of the way round" — and converting
|
|
247
|
+
* at every call site is where the sign errors live.
|
|
248
|
+
*/
|
|
249
|
+
export function arcPath(cx, cy, radius, from, to) {
|
|
250
|
+
'worklet';
|
|
251
|
+
|
|
252
|
+
const sweep = to - from;
|
|
253
|
+
if (radius <= 0 || sweep <= 0) return '';
|
|
254
|
+
|
|
255
|
+
// A full turn cannot be drawn as one arc — start and end are the same point,
|
|
256
|
+
// and the renderer draws nothing rather than everything. Two halves can.
|
|
257
|
+
if (sweep >= 1) {
|
|
258
|
+
const top = `${cx},${cy - radius}`;
|
|
259
|
+
const bottomPoint = `${cx},${cy + radius}`;
|
|
260
|
+
return `M${top}A${radius},${radius} 0 0 1 ${bottomPoint}` + `A${radius},${radius} 0 0 1 ${top}`;
|
|
261
|
+
}
|
|
262
|
+
const angle = turn => (turn - 0.25) * Math.PI * 2;
|
|
263
|
+
const x1 = cx + radius * Math.cos(angle(from));
|
|
264
|
+
const y1 = cy + radius * Math.sin(angle(from));
|
|
265
|
+
const x2 = cx + radius * Math.cos(angle(to));
|
|
266
|
+
const y2 = cy + radius * Math.sin(angle(to));
|
|
267
|
+
return `M${x1},${y1}A${radius},${radius} 0 ${sweep > 0.5 ? 1 : 0} 1 ${x2},${y2}`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** The numbers of one column, with anything unusable left as a gap. */
|
|
271
|
+
export function columnValues(data, key) {
|
|
272
|
+
'worklet';
|
|
273
|
+
|
|
274
|
+
return data.map(row => {
|
|
275
|
+
const value = row[key];
|
|
276
|
+
return typeof value === 'number' && !Number.isNaN(value) ? value : null;
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useCSSVariable","FALLBACK_SERIES","useSeriesColor","explicit","index","token","compactNumber","value","abs","Math","toFixed","Number","isInteger","String","xOf","total","plot","left","width","yOf","min","max","span","top","height","bandOf","tangents","xs","ys","n","length","slopes","i","push","result","Array","fill","previous","next","slope","a","b","magnitude","sqrt","runsOf","values","baselines","runs","run","undefined","stacked","x","y","segment","points","curve","map","p","join","ms","d","dx","linePath","loading","areaPath","bottom","first","last","floors","floor","under","reverse","replace","barPath","radius","towards","r","right","arcPath","cx","cy","from","to","sweep","bottomPoint","angle","turn","PI","x1","cos","y1","sin","x2","y2","columnValues","data","key","row","isNaN"],"sourceRoot":"../../../src","sources":["utils/chart.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Date helpers for the calendar.
|
|
5
|
+
*
|
|
6
|
+
* No date library. Everything a month grid needs is arithmetic on `Date`, and
|
|
7
|
+
* a dependency that ships a full timezone database to render seven columns is
|
|
8
|
+
* a poor trade for a library whose whole runtime is three small packages.
|
|
9
|
+
*
|
|
10
|
+
* Two rules hold throughout:
|
|
11
|
+
*
|
|
12
|
+
* - **Days are compared at local midnight.** A `Date` carries a time, and two
|
|
13
|
+
* values on the same day are not equal unless that time is stripped. Every
|
|
14
|
+
* comparison here goes through `startOfDay`.
|
|
15
|
+
* - **Month arithmetic is done with `setMonth`, not by adding days.** The
|
|
16
|
+
* platform already knows that a month is 28, 29, 30 or 31 days long.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** Names of the weekdays and months, in the caller's locale. */
|
|
20
|
+
|
|
21
|
+
export function startOfDay(date) {
|
|
22
|
+
const copy = new Date(date);
|
|
23
|
+
copy.setHours(0, 0, 0, 0);
|
|
24
|
+
return copy;
|
|
25
|
+
}
|
|
26
|
+
export function isSameDay(a, b) {
|
|
27
|
+
if (!a || !b) return false;
|
|
28
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
29
|
+
}
|
|
30
|
+
export function isSameMonth(a, b) {
|
|
31
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
32
|
+
}
|
|
33
|
+
export function startOfMonth(date) {
|
|
34
|
+
return new Date(date.getFullYear(), date.getMonth(), 1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Day 0 of the *next* month, which the platform resolves to the last day of
|
|
39
|
+
* this one — so a leap February needs no special case.
|
|
40
|
+
*/
|
|
41
|
+
export function endOfMonth(date) {
|
|
42
|
+
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
|
|
43
|
+
}
|
|
44
|
+
export function addMonths(date, months) {
|
|
45
|
+
const copy = new Date(date.getFullYear(), date.getMonth(), 1);
|
|
46
|
+
copy.setMonth(copy.getMonth() + months);
|
|
47
|
+
return copy;
|
|
48
|
+
}
|
|
49
|
+
export function addDays(date, days) {
|
|
50
|
+
const copy = new Date(date);
|
|
51
|
+
copy.setDate(copy.getDate() + days);
|
|
52
|
+
return copy;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Whole days from `a` to `b`, ignoring the time of day on both. */
|
|
56
|
+
export function daysBetween(a, b) {
|
|
57
|
+
const MS = 24 * 60 * 60 * 1000;
|
|
58
|
+
return Math.round((startOfDay(b).getTime() - startOfDay(a).getTime()) / MS);
|
|
59
|
+
}
|
|
60
|
+
export function isBefore(a, b) {
|
|
61
|
+
return startOfDay(a).getTime() < startOfDay(b).getTime();
|
|
62
|
+
}
|
|
63
|
+
export function isAfter(a, b) {
|
|
64
|
+
return startOfDay(a).getTime() > startOfDay(b).getTime();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Inclusive at both ends, which is what a selected range means to a reader. */
|
|
68
|
+
export function isWithin(date, from, to) {
|
|
69
|
+
const time = startOfDay(date).getTime();
|
|
70
|
+
const start = startOfDay(from).getTime();
|
|
71
|
+
const end = startOfDay(to).getTime();
|
|
72
|
+
return time >= Math.min(start, end) && time <= Math.max(start, end);
|
|
73
|
+
}
|
|
74
|
+
export function clampDate(date, min, max) {
|
|
75
|
+
if (min && isBefore(date, min)) return min;
|
|
76
|
+
if (max && isAfter(date, max)) return max;
|
|
77
|
+
return date;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The six-week grid for a month.
|
|
82
|
+
*
|
|
83
|
+
* Always six rows, and always starting on the chosen first day of the week, so
|
|
84
|
+
* the calendar does not change height as the months are paged through. A grid
|
|
85
|
+
* that grows a row in March and loses it again in April makes everything below
|
|
86
|
+
* it jump, and the days themselves appear to move between months.
|
|
87
|
+
*
|
|
88
|
+
* The leading and trailing cells belong to the neighbouring months; whether
|
|
89
|
+
* they are drawn or left blank is the caller's decision.
|
|
90
|
+
*/
|
|
91
|
+
export function monthGrid(month, weekStartsOn) {
|
|
92
|
+
const first = startOfMonth(month);
|
|
93
|
+
// How far back to the most recent `weekStartsOn`. The `+ 7` keeps the
|
|
94
|
+
// modulo positive when the week starts later than the first of the month.
|
|
95
|
+
const lead = (first.getDay() - weekStartsOn + 7) % 7;
|
|
96
|
+
const start = addDays(first, -lead);
|
|
97
|
+
return Array.from({
|
|
98
|
+
length: 6
|
|
99
|
+
}, (_unusedWeek, week) => Array.from({
|
|
100
|
+
length: 7
|
|
101
|
+
}, (_unusedDay, day) => addDays(start, week * 7 + day)));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Formatting, guarded.
|
|
106
|
+
*
|
|
107
|
+
* `Intl` is on modern Hermes, but the data behind it is not guaranteed —
|
|
108
|
+
* builds without the full ICU set throw or return something unusable for
|
|
109
|
+
* locales they do not carry. Every formatter here falls back to English rather
|
|
110
|
+
* than taking the screen down over a month name.
|
|
111
|
+
*/
|
|
112
|
+
function format(date, locale, options) {
|
|
113
|
+
try {
|
|
114
|
+
return new Intl.DateTimeFormat(locale, options).format(date);
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* A locale tag carrying an explicit calendar and Latin digits.
|
|
122
|
+
*
|
|
123
|
+
* The calendar has to go in the *tag*, not in the options bag. Hermes builds
|
|
124
|
+
* its `Intl` on the platform's own date formatter, which reads the Unicode
|
|
125
|
+
* extension on a locale identifier but does not reliably honour `calendar` as
|
|
126
|
+
* an option — so `{ calendar: 'gregory' }` was quietly ignored and an Arabic
|
|
127
|
+
* device kept answering in Hijri. Any extension already on the tag is dropped
|
|
128
|
+
* first, so a caller passing `ar-u-ca-islamic` cannot end up with two.
|
|
129
|
+
*/
|
|
130
|
+
function withCalendar(locale, calendar) {
|
|
131
|
+
const base = (locale ?? 'en').split('-u-')[0] || 'en';
|
|
132
|
+
return `${base}-u-ca-${calendar}-nu-latn`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Gregorian formatting, pinned.
|
|
137
|
+
*
|
|
138
|
+
* Asking for a month name in Arabic without saying which calendar gets a Hijri
|
|
139
|
+
* one back, because that is what the locale resolves to — right for the
|
|
140
|
+
* language, wrong for a grid whose cells are counting Gregorian days. The
|
|
141
|
+
* digits are pinned too, so the caption and the numbers under it are in one
|
|
142
|
+
* set.
|
|
143
|
+
*/
|
|
144
|
+
function formatGregory(date, locale, options) {
|
|
145
|
+
return format(date, withCalendar(locale, 'gregory'), options) ??
|
|
146
|
+
// A build that cannot parse the extension at all still gets asked, in the
|
|
147
|
+
// hope that it honours the option instead.
|
|
148
|
+
format(date, locale, {
|
|
149
|
+
...options,
|
|
150
|
+
calendar: 'gregory',
|
|
151
|
+
numberingSystem: 'latn'
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* -------------------------------------------------------------------------- */
|
|
156
|
+
/* Calendar systems */
|
|
157
|
+
/* -------------------------------------------------------------------------- */
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Which calendar the months and day numbers are counted in.
|
|
161
|
+
*
|
|
162
|
+
* `auto` takes whatever the locale resolves to, which on an Arabic device is
|
|
163
|
+
* usually islamic. It is not the default: a grid whose month boundaries move
|
|
164
|
+
* with the device's language is a surprise, and the caller who wants that can
|
|
165
|
+
* ask for it.
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
/** Year, month and day as the chosen calendar counts them. 1-based month. */
|
|
169
|
+
|
|
170
|
+
/** What `auto` resolves to for a locale, falling back to the Gregorian. */
|
|
171
|
+
export function resolveCalendar(system, locale) {
|
|
172
|
+
if (system !== 'auto') return system;
|
|
173
|
+
try {
|
|
174
|
+
const resolved = new Intl.DateTimeFormat(locale).resolvedOptions().calendar ?? '';
|
|
175
|
+
return resolved.startsWith('islamic') ? 'islamic' : 'gregory';
|
|
176
|
+
} catch {
|
|
177
|
+
return 'gregory';
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* A date's year, month and day in the given calendar.
|
|
183
|
+
*
|
|
184
|
+
* `formatToParts` rather than a parsed string, because the order and the
|
|
185
|
+
* separators are the locale's business and we only want the numbers. The
|
|
186
|
+
* numbering system is pinned to Latin so the parts come back parseable
|
|
187
|
+
* whatever language is on the device, and so the cells and the caption above
|
|
188
|
+
* them end up in one set of digits.
|
|
189
|
+
*/
|
|
190
|
+
export function calendarParts(date, system, locale) {
|
|
191
|
+
if (system === 'gregory') {
|
|
192
|
+
return {
|
|
193
|
+
year: date.getFullYear(),
|
|
194
|
+
month: date.getMonth() + 1,
|
|
195
|
+
day: date.getDate()
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
try {
|
|
199
|
+
const parts = new Intl.DateTimeFormat(withCalendar(locale, 'islamic'), {
|
|
200
|
+
year: 'numeric',
|
|
201
|
+
month: 'numeric',
|
|
202
|
+
day: 'numeric'
|
|
203
|
+
}).formatToParts(date);
|
|
204
|
+
const read = type => Number(parts.find(part => part.type === type)?.value);
|
|
205
|
+
const year = read('year');
|
|
206
|
+
const month = read('month');
|
|
207
|
+
const day = read('day');
|
|
208
|
+
if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) {
|
|
209
|
+
throw new Error('unusable');
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
year,
|
|
213
|
+
month,
|
|
214
|
+
day
|
|
215
|
+
};
|
|
216
|
+
} catch {
|
|
217
|
+
// No islamic data in this build. Gregorian is wrong, but it is coherent —
|
|
218
|
+
// the grid, the caption and the cells will at least agree with each other.
|
|
219
|
+
return {
|
|
220
|
+
year: date.getFullYear(),
|
|
221
|
+
month: date.getMonth() + 1,
|
|
222
|
+
day: date.getDate()
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
export function isSameCalendarMonth(a, b, system, locale) {
|
|
227
|
+
if (system === 'gregory') return isSameMonth(a, b);
|
|
228
|
+
const one = calendarParts(a, system, locale);
|
|
229
|
+
const two = calendarParts(b, system, locale);
|
|
230
|
+
return one.year === two.year && one.month === two.month;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The first day of the calendar month `date` falls in.
|
|
235
|
+
*
|
|
236
|
+
* Walked back a day at a time rather than computed. A Hijri month is 29 or 30
|
|
237
|
+
* days depending on the year, and the platform's own calendar data already
|
|
238
|
+
* knows which — stepping until the day number reads 1 asks it, instead of
|
|
239
|
+
* shipping a table that will disagree with the device.
|
|
240
|
+
*/
|
|
241
|
+
export function startOfCalendarMonth(date, system, locale) {
|
|
242
|
+
if (system === 'gregory') return startOfMonth(date);
|
|
243
|
+
let cursor = startOfDay(date);
|
|
244
|
+
for (let step = 0; step < 31; step += 1) {
|
|
245
|
+
if (calendarParts(cursor, system, locale).day === 1) return cursor;
|
|
246
|
+
cursor = addDays(cursor, -1);
|
|
247
|
+
}
|
|
248
|
+
return cursor;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Days in the calendar month `date` falls in. */
|
|
252
|
+
export function daysInCalendarMonth(date, system, locale) {
|
|
253
|
+
if (system === 'gregory') return endOfMonth(date).getDate();
|
|
254
|
+
const start = startOfCalendarMonth(date, system, locale);
|
|
255
|
+
for (let length = 28; length <= 31; length += 1) {
|
|
256
|
+
if (calendarParts(addDays(start, length), system, locale).day === 1) return length;
|
|
257
|
+
}
|
|
258
|
+
return 30;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Page by whole calendar months, forwards or back. */
|
|
262
|
+
export function addCalendarMonths(date, months, system, locale) {
|
|
263
|
+
if (system === 'gregory') return addMonths(date, months);
|
|
264
|
+
let cursor = startOfCalendarMonth(date, system, locale);
|
|
265
|
+
for (let step = 0; step < Math.abs(months); step += 1) {
|
|
266
|
+
cursor = months > 0 ?
|
|
267
|
+
// One past the end of this month is the first of the next.
|
|
268
|
+
addDays(cursor, daysInCalendarMonth(cursor, system, locale)) :
|
|
269
|
+
// One before the start of this month is somewhere in the previous
|
|
270
|
+
// one, which then gets walked back to its own first day.
|
|
271
|
+
startOfCalendarMonth(addDays(cursor, -1), system, locale);
|
|
272
|
+
}
|
|
273
|
+
return cursor;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** The day-of-month a cell shows. */
|
|
277
|
+
export function calendarDayNumber(date, system, locale) {
|
|
278
|
+
return system === 'gregory' ? date.getDate() : calendarParts(date, system, locale).day;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/** "Ramadan 1447" or "March 2026", in whichever calendar is in force. */
|
|
282
|
+
export function calendarMonthLabel(date, system, locale) {
|
|
283
|
+
if (system === 'gregory') return monthLabel(date, locale);
|
|
284
|
+
return format(date, withCalendar(locale, 'islamic'), {
|
|
285
|
+
month: 'long',
|
|
286
|
+
year: 'numeric'
|
|
287
|
+
}) ?? monthLabel(date, locale);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* The names of a calendar's months, in order, for the dropdown.
|
|
292
|
+
*
|
|
293
|
+
* Sampled from a real year in that calendar rather than from twelve Gregorian
|
|
294
|
+
* firsts — the old code did the latter and got twelve arbitrary Hijri names in
|
|
295
|
+
* whatever order the Gregorian 1sts happened to fall, then indexed them by
|
|
296
|
+
* Gregorian month, which meant nothing at all.
|
|
297
|
+
*/
|
|
298
|
+
export function calendarMonthNames(reference, system, locale, style = 'short') {
|
|
299
|
+
if (system === 'gregory') return monthNames(locale, style);
|
|
300
|
+
const names = [];
|
|
301
|
+
let cursor = startOfCalendarMonth(reference, system, locale);
|
|
302
|
+
// Back to month 1 of this year, then forward through all twelve.
|
|
303
|
+
cursor = addCalendarMonths(cursor, -(calendarParts(cursor, system, locale).month - 1), system, locale);
|
|
304
|
+
for (let month = 0; month < 12; month += 1) {
|
|
305
|
+
names.push(format(cursor, withCalendar(locale, 'islamic'), {
|
|
306
|
+
month: style
|
|
307
|
+
}) ?? String(month + 1));
|
|
308
|
+
cursor = addCalendarMonths(cursor, 1, system, locale);
|
|
309
|
+
}
|
|
310
|
+
return names;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/** The whole date read out, in whichever calendar is in force. */
|
|
314
|
+
export function calendarLongDate(date, system, locale) {
|
|
315
|
+
if (system === 'gregory') return longDate(date, locale);
|
|
316
|
+
return format(date, withCalendar(locale, 'islamic'), {
|
|
317
|
+
weekday: 'long',
|
|
318
|
+
day: 'numeric',
|
|
319
|
+
month: 'long',
|
|
320
|
+
year: 'numeric'
|
|
321
|
+
}) ?? longDate(date, locale);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** The compact form a trigger shows, in whichever calendar is in force. */
|
|
325
|
+
export function calendarShortDate(date, system, locale) {
|
|
326
|
+
if (system === 'gregory') return shortDate(date, locale);
|
|
327
|
+
return format(date, withCalendar(locale, 'islamic'), {
|
|
328
|
+
day: 'numeric',
|
|
329
|
+
month: 'short',
|
|
330
|
+
year: 'numeric'
|
|
331
|
+
}) ?? shortDate(date, locale);
|
|
332
|
+
}
|
|
333
|
+
const MONTHS_EN = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
334
|
+
const WEEKDAYS_EN = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
335
|
+
|
|
336
|
+
/** Month names in order, for the caption and its dropdown. */
|
|
337
|
+
export function monthNames(locale, style = 'long') {
|
|
338
|
+
return MONTHS_EN.map((fallback, month) => {
|
|
339
|
+
const formatted = formatGregory(new Date(2021, month, 1), locale, {
|
|
340
|
+
month: style
|
|
341
|
+
});
|
|
342
|
+
return formatted ?? (style === 'short' ? fallback.slice(0, 3) : fallback);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** Column headings, rotated so the first one is `weekStartsOn`. */
|
|
347
|
+
export function weekdayNames(locale, weekStartsOn) {
|
|
348
|
+
// 2021-08-01 was a Sunday, so adding the index lands on each weekday in turn.
|
|
349
|
+
return Array.from({
|
|
350
|
+
length: 7
|
|
351
|
+
}, (_unused, day) => {
|
|
352
|
+
const index = (day + weekStartsOn) % 7;
|
|
353
|
+
const formatted = formatGregory(new Date(2021, 7, 1 + index), locale, {
|
|
354
|
+
weekday: 'short'
|
|
355
|
+
});
|
|
356
|
+
return formatted ?? WEEKDAYS_EN[index];
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** "March 2026", for the caption. */
|
|
361
|
+
export function monthLabel(date, locale) {
|
|
362
|
+
return formatGregory(date, locale, {
|
|
363
|
+
month: 'long',
|
|
364
|
+
year: 'numeric'
|
|
365
|
+
}) ?? `${MONTHS_EN[date.getMonth()]} ${date.getFullYear()}`;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/** "12 March 2026" — the whole date, for a screen reader to read out. */
|
|
369
|
+
export function longDate(date, locale) {
|
|
370
|
+
return formatGregory(date, locale, {
|
|
371
|
+
weekday: 'long',
|
|
372
|
+
day: 'numeric',
|
|
373
|
+
month: 'long',
|
|
374
|
+
year: 'numeric'
|
|
375
|
+
}) ?? `${WEEKDAYS_EN[date.getDay()]} ${date.getDate()} ${MONTHS_EN[date.getMonth()]} ${date.getFullYear()}`;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** "12 Mar 2026" — the compact form a trigger shows. */
|
|
379
|
+
export function shortDate(date, locale) {
|
|
380
|
+
return formatGregory(date, locale, {
|
|
381
|
+
day: 'numeric',
|
|
382
|
+
month: 'short',
|
|
383
|
+
year: 'numeric'
|
|
384
|
+
}) ?? `${date.getDate()} ${MONTHS_EN[date.getMonth()].slice(0, 3)} ${date.getFullYear()}`;
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=date.js.map
|