@blukavantui/charts-community 0.0.0-stage → 1.2.0
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/LICENSE.txt +103 -0
- package/README.md +98 -2
- package/THIRD_PARTY_NOTICES.txt +288 -0
- package/dist/accessibility.d.ts +53 -0
- package/dist/async.d.ts +2 -0
- package/dist/bar.css +1 -0
- package/dist/bar.d.ts +5 -0
- package/dist/bar.js +1 -0
- package/dist/browser/charts-community.css +1 -0
- package/dist/browser/charts-community.js +52 -0
- package/dist/build-audit.json +209 -0
- package/dist/builders/bar.d.ts +6 -0
- package/dist/builders/doughnut.d.ts +6 -0
- package/dist/builders/heatmap.d.ts +16 -0
- package/dist/builders/line.d.ts +6 -0
- package/dist/builders/pie.d.ts +6 -0
- package/dist/builders/radar.d.ts +6 -0
- package/dist/builders/scatter.d.ts +6 -0
- package/dist/catalogue-model.d.ts +11 -0
- package/dist/catalogue-runtime.d.ts +23 -0
- package/dist/catalogue-types.d.ts +167 -0
- package/dist/chart-state.d.ts +18 -0
- package/dist/chunk-2GUWWKHW.js +1 -0
- package/dist/chunk-3PITHTEO.js +1 -0
- package/dist/chunk-4B5MQ6GZ.js +1 -0
- package/dist/chunk-4EQMOBBN.js +1 -0
- package/dist/chunk-4WDZUJDS.js +1 -0
- package/dist/chunk-5NUOOMHV.js +1 -0
- package/dist/chunk-7OCMRHIH.js +1 -0
- package/dist/chunk-CF5Q2DDP.js +1 -0
- package/dist/chunk-EITBQBN2.js +1 -0
- package/dist/chunk-FXNKAHRG.js +1 -0
- package/dist/chunk-IDMAFTWV.js +1 -0
- package/dist/chunk-ILTENI35.js +1 -0
- package/dist/chunk-KRMM7EWI.js +1 -0
- package/dist/chunk-LUUPBBD4.js +1 -0
- package/dist/chunk-MR5VITXX.js +1 -0
- package/dist/chunk-NASBRHIW.js +1 -0
- package/dist/chunk-NXDBBMF5.js +1 -0
- package/dist/chunk-OQ6MP7PY.js +1 -0
- package/dist/chunk-RC2TCMJF.js +1 -0
- package/dist/chunk-RXOGAN23.js +1 -0
- package/dist/chunk-UGXWOWAG.js +2 -0
- package/dist/chunk-UO2KNHTU.js +2 -0
- package/dist/chunk-UQMMBG26.js +3 -0
- package/dist/chunk-VTJ4XPRV.js +1 -0
- package/dist/chunk-WJ3UHH6J.js +1 -0
- package/dist/chunk-XLJUSNGV.js +1 -0
- package/dist/colors.d.ts +15 -0
- package/dist/community.d.ts +11 -0
- package/dist/doughnut.css +1 -0
- package/dist/doughnut.d.ts +5 -0
- package/dist/doughnut.js +1 -0
- package/dist/export.d.ts +5 -0
- package/dist/fonts/dm-sans-LICENSE.txt +93 -0
- package/dist/fonts/dm-sans-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/dm-sans-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/dm-sans-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/dm-sans-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-LICENSE.txt +93 -0
- package/dist/fonts/ibm-plex-mono-latin-100-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-100-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-200-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-200-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-300-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-300-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-400-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-500-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-600-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-700-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-700-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-100-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-100-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-200-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-200-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-300-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-300-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-400-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-500-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-600-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-600-normal.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-700-italic.woff2 +0 -0
- package/dist/fonts/ibm-plex-mono-latin-ext-700-normal.woff2 +0 -0
- package/dist/fonts/inter-LICENSE.txt +93 -0
- package/dist/fonts/inter-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/inter-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/inter-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/inter-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-LICENSE.txt +93 -0
- package/dist/fonts/jetbrains-mono-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/jetbrains-mono-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/lora-LICENSE.txt +93 -0
- package/dist/fonts/lora-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/lora-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/lora-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/lora-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/manifest.json +618 -0
- package/dist/fonts/manrope-LICENSE.txt +93 -0
- package/dist/fonts/manrope-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/manrope-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/merriweather-LICENSE.txt +93 -0
- package/dist/fonts/merriweather-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/merriweather-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/merriweather-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/merriweather-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/montserrat-LICENSE.txt +93 -0
- package/dist/fonts/montserrat-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/montserrat-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/montserrat-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/montserrat-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-LICENSE.txt +93 -0
- package/dist/fonts/playfair-display-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/playfair-display-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/roboto-LICENSE.txt +93 -0
- package/dist/fonts/roboto-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/roboto-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/roboto-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/roboto-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/source-sans-3-LICENSE.txt +93 -0
- package/dist/fonts/source-sans-3-latin-ext-wght-italic.woff2 +0 -0
- package/dist/fonts/source-sans-3-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/source-sans-3-latin-wght-italic.woff2 +0 -0
- package/dist/fonts/source-sans-3-latin-wght-normal.woff2 +0 -0
- package/dist/heatmap.css +1 -0
- package/dist/heatmap.d.ts +3 -0
- package/dist/heatmap.js +1 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1 -0
- package/dist/legend-export.d.ts +9 -0
- package/dist/legend-model.d.ts +39 -0
- package/dist/legend.d.ts +19 -0
- package/dist/limits.d.ts +16 -0
- package/dist/line.css +1 -0
- package/dist/line.d.ts +5 -0
- package/dist/line.js +1 -0
- package/dist/loading-state.d.ts +6 -0
- package/dist/map-assets.d.ts +4 -0
- package/dist/map-resources.d.ts +24 -0
- package/dist/messages.d.ts +3 -0
- package/dist/model.d.ts +41 -0
- package/dist/motion/bar.css +1 -0
- package/dist/motion/bar.d.ts +8 -0
- package/dist/motion/bar.js +1 -0
- package/dist/motion/doughnut.css +1 -0
- package/dist/motion/doughnut.d.ts +8 -0
- package/dist/motion/doughnut.js +1 -0
- package/dist/motion/heatmap.css +1 -0
- package/dist/motion/heatmap.d.ts +7 -0
- package/dist/motion/heatmap.js +1 -0
- package/dist/motion/line.css +1 -0
- package/dist/motion/line.d.ts +8 -0
- package/dist/motion/line.js +1 -0
- package/dist/motion/pie.css +1 -0
- package/dist/motion/pie.d.ts +8 -0
- package/dist/motion/pie.js +1 -0
- package/dist/motion/radar.css +1 -0
- package/dist/motion/radar.d.ts +8 -0
- package/dist/motion/radar.js +1 -0
- package/dist/motion/scatter.css +1 -0
- package/dist/motion/scatter.d.ts +8 -0
- package/dist/motion/scatter.js +1 -0
- package/dist/motion/sparkline.d.ts +7 -0
- package/dist/motion/sparkline.js +1 -0
- package/dist/motion-collection.d.ts +7 -0
- package/dist/motion-community.d.ts +40 -0
- package/dist/motion-policy.d.ts +14 -0
- package/dist/motion.css +1 -0
- package/dist/motion.d.ts +40 -0
- package/dist/motion.js +1 -0
- package/dist/options.d.ts +11 -0
- package/dist/pie.css +1 -0
- package/dist/pie.d.ts +5 -0
- package/dist/pie.js +1 -0
- package/dist/radar.css +1 -0
- package/dist/radar.d.ts +4 -0
- package/dist/radar.js +1 -0
- package/dist/runtime.d.ts +4 -0
- package/dist/scatter.css +1 -0
- package/dist/scatter.d.ts +5 -0
- package/dist/scatter.js +1 -0
- package/dist/sparkline-runtime/runtime.d.ts +10 -0
- package/dist/sparkline-validation.d.ts +3 -0
- package/dist/sparkline.css +25 -0
- package/dist/sparkline.d.ts +44 -0
- package/dist/sparkline.js +1 -0
- package/dist/state-announcement.d.ts +6 -0
- package/dist/styles.css +496 -0
- package/dist/theme.css +1391 -0
- package/dist/types.d.ts +137 -0
- package/dist/validation.d.ts +8 -0
- package/dist/web-api.json +4305 -0
- package/dist/web-motion-sparkline.d.ts +4 -0
- package/edition.json +48 -0
- package/package.json +103 -4
- package/src/accessibility.ts +81 -0
- package/src/assets.d.ts +1 -0
- package/src/async.ts +12 -0
- package/src/bar.ts +13 -0
- package/src/builders/bar.ts +39 -0
- package/src/builders/doughnut.ts +66 -0
- package/src/builders/heatmap.ts +60 -0
- package/src/builders/line.ts +39 -0
- package/src/builders/pie.ts +66 -0
- package/src/builders/radar.ts +65 -0
- package/src/builders/scatter.ts +34 -0
- package/src/catalogue-model.ts +235 -0
- package/src/catalogue-runtime.ts +244 -0
- package/src/catalogue-types.ts +163 -0
- package/src/chart-state.ts +35 -0
- package/src/charts.css +135 -0
- package/src/colors.ts +277 -0
- package/src/community.ts +11 -0
- package/src/doughnut.ts +12 -0
- package/src/export.ts +50 -0
- package/src/heatmap.ts +11 -0
- package/src/index.ts +11 -0
- package/src/legend-export.ts +36 -0
- package/src/legend-model.ts +76 -0
- package/src/legend.css +64 -0
- package/src/legend.ts +90 -0
- package/src/limits.ts +7 -0
- package/src/line.ts +13 -0
- package/src/loading-state.ts +39 -0
- package/src/map-assets.ts +1 -0
- package/src/map-resources.ts +46 -0
- package/src/messages.ts +5 -0
- package/src/model.ts +32 -0
- package/src/motion/bar.ts +15 -0
- package/src/motion/doughnut.ts +14 -0
- package/src/motion/heatmap.ts +14 -0
- package/src/motion/line.ts +15 -0
- package/src/motion/pie.ts +14 -0
- package/src/motion/radar.ts +15 -0
- package/src/motion/scatter.ts +15 -0
- package/src/motion/sparkline.ts +10 -0
- package/src/motion-collection.ts +20 -0
- package/src/motion-community.ts +22 -0
- package/src/motion-policy.ts +36 -0
- package/src/options.ts +24 -0
- package/src/pie.ts +12 -0
- package/src/radar.ts +12 -0
- package/src/runtime.ts +7 -0
- package/src/scatter.ts +13 -0
- package/src/sparkline-runtime/runtime.d.ts +10 -0
- package/src/sparkline-runtime/runtime.js +263 -0
- package/src/sparkline-validation.ts +19 -0
- package/src/sparkline.css +25 -0
- package/src/sparkline.ts +68 -0
- package/src/state-announcement.ts +17 -0
- package/src/types.ts +104 -0
- package/src/validation.ts +75 -0
- package/src/web-motion-sparkline.ts +37 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/** Shared Web chart contracts; native inputs are normalized by the private adapter. */
|
|
2
|
+
export type ComponentColor = 'Default' | 'Primary' | 'Secondary' | 'Success' | 'Processing' | 'Warning' | 'Error' | 'Danger' | 'Magenta' | 'Red' | 'Volcano' | 'Orange' | 'Gold' | 'Lime' | 'Green' | 'Cyan' | 'Blue' | 'GeekBlue' | 'Purple';
|
|
3
|
+
export type ChartColor = ComponentColor | `#${string}`;
|
|
4
|
+
export type ChartFormat = 'png' | 'svg';
|
|
5
|
+
export type ValueFormat = 'Currency' | 'Number' | 'Percent';
|
|
6
|
+
export type LegendStyle = 'Standard' | 'ValueList' | 'Compact' | 'SummaryCards';
|
|
7
|
+
export type LegendPosition = 'Top' | 'Left' | 'Right' | 'Bottom';
|
|
8
|
+
export interface ChartIdentity { Key: string; Label: string; Color?: ChartColor }
|
|
9
|
+
export interface ChartDatum extends ChartIdentity { Value: number | null }
|
|
10
|
+
export interface ChartCategory extends ChartIdentity {}
|
|
11
|
+
export interface ChartOptions {
|
|
12
|
+
Title?: string;
|
|
13
|
+
Description?: string;
|
|
14
|
+
/** Plot height in pixels, excluding title, toolbar and data table. */
|
|
15
|
+
Height?: number;
|
|
16
|
+
ValueFormat?: ValueFormat;
|
|
17
|
+
CurrencyCode?: string;
|
|
18
|
+
Locale?: string;
|
|
19
|
+
UseCustomPrecision?: boolean;
|
|
20
|
+
/** Display precision only; the data alternative retains the original values. */
|
|
21
|
+
DecimalPlaces?: number;
|
|
22
|
+
AccessibleLabel?: string;
|
|
23
|
+
ExtendedClass?: string;
|
|
24
|
+
/** Change to reset map/treemap view state. */
|
|
25
|
+
ResetKey?: string;
|
|
26
|
+
/** Plain-text replacements for shared controls and announcements. */
|
|
27
|
+
Messages?: Record<string, string>;
|
|
28
|
+
ShowHeader?: boolean;
|
|
29
|
+
ShowToolbar?: boolean;
|
|
30
|
+
ShowLegend?: boolean;
|
|
31
|
+
LegendStyle?: LegendStyle;
|
|
32
|
+
LegendPosition?: LegendPosition;
|
|
33
|
+
LegendShowValues?: boolean;
|
|
34
|
+
/** Percentages only appear for meaningful partitions, separately for each nested ring. */
|
|
35
|
+
LegendShowPercentages?: boolean;
|
|
36
|
+
ShowTooltip?: boolean;
|
|
37
|
+
ShowLabels?: boolean;
|
|
38
|
+
ShowDataTable?: boolean;
|
|
39
|
+
/** Optional fill textures. Off by default; exact-value data remains available. */
|
|
40
|
+
ShowPatterns?: boolean;
|
|
41
|
+
EnableSelection?: boolean;
|
|
42
|
+
EnableAnimation?: boolean;
|
|
43
|
+
IsLoading?: boolean;
|
|
44
|
+
EmptyMessage?: string;
|
|
45
|
+
SelectedKey?: string | null;
|
|
46
|
+
ExportFootnote?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface MixedSeries {
|
|
49
|
+
Key: string;
|
|
50
|
+
Name: string;
|
|
51
|
+
Type: 'Bar' | 'Line';
|
|
52
|
+
/** One value per category. null means missing; zero is a real value. */
|
|
53
|
+
Values: (number | null)[];
|
|
54
|
+
/** Shared BluKavant ComponentColor or a custom hex color. */
|
|
55
|
+
Color?: ChartColor;
|
|
56
|
+
IsDashed?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface MixedChartOptions extends ChartOptions {
|
|
59
|
+
Categories: ChartCategory[];
|
|
60
|
+
Series: MixedSeries[];
|
|
61
|
+
BarLayout?: 'Stacked' | 'Grouped';
|
|
62
|
+
SmoothLines?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export interface HeatmapCell {
|
|
65
|
+
Key: string;
|
|
66
|
+
XKey: string;
|
|
67
|
+
YKey: string;
|
|
68
|
+
Value: number | null;
|
|
69
|
+
}
|
|
70
|
+
export interface HeatmapOptions extends ChartOptions {
|
|
71
|
+
XCategories: ChartCategory[];
|
|
72
|
+
YCategories: ChartCategory[];
|
|
73
|
+
Cells: HeatmapCell[];
|
|
74
|
+
ColorScale?: ComponentColor | 'Automatic' | 'Teal' | 'Diverging';
|
|
75
|
+
MinValue?: number;
|
|
76
|
+
MaxValue?: number;
|
|
77
|
+
}
|
|
78
|
+
export interface MixedPoint {
|
|
79
|
+
Key: string; CategoryLabel: string; SeriesKey: string; SeriesName: string; Value: number | null;
|
|
80
|
+
}
|
|
81
|
+
export interface HeatmapPoint extends HeatmapCell { XLabel: string; YLabel: string }
|
|
82
|
+
export interface ChartEvents<Point> {
|
|
83
|
+
PointClick?: (point: Point, origin?: 'Chart' | 'Table') => void;
|
|
84
|
+
SelectionChange?: (selection: { Key: string | null; Reason?: 'User' | 'DataChanged' }) => void;
|
|
85
|
+
Ready?: () => void;
|
|
86
|
+
StateChange?: (state: { State: 'Loading' | 'Ready' | 'Empty' | 'Error'; Revision: number }) => void;
|
|
87
|
+
PatternsChange?: (state: { ShowPatterns: boolean }) => void;
|
|
88
|
+
ExportStarted?: (result: { Format: ChartFormat; FileName: string; RequestId: string }) => void;
|
|
89
|
+
/** @deprecated Use ExportStarted. Completion means download initiated, not file saved. */
|
|
90
|
+
ExportComplete?: (result: { Format: ChartFormat; FileName: string }) => void;
|
|
91
|
+
Error?: (error: { Message: string; Code?: string; RequestId?: string }) => void;
|
|
92
|
+
}
|
|
93
|
+
export interface ChartInstance<Options> {
|
|
94
|
+
update(options: Partial<Options>): void;
|
|
95
|
+
resize(): void;
|
|
96
|
+
/** Silent application-controlled selection. Does not emit SelectionChange. */
|
|
97
|
+
setSelection(key: string | null): void;
|
|
98
|
+
/** Transient emphasis, useful for Grid row hover/click. */
|
|
99
|
+
highlight(key: string | null): void;
|
|
100
|
+
/** PNG defaults to 2× the plot resolution. Initiates a browser download. */
|
|
101
|
+
download(format?: ChartFormat, filename?: string, requestId?: string): Promise<void>;
|
|
102
|
+
/** Idempotent. Releases observers, events and the ECharts instance. */
|
|
103
|
+
destroy(): void;
|
|
104
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { ChartCategory, ChartOptions, MixedChartOptions, HeatmapOptions } from './types.ts';
|
|
2
|
+
import { isChartColor, isComponentColor } from './colors.ts';
|
|
3
|
+
import { boundedList, boundedText, safeNumber, limits } from './limits.ts';
|
|
4
|
+
|
|
5
|
+
export function assert(condition: unknown, message: string): asserts condition {
|
|
6
|
+
if (!condition) throw new Error(message);
|
|
7
|
+
}
|
|
8
|
+
export function categories(items: ChartCategory[], name: string) {
|
|
9
|
+
boundedList(items, name);
|
|
10
|
+
const keys = new Set<string>();
|
|
11
|
+
for (const item of items) {
|
|
12
|
+
assert(item && boundedText(item.Key) && item.Key.length > 0 && boundedText(item.Label), `${name} require a non-empty Key and a Label within the text limit.`);
|
|
13
|
+
assert(!keys.has(item.Key), `${name} contain a duplicate key: ${item.Key}.`);
|
|
14
|
+
keys.add(item.Key);
|
|
15
|
+
}
|
|
16
|
+
return keys;
|
|
17
|
+
}
|
|
18
|
+
export function value(value: unknown) { return value === null || safeNumber(value); }
|
|
19
|
+
export function base(options: ChartOptions) {
|
|
20
|
+
assert(options.Height === undefined || (Number.isFinite(options.Height) && options.Height >= 160 && options.Height <= 1000), 'Height must be between 160 and 1000 pixels.');
|
|
21
|
+
assert(options.ValueFormat === undefined || ['Currency', 'Number', 'Percent'].includes(options.ValueFormat), 'Invalid ValueFormat.');
|
|
22
|
+
for (const key of ['UseCustomPrecision','ShowHeader', 'ShowToolbar', 'ShowLegend', 'LegendShowValues', 'LegendShowPercentages', 'ShowTooltip', 'ShowLabels', 'ShowDataTable', 'ShowPatterns', 'EnableSelection', 'EnableAnimation', 'IsLoading'] as const) {
|
|
23
|
+
assert(options[key] === undefined || typeof options[key] === 'boolean', `${key} must be a boolean.`);
|
|
24
|
+
}
|
|
25
|
+
for (const key of ['AccessibleLabel','ExtendedClass','ResetKey','Title', 'Description', 'EmptyMessage', 'ExportFootnote', 'Locale', 'CurrencyCode'] as const) {
|
|
26
|
+
assert(options[key] === undefined || boundedText(options[key]), `${key} must be text within the text limit.`);
|
|
27
|
+
}
|
|
28
|
+
assert(options.LegendStyle === undefined || ['Standard', 'ValueList', 'Compact', 'SummaryCards'].includes(options.LegendStyle), 'Invalid LegendStyle.');
|
|
29
|
+
assert(options.LegendPosition === undefined || ['Top', 'Left', 'Right', 'Bottom'].includes(options.LegendPosition), 'Invalid LegendPosition.');
|
|
30
|
+
assert(options.DecimalPlaces === undefined || Number.isInteger(options.DecimalPlaces) && options.DecimalPlaces >= 0 && options.DecimalPlaces <= 12, 'DecimalPlaces must be an integer from 0 to 12.');
|
|
31
|
+
assert(options.Messages === undefined || !!options.Messages && typeof options.Messages === 'object' && !Array.isArray(options.Messages) && Object.keys(options.Messages).length <= 100 && Object.values(options.Messages).every(boundedText), 'Messages must contain plain text translations.');
|
|
32
|
+
new Intl.NumberFormat(options.Locale || 'en-US', options.ValueFormat === 'Currency' ? {style:'currency',currency:options.CurrencyCode || 'USD'} : {});
|
|
33
|
+
}
|
|
34
|
+
export function validateMixed(options: MixedChartOptions) {
|
|
35
|
+
base(options);
|
|
36
|
+
const keys = categories(options.Categories, 'Categories');
|
|
37
|
+
assert(options.SelectedKey == null || keys.has(options.SelectedKey), 'SelectedKey must match a category.');
|
|
38
|
+
assert(options.BarLayout === undefined || ['Stacked', 'Grouped'].includes(options.BarLayout), 'Invalid BarLayout.');
|
|
39
|
+
assert(options.SmoothLines === undefined || typeof options.SmoothLines === 'boolean', 'SmoothLines must be a boolean.');
|
|
40
|
+
boundedList(options.Series, 'Series');
|
|
41
|
+
assert(options.Categories.length * options.Series.length <= limits.observations, 'Too many chart observations. Aggregate the data first.');
|
|
42
|
+
const seriesKeys = new Set<string>();
|
|
43
|
+
for (const series of options.Series) {
|
|
44
|
+
assert(series && boundedText(series.Key) && series.Key.length && !seriesKeys.has(series.Key), 'Each series needs a unique, non-empty Key.');
|
|
45
|
+
seriesKeys.add(series.Key);
|
|
46
|
+
assert(boundedText(series.Name) && ['Bar', 'Line'].includes(series.Type), 'Each series needs a Name and a Bar or Line Type.');
|
|
47
|
+
assert(Array.isArray(series.Values) && series.Values.length === options.Categories.length, `${series.Key}: Values must match the category count.`);
|
|
48
|
+
assert(series.Values.every(value), `${series.Key}: Values must be finite numbers or null.`);
|
|
49
|
+
assert(series.Color === undefined || isChartColor(series.Color), 'Series Color must be a ComponentColor or hex color.');
|
|
50
|
+
assert(series.IsDashed === undefined || typeof series.IsDashed === 'boolean', 'IsDashed must be a boolean.');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function validateHeatmap(options: HeatmapOptions) {
|
|
54
|
+
base(options);
|
|
55
|
+
const x = categories(options.XCategories, 'XCategories'), y = categories(options.YCategories, 'YCategories');
|
|
56
|
+
boundedList(options.Cells, 'Cells');
|
|
57
|
+
assert(x.size * y.size <= limits.observations, 'Too many heatmap positions. Aggregate the data first.');
|
|
58
|
+
const keys = new Set<string>(), positions = new Set<string>();
|
|
59
|
+
for (const cell of options.Cells) {
|
|
60
|
+
assert(cell && typeof cell.Key === 'string' && cell.Key.length && !keys.has(cell.Key), 'Each cell needs a unique, non-empty Key.');
|
|
61
|
+
assert(x.has(cell.XKey) && y.has(cell.YKey), `${cell.Key}: XKey and YKey must match category keys.`);
|
|
62
|
+
const position = JSON.stringify([cell.XKey, cell.YKey]);
|
|
63
|
+
assert(!positions.has(position), 'Only one cell may occupy each X/Y position.');
|
|
64
|
+
assert(value(cell.Value), `${cell.Key}: Value must be a finite number or null.`);
|
|
65
|
+
positions.add(position); keys.add(cell.Key);
|
|
66
|
+
}
|
|
67
|
+
assert(options.SelectedKey == null || keys.has(options.SelectedKey), 'SelectedKey must match a cell.');
|
|
68
|
+
assert(options.ColorScale === undefined || (isComponentColor(options.ColorScale) || ['Automatic', 'Teal', 'Diverging'].includes(options.ColorScale)), 'Invalid ColorScale.');
|
|
69
|
+
assert(options.MinValue === undefined || Number.isFinite(options.MinValue), 'MinValue must be finite.');
|
|
70
|
+
assert(options.MaxValue === undefined || Number.isFinite(options.MaxValue), 'MaxValue must be finite.');
|
|
71
|
+
assert(options.MinValue === undefined || options.MaxValue === undefined || options.MinValue < options.MaxValue, 'MinValue must be less than MaxValue.');
|
|
72
|
+
}
|
|
73
|
+
export function escapeText(text: string): string {
|
|
74
|
+
return text.replace(/[&<>"']/g, char => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[char]!));
|
|
75
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Local opt-in adapter. The compact SVG runtime and its ordinary defaults stay intact. */
|
|
2
|
+
import { createSparkline, type SparklineOptions, type SparklineEvents } from './sparkline.ts';
|
|
3
|
+
import { validateSparkline } from './sparkline-validation.ts';
|
|
4
|
+
import type { ChartPresentation } from './catalogue-runtime.ts';
|
|
5
|
+
export function createMotionSparkline(host: HTMLElement, options: SparklineOptions, events: SparklineEvents, policy: ChartPresentation) {
|
|
6
|
+
let requested = structuredClone(options), dead = false, paused = false;
|
|
7
|
+
const effective = () => {
|
|
8
|
+
if(policy.enabled?.()===false)return {...requested};
|
|
9
|
+
const animation=requested.Animation??(requested.AnimateGlow===false?'Off':'Once');
|
|
10
|
+
return {...requested,Animation:policy.mode(host)!=='full'||(animation==='Once'&&policy.timing?.().duration===0)?'Off':animation} as SparklineOptions;
|
|
11
|
+
};
|
|
12
|
+
function finiteTiming() {
|
|
13
|
+
if(policy.enabled?.()===false||effective().Animation!=='Once')return; // Continuous glow keeps its own cadence and Pause control.
|
|
14
|
+
const timing=policy.timing?.();
|
|
15
|
+
for(const element of instance.element.querySelectorAll('animateMotion')){
|
|
16
|
+
if(timing?.duration!==undefined)element.setAttribute('dur',timing.duration/1000+'s');
|
|
17
|
+
const curve=timing?.curve?.match(/^cubic-bezier\((.+)\)$/)?.[1];
|
|
18
|
+
if(curve){element.setAttribute('calcMode','spline');element.setAttribute('keyTimes','0;1');element.setAttribute('keySplines',curve.split(',').map(v=>Math.max(0,Math.min(1,Number(v)))).join(' '));}
|
|
19
|
+
else if(timing?.curve==='linear')element.setAttribute('calcMode','linear');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const instance = createSparkline(host, effective(), events), update = instance.update, destroy = instance.destroy;
|
|
23
|
+
const pauseState = (event: Event) => { if (!(event.target instanceof Element) || !event.target.closest('.blu-sparkline__pause')) return; const svg = instance.element.querySelector('svg'); if (svg?.animationsPaused) paused = svg.animationsPaused(); };
|
|
24
|
+
// Preserve the user's Pause choice across scope changes and recreated SVGs.
|
|
25
|
+
instance.element.addEventListener('click', pauseState);
|
|
26
|
+
const restorePause = () => { const svg = instance.element.querySelector('svg'); if (paused && svg?.animationsPaused && !svg.animationsPaused()) instance.element.querySelector<HTMLButtonElement>('.blu-sparkline__pause')?.click(); };
|
|
27
|
+
finiteTiming();
|
|
28
|
+
const stop = policy.subscribe(host, () => { update(effective()); finiteTiming(); restorePause(); });
|
|
29
|
+
instance.update = patch => {
|
|
30
|
+
if (dead) throw Error('Component is destroyed.');
|
|
31
|
+
const next = { ...requested, ...structuredClone(patch) }; validateSparkline(next);
|
|
32
|
+
if (patch.Animation !== undefined && patch.Animation !== requested.Animation) paused = false;
|
|
33
|
+
requested = next; update(effective()); finiteTiming(); restorePause();
|
|
34
|
+
};
|
|
35
|
+
instance.destroy = () => { if (dead) return; dead = true; stop(); instance.element.removeEventListener('click', pauseState); destroy(); };
|
|
36
|
+
return instance;
|
|
37
|
+
}
|