@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.
Files changed (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/assets/brands/digital-boost-group.svg +1 -0
  4. package/assets/brands/rtsg.svg +1 -0
  5. package/assets/brands/tech-it-out.svg +1 -0
  6. package/assets/brands/techfides.svg +1 -0
  7. package/css/index.css +8 -0
  8. package/css/theme.css +1640 -0
  9. package/dist/brands.d.ts +39 -0
  10. package/dist/brands.js +41 -0
  11. package/dist/brands.js.map +1 -0
  12. package/dist/charts/animation.js +14 -0
  13. package/dist/charts/animation.js.map +1 -0
  14. package/dist/charts/bars.d.ts +22 -0
  15. package/dist/charts/bars.js +61 -0
  16. package/dist/charts/bars.js.map +1 -0
  17. package/dist/charts/groupedBars.d.ts +20 -0
  18. package/dist/charts/groupedBars.js +82 -0
  19. package/dist/charts/groupedBars.js.map +1 -0
  20. package/dist/charts/paint.js +19 -0
  21. package/dist/charts/paint.js.map +1 -0
  22. package/dist/charts/spark.d.ts +17 -0
  23. package/dist/charts/spark.js +159 -0
  24. package/dist/charts/spark.js.map +1 -0
  25. package/dist/charts/tooltip.js +41 -0
  26. package/dist/charts/tooltip.js.map +1 -0
  27. package/dist/cn.d.ts +6 -0
  28. package/dist/cn.js +178 -0
  29. package/dist/cn.js.map +1 -0
  30. package/dist/control.d.ts +15 -0
  31. package/dist/control.js +13 -0
  32. package/dist/control.js.map +1 -0
  33. package/dist/index.d.ts +65 -0
  34. package/dist/index.js +65 -0
  35. package/dist/mark.d.ts +7 -0
  36. package/dist/mark.js +11 -0
  37. package/dist/mark.js.map +1 -0
  38. package/dist/parts/control.js +55 -0
  39. package/dist/parts/control.js.map +1 -0
  40. package/dist/parts/eyebrow.js +8 -0
  41. package/dist/parts/eyebrow.js.map +1 -0
  42. package/dist/parts/mark.js +52 -0
  43. package/dist/parts/mark.js.map +1 -0
  44. package/dist/parts/reveal.js +35 -0
  45. package/dist/parts/reveal.js.map +1 -0
  46. package/dist/parts/rouse.js +25 -0
  47. package/dist/parts/rouse.js.map +1 -0
  48. package/dist/parts/rule.js +12 -0
  49. package/dist/parts/rule.js.map +1 -0
  50. package/dist/parts/scroll.js +10 -0
  51. package/dist/parts/scroll.js.map +1 -0
  52. package/dist/parts/shell.js +23 -0
  53. package/dist/parts/shell.js.map +1 -0
  54. package/dist/parts/surface.js +15 -0
  55. package/dist/parts/surface.js.map +1 -0
  56. package/dist/parts/tone.js +13 -0
  57. package/dist/parts/tone.js.map +1 -0
  58. package/dist/parts/travel.js +11 -0
  59. package/dist/parts/travel.js.map +1 -0
  60. package/dist/recipes/accordion.d.ts +13 -0
  61. package/dist/recipes/accordion.js +42 -0
  62. package/dist/recipes/accordion.js.map +1 -0
  63. package/dist/recipes/alert.d.ts +16 -0
  64. package/dist/recipes/alert.js +21 -0
  65. package/dist/recipes/alert.js.map +1 -0
  66. package/dist/recipes/band.d.ts +8 -0
  67. package/dist/recipes/band.js +22 -0
  68. package/dist/recipes/band.js.map +1 -0
  69. package/dist/recipes/bars.d.ts +17 -0
  70. package/dist/recipes/bars.js +27 -0
  71. package/dist/recipes/bars.js.map +1 -0
  72. package/dist/recipes/brandMark.d.ts +5 -0
  73. package/dist/recipes/brandMark.js +7 -0
  74. package/dist/recipes/brandMark.js.map +1 -0
  75. package/dist/recipes/button.d.ts +23 -0
  76. package/dist/recipes/button.js +229 -0
  77. package/dist/recipes/button.js.map +1 -0
  78. package/dist/recipes/cardHeader.d.ts +10 -0
  79. package/dist/recipes/cardHeader.js +11 -0
  80. package/dist/recipes/cardHeader.js.map +1 -0
  81. package/dist/recipes/checkbox.d.ts +26 -0
  82. package/dist/recipes/checkbox.js +103 -0
  83. package/dist/recipes/checkbox.js.map +1 -0
  84. package/dist/recipes/chip.d.ts +26 -0
  85. package/dist/recipes/chip.js +123 -0
  86. package/dist/recipes/chip.js.map +1 -0
  87. package/dist/recipes/codeEditor.d.ts +74 -0
  88. package/dist/recipes/codeEditor.js +71 -0
  89. package/dist/recipes/codeEditor.js.map +1 -0
  90. package/dist/recipes/datePicker.d.ts +39 -0
  91. package/dist/recipes/datePicker.js +166 -0
  92. package/dist/recipes/datePicker.js.map +1 -0
  93. package/dist/recipes/dialog.d.ts +37 -0
  94. package/dist/recipes/dialog.js +116 -0
  95. package/dist/recipes/dialog.js.map +1 -0
  96. package/dist/recipes/feature.d.ts +15 -0
  97. package/dist/recipes/feature.js +48 -0
  98. package/dist/recipes/feature.js.map +1 -0
  99. package/dist/recipes/field.d.ts +26 -0
  100. package/dist/recipes/field.js +129 -0
  101. package/dist/recipes/field.js.map +1 -0
  102. package/dist/recipes/findings.d.ts +11 -0
  103. package/dist/recipes/findings.js +16 -0
  104. package/dist/recipes/findings.js.map +1 -0
  105. package/dist/recipes/heading.d.ts +17 -0
  106. package/dist/recipes/heading.js +37 -0
  107. package/dist/recipes/heading.js.map +1 -0
  108. package/dist/recipes/heartbeat.d.ts +23 -0
  109. package/dist/recipes/heartbeat.js +43 -0
  110. package/dist/recipes/heartbeat.js.map +1 -0
  111. package/dist/recipes/input.d.ts +17 -0
  112. package/dist/recipes/input.js +90 -0
  113. package/dist/recipes/input.js.map +1 -0
  114. package/dist/recipes/listItem.d.ts +6 -0
  115. package/dist/recipes/listItem.js +8 -0
  116. package/dist/recipes/listItem.js.map +1 -0
  117. package/dist/recipes/listbox.d.ts +12 -0
  118. package/dist/recipes/listbox.js +29 -0
  119. package/dist/recipes/listbox.js.map +1 -0
  120. package/dist/recipes/marquee.d.ts +19 -0
  121. package/dist/recipes/marquee.js +36 -0
  122. package/dist/recipes/marquee.js.map +1 -0
  123. package/dist/recipes/menu.d.ts +26 -0
  124. package/dist/recipes/menu.js +86 -0
  125. package/dist/recipes/menu.js.map +1 -0
  126. package/dist/recipes/metaRow.d.ts +14 -0
  127. package/dist/recipes/metaRow.js +19 -0
  128. package/dist/recipes/metaRow.js.map +1 -0
  129. package/dist/recipes/meter.d.ts +23 -0
  130. package/dist/recipes/meter.js +39 -0
  131. package/dist/recipes/meter.js.map +1 -0
  132. package/dist/recipes/motion.d.ts +6 -0
  133. package/dist/recipes/motion.js +34 -0
  134. package/dist/recipes/motion.js.map +1 -0
  135. package/dist/recipes/nebula.d.ts +9 -0
  136. package/dist/recipes/nebula.js +15 -0
  137. package/dist/recipes/nebula.js.map +1 -0
  138. package/dist/recipes/numberRange.d.ts +15 -0
  139. package/dist/recipes/numberRange.js +109 -0
  140. package/dist/recipes/numberRange.js.map +1 -0
  141. package/dist/recipes/paper.d.ts +22 -0
  142. package/dist/recipes/paper.js +42 -0
  143. package/dist/recipes/paper.js.map +1 -0
  144. package/dist/recipes/progressBar.d.ts +7 -0
  145. package/dist/recipes/progressBar.js +11 -0
  146. package/dist/recipes/progressBar.js.map +1 -0
  147. package/dist/recipes/queue.d.ts +16 -0
  148. package/dist/recipes/queue.js +27 -0
  149. package/dist/recipes/queue.js.map +1 -0
  150. package/dist/recipes/radioGroup.d.ts +27 -0
  151. package/dist/recipes/radioGroup.js +68 -0
  152. package/dist/recipes/radioGroup.js.map +1 -0
  153. package/dist/recipes/scopeSwitcher.d.ts +26 -0
  154. package/dist/recipes/scopeSwitcher.js +80 -0
  155. package/dist/recipes/scopeSwitcher.js.map +1 -0
  156. package/dist/recipes/scrollArea.d.ts +19 -0
  157. package/dist/recipes/scrollArea.js +43 -0
  158. package/dist/recipes/scrollArea.js.map +1 -0
  159. package/dist/recipes/searchPalette.d.ts +19 -0
  160. package/dist/recipes/searchPalette.js +63 -0
  161. package/dist/recipes/searchPalette.js.map +1 -0
  162. package/dist/recipes/sectionHeader.d.ts +9 -0
  163. package/dist/recipes/sectionHeader.js +10 -0
  164. package/dist/recipes/sectionHeader.js.map +1 -0
  165. package/dist/recipes/segmentedControl.d.ts +9 -0
  166. package/dist/recipes/segmentedControl.js +29 -0
  167. package/dist/recipes/segmentedControl.js.map +1 -0
  168. package/dist/recipes/select.d.ts +9 -0
  169. package/dist/recipes/select.js +21 -0
  170. package/dist/recipes/select.js.map +1 -0
  171. package/dist/recipes/separator.d.ts +14 -0
  172. package/dist/recipes/separator.js +59 -0
  173. package/dist/recipes/separator.js.map +1 -0
  174. package/dist/recipes/sidebar.d.ts +40 -0
  175. package/dist/recipes/sidebar.js +128 -0
  176. package/dist/recipes/sidebar.js.map +1 -0
  177. package/dist/recipes/sky.d.ts +20 -0
  178. package/dist/recipes/sky.js +127 -0
  179. package/dist/recipes/sky.js.map +1 -0
  180. package/dist/recipes/slider.d.ts +20 -0
  181. package/dist/recipes/slider.js +62 -0
  182. package/dist/recipes/slider.js.map +1 -0
  183. package/dist/recipes/stat.d.ts +30 -0
  184. package/dist/recipes/stat.js +52 -0
  185. package/dist/recipes/stat.js.map +1 -0
  186. package/dist/recipes/switch.d.ts +20 -0
  187. package/dist/recipes/switch.js +60 -0
  188. package/dist/recipes/switch.js.map +1 -0
  189. package/dist/recipes/table.d.ts +74 -0
  190. package/dist/recipes/table.js +182 -0
  191. package/dist/recipes/table.js.map +1 -0
  192. package/dist/recipes/tableFilter.d.ts +14 -0
  193. package/dist/recipes/tableFilter.js +28 -0
  194. package/dist/recipes/tableFilter.js.map +1 -0
  195. package/dist/recipes/tablePaging.d.ts +15 -0
  196. package/dist/recipes/tablePaging.js +50 -0
  197. package/dist/recipes/tablePaging.js.map +1 -0
  198. package/dist/recipes/tail.d.ts +20 -0
  199. package/dist/recipes/tail.js +48 -0
  200. package/dist/recipes/tail.js.map +1 -0
  201. package/dist/recipes/text.d.ts +25 -0
  202. package/dist/recipes/text.js +94 -0
  203. package/dist/recipes/text.js.map +1 -0
  204. package/dist/recipes/textarea.d.ts +13 -0
  205. package/dist/recipes/textarea.js +48 -0
  206. package/dist/recipes/textarea.js.map +1 -0
  207. package/dist/recipes/tile.d.ts +18 -0
  208. package/dist/recipes/tile.js +85 -0
  209. package/dist/recipes/tile.js.map +1 -0
  210. package/dist/recipes/tooltip.d.ts +12 -0
  211. package/dist/recipes/tooltip.js +26 -0
  212. package/dist/recipes/tooltip.js.map +1 -0
  213. package/dist/recipes/topBar.d.ts +15 -0
  214. package/dist/recipes/topBar.js +35 -0
  215. package/dist/recipes/topBar.js.map +1 -0
  216. package/dist/recipes/trail.d.ts +27 -0
  217. package/dist/recipes/trail.js +66 -0
  218. package/dist/recipes/trail.js.map +1 -0
  219. package/dist/recipes/userMenu.d.ts +11 -0
  220. package/dist/recipes/userMenu.js +38 -0
  221. package/dist/recipes/userMenu.js.map +1 -0
  222. package/dist/tally.d.ts +17 -0
  223. package/dist/tally.js +75 -0
  224. package/dist/tally.js.map +1 -0
  225. package/dist/tone.d.ts +26 -0
  226. package/dist/tone.js +26 -0
  227. package/dist/tone.js.map +1 -0
  228. package/dist/words.d.ts +116 -0
  229. package/dist/words.js +93 -0
  230. package/dist/words.js.map +1 -0
  231. package/package.json +72 -0
@@ -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"}
package/dist/cn.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { ClassValue } from "clsx";
2
+ //#region src/cn.d.ts
3
+ declare const cn: (...inputs: ClassValue[]) => string;
4
+ //#endregion
5
+ export { cn };
6
+ //# sourceMappingURL=cn.d.ts.map