@techfides/ui-library-design 0.1.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 +21 -0
- package/README.md +55 -0
- package/assets/brands/digital-boost-group.svg +1 -0
- package/assets/brands/rtsg.svg +1 -0
- package/assets/brands/tech-it-out.svg +1 -0
- package/assets/brands/techfides.svg +1 -0
- package/css/index.css +8 -0
- package/css/theme.css +1640 -0
- package/dist/brands.d.ts +39 -0
- package/dist/brands.js +41 -0
- package/dist/brands.js.map +1 -0
- package/dist/charts/animation.js +14 -0
- package/dist/charts/animation.js.map +1 -0
- package/dist/charts/bars.d.ts +22 -0
- package/dist/charts/bars.js +61 -0
- package/dist/charts/bars.js.map +1 -0
- package/dist/charts/groupedBars.d.ts +20 -0
- package/dist/charts/groupedBars.js +82 -0
- package/dist/charts/groupedBars.js.map +1 -0
- package/dist/charts/paint.js +19 -0
- package/dist/charts/paint.js.map +1 -0
- package/dist/charts/spark.d.ts +17 -0
- package/dist/charts/spark.js +159 -0
- package/dist/charts/spark.js.map +1 -0
- package/dist/charts/tooltip.js +41 -0
- package/dist/charts/tooltip.js.map +1 -0
- package/dist/cn.d.ts +6 -0
- package/dist/cn.js +178 -0
- package/dist/cn.js.map +1 -0
- package/dist/control.d.ts +15 -0
- package/dist/control.js +13 -0
- package/dist/control.js.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +65 -0
- package/dist/mark.d.ts +7 -0
- package/dist/mark.js +11 -0
- package/dist/mark.js.map +1 -0
- package/dist/parts/control.js +55 -0
- package/dist/parts/control.js.map +1 -0
- package/dist/parts/eyebrow.js +8 -0
- package/dist/parts/eyebrow.js.map +1 -0
- package/dist/parts/mark.js +52 -0
- package/dist/parts/mark.js.map +1 -0
- package/dist/parts/reveal.js +35 -0
- package/dist/parts/reveal.js.map +1 -0
- package/dist/parts/rouse.js +25 -0
- package/dist/parts/rouse.js.map +1 -0
- package/dist/parts/rule.js +12 -0
- package/dist/parts/rule.js.map +1 -0
- package/dist/parts/scroll.js +10 -0
- package/dist/parts/scroll.js.map +1 -0
- package/dist/parts/shell.js +23 -0
- package/dist/parts/shell.js.map +1 -0
- package/dist/parts/surface.js +15 -0
- package/dist/parts/surface.js.map +1 -0
- package/dist/parts/tone.js +13 -0
- package/dist/parts/tone.js.map +1 -0
- package/dist/parts/travel.js +11 -0
- package/dist/parts/travel.js.map +1 -0
- package/dist/recipes/accordion.d.ts +13 -0
- package/dist/recipes/accordion.js +42 -0
- package/dist/recipes/accordion.js.map +1 -0
- package/dist/recipes/alert.d.ts +16 -0
- package/dist/recipes/alert.js +21 -0
- package/dist/recipes/alert.js.map +1 -0
- package/dist/recipes/band.d.ts +8 -0
- package/dist/recipes/band.js +22 -0
- package/dist/recipes/band.js.map +1 -0
- package/dist/recipes/bars.d.ts +17 -0
- package/dist/recipes/bars.js +27 -0
- package/dist/recipes/bars.js.map +1 -0
- package/dist/recipes/brandMark.d.ts +5 -0
- package/dist/recipes/brandMark.js +7 -0
- package/dist/recipes/brandMark.js.map +1 -0
- package/dist/recipes/button.d.ts +23 -0
- package/dist/recipes/button.js +229 -0
- package/dist/recipes/button.js.map +1 -0
- package/dist/recipes/cardHeader.d.ts +10 -0
- package/dist/recipes/cardHeader.js +11 -0
- package/dist/recipes/cardHeader.js.map +1 -0
- package/dist/recipes/checkbox.d.ts +26 -0
- package/dist/recipes/checkbox.js +103 -0
- package/dist/recipes/checkbox.js.map +1 -0
- package/dist/recipes/chip.d.ts +26 -0
- package/dist/recipes/chip.js +123 -0
- package/dist/recipes/chip.js.map +1 -0
- package/dist/recipes/codeEditor.d.ts +74 -0
- package/dist/recipes/codeEditor.js +71 -0
- package/dist/recipes/codeEditor.js.map +1 -0
- package/dist/recipes/datePicker.d.ts +39 -0
- package/dist/recipes/datePicker.js +166 -0
- package/dist/recipes/datePicker.js.map +1 -0
- package/dist/recipes/dialog.d.ts +37 -0
- package/dist/recipes/dialog.js +116 -0
- package/dist/recipes/dialog.js.map +1 -0
- package/dist/recipes/feature.d.ts +15 -0
- package/dist/recipes/feature.js +48 -0
- package/dist/recipes/feature.js.map +1 -0
- package/dist/recipes/field.d.ts +26 -0
- package/dist/recipes/field.js +129 -0
- package/dist/recipes/field.js.map +1 -0
- package/dist/recipes/findings.d.ts +11 -0
- package/dist/recipes/findings.js +16 -0
- package/dist/recipes/findings.js.map +1 -0
- package/dist/recipes/heading.d.ts +17 -0
- package/dist/recipes/heading.js +37 -0
- package/dist/recipes/heading.js.map +1 -0
- package/dist/recipes/heartbeat.d.ts +23 -0
- package/dist/recipes/heartbeat.js +43 -0
- package/dist/recipes/heartbeat.js.map +1 -0
- package/dist/recipes/input.d.ts +17 -0
- package/dist/recipes/input.js +90 -0
- package/dist/recipes/input.js.map +1 -0
- package/dist/recipes/listItem.d.ts +6 -0
- package/dist/recipes/listItem.js +8 -0
- package/dist/recipes/listItem.js.map +1 -0
- package/dist/recipes/listbox.d.ts +12 -0
- package/dist/recipes/listbox.js +29 -0
- package/dist/recipes/listbox.js.map +1 -0
- package/dist/recipes/marquee.d.ts +19 -0
- package/dist/recipes/marquee.js +36 -0
- package/dist/recipes/marquee.js.map +1 -0
- package/dist/recipes/menu.d.ts +26 -0
- package/dist/recipes/menu.js +86 -0
- package/dist/recipes/menu.js.map +1 -0
- package/dist/recipes/metaRow.d.ts +14 -0
- package/dist/recipes/metaRow.js +19 -0
- package/dist/recipes/metaRow.js.map +1 -0
- package/dist/recipes/meter.d.ts +23 -0
- package/dist/recipes/meter.js +39 -0
- package/dist/recipes/meter.js.map +1 -0
- package/dist/recipes/motion.d.ts +6 -0
- package/dist/recipes/motion.js +34 -0
- package/dist/recipes/motion.js.map +1 -0
- package/dist/recipes/nebula.d.ts +9 -0
- package/dist/recipes/nebula.js +15 -0
- package/dist/recipes/nebula.js.map +1 -0
- package/dist/recipes/numberRange.d.ts +15 -0
- package/dist/recipes/numberRange.js +109 -0
- package/dist/recipes/numberRange.js.map +1 -0
- package/dist/recipes/paper.d.ts +22 -0
- package/dist/recipes/paper.js +42 -0
- package/dist/recipes/paper.js.map +1 -0
- package/dist/recipes/progressBar.d.ts +7 -0
- package/dist/recipes/progressBar.js +11 -0
- package/dist/recipes/progressBar.js.map +1 -0
- package/dist/recipes/queue.d.ts +16 -0
- package/dist/recipes/queue.js +27 -0
- package/dist/recipes/queue.js.map +1 -0
- package/dist/recipes/radioGroup.d.ts +27 -0
- package/dist/recipes/radioGroup.js +68 -0
- package/dist/recipes/radioGroup.js.map +1 -0
- package/dist/recipes/scopeSwitcher.d.ts +26 -0
- package/dist/recipes/scopeSwitcher.js +80 -0
- package/dist/recipes/scopeSwitcher.js.map +1 -0
- package/dist/recipes/scrollArea.d.ts +19 -0
- package/dist/recipes/scrollArea.js +43 -0
- package/dist/recipes/scrollArea.js.map +1 -0
- package/dist/recipes/searchPalette.d.ts +19 -0
- package/dist/recipes/searchPalette.js +63 -0
- package/dist/recipes/searchPalette.js.map +1 -0
- package/dist/recipes/sectionHeader.d.ts +9 -0
- package/dist/recipes/sectionHeader.js +10 -0
- package/dist/recipes/sectionHeader.js.map +1 -0
- package/dist/recipes/segmentedControl.d.ts +9 -0
- package/dist/recipes/segmentedControl.js +29 -0
- package/dist/recipes/segmentedControl.js.map +1 -0
- package/dist/recipes/select.d.ts +9 -0
- package/dist/recipes/select.js +21 -0
- package/dist/recipes/select.js.map +1 -0
- package/dist/recipes/separator.d.ts +14 -0
- package/dist/recipes/separator.js +59 -0
- package/dist/recipes/separator.js.map +1 -0
- package/dist/recipes/sidebar.d.ts +40 -0
- package/dist/recipes/sidebar.js +128 -0
- package/dist/recipes/sidebar.js.map +1 -0
- package/dist/recipes/sky.d.ts +20 -0
- package/dist/recipes/sky.js +127 -0
- package/dist/recipes/sky.js.map +1 -0
- package/dist/recipes/slider.d.ts +20 -0
- package/dist/recipes/slider.js +62 -0
- package/dist/recipes/slider.js.map +1 -0
- package/dist/recipes/stat.d.ts +30 -0
- package/dist/recipes/stat.js +52 -0
- package/dist/recipes/stat.js.map +1 -0
- package/dist/recipes/switch.d.ts +20 -0
- package/dist/recipes/switch.js +60 -0
- package/dist/recipes/switch.js.map +1 -0
- package/dist/recipes/table.d.ts +74 -0
- package/dist/recipes/table.js +182 -0
- package/dist/recipes/table.js.map +1 -0
- package/dist/recipes/tableFilter.d.ts +14 -0
- package/dist/recipes/tableFilter.js +28 -0
- package/dist/recipes/tableFilter.js.map +1 -0
- package/dist/recipes/tablePaging.d.ts +15 -0
- package/dist/recipes/tablePaging.js +50 -0
- package/dist/recipes/tablePaging.js.map +1 -0
- package/dist/recipes/tail.d.ts +20 -0
- package/dist/recipes/tail.js +48 -0
- package/dist/recipes/tail.js.map +1 -0
- package/dist/recipes/text.d.ts +25 -0
- package/dist/recipes/text.js +94 -0
- package/dist/recipes/text.js.map +1 -0
- package/dist/recipes/textarea.d.ts +13 -0
- package/dist/recipes/textarea.js +48 -0
- package/dist/recipes/textarea.js.map +1 -0
- package/dist/recipes/tile.d.ts +18 -0
- package/dist/recipes/tile.js +85 -0
- package/dist/recipes/tile.js.map +1 -0
- package/dist/recipes/tooltip.d.ts +12 -0
- package/dist/recipes/tooltip.js +26 -0
- package/dist/recipes/tooltip.js.map +1 -0
- package/dist/recipes/topBar.d.ts +15 -0
- package/dist/recipes/topBar.js +35 -0
- package/dist/recipes/topBar.js.map +1 -0
- package/dist/recipes/trail.d.ts +27 -0
- package/dist/recipes/trail.js +66 -0
- package/dist/recipes/trail.js.map +1 -0
- package/dist/recipes/userMenu.d.ts +11 -0
- package/dist/recipes/userMenu.js +38 -0
- package/dist/recipes/userMenu.js.map +1 -0
- package/dist/tally.d.ts +17 -0
- package/dist/tally.js +75 -0
- package/dist/tally.js.map +1 -0
- package/dist/tone.d.ts +26 -0
- package/dist/tone.js +26 -0
- package/dist/tone.js.map +1 -0
- package/dist/words.d.ts +116 -0
- package/dist/words.js +93 -0
- package/dist/words.js.map +1 -0
- package/package.json +72 -0
package/dist/brands.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/brands.d.ts
|
|
2
|
+
type BrandSlug = 'techfides' | 'tech-it-out' | 'rtsg' | 'digital-boost-group';
|
|
3
|
+
interface Brand {
|
|
4
|
+
accent: string;
|
|
5
|
+
asset: string;
|
|
6
|
+
domain: string;
|
|
7
|
+
slug: BrandSlug;
|
|
8
|
+
title: string;
|
|
9
|
+
}
|
|
10
|
+
declare const brands: readonly [{
|
|
11
|
+
readonly accent: "#0075c9";
|
|
12
|
+
readonly asset: "assets/brands/techfides.svg";
|
|
13
|
+
readonly domain: "techfides.cz";
|
|
14
|
+
readonly slug: "techfides";
|
|
15
|
+
readonly title: "TechFides";
|
|
16
|
+
}, {
|
|
17
|
+
readonly accent: "#84bd23";
|
|
18
|
+
readonly asset: "assets/brands/tech-it-out.svg";
|
|
19
|
+
readonly domain: "techitout.io";
|
|
20
|
+
readonly slug: "tech-it-out";
|
|
21
|
+
readonly title: "Tech It Out";
|
|
22
|
+
}, {
|
|
23
|
+
readonly accent: "#eb7500";
|
|
24
|
+
readonly asset: "assets/brands/rtsg.svg";
|
|
25
|
+
readonly domain: "rtsg.cz";
|
|
26
|
+
readonly slug: "rtsg";
|
|
27
|
+
readonly title: "RTSG";
|
|
28
|
+
}, {
|
|
29
|
+
readonly accent: "#995fd2";
|
|
30
|
+
readonly asset: "assets/brands/digital-boost-group.svg";
|
|
31
|
+
readonly domain: "digitalboostgroup.cz";
|
|
32
|
+
readonly slug: "digital-boost-group";
|
|
33
|
+
readonly title: "Digital Boost Group";
|
|
34
|
+
}];
|
|
35
|
+
declare const defaultBrand: BrandSlug;
|
|
36
|
+
declare const brandTitle: (slug: string) => string;
|
|
37
|
+
//#endregion
|
|
38
|
+
export { type Brand, type BrandSlug, brandTitle, brands, defaultBrand };
|
|
39
|
+
//# sourceMappingURL=brands.d.ts.map
|
package/dist/brands.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/brands.ts
|
|
2
|
+
const brands = [
|
|
3
|
+
{
|
|
4
|
+
accent: "#0075c9",
|
|
5
|
+
asset: "assets/brands/techfides.svg",
|
|
6
|
+
domain: "techfides.cz",
|
|
7
|
+
slug: "techfides",
|
|
8
|
+
title: "TechFides"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
accent: "#84bd23",
|
|
12
|
+
asset: "assets/brands/tech-it-out.svg",
|
|
13
|
+
domain: "techitout.io",
|
|
14
|
+
slug: "tech-it-out",
|
|
15
|
+
title: "Tech It Out"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
accent: "#eb7500",
|
|
19
|
+
asset: "assets/brands/rtsg.svg",
|
|
20
|
+
domain: "rtsg.cz",
|
|
21
|
+
slug: "rtsg",
|
|
22
|
+
title: "RTSG"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
accent: "#995fd2",
|
|
26
|
+
asset: "assets/brands/digital-boost-group.svg",
|
|
27
|
+
domain: "digitalboostgroup.cz",
|
|
28
|
+
slug: "digital-boost-group",
|
|
29
|
+
title: "Digital Boost Group"
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
const defaultBrand = "techfides";
|
|
33
|
+
const brandTitle = (slug) => {
|
|
34
|
+
const match = brands.find((brand) => brand.slug === slug);
|
|
35
|
+
if (match) return match.title;
|
|
36
|
+
return slug;
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { brandTitle, brands, defaultBrand };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=brands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brands.js","names":[],"sources":["../src/brands.ts"],"sourcesContent":["type BrandSlug = 'techfides' | 'tech-it-out' | 'rtsg' | 'digital-boost-group'\n\ninterface Brand {\n accent: string\n asset: string\n domain: string\n slug: BrandSlug\n title: string\n}\n\nconst brands = [\n {\n accent: '#0075c9',\n asset: 'assets/brands/techfides.svg',\n domain: 'techfides.cz',\n slug: 'techfides',\n title: 'TechFides',\n },\n {\n accent: '#84bd23',\n asset: 'assets/brands/tech-it-out.svg',\n domain: 'techitout.io',\n slug: 'tech-it-out',\n title: 'Tech It Out',\n },\n {\n accent: '#eb7500',\n asset: 'assets/brands/rtsg.svg',\n domain: 'rtsg.cz',\n slug: 'rtsg',\n title: 'RTSG',\n },\n {\n accent: '#995fd2',\n asset: 'assets/brands/digital-boost-group.svg',\n domain: 'digitalboostgroup.cz',\n slug: 'digital-boost-group',\n title: 'Digital Boost Group',\n },\n] as const satisfies readonly Brand[]\n\nconst defaultBrand: BrandSlug = 'techfides'\n\nconst brandTitle = (slug: string): string => {\n const match = brands.find((brand) => brand.slug === slug)\n if (match) {\n return match.title\n }\n return slug\n}\n\nexport type { Brand, BrandSlug }\nexport { brandTitle, brands, defaultBrand }\n"],"mappings":";AAUA,MAAM,SAAS;CACb;EACE,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,MAAM;EACN,OAAO;CACT;CACA;EACE,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,MAAM;EACN,OAAO;CACT;CACA;EACE,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,MAAM;EACN,OAAO;CACT;CACA;EACE,QAAQ;EACR,OAAO;EACP,QAAQ;EACR,MAAM;EACN,OAAO;CACT;AACF;AAEA,MAAM,eAA0B;AAEhC,MAAM,cAAc,SAAyB;CAC3C,MAAM,QAAQ,OAAO,MAAM,UAAU,MAAM,SAAS,IAAI;CACxD,IAAI,OACF,OAAO,MAAM;CAEf,OAAO;AACT"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/charts/animation.ts
|
|
2
|
+
const CHART_EASING = "cubicOut";
|
|
3
|
+
const chartAnimation = (durationMs) => ({
|
|
4
|
+
animation: true,
|
|
5
|
+
animationDuration: durationMs,
|
|
6
|
+
animationDurationUpdate: durationMs,
|
|
7
|
+
animationEasing: CHART_EASING,
|
|
8
|
+
animationEasingUpdate: CHART_EASING
|
|
9
|
+
});
|
|
10
|
+
const chartStagger = (stepMs) => (index) => index * stepMs;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { CHART_EASING, chartAnimation, chartStagger };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=animation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animation.js","names":[],"sources":["../../src/charts/animation.ts"],"sourcesContent":["import type { EChartsOption } from 'echarts'\n\nconst CHART_EASING = 'cubicOut'\n\ntype ChartAnimation = Pick<\n EChartsOption,\n | 'animation'\n | 'animationDuration'\n | 'animationDurationUpdate'\n | 'animationEasing'\n | 'animationEasingUpdate'\n>\n\nconst chartAnimation = (durationMs: number): ChartAnimation => ({\n animation: true,\n animationDuration: durationMs,\n animationDurationUpdate: durationMs,\n animationEasing: CHART_EASING,\n animationEasingUpdate: CHART_EASING,\n})\n\nconst chartStagger =\n (stepMs: number) =>\n (index: number): number =>\n index * stepMs\n\nexport { CHART_EASING, chartAnimation, chartStagger }\n"],"mappings":";AAEA,MAAM,eAAe;AAWrB,MAAM,kBAAkB,gBAAwC;CAC9D,WAAW;CACX,mBAAmB;CACnB,yBAAyB;CACzB,iBAAiB;CACjB,uBAAuB;AACzB;AAEA,MAAM,gBACH,YACA,UACC,QAAQ"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EChartsOption } from "echarts";
|
|
2
|
+
//#region src/charts/bars.d.ts
|
|
3
|
+
interface BarsAccent {
|
|
4
|
+
hi: string;
|
|
5
|
+
surface: string;
|
|
6
|
+
}
|
|
7
|
+
interface BarsPoint {
|
|
8
|
+
label: string;
|
|
9
|
+
value: number | null;
|
|
10
|
+
}
|
|
11
|
+
interface BarsOptionInput {
|
|
12
|
+
accent: BarsAccent;
|
|
13
|
+
durationMs: number;
|
|
14
|
+
labelColor: string;
|
|
15
|
+
radius: number;
|
|
16
|
+
stateDurationMs: number;
|
|
17
|
+
values: readonly BarsPoint[];
|
|
18
|
+
}
|
|
19
|
+
declare const barsOption: (input: BarsOptionInput) => EChartsOption;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { type BarsAccent, type BarsOptionInput, type BarsPoint, barsOption };
|
|
22
|
+
//# sourceMappingURL=bars.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { CHART_EASING, chartAnimation, chartStagger } from "./animation.js";
|
|
2
|
+
import { verticalGradient } from "./paint.js";
|
|
3
|
+
import { chartTooltip, formatCallbackValue } from "./tooltip.js";
|
|
4
|
+
//#region src/charts/bars.ts
|
|
5
|
+
const GRID = {
|
|
6
|
+
bottom: 22,
|
|
7
|
+
left: 4,
|
|
8
|
+
right: 4,
|
|
9
|
+
top: 8
|
|
10
|
+
};
|
|
11
|
+
const BAR_CATEGORY_GAP = "35%";
|
|
12
|
+
const LABEL_FONT_SIZE = 11;
|
|
13
|
+
const STAGGER_MS = 40;
|
|
14
|
+
const EMPTY_LENGTH = 0;
|
|
15
|
+
const FIRST_INDEX = 0;
|
|
16
|
+
const barPointFormatter = (params) => {
|
|
17
|
+
const point = params[FIRST_INDEX];
|
|
18
|
+
if (!point) return "";
|
|
19
|
+
return `${point.name}: ${formatCallbackValue(point.value)}`;
|
|
20
|
+
};
|
|
21
|
+
const barsOption = (input) => {
|
|
22
|
+
if (input.values.length === EMPTY_LENGTH) return { series: [] };
|
|
23
|
+
return {
|
|
24
|
+
...chartAnimation(input.durationMs),
|
|
25
|
+
grid: GRID,
|
|
26
|
+
series: [{
|
|
27
|
+
animationDelay: chartStagger(STAGGER_MS),
|
|
28
|
+
barCategoryGap: BAR_CATEGORY_GAP,
|
|
29
|
+
data: input.values.map((point) => point.value),
|
|
30
|
+
emphasis: { disabled: true },
|
|
31
|
+
itemStyle: {
|
|
32
|
+
borderRadius: input.radius,
|
|
33
|
+
color: verticalGradient(input.accent.hi, input.accent.surface)
|
|
34
|
+
},
|
|
35
|
+
stateAnimation: {
|
|
36
|
+
duration: input.stateDurationMs,
|
|
37
|
+
easing: CHART_EASING
|
|
38
|
+
},
|
|
39
|
+
type: "bar"
|
|
40
|
+
}],
|
|
41
|
+
tooltip: chartTooltip(barPointFormatter),
|
|
42
|
+
xAxis: {
|
|
43
|
+
axisLabel: {
|
|
44
|
+
color: input.labelColor,
|
|
45
|
+
fontSize: LABEL_FONT_SIZE
|
|
46
|
+
},
|
|
47
|
+
axisLine: { show: false },
|
|
48
|
+
axisTick: { show: false },
|
|
49
|
+
data: input.values.map((point) => point.label),
|
|
50
|
+
type: "category"
|
|
51
|
+
},
|
|
52
|
+
yAxis: {
|
|
53
|
+
show: false,
|
|
54
|
+
type: "value"
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { barsOption };
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=bars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bars.js","names":[],"sources":["../../src/charts/bars.ts"],"sourcesContent":["import type { DefaultLabelFormatterCallbackParams, EChartsOption } from 'echarts'\n\nimport { CHART_EASING, chartAnimation, chartStagger } from './animation'\nimport { verticalGradient } from './paint'\nimport { chartTooltip, formatCallbackValue } from './tooltip'\n\ninterface BarsAccent {\n hi: string\n\n surface: string\n}\n\ninterface BarsPoint {\n label: string\n\n value: number | null\n}\n\ninterface BarsOptionInput {\n accent: BarsAccent\n\n durationMs: number\n\n labelColor: string\n\n radius: number\n\n stateDurationMs: number\n\n values: readonly BarsPoint[]\n}\n\nconst GRID = { bottom: 22, left: 4, right: 4, top: 8 }\n\nconst BAR_CATEGORY_GAP = '35%'\n\nconst LABEL_FONT_SIZE = 11\n\nconst STAGGER_MS = 40\n\nconst EMPTY_LENGTH = 0\n\nconst FIRST_INDEX = 0\n\nconst barPointFormatter = (params: readonly DefaultLabelFormatterCallbackParams[]): string => {\n const point = params[FIRST_INDEX]\n\n if (!point) {\n return ''\n }\n return `${point.name}: ${formatCallbackValue(point.value)}`\n}\n\nconst barsOption = (input: BarsOptionInput): EChartsOption => {\n if (input.values.length === EMPTY_LENGTH) {\n return { series: [] }\n }\n return {\n ...chartAnimation(input.durationMs),\n grid: GRID,\n series: [\n {\n animationDelay: chartStagger(STAGGER_MS),\n barCategoryGap: BAR_CATEGORY_GAP,\n data: input.values.map((point) => point.value),\n emphasis: { disabled: true },\n itemStyle: {\n borderRadius: input.radius,\n color: verticalGradient(input.accent.hi, input.accent.surface),\n },\n stateAnimation: { duration: input.stateDurationMs, easing: CHART_EASING },\n type: 'bar',\n },\n ],\n tooltip: chartTooltip(barPointFormatter),\n xAxis: {\n axisLabel: { color: input.labelColor, fontSize: LABEL_FONT_SIZE },\n axisLine: { show: false },\n axisTick: { show: false },\n data: input.values.map((point) => point.label),\n type: 'category',\n },\n yAxis: { show: false, type: 'value' },\n }\n}\n\nexport { type BarsAccent, type BarsOptionInput, type BarsPoint, barsOption }\n"],"mappings":";;;;AAgCA,MAAM,OAAO;CAAE,QAAQ;CAAI,MAAM;CAAG,OAAO;CAAG,KAAK;AAAE;AAErD,MAAM,mBAAmB;AAEzB,MAAM,kBAAkB;AAExB,MAAM,aAAa;AAEnB,MAAM,eAAe;AAErB,MAAM,cAAc;AAEpB,MAAM,qBAAqB,WAAmE;CAC5F,MAAM,QAAQ,OAAO;CAErB,IAAI,CAAC,OACH,OAAO;CAET,OAAO,GAAG,MAAM,KAAK,IAAI,oBAAoB,MAAM,KAAK;AAC1D;AAEA,MAAM,cAAc,UAA0C;CAC5D,IAAI,MAAM,OAAO,WAAW,cAC1B,OAAO,EAAE,QAAQ,CAAC,EAAE;CAEtB,OAAO;EACL,GAAG,eAAe,MAAM,UAAU;EAClC,MAAM;EACN,QAAQ,CACN;GACE,gBAAgB,aAAa,UAAU;GACvC,gBAAgB;GAChB,MAAM,MAAM,OAAO,KAAK,UAAU,MAAM,KAAK;GAC7C,UAAU,EAAE,UAAU,KAAK;GAC3B,WAAW;IACT,cAAc,MAAM;IACpB,OAAO,iBAAiB,MAAM,OAAO,IAAI,MAAM,OAAO,OAAO;GAC/D;GACA,gBAAgB;IAAE,UAAU,MAAM;IAAiB,QAAQ;GAAa;GACxE,MAAM;EACR,CACF;EACA,SAAS,aAAa,iBAAiB;EACvC,OAAO;GACL,WAAW;IAAE,OAAO,MAAM;IAAY,UAAU;GAAgB;GAChE,UAAU,EAAE,MAAM,MAAM;GACxB,UAAU,EAAE,MAAM,MAAM;GACxB,MAAM,MAAM,OAAO,KAAK,UAAU,MAAM,KAAK;GAC7C,MAAM;EACR;EACA,OAAO;GAAE,MAAM;GAAO,MAAM;EAAQ;CACtC;AACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EChartsOption } from "echarts";
|
|
2
|
+
//#region src/charts/groupedBars.d.ts
|
|
3
|
+
interface GroupedBarsSeries {
|
|
4
|
+
color: string;
|
|
5
|
+
name: string;
|
|
6
|
+
values: readonly (number | null)[];
|
|
7
|
+
}
|
|
8
|
+
interface GroupedBarsOptionInput {
|
|
9
|
+
categories: readonly string[];
|
|
10
|
+
durationMs: number;
|
|
11
|
+
labelColor: string;
|
|
12
|
+
radius: number;
|
|
13
|
+
series: readonly GroupedBarsSeries[];
|
|
14
|
+
stateDurationMs: number;
|
|
15
|
+
valueFormat?: (value: number) => string;
|
|
16
|
+
}
|
|
17
|
+
declare const groupedBarsOption: (input: GroupedBarsOptionInput) => EChartsOption;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { type GroupedBarsOptionInput, type GroupedBarsSeries, groupedBarsOption };
|
|
20
|
+
//# sourceMappingURL=groupedBars.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { CHART_EASING, chartAnimation } from "./animation.js";
|
|
2
|
+
import { chartTooltip, formatCallbackValue } from "./tooltip.js";
|
|
3
|
+
//#region src/charts/groupedBars.ts
|
|
4
|
+
const GRID = {
|
|
5
|
+
bottom: 22,
|
|
6
|
+
left: 4,
|
|
7
|
+
right: 4,
|
|
8
|
+
top: 8
|
|
9
|
+
};
|
|
10
|
+
const BAR_CATEGORY_GAP = "35%";
|
|
11
|
+
const LABEL_FONT_SIZE = 11;
|
|
12
|
+
const EMPTY_LENGTH = 0;
|
|
13
|
+
const FIRST_INDEX = 0;
|
|
14
|
+
const DOT_CLASS = "inline-block size-2 flex-none rounded-tf-pill";
|
|
15
|
+
const ROW_CLASS = "flex items-center justify-between gap-3";
|
|
16
|
+
const NAME_CLASS = "flex items-center gap-1.5";
|
|
17
|
+
const VALUE_CLASS = "font-semibold tabular-nums";
|
|
18
|
+
const formatValue = (value, valueFormat) => {
|
|
19
|
+
if (typeof value === "number") return valueFormat(value);
|
|
20
|
+
return formatCallbackValue(value);
|
|
21
|
+
};
|
|
22
|
+
const NO_COLOR = "";
|
|
23
|
+
const colorOf = (point) => {
|
|
24
|
+
if (typeof point.color === "string") return point.color;
|
|
25
|
+
return NO_COLOR;
|
|
26
|
+
};
|
|
27
|
+
const groupedBarRow = (point, valueFormat) => {
|
|
28
|
+
const color = colorOf(point);
|
|
29
|
+
const name = formatCallbackValue(point.seriesName);
|
|
30
|
+
return `<div class="${ROW_CLASS}"><span class="${NAME_CLASS}"><span aria-hidden="true" class="${DOT_CLASS}" style="background:${color}"></span>${name}</span><span class="${VALUE_CLASS}">${formatValue(point.value, valueFormat)}</span></div>`;
|
|
31
|
+
};
|
|
32
|
+
const groupedBarsFormatter = (valueFormat) => (params) => {
|
|
33
|
+
const first = params[FIRST_INDEX];
|
|
34
|
+
if (!first) return "";
|
|
35
|
+
return `<div class="flex flex-col gap-1"><span class="font-semibold">${formatCallbackValue(first.name)}</span>${params.map((point) => groupedBarRow(point, valueFormat)).join("")}</div>`;
|
|
36
|
+
};
|
|
37
|
+
const IDENTITY_FORMAT = String;
|
|
38
|
+
const AXIS_SHADOW_COLOR = "rgb(255 255 255 / 9%)";
|
|
39
|
+
const groupedBarsOption = (input) => {
|
|
40
|
+
if (input.categories.length === EMPTY_LENGTH) return { series: [] };
|
|
41
|
+
const valueFormat = input.valueFormat ?? IDENTITY_FORMAT;
|
|
42
|
+
return {
|
|
43
|
+
...chartAnimation(input.durationMs),
|
|
44
|
+
grid: GRID,
|
|
45
|
+
series: input.series.map((series) => ({
|
|
46
|
+
barCategoryGap: BAR_CATEGORY_GAP,
|
|
47
|
+
data: [...series.values],
|
|
48
|
+
itemStyle: {
|
|
49
|
+
borderRadius: input.radius,
|
|
50
|
+
color: series.color
|
|
51
|
+
},
|
|
52
|
+
name: series.name,
|
|
53
|
+
stateAnimation: {
|
|
54
|
+
duration: input.stateDurationMs,
|
|
55
|
+
easing: CHART_EASING
|
|
56
|
+
},
|
|
57
|
+
type: "bar"
|
|
58
|
+
})),
|
|
59
|
+
tooltip: chartTooltip(groupedBarsFormatter(valueFormat), "axis", {
|
|
60
|
+
shadowStyle: { color: AXIS_SHADOW_COLOR },
|
|
61
|
+
type: "shadow"
|
|
62
|
+
}),
|
|
63
|
+
xAxis: {
|
|
64
|
+
axisLabel: {
|
|
65
|
+
color: input.labelColor,
|
|
66
|
+
fontSize: LABEL_FONT_SIZE
|
|
67
|
+
},
|
|
68
|
+
axisLine: { show: false },
|
|
69
|
+
axisTick: { show: false },
|
|
70
|
+
data: [...input.categories],
|
|
71
|
+
type: "category"
|
|
72
|
+
},
|
|
73
|
+
yAxis: {
|
|
74
|
+
show: false,
|
|
75
|
+
type: "value"
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { groupedBarsOption };
|
|
81
|
+
|
|
82
|
+
//# sourceMappingURL=groupedBars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groupedBars.js","names":[],"sources":["../../src/charts/groupedBars.ts"],"sourcesContent":["import type { DefaultLabelFormatterCallbackParams, EChartsOption } from 'echarts'\n\nimport { CHART_EASING, chartAnimation } from './animation'\nimport { chartTooltip, formatCallbackValue } from './tooltip'\n\ninterface GroupedBarsSeries {\n color: string\n\n name: string\n\n values: readonly (number | null)[]\n}\n\ninterface GroupedBarsOptionInput {\n categories: readonly string[]\n\n durationMs: number\n\n labelColor: string\n\n radius: number\n\n series: readonly GroupedBarsSeries[]\n\n stateDurationMs: number\n\n valueFormat?: (value: number) => string\n}\n\nconst GRID = { bottom: 22, left: 4, right: 4, top: 8 }\n\nconst BAR_CATEGORY_GAP = '35%'\n\nconst LABEL_FONT_SIZE = 11\n\nconst EMPTY_LENGTH = 0\n\nconst FIRST_INDEX = 0\n\nconst DOT_CLASS = 'inline-block size-2 flex-none rounded-tf-pill'\n\nconst ROW_CLASS = 'flex items-center justify-between gap-3'\n\nconst NAME_CLASS = 'flex items-center gap-1.5'\n\nconst VALUE_CLASS = 'font-semibold tabular-nums'\n\nconst formatValue = (value: unknown, valueFormat: (value: number) => string): string => {\n if (typeof value === 'number') {\n return valueFormat(value)\n }\n return formatCallbackValue(value)\n}\n\nconst NO_COLOR = ''\n\nconst colorOf = (point: DefaultLabelFormatterCallbackParams): string => {\n if (typeof point.color === 'string') {\n return point.color\n }\n return NO_COLOR\n}\n\nconst groupedBarRow = (\n point: DefaultLabelFormatterCallbackParams,\n valueFormat: (value: number) => string,\n): string => {\n const color = colorOf(point)\n const name = formatCallbackValue(point.seriesName)\n\n return (\n `<div class=\"${ROW_CLASS}\">` +\n `<span class=\"${NAME_CLASS}\"><span aria-hidden=\"true\" class=\"${DOT_CLASS}\" style=\"background:${color}\"></span>${name}</span>` +\n `<span class=\"${VALUE_CLASS}\">${formatValue(point.value, valueFormat)}</span>` +\n `</div>`\n )\n}\n\nconst groupedBarsFormatter =\n (valueFormat: (value: number) => string) =>\n (params: readonly DefaultLabelFormatterCallbackParams[]): string => {\n const first = params[FIRST_INDEX]\n\n if (!first) {\n return ''\n }\n const heading = formatCallbackValue(first.name)\n const rows = params.map((point) => groupedBarRow(point, valueFormat)).join('')\n\n return `<div class=\"flex flex-col gap-1\"><span class=\"font-semibold\">${heading}</span>${rows}</div>`\n }\n\nconst IDENTITY_FORMAT = String\n\nconst AXIS_SHADOW_COLOR = 'rgb(255 255 255 / 9%)'\n\nconst groupedBarsOption = (input: GroupedBarsOptionInput): EChartsOption => {\n if (input.categories.length === EMPTY_LENGTH) {\n return { series: [] }\n }\n const valueFormat = input.valueFormat ?? IDENTITY_FORMAT\n\n return {\n ...chartAnimation(input.durationMs),\n grid: GRID,\n series: input.series.map((series) => ({\n barCategoryGap: BAR_CATEGORY_GAP,\n data: [...series.values],\n itemStyle: { borderRadius: input.radius, color: series.color },\n name: series.name,\n stateAnimation: { duration: input.stateDurationMs, easing: CHART_EASING },\n type: 'bar' as const,\n })),\n tooltip: chartTooltip(groupedBarsFormatter(valueFormat), 'axis', {\n shadowStyle: { color: AXIS_SHADOW_COLOR },\n type: 'shadow',\n }),\n xAxis: {\n axisLabel: { color: input.labelColor, fontSize: LABEL_FONT_SIZE },\n axisLine: { show: false },\n axisTick: { show: false },\n data: [...input.categories],\n type: 'category',\n },\n yAxis: { show: false, type: 'value' },\n }\n}\n\nexport { type GroupedBarsOptionInput, type GroupedBarsSeries, groupedBarsOption }\n"],"mappings":";;;AA6BA,MAAM,OAAO;CAAE,QAAQ;CAAI,MAAM;CAAG,OAAO;CAAG,KAAK;AAAE;AAErD,MAAM,mBAAmB;AAEzB,MAAM,kBAAkB;AAExB,MAAM,eAAe;AAErB,MAAM,cAAc;AAEpB,MAAM,YAAY;AAElB,MAAM,YAAY;AAElB,MAAM,aAAa;AAEnB,MAAM,cAAc;AAEpB,MAAM,eAAe,OAAgB,gBAAmD;CACtF,IAAI,OAAO,UAAU,UACnB,OAAO,YAAY,KAAK;CAE1B,OAAO,oBAAoB,KAAK;AAClC;AAEA,MAAM,WAAW;AAEjB,MAAM,WAAW,UAAuD;CACtE,IAAI,OAAO,MAAM,UAAU,UACzB,OAAO,MAAM;CAEf,OAAO;AACT;AAEA,MAAM,iBACJ,OACA,gBACW;CACX,MAAM,QAAQ,QAAQ,KAAK;CAC3B,MAAM,OAAO,oBAAoB,MAAM,UAAU;CAEjD,OACE,eAAe,UAAU,iBACT,WAAW,oCAAoC,UAAU,sBAAsB,MAAM,WAAW,KAAK,sBACrG,YAAY,IAAI,YAAY,MAAM,OAAO,WAAW,EAAE;AAG1E;AAEA,MAAM,wBACH,iBACA,WAAmE;CAClE,MAAM,QAAQ,OAAO;CAErB,IAAI,CAAC,OACH,OAAO;CAKT,OAAO,gEAHS,oBAAoB,MAAM,IAGmC,EAAE,SAFlE,OAAO,KAAK,UAAU,cAAc,OAAO,WAAW,CAAC,CAAC,CAAC,KAAK,EAEgB,EAAE;AAC/F;AAEF,MAAM,kBAAkB;AAExB,MAAM,oBAAoB;AAE1B,MAAM,qBAAqB,UAAiD;CAC1E,IAAI,MAAM,WAAW,WAAW,cAC9B,OAAO,EAAE,QAAQ,CAAC,EAAE;CAEtB,MAAM,cAAc,MAAM,eAAe;CAEzC,OAAO;EACL,GAAG,eAAe,MAAM,UAAU;EAClC,MAAM;EACN,QAAQ,MAAM,OAAO,KAAK,YAAY;GACpC,gBAAgB;GAChB,MAAM,CAAC,GAAG,OAAO,MAAM;GACvB,WAAW;IAAE,cAAc,MAAM;IAAQ,OAAO,OAAO;GAAM;GAC7D,MAAM,OAAO;GACb,gBAAgB;IAAE,UAAU,MAAM;IAAiB,QAAQ;GAAa;GACxE,MAAM;EACR,EAAE;EACF,SAAS,aAAa,qBAAqB,WAAW,GAAG,QAAQ;GAC/D,aAAa,EAAE,OAAO,kBAAkB;GACxC,MAAM;EACR,CAAC;EACD,OAAO;GACL,WAAW;IAAE,OAAO,MAAM;IAAY,UAAU;GAAgB;GAChE,UAAU,EAAE,MAAM,MAAM;GACxB,UAAU,EAAE,MAAM,MAAM;GACxB,MAAM,CAAC,GAAG,MAAM,UAAU;GAC1B,MAAM;EACR;EACA,OAAO;GAAE,MAAM;GAAO,MAAM;EAAQ;CACtC;AACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { graphic } from "echarts/core";
|
|
2
|
+
//#region src/charts/paint.ts
|
|
3
|
+
const TOP = 0;
|
|
4
|
+
const BOTTOM = 1;
|
|
5
|
+
const LEFT = 0;
|
|
6
|
+
const START = 0;
|
|
7
|
+
const END = 1;
|
|
8
|
+
const verticalGradient = (from, to) => new graphic.LinearGradient(LEFT, TOP, LEFT, BOTTOM, [{
|
|
9
|
+
color: from,
|
|
10
|
+
offset: START
|
|
11
|
+
}, {
|
|
12
|
+
color: to,
|
|
13
|
+
offset: END
|
|
14
|
+
}]);
|
|
15
|
+
const TRANSPARENT = "rgba(0, 0, 0, 0)";
|
|
16
|
+
//#endregion
|
|
17
|
+
export { TRANSPARENT, verticalGradient };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=paint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paint.js","names":[],"sources":["../../src/charts/paint.ts"],"sourcesContent":["import { graphic } from 'echarts/core'\n\nconst TOP = 0\n\nconst BOTTOM = 1\n\nconst LEFT = 0\n\nconst START = 0\n\nconst END = 1\n\nconst verticalGradient = (from: string, to: string): graphic.LinearGradient =>\n new graphic.LinearGradient(LEFT, TOP, LEFT, BOTTOM, [\n { color: from, offset: START },\n { color: to, offset: END },\n ])\n\nconst TRANSPARENT = 'rgba(0, 0, 0, 0)'\n\nexport { TRANSPARENT, verticalGradient }\n"],"mappings":";;AAEA,MAAM,MAAM;AAEZ,MAAM,SAAS;AAEf,MAAM,OAAO;AAEb,MAAM,QAAQ;AAEd,MAAM,MAAM;AAEZ,MAAM,oBAAoB,MAAc,OACtC,IAAI,QAAQ,eAAe,MAAM,KAAK,MAAM,QAAQ,CAClD;CAAE,OAAO;CAAM,QAAQ;AAAM,GAC7B;CAAE,OAAO;CAAI,QAAQ;AAAI,CAC3B,CAAC;AAEH,MAAM,cAAc"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BarsAccent } from "./bars.js";
|
|
2
|
+
import { EChartsOption } from "echarts";
|
|
3
|
+
//#region src/charts/spark.d.ts
|
|
4
|
+
type SparkShape = 'line' | 'bars';
|
|
5
|
+
type SparkAccent = BarsAccent;
|
|
6
|
+
interface SparkOptionInput {
|
|
7
|
+
accent: SparkAccent;
|
|
8
|
+
durationMs: number;
|
|
9
|
+
stateDurationMs: number;
|
|
10
|
+
radius: number;
|
|
11
|
+
shape: SparkShape;
|
|
12
|
+
values: readonly number[];
|
|
13
|
+
}
|
|
14
|
+
declare const sparkOption: (input: SparkOptionInput) => EChartsOption;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { type SparkAccent, type SparkOptionInput, type SparkShape, sparkOption };
|
|
17
|
+
//# sourceMappingURL=spark.d.ts.map
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { CHART_EASING, chartAnimation, chartStagger } from "./animation.js";
|
|
2
|
+
import { TRANSPARENT, verticalGradient } from "./paint.js";
|
|
3
|
+
import { chartTooltip } from "./tooltip.js";
|
|
4
|
+
//#region src/charts/spark.ts
|
|
5
|
+
const LINE_WIDTH = 2;
|
|
6
|
+
const MARKER_SIZE = 5;
|
|
7
|
+
const MIN_SPAN = 1;
|
|
8
|
+
const EMPTY_LENGTH = 0;
|
|
9
|
+
const LAST_INDEX_OFFSET = 1;
|
|
10
|
+
const NO_GAP = 0;
|
|
11
|
+
const LINE_BOUNDARY_GAP = [NO_GAP, NO_GAP];
|
|
12
|
+
const LINE_GRID = {
|
|
13
|
+
bottom: 4,
|
|
14
|
+
left: 4,
|
|
15
|
+
right: 4,
|
|
16
|
+
top: 4
|
|
17
|
+
};
|
|
18
|
+
const BAR_GRID = {
|
|
19
|
+
bottom: 0,
|
|
20
|
+
left: 0,
|
|
21
|
+
right: 0,
|
|
22
|
+
top: 0
|
|
23
|
+
};
|
|
24
|
+
const BAR_CATEGORY_GAP = "25%";
|
|
25
|
+
const MIN_HEIGHT_RATIO = .15;
|
|
26
|
+
const BAR_AXIS_MAX = 1;
|
|
27
|
+
const BAR_AXIS_MIN = 0;
|
|
28
|
+
const AREA_OPACITY = .32;
|
|
29
|
+
const STAGGER_MS = 30;
|
|
30
|
+
const lastIndexOf = (values) => values.length - LAST_INDEX_OFFSET;
|
|
31
|
+
const NO_VALUE = 0;
|
|
32
|
+
const FIRST_INDEX = 0;
|
|
33
|
+
const pointFormatter = (values) => (params) => {
|
|
34
|
+
const point = params[FIRST_INDEX];
|
|
35
|
+
if (!point || typeof point.dataIndex !== "number") return String(NO_VALUE);
|
|
36
|
+
return String(values[point.dataIndex] ?? NO_VALUE);
|
|
37
|
+
};
|
|
38
|
+
const yRange = (values) => {
|
|
39
|
+
const min = Math.min(...values);
|
|
40
|
+
const max = Math.max(...values);
|
|
41
|
+
if (max === min) return {
|
|
42
|
+
max: min + MIN_SPAN,
|
|
43
|
+
min
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
max,
|
|
47
|
+
min
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const lineOption = (input) => {
|
|
51
|
+
const last = lastIndexOf(input.values);
|
|
52
|
+
const range = yRange(input.values);
|
|
53
|
+
const lastValue = input.values[last] ?? range.min;
|
|
54
|
+
return {
|
|
55
|
+
...chartAnimation(input.durationMs),
|
|
56
|
+
grid: LINE_GRID,
|
|
57
|
+
series: [{
|
|
58
|
+
areaStyle: {
|
|
59
|
+
color: verticalGradient(input.accent.hi, TRANSPARENT),
|
|
60
|
+
opacity: AREA_OPACITY
|
|
61
|
+
},
|
|
62
|
+
data: input.values.map((value, index) => [index, value]),
|
|
63
|
+
emphasis: { disabled: true },
|
|
64
|
+
lineStyle: {
|
|
65
|
+
cap: "round",
|
|
66
|
+
color: input.accent.surface,
|
|
67
|
+
join: "round",
|
|
68
|
+
width: LINE_WIDTH
|
|
69
|
+
},
|
|
70
|
+
markPoint: {
|
|
71
|
+
animation: true,
|
|
72
|
+
data: [{
|
|
73
|
+
coord: [last, lastValue],
|
|
74
|
+
name: ""
|
|
75
|
+
}],
|
|
76
|
+
itemStyle: { color: input.accent.hi },
|
|
77
|
+
label: { show: false },
|
|
78
|
+
symbol: "circle",
|
|
79
|
+
symbolSize: MARKER_SIZE
|
|
80
|
+
},
|
|
81
|
+
showSymbol: false,
|
|
82
|
+
stateAnimation: {
|
|
83
|
+
duration: input.stateDurationMs,
|
|
84
|
+
easing: CHART_EASING
|
|
85
|
+
},
|
|
86
|
+
symbolSize: MARKER_SIZE,
|
|
87
|
+
type: "line"
|
|
88
|
+
}],
|
|
89
|
+
tooltip: chartTooltip(pointFormatter(input.values), "axis"),
|
|
90
|
+
xAxis: {
|
|
91
|
+
boundaryGap: LINE_BOUNDARY_GAP,
|
|
92
|
+
max: last,
|
|
93
|
+
min: 0,
|
|
94
|
+
show: false,
|
|
95
|
+
type: "value"
|
|
96
|
+
},
|
|
97
|
+
yAxis: {
|
|
98
|
+
max: range.max,
|
|
99
|
+
min: range.min,
|
|
100
|
+
show: false,
|
|
101
|
+
type: "value"
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
const barHeightRatio = (value, range) => {
|
|
106
|
+
const ratio = (value - range.min) / (range.max - range.min);
|
|
107
|
+
return Math.max(ratio, MIN_HEIGHT_RATIO);
|
|
108
|
+
};
|
|
109
|
+
const barOption = (input) => {
|
|
110
|
+
const last = lastIndexOf(input.values);
|
|
111
|
+
const range = yRange(input.values);
|
|
112
|
+
return {
|
|
113
|
+
...chartAnimation(input.durationMs),
|
|
114
|
+
grid: BAR_GRID,
|
|
115
|
+
series: [{
|
|
116
|
+
animationDelay: chartStagger(STAGGER_MS),
|
|
117
|
+
barCategoryGap: BAR_CATEGORY_GAP,
|
|
118
|
+
data: input.values.map((value, index) => {
|
|
119
|
+
const height = barHeightRatio(value, range);
|
|
120
|
+
if (index === last) return {
|
|
121
|
+
itemStyle: { color: input.accent.hi },
|
|
122
|
+
value: height
|
|
123
|
+
};
|
|
124
|
+
return height;
|
|
125
|
+
}),
|
|
126
|
+
emphasis: { disabled: true },
|
|
127
|
+
itemStyle: {
|
|
128
|
+
borderRadius: input.radius,
|
|
129
|
+
color: verticalGradient(input.accent.hi, input.accent.surface)
|
|
130
|
+
},
|
|
131
|
+
stateAnimation: {
|
|
132
|
+
duration: input.stateDurationMs,
|
|
133
|
+
easing: CHART_EASING
|
|
134
|
+
},
|
|
135
|
+
type: "bar"
|
|
136
|
+
}],
|
|
137
|
+
tooltip: chartTooltip(pointFormatter(input.values)),
|
|
138
|
+
xAxis: {
|
|
139
|
+
data: input.values.map((_value, index) => String(index)),
|
|
140
|
+
show: false,
|
|
141
|
+
type: "category"
|
|
142
|
+
},
|
|
143
|
+
yAxis: {
|
|
144
|
+
max: BAR_AXIS_MAX,
|
|
145
|
+
min: BAR_AXIS_MIN,
|
|
146
|
+
show: false,
|
|
147
|
+
type: "value"
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
const sparkOption = (input) => {
|
|
152
|
+
if (input.values.length === EMPTY_LENGTH) return { series: [] };
|
|
153
|
+
if (input.shape === "bars") return barOption(input);
|
|
154
|
+
return lineOption(input);
|
|
155
|
+
};
|
|
156
|
+
//#endregion
|
|
157
|
+
export { sparkOption };
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=spark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spark.js","names":[],"sources":["../../src/charts/spark.ts"],"sourcesContent":["import type { DefaultLabelFormatterCallbackParams, EChartsOption } from 'echarts'\n\nimport { CHART_EASING, chartAnimation, chartStagger } from './animation'\nimport type { BarsAccent } from './bars'\nimport { TRANSPARENT, verticalGradient } from './paint'\nimport { chartTooltip } from './tooltip'\n\ntype SparkShape = 'line' | 'bars'\n\ntype SparkAccent = BarsAccent\n\ninterface SparkOptionInput {\n accent: SparkAccent\n durationMs: number\n stateDurationMs: number\n radius: number\n shape: SparkShape\n values: readonly number[]\n}\n\nconst LINE_WIDTH = 2\n\nconst MARKER_SIZE = 5\n\nconst MIN_SPAN = 1\n\nconst EMPTY_LENGTH = 0\n\nconst LAST_INDEX_OFFSET = 1\n\nconst NO_GAP = 0\n\nconst LINE_BOUNDARY_GAP: [number, number] = [NO_GAP, NO_GAP]\n\nconst LINE_GRID = { bottom: 4, left: 4, right: 4, top: 4 }\n\nconst BAR_GRID = { bottom: 0, left: 0, right: 0, top: 0 }\n\nconst BAR_CATEGORY_GAP = '25%'\n\nconst MIN_HEIGHT_RATIO = 0.15\n\nconst BAR_AXIS_MAX = 1\n\nconst BAR_AXIS_MIN = 0\n\nconst AREA_OPACITY = 0.32\n\nconst STAGGER_MS = 30\n\nconst lastIndexOf = (values: readonly number[]): number => values.length - LAST_INDEX_OFFSET\n\nconst NO_VALUE = 0\n\nconst FIRST_INDEX = 0\n\nconst pointFormatter =\n (values: readonly number[]) =>\n (params: readonly DefaultLabelFormatterCallbackParams[]): string => {\n const point = params[FIRST_INDEX]\n\n if (!point || typeof point.dataIndex !== 'number') {\n return String(NO_VALUE)\n }\n return String(values[point.dataIndex] ?? NO_VALUE)\n }\n\nconst yRange = (values: readonly number[]): { max: number; min: number } => {\n const min = Math.min(...values)\n const max = Math.max(...values)\n\n if (max === min) {\n return { max: min + MIN_SPAN, min }\n }\n return { max, min }\n}\n\nconst lineOption = (input: SparkOptionInput): EChartsOption => {\n const last = lastIndexOf(input.values)\n const range = yRange(input.values)\n const lastValue = input.values[last] ?? range.min\n\n return {\n ...chartAnimation(input.durationMs),\n grid: LINE_GRID,\n series: [\n {\n areaStyle: {\n color: verticalGradient(input.accent.hi, TRANSPARENT),\n opacity: AREA_OPACITY,\n },\n data: input.values.map((value, index) => [index, value]),\n emphasis: { disabled: true },\n lineStyle: {\n cap: 'round',\n color: input.accent.surface,\n join: 'round',\n width: LINE_WIDTH,\n },\n markPoint: {\n animation: true,\n data: [{ coord: [last, lastValue], name: '' }],\n itemStyle: { color: input.accent.hi },\n label: { show: false },\n symbol: 'circle',\n symbolSize: MARKER_SIZE,\n },\n showSymbol: false,\n stateAnimation: { duration: input.stateDurationMs, easing: CHART_EASING },\n symbolSize: MARKER_SIZE,\n type: 'line',\n },\n ],\n tooltip: chartTooltip(pointFormatter(input.values), 'axis'),\n xAxis: { boundaryGap: LINE_BOUNDARY_GAP, max: last, min: 0, show: false, type: 'value' },\n yAxis: { max: range.max, min: range.min, show: false, type: 'value' },\n }\n}\n\nconst barHeightRatio = (value: number, range: { max: number; min: number }): number => {\n const ratio = (value - range.min) / (range.max - range.min)\n\n return Math.max(ratio, MIN_HEIGHT_RATIO)\n}\n\nconst barOption = (input: SparkOptionInput): EChartsOption => {\n const last = lastIndexOf(input.values)\n const range = yRange(input.values)\n\n return {\n ...chartAnimation(input.durationMs),\n grid: BAR_GRID,\n series: [\n {\n animationDelay: chartStagger(STAGGER_MS),\n barCategoryGap: BAR_CATEGORY_GAP,\n data: input.values.map((value, index) => {\n const height = barHeightRatio(value, range)\n\n if (index === last) {\n return { itemStyle: { color: input.accent.hi }, value: height }\n }\n return height\n }),\n emphasis: { disabled: true },\n itemStyle: {\n borderRadius: input.radius,\n color: verticalGradient(input.accent.hi, input.accent.surface),\n },\n stateAnimation: { duration: input.stateDurationMs, easing: CHART_EASING },\n type: 'bar',\n },\n ],\n tooltip: chartTooltip(pointFormatter(input.values)),\n xAxis: {\n data: input.values.map((_value, index) => String(index)),\n show: false,\n type: 'category',\n },\n yAxis: { max: BAR_AXIS_MAX, min: BAR_AXIS_MIN, show: false, type: 'value' },\n }\n}\n\nconst sparkOption = (input: SparkOptionInput): EChartsOption => {\n if (input.values.length === EMPTY_LENGTH) {\n return { series: [] }\n }\n if (input.shape === 'bars') {\n return barOption(input)\n }\n return lineOption(input)\n}\n\nexport { type SparkAccent, type SparkOptionInput, type SparkShape, sparkOption }\n"],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/charts/tooltip.ts
|
|
2
|
+
const TOOLTIP_CLASS = ["tf-edge-sweep tf-edge-plain rounded-tf-inline bg-tf-glass px-2 py-1", "font-tf-body text-tf-caption-sm text-tf-fg shadow-tf-float backdrop-blur-tf-glass"].join(" ");
|
|
3
|
+
const NO_CHROME_CSS = "box-shadow: none; pointer-events: none;";
|
|
4
|
+
const NO_CONTENT = "";
|
|
5
|
+
const SNAP_TO_CURSOR = 0;
|
|
6
|
+
const EMPTY_LENGTH = 0;
|
|
7
|
+
const DEFAULT_AXIS_POINTER = { type: "none" };
|
|
8
|
+
const appendToBody = () => document.body;
|
|
9
|
+
const formatCallbackValue = (value) => {
|
|
10
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
11
|
+
return NO_CONTENT;
|
|
12
|
+
};
|
|
13
|
+
const asParams = (raw) => {
|
|
14
|
+
if (Array.isArray(raw)) return raw;
|
|
15
|
+
return [raw];
|
|
16
|
+
};
|
|
17
|
+
const chartTooltip = (formatter, trigger = "item", axisPointer = DEFAULT_AXIS_POINTER) => {
|
|
18
|
+
const base = {
|
|
19
|
+
appendTo: appendToBody,
|
|
20
|
+
backgroundColor: "transparent",
|
|
21
|
+
borderWidth: 0,
|
|
22
|
+
extraCssText: NO_CHROME_CSS,
|
|
23
|
+
formatter: (raw) => {
|
|
24
|
+
const params = asParams(raw);
|
|
25
|
+
if (params.length === EMPTY_LENGTH) return NO_CONTENT;
|
|
26
|
+
return `<div class="${TOOLTIP_CLASS}">${formatter(params)}</div>`;
|
|
27
|
+
},
|
|
28
|
+
padding: 0,
|
|
29
|
+
transitionDuration: SNAP_TO_CURSOR,
|
|
30
|
+
trigger
|
|
31
|
+
};
|
|
32
|
+
if (trigger === "axis") return {
|
|
33
|
+
...base,
|
|
34
|
+
axisPointer
|
|
35
|
+
};
|
|
36
|
+
return base;
|
|
37
|
+
};
|
|
38
|
+
//#endregion
|
|
39
|
+
export { chartTooltip, formatCallbackValue };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=tooltip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip.js","names":[],"sources":["../../src/charts/tooltip.ts"],"sourcesContent":["import type {\n DefaultLabelFormatterCallbackParams,\n TooltipComponentFormatterCallbackParams,\n TooltipComponentOption,\n} from 'echarts'\n\nconst TOOLTIP_CLASS = [\n 'tf-edge-sweep tf-edge-plain rounded-tf-inline bg-tf-glass px-2 py-1',\n 'font-tf-body text-tf-caption-sm text-tf-fg shadow-tf-float backdrop-blur-tf-glass',\n].join(' ')\n\nconst NO_CHROME_CSS = 'box-shadow: none; pointer-events: none;'\n\nconst NO_CONTENT = ''\n\nconst SNAP_TO_CURSOR = 0\n\nconst EMPTY_LENGTH = 0\n\ntype ChartTooltipTrigger = 'item' | 'axis'\n\ntype ChartTooltipAxisPointer = NonNullable<TooltipComponentOption['axisPointer']>\n\nconst DEFAULT_AXIS_POINTER: ChartTooltipAxisPointer = { type: 'none' }\n\nconst appendToBody = (): HTMLElement => document.body\n\nconst formatCallbackValue = (value: unknown): string => {\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value)\n }\n return NO_CONTENT\n}\n\nconst asParams = (\n raw: TooltipComponentFormatterCallbackParams,\n): readonly DefaultLabelFormatterCallbackParams[] => {\n if (Array.isArray(raw)) {\n return raw\n }\n return [raw]\n}\n\nconst chartTooltip = (\n formatter: (params: readonly DefaultLabelFormatterCallbackParams[]) => string,\n trigger: ChartTooltipTrigger = 'item',\n axisPointer: ChartTooltipAxisPointer = DEFAULT_AXIS_POINTER,\n): TooltipComponentOption => {\n const base: TooltipComponentOption = {\n appendTo: appendToBody,\n backgroundColor: 'transparent',\n borderWidth: 0,\n extraCssText: NO_CHROME_CSS,\n formatter: (raw: TooltipComponentFormatterCallbackParams) => {\n const params = asParams(raw)\n\n if (params.length === EMPTY_LENGTH) {\n return NO_CONTENT\n }\n return `<div class=\"${TOOLTIP_CLASS}\">${formatter(params)}</div>`\n },\n padding: 0,\n transitionDuration: SNAP_TO_CURSOR,\n trigger,\n }\n\n if (trigger === 'axis') {\n return { ...base, axisPointer }\n }\n return base\n}\n\nexport { chartTooltip, formatCallbackValue }\n"],"mappings":";AAMA,MAAM,gBAAgB,CACpB,uEACA,mFACF,CAAC,CAAC,KAAK,GAAG;AAEV,MAAM,gBAAgB;AAEtB,MAAM,aAAa;AAEnB,MAAM,iBAAiB;AAEvB,MAAM,eAAe;AAMrB,MAAM,uBAAgD,EAAE,MAAM,OAAO;AAErE,MAAM,qBAAkC,SAAS;AAEjD,MAAM,uBAAuB,UAA2B;CACtD,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAChD,OAAO,OAAO,KAAK;CAErB,OAAO;AACT;AAEA,MAAM,YACJ,QACmD;CACnD,IAAI,MAAM,QAAQ,GAAG,GACnB,OAAO;CAET,OAAO,CAAC,GAAG;AACb;AAEA,MAAM,gBACJ,WACA,UAA+B,QAC/B,cAAuC,yBACZ;CAC3B,MAAM,OAA+B;EACnC,UAAU;EACV,iBAAiB;EACjB,aAAa;EACb,cAAc;EACd,YAAY,QAAiD;GAC3D,MAAM,SAAS,SAAS,GAAG;GAE3B,IAAI,OAAO,WAAW,cACpB,OAAO;GAET,OAAO,eAAe,cAAc,IAAI,UAAU,MAAM,EAAE;EAC5D;EACA,SAAS;EACT,oBAAoB;EACpB;CACF;CAEA,IAAI,YAAY,QACd,OAAO;EAAE,GAAG;EAAM;CAAY;CAEhC,OAAO;AACT"}
|