@lobehub/charts 1.1.0 → 1.3.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 (45) hide show
  1. package/README.md +1 -0
  2. package/es/BarChart/index.js +0 -1
  3. package/es/DataBars/CategoryBar.d.ts +13 -0
  4. package/es/DataBars/CategoryBar.js +191 -0
  5. package/es/DataBars/DeltaBar.d.ts +13 -0
  6. package/es/DataBars/DeltaBar.js +115 -0
  7. package/es/DataBars/MarkerBar.d.ts +16 -0
  8. package/es/DataBars/MarkerBar.js +91 -0
  9. package/es/DataBars/ProgressBar.d.ts +12 -0
  10. package/es/DataBars/ProgressBar.js +68 -0
  11. package/es/DataBars/index.d.ts +4 -0
  12. package/es/DataBars/index.js +4 -0
  13. package/es/DataBars/styles.d.ts +7 -0
  14. package/es/DataBars/styles.js +14 -0
  15. package/es/Heatmaps/Calendar.d.ts +18 -0
  16. package/es/Heatmaps/Calendar.js +67 -0
  17. package/es/Heatmaps/ChartLabels.d.ts +15 -0
  18. package/es/Heatmaps/ChartLabels.js +50 -0
  19. package/es/Heatmaps/Footer.d.ts +22 -0
  20. package/es/Heatmaps/Footer.js +60 -0
  21. package/es/Heatmaps/index.d.ts +28 -0
  22. package/es/Heatmaps/index.js +181 -0
  23. package/es/Heatmaps/styles.d.ts +7 -0
  24. package/es/Heatmaps/styles.js +14 -0
  25. package/es/{components/Legend → Legend}/index.js +1 -1
  26. package/es/common/ChartLegend.js +1 -1
  27. package/es/hooks/useOnWindowResize.js +2 -1
  28. package/es/hooks/usePrefersReducedMotion.d.ts +1 -0
  29. package/es/hooks/usePrefersReducedMotion.js +23 -0
  30. package/es/index.d.ts +3 -1
  31. package/es/index.js +3 -1
  32. package/es/types.d.ts +30 -0
  33. package/es/types.js +8 -1
  34. package/es/utils/calendar.d.ts +29 -0
  35. package/es/utils/calendar.js +194 -0
  36. package/es/utils/index.d.ts +2 -0
  37. package/es/utils/index.js +26 -0
  38. package/es/utils/theme.d.ts +2 -0
  39. package/es/utils/theme.js +49 -0
  40. package/package.json +7 -4
  41. /package/es/{components/Legend → Legend}/LegendItem.d.ts +0 -0
  42. /package/es/{components/Legend → Legend}/LegendItem.js +0 -0
  43. /package/es/{components/Legend → Legend}/ScrollButton.d.ts +0 -0
  44. /package/es/{components/Legend → Legend}/ScrollButton.js +0 -0
  45. /package/es/{components/Legend → Legend}/index.d.ts +0 -0
@@ -0,0 +1,194 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2
+ import { differenceInCalendarDays, eachDayOfInterval, endOfYear, formatISO, getDay, getMonth, nextDay, parseISO, startOfYear, subWeeks } from 'date-fns';
3
+ import { isOnSeverSide } from "./index";
4
+ export var DEFAULT_MONTH_LABELS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
5
+ export var DEFAULT_LABELS = {
6
+ legend: {
7
+ less: 'Less',
8
+ more: 'More'
9
+ },
10
+ months: DEFAULT_MONTH_LABELS,
11
+ tooltip: '{{count}} activities on {{date}}',
12
+ totalCount: '{{count}} activities in {{year}}',
13
+ weekdays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
14
+ };
15
+ var fillHoles = function fillHoles(activities) {
16
+ if (activities.length === 0) {
17
+ return [];
18
+ }
19
+ var calendar = new Map(activities.map(function (a) {
20
+ return [a.date, a];
21
+ }));
22
+ var firstActivity = activities[0];
23
+ var lastActivity = activities.at(-1);
24
+ return eachDayOfInterval({
25
+ end: parseISO(lastActivity.date),
26
+ start: parseISO(firstActivity.date)
27
+ }).map(function (day) {
28
+ var date = formatISO(day, {
29
+ representation: 'date'
30
+ });
31
+ if (calendar.has(date)) {
32
+ return calendar.get(date);
33
+ }
34
+ return {
35
+ count: 0,
36
+ date: date,
37
+ level: 0
38
+ };
39
+ });
40
+ };
41
+ var calcTextDimensions = function calcTextDimensions(text, fontSize) {
42
+ if (isOnSeverSide) return;
43
+ if (fontSize < 1) {
44
+ throw new RangeError('fontSize must be positive');
45
+ }
46
+ if (text.length === 0) {
47
+ return {
48
+ height: 0,
49
+ width: 0
50
+ };
51
+ }
52
+ var namespace = 'http://www.w3.org/2000/svg';
53
+ var svg = document.createElementNS(namespace, 'svg');
54
+ svg.style.position = 'absolute';
55
+ svg.style.visibility = 'hidden';
56
+ svg.style.fontFamily = window.getComputedStyle(document.body).fontFamily;
57
+ svg.style.fontSize = "".concat(fontSize, "px");
58
+ var textNode = document.createElementNS(namespace, 'text');
59
+ textNode.textContent = text;
60
+ svg.append(textNode);
61
+ document.body.append(svg);
62
+ var boundingBox = textNode.getBBox();
63
+ svg.remove();
64
+ return {
65
+ height: boundingBox.height,
66
+ width: boundingBox.width
67
+ };
68
+ };
69
+ export var groupByWeeks = function groupByWeeks(activities) {
70
+ var weekStart = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
71
+ if (activities.length === 0) {
72
+ return [];
73
+ }
74
+ var normalizedActivities = fillHoles(activities);
75
+
76
+ // Determine the first date of the calendar. If the first date is not the
77
+ // set start weekday, the selected weekday one week earlier is used.
78
+ var firstActivity = normalizedActivities[0];
79
+ var firstDate = parseISO(firstActivity.date);
80
+ var firstCalendarDate = getDay(firstDate) === weekStart ? firstDate : subWeeks(nextDay(firstDate, weekStart), 1);
81
+
82
+ // To correctly group activities by week, it is necessary to left-pad the list
83
+ // because the first date might not be set start weekday.
84
+ var paddedActivities = [].concat(_toConsumableArray(Array.from({
85
+ length: differenceInCalendarDays(firstDate, firstCalendarDate)
86
+ }).fill(null)), _toConsumableArray(normalizedActivities));
87
+ var numberOfWeeks = Math.ceil(paddedActivities.length / 7);
88
+
89
+ // Finally, group activities by week
90
+ return Array.from({
91
+ length: numberOfWeeks
92
+ }).fill(null).map(function (_, weekIndex) {
93
+ return paddedActivities.slice(weekIndex * 7, weekIndex * 7 + 7);
94
+ });
95
+ };
96
+ export var getMonthLabels = function getMonthLabels(weeks) {
97
+ var monthNames = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_MONTH_LABELS;
98
+ return weeks.reduce(function (labels, week, weekIndex) {
99
+ var firstActivity = week.filter(Boolean).find(function (activity) {
100
+ return activity !== undefined;
101
+ });
102
+ if (!firstActivity) {
103
+ throw new Error("Unexpected error: Week ".concat(weekIndex + 1, " is empty: [").concat(week, "]."));
104
+ }
105
+ var month = monthNames[getMonth(parseISO(firstActivity.date))];
106
+ if (!month) {
107
+ var monthName = new Date(firstActivity.date).toLocaleString('en-US', {
108
+ month: 'short'
109
+ });
110
+ throw new Error("Unexpected error: undefined month label for ".concat(monthName, "."));
111
+ }
112
+ var prevLabel = labels.at(-1);
113
+ if (weekIndex === 0 || !prevLabel || prevLabel.label !== month) {
114
+ return [].concat(_toConsumableArray(labels), [{
115
+ label: month,
116
+ weekIndex: weekIndex
117
+ }]);
118
+ }
119
+ return labels;
120
+ }, []).filter(function (_ref, index, labels) {
121
+ var weekIndex = _ref.weekIndex;
122
+ // Labels should only be shown if there is "enough" space (data).
123
+ // This is a naive implementation that does not take the block size,
124
+ // font size, etc. into account.
125
+ var minWeeks = 3;
126
+
127
+ // Skip the first month label if there is not enough space to the next one.
128
+ if (index === 0) {
129
+ return labels[1] && labels[1].weekIndex - weekIndex >= minWeeks;
130
+ }
131
+
132
+ // Skip the last month label if there is not enough data in that month
133
+ // to avoid overflowing the calendar on the right.
134
+ if (index === labels.length - 1) {
135
+ return weeks.slice(weekIndex).length >= minWeeks;
136
+ }
137
+ return true;
138
+ });
139
+ };
140
+ export var generateEmptyData = function generateEmptyData() {
141
+ var year = new Date().getFullYear();
142
+ var days = eachDayOfInterval({
143
+ end: new Date(year, 11, 31),
144
+ start: new Date(year, 0, 1)
145
+ });
146
+ return days.map(function (date) {
147
+ return {
148
+ count: 0,
149
+ date: formatISO(date, {
150
+ representation: 'date'
151
+ }),
152
+ level: 0
153
+ };
154
+ });
155
+ };
156
+ export var generateTestData = function generateTestData(args) {
157
+ var _args$interval;
158
+ var maxCount = 20;
159
+ var maxLevel = args.maxLevel ? Math.max(1, args.maxLevel) : 4;
160
+ var now = new Date();
161
+ var days = eachDayOfInterval((_args$interval = args.interval) !== null && _args$interval !== void 0 ? _args$interval : {
162
+ end: endOfYear(now),
163
+ start: startOfYear(now)
164
+ });
165
+ return days.map(function (date) {
166
+ // The random activity count is shifted by up to 80% towards zero.
167
+ var c = Math.round(Math.random() * maxCount - Math.random() * (0.8 * maxCount));
168
+ var count = Math.max(0, c);
169
+ var level = Math.ceil(count / maxCount * maxLevel);
170
+ return {
171
+ count: count,
172
+ date: formatISO(date, {
173
+ representation: 'date'
174
+ }),
175
+ level: level
176
+ };
177
+ });
178
+ };
179
+ export var maxWeekdayLabelLength = function maxWeekdayLabelLength(firstWeek, weekStart, labels, fontSize) {
180
+ if (isOnSeverSide) return 0;
181
+ if (labels.length !== 7) {
182
+ throw new Error('Exactly 7 labels, one for each weekday must be passed.');
183
+ }
184
+ return firstWeek.reduce(function (maxLength, _, index) {
185
+ if (index % 2 !== 0) {
186
+ var dayIndex = (index + weekStart) % 7;
187
+ var label = labels[dayIndex];
188
+ // @ts-ignore
189
+ var curLength = Math.ceil(calcTextDimensions(label, fontSize).width);
190
+ return Math.max(maxLength, curLength);
191
+ }
192
+ return maxLength;
193
+ }, 0);
194
+ };
@@ -1,3 +1,5 @@
1
1
  import { ValueFormatter } from "../types";
2
2
  export declare const defaultValueFormatter: ValueFormatter;
3
3
  export declare const sumNumericArray: (arr: number[]) => number;
4
+ export declare const isOnSeverSide: boolean;
5
+ export declare const mapInputsToDeltaType: (deltaType: string, isIncreasePositive: boolean) => string;
package/es/utils/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { DeltaTypes } from "../types";
1
2
  export var defaultValueFormatter = function defaultValueFormatter(value) {
2
3
  return value.toString();
3
4
  };
@@ -5,4 +6,29 @@ export var sumNumericArray = function sumNumericArray(arr) {
5
6
  return arr.reduce(function (prefixSum, num) {
6
7
  return prefixSum + num;
7
8
  }, 0);
9
+ };
10
+ export var isOnSeverSide = typeof document === 'undefined' || typeof window === 'undefined';
11
+ export var mapInputsToDeltaType = function mapInputsToDeltaType(deltaType, isIncreasePositive) {
12
+ if (isIncreasePositive || deltaType === DeltaTypes.Unchanged) {
13
+ return deltaType;
14
+ }
15
+ switch (deltaType) {
16
+ case DeltaTypes.Increase:
17
+ {
18
+ return DeltaTypes.Decrease;
19
+ }
20
+ case DeltaTypes.ModerateIncrease:
21
+ {
22
+ return DeltaTypes.ModerateDecrease;
23
+ }
24
+ case DeltaTypes.Decrease:
25
+ {
26
+ return DeltaTypes.Increase;
27
+ }
28
+ case DeltaTypes.ModerateDecrease:
29
+ {
30
+ return DeltaTypes.ModerateIncrease;
31
+ }
32
+ }
33
+ return '';
8
34
  };
@@ -0,0 +1,2 @@
1
+ export declare function createTheme(input?: string[], size?: number): string[];
2
+ export declare const convertAlphaToSolid: (foreground: string, background: string) => string;
@@ -0,0 +1,49 @@
1
+ import _typeof from "@babel/runtime/helpers/esm/typeof";
2
+ import chroma from 'chroma-js';
3
+ var isstringScale = function isstringScale(colors, size) {
4
+ var invalidstring = colors.find(function (color) {
5
+ return !chroma.valid(color);
6
+ });
7
+ if (invalidstring) {
8
+ throw new Error("Invalid color \"".concat(String(invalidstring), "\" passed. All CSS color formats are accepted."));
9
+ }
10
+ return colors.length === size;
11
+ };
12
+ var createstringScale = function createstringScale(colors, size) {
13
+ return chroma.scale(colors).mode('lch').colors(size);
14
+ };
15
+ var validateTheme = function validateTheme(input, size) {
16
+ if (_typeof(input) !== 'object' || input === undefined) {
17
+ throw new Error("The theme object must contain at least 2 or ".concat(size, " colors respectively."));
18
+ }
19
+ if (input) {
20
+ var length = input.length;
21
+ if (length !== 2 && length !== size) {
22
+ throw new Error("theme must contain exactly 2 or ".concat(size, " colors, ").concat(length, " passed."));
23
+ }
24
+ }
25
+ };
26
+ var createDefaultTheme = function createDefaultTheme(size) {
27
+ return createstringScale(['hsl(0, 0%, 20%)', 'hsl(0, 0%, 92%)'], size);
28
+ };
29
+ export function createTheme(input) {
30
+ var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5;
31
+ var defaultTheme = createDefaultTheme(size);
32
+ if (input) {
33
+ validateTheme(input, size);
34
+ var theme = input !== null && input !== void 0 ? input : defaultTheme;
35
+
36
+ // @ts-ignore
37
+ return isstringScale(theme, size) ? theme : createstringScale(theme, size);
38
+ }
39
+ return defaultTheme;
40
+ }
41
+ export var convertAlphaToSolid = function convertAlphaToSolid(foreground, background) {
42
+ var fgColor = chroma(foreground);
43
+ var bgColor = chroma(background);
44
+ var alpha = fgColor.alpha();
45
+ var alphaComplement = 1 - alpha;
46
+ var mixedColor = [fgColor.get('rgb.r') * alpha + bgColor.get('rgb.r') * alphaComplement, fgColor.get('rgb.g') * alpha + bgColor.get('rgb.g') * alphaComplement, fgColor.get('rgb.b') * alpha + bgColor.get('rgb.b') * alphaComplement];
47
+ var resultColor = chroma(mixedColor);
48
+ return resultColor.hex();
49
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/charts",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "React modern charts components built on recharts",
5
5
  "keywords": [
6
6
  "lobehub",
@@ -68,8 +68,8 @@
68
68
  },
69
69
  "dependencies": {
70
70
  "@babel/runtime": "^7.24.8",
71
+ "date-fns": "^3.6.0",
71
72
  "polished": "^4.3.1",
72
- "react-layout-kit": "^1.9.0",
73
73
  "recharts": "^2.12.7"
74
74
  },
75
75
  "devDependencies": {
@@ -78,6 +78,7 @@
78
78
  "@lobehub/lint": "^1.24.3",
79
79
  "@lobehub/ui": "^1.146.8",
80
80
  "@testing-library/react": "^14.3.1",
81
+ "@types/chroma-js": "^2.4.4",
81
82
  "@types/pangu": "^4.0.2",
82
83
  "@types/query-string": "^6.3.0",
83
84
  "@types/react": "18.2.40",
@@ -91,7 +92,7 @@
91
92
  "dumi-theme-lobehub": "^1.8.1",
92
93
  "eslint": "^8.57.0",
93
94
  "father": "4.3.1",
94
- "husky": "^9.0.11",
95
+ "husky": "9.0.11",
95
96
  "jsdom": "^23.2.0",
96
97
  "lint-staged": "^15.2.7",
97
98
  "prettier": "^3.3.3",
@@ -109,9 +110,11 @@
109
110
  "ahooks": ">=3",
110
111
  "antd": ">=5.13.0",
111
112
  "antd-style": ">=3",
113
+ "chroma-js": ">=2",
112
114
  "lucide-react": ">=0.396.0",
113
115
  "react": ">=18",
114
- "react-dom": ">=18"
116
+ "react-dom": ">=18",
117
+ "react-layout-kit": ">=1"
115
118
  },
116
119
  "publishConfig": {
117
120
  "access": "public",
File without changes
File without changes