@libs-ui/utils 0.2.281 → 0.2.282

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.
@@ -1,31 +1,96 @@
1
+ import { isNil } from "./helpers";
2
+ /**
3
+ * Hàm có thể trả về lỗi nếu:
4
+ * - maxData < 0 và acceptNegative là false
5
+ * - minNegative là undefined và acceptNegative là true
6
+ * - maxData < minNegative (chỉ xảy ra khi acceptNegative là true)
7
+ * - minNegative > 0 (chỉ xảy ra khi acceptNegative là true)
8
+ * @throws {Error}
9
+ * @required luôn đặt hàm này trong try catch và xử lý ngoại lệ
10
+ * @hint Truyền 3 tham số: min,max và tick
11
+ */
1
12
  export const getSmartAxisScale = (maxData, options) => {
2
- const stepCandidates = options?.stepCandidates || [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000];
13
+ const minTickCount = options?.minTickCount || 5;
14
+ const maxTickCount = options?.maxTickCount || 10;
15
+ const stepCandidatesDefault = new Array();
16
+ const loopStepCandidates = Array.from({ length: 10 }, (_, index) => Math.pow(10, index)).findIndex(item => item > Math.abs(Math.max(maxData, Math.abs(options?.minNegative || 0)))) + 1;
17
+ Array.from({ length: loopStepCandidates }, (_, index) => {
18
+ for (let templateNumber = 1; templateNumber < 10; templateNumber++) {
19
+ if (options?.acceptStepIsTypeFloat) {
20
+ stepCandidatesDefault.push(Math.pow(10, index) * (((templateNumber - 1) * 2 + 1) / 2));
21
+ }
22
+ stepCandidatesDefault.push(Math.pow(10, index) * templateNumber);
23
+ }
24
+ });
25
+ const stepCandidates = options?.stepCandidates || stepCandidatesDefault;
26
+ let distanceToZero = maxData;
27
+ let reverse = 1;
28
+ if (maxData < 0 && !options?.acceptNegative) {
29
+ throw new Error("maxData is less than 0 and acceptNegative is false");
30
+ }
31
+ if (options?.acceptNegative) {
32
+ if (isNil(options.minNegative)) {
33
+ throw new Error("minNegative is required when acceptNegative is true");
34
+ }
35
+ if (maxData < options.minNegative) {
36
+ throw new Error("maxData is less than minNegative");
37
+ }
38
+ if (options.minNegative >= 0) {
39
+ throw new Error("minNegative must be negative");
40
+ }
41
+ if (maxData === 0) {
42
+ maxData = -1;
43
+ }
44
+ stepCandidates.unshift(...stepCandidates.map(item => item * -1));
45
+ if (maxData <= 0) {
46
+ distanceToZero = options.minNegative;
47
+ }
48
+ if (distanceToZero > -5) {
49
+ distanceToZero = -4;
50
+ }
51
+ if (maxData > 0) {
52
+ distanceToZero = maxData + Math.abs(options.minNegative);
53
+ reverse = -1;
54
+ }
55
+ }
56
+ if (Math.abs(distanceToZero) < 3) {
57
+ distanceToZero = 3;
58
+ }
3
59
  for (const step of stepCandidates) {
4
- let tickCount = Math.ceil(maxData / step) + 1;
5
- let maxY = step * tickCount;
6
- if (tickCount >= (options?.minTickCount || 5) && tickCount <= (options?.maxTickCount || 10)) {
7
- if (maxData < maxY) {
8
- tickCount = maxData - (tickCount - 1) * step < -1 * (step / 4) ? tickCount - 1 : tickCount;
9
- maxY = step * tickCount;
60
+ let tickCount = Math.abs(Math.ceil(distanceToZero / step)) + (reverse === -1 ? 2 : 1);
61
+ let maxValue = maxData <= 0 ? 0 : step * tickCount * reverse;
62
+ let minValue = 0;
63
+ if (tickCount >= minTickCount && tickCount <= maxTickCount) {
64
+ if (maxData < maxValue) {
65
+ if (options?.acceptNegative) {
66
+ let tick = 1;
67
+ while (!isNil(options.minNegative) && tick <= tickCount && minValue >= options.minNegative) {
68
+ minValue = tick * step;
69
+ tick++;
70
+ }
71
+ }
72
+ tickCount = distanceToZero - (tickCount - 1) * step < -1 * (step / 4) ? tickCount - 1 : tickCount;
73
+ maxValue = (step * tickCount * reverse) - (minValue * reverse);
10
74
  return {
11
- step: step,
12
- maxY: maxY,
13
- ticks: tickCount
75
+ stepSize: Math.abs(step),
76
+ max: maxValue,
77
+ min: minValue,
78
+ tickAmount: tickCount
14
79
  };
15
80
  }
16
81
  }
17
82
  }
18
- const tickCount = options?.maxTickCount || 10;
19
- let step = Math.ceil(maxData / tickCount);
20
- let maxY = step * tickCount;
21
- if (maxData === maxY) {
83
+ let step = Math.ceil(distanceToZero / minTickCount) || 1;
84
+ let maxValue = step * minTickCount;
85
+ if (distanceToZero === maxValue) {
22
86
  step = step + Math.ceil(step / 10);
23
- maxY = step * tickCount;
87
+ maxValue = step * minTickCount;
24
88
  }
25
89
  return {
26
- step: step,
27
- maxY: maxY,
28
- ticks: tickCount
90
+ stepSize: Math.abs(step),
91
+ max: maxValue,
92
+ min: 0,
93
+ tickAmount: minTickCount
29
94
  };
30
95
  };
31
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXNtYXJ0LWF4aXMtc2NhbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJzLXVpL3V0aWxzL3NyYy9nZXQtc21hcnQtYXhpcy1zY2FsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLE9BQWUsRUFBQyxPQUlqRCxFQUFFLEVBQUU7SUFDRCxNQUFNLGNBQWMsR0FBRyxPQUFPLEVBQUUsY0FBYyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBR25LLEtBQUssTUFBTSxJQUFJLElBQUksY0FBYyxFQUFFLENBQUM7UUFDbEMsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlDLElBQUksSUFBSSxHQUFHLElBQUksR0FBRyxTQUFTLENBQUM7UUFFNUIsSUFBSSxTQUFTLElBQUksQ0FBQyxPQUFPLEVBQUUsWUFBWSxJQUFJLENBQUMsQ0FBQyxJQUFJLFNBQVMsSUFBSSxDQUFDLE9BQU8sRUFBRSxZQUFZLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUM1RixJQUFJLE9BQU8sR0FBRyxJQUFJLEVBQUUsQ0FBQztnQkFDbkIsU0FBUyxHQUFHLE9BQU8sR0FBRyxDQUFDLFNBQVMsR0FBQyxDQUFDLENBQUMsR0FBQyxJQUFJLEdBQUksQ0FBQyxDQUFDLEdBQUMsQ0FBQyxJQUFJLEdBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztnQkFDcEYsSUFBSSxHQUFHLElBQUksR0FBRyxTQUFTLENBQUM7Z0JBQ3hCLE9BQU87b0JBQ0wsSUFBSSxFQUFFLElBQUk7b0JBQ1YsSUFBSSxFQUFFLElBQUk7b0JBQ1YsS0FBSyxFQUFFLFNBQVM7aUJBQ2pCLENBQUM7WUFFSixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLFNBQVMsR0FBRyxPQUFPLEVBQUUsWUFBWSxJQUFJLEVBQUUsQ0FBQztJQUM5QyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUMxQyxJQUFJLElBQUksR0FBRyxJQUFJLEdBQUcsU0FBUyxDQUFDO0lBQzVCLElBQUcsT0FBTyxLQUFLLElBQUksRUFBQyxDQUFDO1FBQ25CLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUMsRUFBRSxDQUFDLENBQUM7UUFDakMsSUFBSSxHQUFHLElBQUksR0FBRyxTQUFTLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU87UUFDTCxJQUFJLEVBQUUsSUFBSTtRQUNWLElBQUksRUFBRSxJQUFJO1FBQ1YsS0FBSyxFQUFFLFNBQVM7S0FDakIsQ0FBQztBQUVKLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjb25zdCBnZXRTbWFydEF4aXNTY2FsZSA9IChtYXhEYXRhOiBudW1iZXIsb3B0aW9ucz86IHtcbiAgbWluVGlja0NvdW50PzogbnVtYmVyLFxuICBtYXhUaWNrQ291bnQ/OiBudW1iZXIsXG4gIHN0ZXBDYW5kaWRhdGVzPzogQXJyYXk8bnVtYmVyPlxufSkgPT4ge1xuICAgIGNvbnN0IHN0ZXBDYW5kaWRhdGVzID0gb3B0aW9ucz8uc3RlcENhbmRpZGF0ZXMgfHwgWzEsIDIsIDUsIDEwLCAyMCwgMjUsIDUwLCAxMDAsIDIwMCwgNTAwLCAxMDAwLCAyMDAwLCA1MDAwLCAxMDAwMCwgMjAwMDAsIDUwMDAwLCAxMDAwMDAsIDIwMDAwMCwgNTAwMDAwLCAxMDAwMDAwXTtcbiAgICBcbiAgXG4gICAgZm9yIChjb25zdCBzdGVwIG9mIHN0ZXBDYW5kaWRhdGVzKSB7XG4gICAgICBsZXQgdGlja0NvdW50ID0gTWF0aC5jZWlsKG1heERhdGEgLyBzdGVwKSArIDE7XG4gICAgICBsZXQgbWF4WSA9IHN0ZXAgKiB0aWNrQ291bnQ7XG4gIFxuICAgICAgaWYgKHRpY2tDb3VudCA+PSAob3B0aW9ucz8ubWluVGlja0NvdW50IHx8IDUpICYmIHRpY2tDb3VudCA8PSAob3B0aW9ucz8ubWF4VGlja0NvdW50IHx8IDEwKSkge1xuICAgICAgICBpZiAobWF4RGF0YSA8IG1heFkpIHtcbiAgICAgICAgICB0aWNrQ291bnQgPSBtYXhEYXRhIC0gKHRpY2tDb3VudC0xKSpzdGVwIDwgIC0xKihzdGVwLzQpID8gdGlja0NvdW50IC0gMSA6IHRpY2tDb3VudDtcbiAgICAgICAgICBtYXhZID0gc3RlcCAqIHRpY2tDb3VudDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc3RlcDogc3RlcCxcbiAgICAgICAgICAgIG1heFk6IG1heFksXG4gICAgICAgICAgICB0aWNrczogdGlja0NvdW50XG4gICAgICAgICAgfTtcblxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdGlja0NvdW50ID0gb3B0aW9ucz8ubWF4VGlja0NvdW50IHx8IDEwO1xuICAgIGxldCBzdGVwID0gTWF0aC5jZWlsKG1heERhdGEgLyB0aWNrQ291bnQpO1xuICAgIGxldCBtYXhZID0gc3RlcCAqIHRpY2tDb3VudDtcbiAgICBpZihtYXhEYXRhID09PSBtYXhZKXtcbiAgICAgIHN0ZXAgPSBzdGVwICsgTWF0aC5jZWlsKHN0ZXAvMTApO1xuICAgICAgbWF4WSA9IHN0ZXAgKiB0aWNrQ291bnQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBzdGVwOiBzdGVwLFxuICAgICAgbWF4WTogbWF4WSxcbiAgICAgIHRpY2tzOiB0aWNrQ291bnRcbiAgICB9O1xuXG4gIH0iXX0=
96
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXNtYXJ0LWF4aXMtc2NhbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9saWJzLXVpL3V0aWxzL3NyYy9nZXQtc21hcnQtYXhpcy1zY2FsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2xDOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLENBQUMsT0FBZSxFQUFFLE9BT2xELEVBS0MsRUFBRTtJQUNGLE1BQU0sWUFBWSxHQUFHLE9BQU8sRUFBRSxZQUFZLElBQUksQ0FBQyxDQUFDO0lBQ2hELE1BQU0sWUFBWSxHQUFHLE9BQU8sRUFBRSxZQUFZLElBQUksRUFBRSxDQUFDO0lBQ2pELE1BQU0scUJBQXFCLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztJQUNsRCxNQUFNLGtCQUFrQixHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFdBQVcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFeEwsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxrQkFBa0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFO1FBQ3RELEtBQUssSUFBSSxjQUFjLEdBQUcsQ0FBQyxFQUFFLGNBQWMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFF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QUksR0FBRyxZQUFZLENBQUM7SUFDbkMsSUFBSSxjQUFjLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDaEMsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQztRQUNuQyxRQUFRLEdBQUcsSUFBSSxHQUFHLFlBQVksQ0FBQztJQUNqQyxDQUFDO0lBQ0QsT0FBTztRQUNMLFFBQVEsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztRQUN4QixHQUFHLEVBQUUsUUFBUTtRQUNiLEdBQUcsRUFBRSxDQUFDO1FBQ04sVUFBVSxFQUFFLFlBQVk7S0FDekIsQ0FBQztBQUVKLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzTmlsIH0gZnJvbSBcIi4vaGVscGVyc1wiO1xuLyoqXG4gKiBIw6BtIGPDsyB0aOG7gyB0cuG6oyB24buBIGzhu5dpIG7hur91OlxuICogLSBtYXhEYXRhIDwgMCB2w6AgYWNjZXB0TmVnYXRpdmUgbMOgIGZhbHNlXG4gKiAtIG1pbk5lZ2F0aXZlIGzDoCB1bmRlZmluZWQgdsOgIGFjY2VwdE5lZ2F0aXZlIGzDoCB0cnVlXG4gKiAtIG1heERhdGEgPCBtaW5OZWdhdGl2ZSAoY2jhu4kgeOG6o3kgcmEga2hpIGFjY2VwdE5lZ2F0aXZlIGzDoCB0cnVlKVxuICogLSBtaW5OZWdhdGl2ZSA+IDAgKGNo4buJIHjhuqN5IHJhIGtoaSBhY2NlcHROZWdhdGl2ZSBsw6AgdHJ1ZSlcbiAqIEB0aHJvd3Mge0Vycm9yfVxuICogQHJlcXVpcmVkIGx1w7RuIMSR4bq3dCBow6BtIG7DoHkgdHJvbmcgdHJ5IGNhdGNoIHbDoCB44butIGzDvSBuZ2/huqFpIGzhu4dcbiAqIEBoaW50IFRydXnhu4FuIDMgdGhhbSBz4buROiBtaW4sbWF4IHbDoCB0aWNrXG4gKi9cbmV4cG9ydCBjb25zdCBnZXRTbWFydEF4aXNTY2FsZSA9IChtYXhEYXRhOiBudW1iZXIsIG9wdGlvbnM/OiB7XG4gIG1pblRpY2tDb3VudD86IG51bWJlcjtcbiAgbWF4VGlja0NvdW50PzogbnVtYmVyO1xuICBzdGVwQ2FuZGlkYXRlcz86IEFycmF5PG51bWJlcj47XG4gIGFjY2VwdE5lZ2F0aXZlPzogYm9vbGVhbjtcbiAgbWluTmVnYXRpdmU/OiBudW1iZXI7XG4gIGFjY2VwdFN0ZXBJc1R5cGVGbG9hdD86IGJvb2xlYW47XG59KToge1xuICBzdGVwU2l6ZTogbnVtYmVyO1xuICBtYXg6IG51bWJlcjtcbiAgbWluOiBudW1iZXI7XG4gIHRpY2tBbW91bnQ6IG51bWJlcjtcbn0gPT4ge1xuICBjb25zdCBtaW5UaWNrQ291bnQgPSBvcHRpb25zPy5taW5UaWNrQ291bnQgfHwgNTtcbiAgY29uc3QgbWF4VGlja0NvdW50ID0gb3B0aW9ucz8ubWF4VGlja0NvdW50IHx8IDEwO1xuICBjb25zdCBzdGVwQ2FuZGlkYXRlc0RlZmF1bHQgPSBuZXcgQXJyYXk8bnVtYmVyPigpO1xuICBjb25zdCBsb29wU3RlcENhbmRpZGF0ZXMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiAxMCB9LCAoXywgaW5kZXgpID0+IE1hdGgucG93KDEwLCBpbmRleCkpLmZpbmRJbmRleChpdGVtID0+IGl0ZW0gPiBNYXRoLmFicyhNYXRoLm1heChtYXhEYXRhLCBNYXRoLmFicyhvcHRpb25zPy5taW5OZWdhdGl2ZSB8fCAwKSkpKSArIDE7XG5cbiAgQXJyYXkuZnJvbSh7IGxlbmd0aDogbG9vcFN0ZXBDYW5kaWRhdGVzIH0sIChfLCBpbmRleCkgPT4ge1xuICAgIGZvciAobGV0IHRlbXBsYXRlTnVtYmVyID0gMTsgdGVtcGxhdGVOdW1iZXIgPCAxMDsgdGVtcGxhdGVOdW1iZXIrKykge1xuICAgICAgaWYgKG9wdGlvbnM/LmFjY2VwdFN0ZXBJc1R5cGVGbG9hdCkge1xuICAgICAgICBzdGVwQ2FuZGlkYXRlc0RlZmF1bHQucHVzaChNYXRoLnBvdygxMCwgaW5kZXgpICogKCgodGVtcGxhdGVOdW1iZXIgLSAxKSAqIDIgKyAxKSAvIDIpKTtcbiAgICAgIH1cbiAgICAgIHN0ZXBDYW5kaWRhdGVzRGVmYXVsdC5wdXNoKE1hdGgucG93KDEwLCBpbmRleCkgKiB0ZW1wbGF0ZU51bWJlcik7XG4gICAgfVxuICB9KTtcblxuICBjb25zdCBzdGVwQ2FuZGlkYXRlcyA9IG9wdGlvbnM/LnN0ZXBDYW5kaWRhdGVzIHx8IHN0ZXBDYW5kaWRhdGVzRGVmYXVsdDtcbiAgbGV0IGRpc3RhbmNlVG9aZXJvID0gbWF4RGF0YTtcbiAgbGV0IHJldmVyc2UgPSAxO1xuXG4gIGlmIChtYXhEYXRhIDwgMCAmJiAhb3B0aW9ucz8uYWNjZXB0TmVnYXRpdmUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJtYXhEYXRhIGlzIGxlc3MgdGhhbiAwIGFuZCBhY2NlcHROZWdhdGl2ZSBpcyBmYWxzZVwiKTtcbiAgfVxuICBpZiAob3B0aW9ucz8uYWNjZXB0TmVnYXRpdmUpIHtcbiAgICBpZiAoaXNOaWwob3B0aW9ucy5taW5OZWdhdGl2ZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIm1pbk5lZ2F0aXZlIGlzIHJlcXVpcmVkIHdoZW4gYWNjZXB0TmVnYXRpdmUgaXMgdHJ1ZVwiKTtcbiAgICB9XG5cbiAgICBpZiAobWF4RGF0YSA8IG9wdGlvbnMubWluTmVnYXRpdmUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIm1heERhdGEgaXMgbGVzcyB0aGFuIG1pbk5lZ2F0aXZlXCIpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLm1pbk5lZ2F0aXZlID49IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIm1pbk5lZ2F0aXZlIG11c3QgYmUgbmVnYXRpdmVcIik7XG4gICAgfVxuICAgIGlmIChtYXhEYXRhID09PSAwKSB7XG4gICAgICBtYXhEYXRhID0gLTE7XG4gICAgfVxuXG4gICAgc3RlcENhbmRpZGF0ZXMudW5zaGlmdCguLi5zdGVwQ2FuZGlkYXRlcy5tYXAoaXRlbSA9PiBpdGVtICogLTEpKTtcbiAgICBpZiAobWF4RGF0YSA8PSAwKSB7XG4gICAgICBkaXN0YW5jZVRvWmVybyA9IG9wdGlvbnMubWluTmVnYXRpdmU7XG4gICAgfVxuICAgIGlmIChkaXN0YW5jZVRvWmVybyA+IC01KSB7XG4gICAgICBkaXN0YW5jZVRvWmVybyA9IC00O1xuICAgIH1cbiAgICBpZiAobWF4RGF0YSA+IDApIHtcbiAgICAgIGRpc3RhbmNlVG9aZXJvID0gbWF4RGF0YSArIE1hdGguYWJzKG9wdGlvbnMubWluTmVnYXRpdmUpO1xuICAgICAgcmV2ZXJzZSA9IC0xO1xuICAgIH1cbiAgfVxuICBpZiAoTWF0aC5hYnMoZGlzdGFuY2VUb1plcm8pIDwgMykge1xuICAgIGRpc3RhbmNlVG9aZXJvID0gMztcbiAgfVxuXG4gIGZvciAoY29uc3Qgc3RlcCBvZiBzdGVwQ2FuZGlkYXRlcykge1xuICAgIGxldCB0aWNrQ291bnQgPSBNYXRoLmFicyhNYXRoLmNlaWwoZGlzdGFuY2VUb1plcm8gLyBzdGVwKSkgKyAocmV2ZXJzZSA9PT0gLTEgPyAyIDogMSk7XG4gICAgbGV0IG1heFZhbHVlID0gbWF4RGF0YSA8PSAwID8gMCA6IHN0ZXAgKiB0aWNrQ291bnQgKiByZXZlcnNlO1xuICAgIGxldCBtaW5WYWx1ZSA9IDA7XG5cbiAgICBpZiAodGlja0NvdW50ID49IG1pblRpY2tDb3VudCAmJiB0aWNrQ291bnQgPD0gbWF4VGlja0NvdW50KSB7XG4gICAgICBpZiAobWF4RGF0YSA8IG1heFZhbHVlKSB7XG4gICAgICAgIGlmIChvcHRpb25zPy5hY2NlcHROZWdhdGl2ZSkge1xuICAgICAgICAgIGxldCB0aWNrID0gMTtcbiAgICAgICAgICB3aGlsZSAoIWlzTmlsKG9wdGlvbnMubWluTmVnYXRpdmUpICYmIHRpY2sgPD0gdGlja0NvdW50ICYmIG1pblZhbHVlID49IG9wdGlvbnMubWluTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIG1pblZhbHVlID0gdGljayAqIHN0ZXA7XG4gICAgICAgICAgICB0aWNrKys7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRpY2tDb3VudCA9IGRpc3RhbmNlVG9aZXJvIC0gKHRpY2tDb3VudCAtIDEpICogc3RlcCA8IC0xICogKHN0ZXAgLyA0KSA/IHRpY2tDb3VudCAtIDEgOiB0aWNrQ291bnQ7XG4gICAgICAgIG1heFZhbHVlID0gKHN0ZXAgKiB0aWNrQ291bnQgKiByZXZlcnNlKSAtIChtaW5WYWx1ZSAqIHJldmVyc2UpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHN0ZXBTaXplOiBNYXRoLmFicyhzdGVwKSxcbiAgICAgICAgICBtYXg6IG1heFZhbHVlLFxuICAgICAgICAgIG1pbjogbWluVmFsdWUsXG4gICAgICAgICAgdGlja0Ftb3VudDogdGlja0NvdW50XG4gICAgICAgIH07XG5cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgbGV0IHN0ZXAgPSBNYXRoLmNlaWwoZGlzdGFuY2VUb1plcm8gLyBtaW5UaWNrQ291bnQpIHx8IDE7XG4gIGxldCBtYXhWYWx1ZSA9IHN0ZXAgKiBtaW5UaWNrQ291bnQ7XG4gIGlmIChkaXN0YW5jZVRvWmVybyA9PT0gbWF4VmFsdWUpIHtcbiAgICBzdGVwID0gc3RlcCArIE1hdGguY2VpbChzdGVwIC8gMTApO1xuICAgIG1heFZhbHVlID0gc3RlcCAqIG1pblRpY2tDb3VudDtcbiAgfVxuICByZXR1cm4ge1xuICAgIHN0ZXBTaXplOiBNYXRoLmFicyhzdGVwKSxcbiAgICBtYXg6IG1heFZhbHVlLFxuICAgIG1pbjogMCxcbiAgICB0aWNrQW1vdW50OiBtaW5UaWNrQ291bnRcbiAgfTtcblxufSJdfQ==
@@ -2447,34 +2447,98 @@ const convertUrlToFile = (url, fileName) => {
2447
2447
  });
2448
2448
  };
2449
2449
 
2450
+ /**
2451
+ * Hàm có thể trả về lỗi nếu:
2452
+ * - maxData < 0 và acceptNegative là false
2453
+ * - minNegative là undefined và acceptNegative là true
2454
+ * - maxData < minNegative (chỉ xảy ra khi acceptNegative là true)
2455
+ * - minNegative > 0 (chỉ xảy ra khi acceptNegative là true)
2456
+ * @throws {Error}
2457
+ * @required luôn đặt hàm này trong try catch và xử lý ngoại lệ
2458
+ * @hint Truyền 3 tham số: min,max và tick
2459
+ */
2450
2460
  const getSmartAxisScale = (maxData, options) => {
2451
- const stepCandidates = options?.stepCandidates || [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000];
2461
+ const minTickCount = options?.minTickCount || 5;
2462
+ const maxTickCount = options?.maxTickCount || 10;
2463
+ const stepCandidatesDefault = new Array();
2464
+ const loopStepCandidates = Array.from({ length: 10 }, (_, index) => Math.pow(10, index)).findIndex(item => item > Math.abs(Math.max(maxData, Math.abs(options?.minNegative || 0)))) + 1;
2465
+ Array.from({ length: loopStepCandidates }, (_, index) => {
2466
+ for (let templateNumber = 1; templateNumber < 10; templateNumber++) {
2467
+ if (options?.acceptStepIsTypeFloat) {
2468
+ stepCandidatesDefault.push(Math.pow(10, index) * (((templateNumber - 1) * 2 + 1) / 2));
2469
+ }
2470
+ stepCandidatesDefault.push(Math.pow(10, index) * templateNumber);
2471
+ }
2472
+ });
2473
+ const stepCandidates = options?.stepCandidates || stepCandidatesDefault;
2474
+ let distanceToZero = maxData;
2475
+ let reverse = 1;
2476
+ if (maxData < 0 && !options?.acceptNegative) {
2477
+ throw new Error("maxData is less than 0 and acceptNegative is false");
2478
+ }
2479
+ if (options?.acceptNegative) {
2480
+ if (isNil(options.minNegative)) {
2481
+ throw new Error("minNegative is required when acceptNegative is true");
2482
+ }
2483
+ if (maxData < options.minNegative) {
2484
+ throw new Error("maxData is less than minNegative");
2485
+ }
2486
+ if (options.minNegative >= 0) {
2487
+ throw new Error("minNegative must be negative");
2488
+ }
2489
+ if (maxData === 0) {
2490
+ maxData = -1;
2491
+ }
2492
+ stepCandidates.unshift(...stepCandidates.map(item => item * -1));
2493
+ if (maxData <= 0) {
2494
+ distanceToZero = options.minNegative;
2495
+ }
2496
+ if (distanceToZero > -5) {
2497
+ distanceToZero = -4;
2498
+ }
2499
+ if (maxData > 0) {
2500
+ distanceToZero = maxData + Math.abs(options.minNegative);
2501
+ reverse = -1;
2502
+ }
2503
+ }
2504
+ if (Math.abs(distanceToZero) < 3) {
2505
+ distanceToZero = 3;
2506
+ }
2452
2507
  for (const step of stepCandidates) {
2453
- let tickCount = Math.ceil(maxData / step) + 1;
2454
- let maxY = step * tickCount;
2455
- if (tickCount >= (options?.minTickCount || 5) && tickCount <= (options?.maxTickCount || 10)) {
2456
- if (maxData < maxY) {
2457
- tickCount = maxData - (tickCount - 1) * step < -1 * (step / 4) ? tickCount - 1 : tickCount;
2458
- maxY = step * tickCount;
2508
+ let tickCount = Math.abs(Math.ceil(distanceToZero / step)) + (reverse === -1 ? 2 : 1);
2509
+ let maxValue = maxData <= 0 ? 0 : step * tickCount * reverse;
2510
+ let minValue = 0;
2511
+ if (tickCount >= minTickCount && tickCount <= maxTickCount) {
2512
+ if (maxData < maxValue) {
2513
+ if (options?.acceptNegative) {
2514
+ let tick = 1;
2515
+ while (!isNil(options.minNegative) && tick <= tickCount && minValue >= options.minNegative) {
2516
+ minValue = tick * step;
2517
+ tick++;
2518
+ }
2519
+ }
2520
+ tickCount = distanceToZero - (tickCount - 1) * step < -1 * (step / 4) ? tickCount - 1 : tickCount;
2521
+ maxValue = (step * tickCount * reverse) - (minValue * reverse);
2459
2522
  return {
2460
- step: step,
2461
- maxY: maxY,
2462
- ticks: tickCount
2523
+ stepSize: Math.abs(step),
2524
+ max: maxValue,
2525
+ min: minValue,
2526
+ tickAmount: tickCount
2463
2527
  };
2464
2528
  }
2465
2529
  }
2466
2530
  }
2467
- const tickCount = options?.maxTickCount || 10;
2468
- let step = Math.ceil(maxData / tickCount);
2469
- let maxY = step * tickCount;
2470
- if (maxData === maxY) {
2531
+ let step = Math.ceil(distanceToZero / minTickCount) || 1;
2532
+ let maxValue = step * minTickCount;
2533
+ if (distanceToZero === maxValue) {
2471
2534
  step = step + Math.ceil(step / 10);
2472
- maxY = step * tickCount;
2535
+ maxValue = step * minTickCount;
2473
2536
  }
2474
2537
  return {
2475
- step: step,
2476
- maxY: maxY,
2477
- ticks: tickCount
2538
+ stepSize: Math.abs(step),
2539
+ max: maxValue,
2540
+ min: 0,
2541
+ tickAmount: minTickCount
2478
2542
  };
2479
2543
  };
2480
2544