@kubit-ui-web/react-charts 1.2.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.
- package/README.md +96 -0
- package/dist/cjs/components/zoomArea/hooks/useResponsiveCanvas.d.ts.map +1 -1
- package/dist/cjs/components/zoomArea/hooks/useResponsiveCanvas.js +6 -1
- package/dist/cjs/utils/cssGradientToSvg/cssGradientToSvg.d.ts.map +1 -1
- package/dist/cjs/utils/cssGradientToSvg/cssGradientToSvg.js +2 -2
- package/dist/cjs/utils/getCanvasDimensions/getCanvasDimensions.d.ts.map +1 -1
- package/dist/cjs/utils/getCanvasDimensions/getCanvasDimensions.js +13 -2
- package/dist/cjs/utils/index.d.ts +2 -0
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +2 -0
- package/dist/cjs/utils/logger/index.d.ts +2 -0
- package/dist/cjs/utils/logger/index.d.ts.map +1 -0
- package/dist/cjs/utils/logger/index.js +1 -0
- package/dist/cjs/utils/logger/logger.d.ts +45 -0
- package/dist/cjs/utils/logger/logger.d.ts.map +1 -0
- package/dist/cjs/utils/logger/logger.js +140 -0
- package/dist/cjs/utils/ssr/index.d.ts +2 -0
- package/dist/cjs/utils/ssr/index.d.ts.map +1 -0
- package/dist/cjs/utils/ssr/index.js +1 -0
- package/dist/cjs/utils/ssr/ssr.d.ts +80 -0
- package/dist/cjs/utils/ssr/ssr.d.ts.map +1 -0
- package/dist/cjs/utils/ssr/ssr.js +117 -0
- package/dist/cjs/utils/textBound/textBound.d.ts.map +1 -1
- package/dist/cjs/utils/textBound/textBound.js +17 -5
- package/dist/esm/components/zoomArea/hooks/useResponsiveCanvas.d.ts.map +1 -1
- package/dist/esm/components/zoomArea/hooks/useResponsiveCanvas.js +6 -1
- package/dist/esm/utils/cssGradientToSvg/cssGradientToSvg.d.ts.map +1 -1
- package/dist/esm/utils/cssGradientToSvg/cssGradientToSvg.js +2 -2
- package/dist/esm/utils/getCanvasDimensions/getCanvasDimensions.d.ts.map +1 -1
- package/dist/esm/utils/getCanvasDimensions/getCanvasDimensions.js +13 -2
- package/dist/esm/utils/index.d.ts +2 -0
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +2 -0
- package/dist/esm/utils/logger/index.d.ts +2 -0
- package/dist/esm/utils/logger/index.d.ts.map +1 -0
- package/dist/esm/utils/logger/index.js +1 -0
- package/dist/esm/utils/logger/logger.d.ts +45 -0
- package/dist/esm/utils/logger/logger.d.ts.map +1 -0
- package/dist/esm/utils/logger/logger.js +140 -0
- package/dist/esm/utils/ssr/index.d.ts +2 -0
- package/dist/esm/utils/ssr/index.d.ts.map +1 -0
- package/dist/esm/utils/ssr/index.js +1 -0
- package/dist/esm/utils/ssr/ssr.d.ts +80 -0
- package/dist/esm/utils/ssr/ssr.d.ts.map +1 -0
- package/dist/esm/utils/ssr/ssr.js +117 -0
- package/dist/esm/utils/textBound/textBound.d.ts.map +1 -1
- package/dist/esm/utils/textBound/textBound.js +17 -5
- package/dist/kubit-ui-web-react-charts.cjs.js +1 -1
- package/dist/kubit-ui-web-react-charts.es.js +1 -1
- package/dist/kubit-ui-web-react-charts.umd.js +1 -1
- package/dist/types/components/zoomArea/hooks/useResponsiveCanvas.d.ts.map +1 -1
- package/dist/types/utils/cssGradientToSvg/cssGradientToSvg.d.ts.map +1 -1
- package/dist/types/utils/getCanvasDimensions/getCanvasDimensions.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +2 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/logger/index.d.ts +2 -0
- package/dist/types/utils/logger/index.d.ts.map +1 -0
- package/dist/types/utils/logger/logger.d.ts +45 -0
- package/dist/types/utils/logger/logger.d.ts.map +1 -0
- package/dist/types/utils/ssr/index.d.ts +2 -0
- package/dist/types/utils/ssr/index.d.ts.map +1 -0
- package/dist/types/utils/ssr/ssr.d.ts +80 -0
- package/dist/types/utils/ssr/ssr.d.ts.map +1 -0
- package/dist/types/utils/textBound/textBound.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1,15 +1,27 @@
|
|
|
1
|
+
import { createSVGElement, isBrowser, safeDocument } from '../ssr/ssr';
|
|
1
2
|
export const textBound = ({ bound, data, fontSize, svgHeight, svgWidth, viewBox, }) => {
|
|
2
|
-
if
|
|
3
|
+
// SSR-safe: Return 0 if not in browser or no data
|
|
4
|
+
if (!isBrowser() || !data.length) {
|
|
5
|
+
return 0;
|
|
6
|
+
}
|
|
7
|
+
const doc = safeDocument();
|
|
8
|
+
if (!doc) {
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
const svgContainer = createSVGElement('svg');
|
|
12
|
+
if (!svgContainer) {
|
|
3
13
|
return 0;
|
|
4
14
|
}
|
|
5
|
-
const svgContainer = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
6
15
|
svgContainer.setAttribute('style', 'position: absolute; visibility: hidden; top: -9999px; left: -9999px;');
|
|
7
16
|
svgContainer.setAttribute('viewBox', viewBox);
|
|
8
17
|
svgContainer.setAttribute('width', svgWidth);
|
|
9
18
|
svgContainer.setAttribute('height', svgHeight);
|
|
10
|
-
|
|
19
|
+
doc.body.appendChild(svgContainer);
|
|
11
20
|
const sizes = data.map((d) => {
|
|
12
|
-
const text =
|
|
21
|
+
const text = createSVGElement('text');
|
|
22
|
+
if (!text) {
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
13
25
|
text.setAttribute('font-size', fontSize);
|
|
14
26
|
text.textContent = d;
|
|
15
27
|
svgContainer.appendChild(text);
|
|
@@ -18,5 +30,5 @@ export const textBound = ({ bound, data, fontSize, svgHeight, svgWidth, viewBox,
|
|
|
18
30
|
return size;
|
|
19
31
|
});
|
|
20
32
|
svgContainer.remove();
|
|
21
|
-
return Math.max(...sizes);
|
|
33
|
+
return Math.max(...sizes, 0); // Ensure at least 0 is returned
|
|
22
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResponsiveCanvas.d.ts","sourceRoot":"","sources":["../../../../../src/components/zoomArea/hooks/useResponsiveCanvas.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"useResponsiveCanvas.d.ts","sourceRoot":"","sources":["../../../../../src/components/zoomArea/hooks/useResponsiveCanvas.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,UAAU,yBAAyB;IACjC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED,UAAU,yBAAyB;IACjC,yCAAyC;IACzC,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,mBAAmB,GAAI,0DAMjC,yBAAyB,KAAG,yBA8F9B,CAAC"}
|
|
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useState } from 'react';
|
|
|
2
2
|
import { buildViewBox } from '../../../components/svgContainer/utils/buildViewBox/buildViewBox';
|
|
3
3
|
import { getCanvasDimensions } from '../../../utils/getCanvasDimensions/getCanvasDimensions';
|
|
4
4
|
import { parseStringToNumberPx } from '../../../utils/parseStringToNumberPx.ts/parseStringToNumberPx';
|
|
5
|
+
import { isBrowser, safeQuerySelector } from '../../../utils/ssr/ssr';
|
|
5
6
|
export const useResponsiveCanvas = ({ canvasConfig, dataTestId, extraSpace = 0, height, width, }) => {
|
|
6
7
|
// State for parsed/calculated dimensions
|
|
7
8
|
const [parsedCanvas, setParsedCanvas] = useState({
|
|
@@ -28,8 +29,12 @@ export const useResponsiveCanvas = ({ canvasConfig, dataTestId, extraSpace = 0,
|
|
|
28
29
|
: undefined;
|
|
29
30
|
// Set up responsive dimensions with ResizeObserver
|
|
30
31
|
useEffect(() => {
|
|
32
|
+
// SSR-safe: Skip effect if not in browser
|
|
33
|
+
if (!isBrowser()) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
31
36
|
// Find the SVG element for this specific component instance
|
|
32
|
-
const svgElement =
|
|
37
|
+
const svgElement = safeQuerySelector(`[data-testid="${dataTestId}"]`);
|
|
33
38
|
if (!svgElement) {
|
|
34
39
|
return;
|
|
35
40
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cssGradientToSvg.d.ts","sourceRoot":"","sources":["../../../../src/utils/cssGradientToSvg/cssGradientToSvg.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cssGradientToSvg.d.ts","sourceRoot":"","sources":["../../../../src/utils/cssGradientToSvg/cssGradientToSvg.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,EAAE,WAAoB,KAAG,GAAG,CAAC,OAwChF,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { logger } from '../logger/logger';
|
|
2
3
|
/**
|
|
3
4
|
* Converts a CSS linear gradient string into an SVG linear gradient.
|
|
4
5
|
*
|
|
@@ -38,8 +39,7 @@ export const cssGradientToSVG = (cssGradient, id = 'gradientePath') => {
|
|
|
38
39
|
x1 = '100%';
|
|
39
40
|
break;
|
|
40
41
|
default:
|
|
41
|
-
|
|
42
|
-
console.error('Unsupported angle');
|
|
42
|
+
logger.warn(`Unsupported gradient angle: ${angle}°. Supported angles are 90, 180, 270.`);
|
|
43
43
|
return _jsx(_Fragment, {}); // Return an empty fragment for unsupported angles
|
|
44
44
|
}
|
|
45
45
|
return (_jsx("defs", { children: _jsx("linearGradient", { id: id, x1: x1, x2: x2, y1: y1, y2: y2, children: stops.map((stop, index) => (_jsx("stop", { offset: stop.offset, stopColor: stop.color }, `${index}-${stop.offset}`.toString()))) }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getCanvasDimensions.d.ts","sourceRoot":"","sources":["../../../../src/utils/getCanvasDimensions/getCanvasDimensions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getCanvasDimensions.d.ts","sourceRoot":"","sources":["../../../../src/utils/getCanvasDimensions/getCanvasDimensions.ts"],"names":[],"mappings":"AAsGA,UAAU,wBAAwB;IAChC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,UAAU,EAAE,aAAa,CAAC;CAC3B;AAED,UAAU,yBAAyB;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,4CAIjC,wBAAwB,KAAG,yBAkB7B,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { safeDocument, safeGetComputedStyle } from '../ssr/ssr';
|
|
1
2
|
import { Unit } from '../../types/unit.enum';
|
|
2
3
|
/**
|
|
3
4
|
* A mapping of string representations of units to their corresponding `Unit` enum values.
|
|
@@ -62,13 +63,23 @@ const calculatePercentage = (value, dimension, svgElement) => {
|
|
|
62
63
|
};
|
|
63
64
|
/**
|
|
64
65
|
* Calculates the rem value based on the root font size.
|
|
66
|
+
* SSR-safe: Returns default 16px if not in browser environment.
|
|
65
67
|
*
|
|
66
68
|
* @param {number} value - The value in rem to be converted to pixels.
|
|
67
69
|
* @returns {number} The calculated pixel value.
|
|
68
70
|
*/
|
|
69
71
|
const calculateRem = (value) => {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
+
const doc = safeDocument();
|
|
73
|
+
if (!doc) {
|
|
74
|
+
// SSR fallback: Default browser font size is typically 16px
|
|
75
|
+
return value * 16;
|
|
76
|
+
}
|
|
77
|
+
const style = safeGetComputedStyle(doc.documentElement);
|
|
78
|
+
if (!style) {
|
|
79
|
+
return value * 16;
|
|
80
|
+
}
|
|
81
|
+
const remValue = parseFloat(style.fontSize);
|
|
82
|
+
return value * (remValue || 16); // Fallback to 16 if fontSize is invalid
|
|
72
83
|
};
|
|
73
84
|
/**
|
|
74
85
|
* Calculates the dimensions of an SVG element based on the provided width and height values.
|
|
@@ -3,7 +3,9 @@ export * from './buildTickValues/buildTickValues';
|
|
|
3
3
|
export * from './classNames/classNames';
|
|
4
4
|
export * from './cssGradientToSvg/cssGradientToSvg';
|
|
5
5
|
export * from './cursorNear/isNear';
|
|
6
|
+
export * from './logger';
|
|
6
7
|
export * from './shadowSvg/shadowSvg';
|
|
7
8
|
export * from './shadowSvg/shadowSvg.types';
|
|
9
|
+
export * from './ssr';
|
|
8
10
|
export * from './textBound/textBound';
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAClD,cAAc,yBAAyB,CAAC;AACxC,cAAc,qCAAqC,CAAC;AACpD,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qCAAqC,CAAC;AACpD,cAAc,mCAAmC,CAAC;AAClD,cAAc,yBAAyB,CAAC;AACxC,cAAc,qCAAqC,CAAC;AACpD,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,OAAO,CAAC;AACtB,cAAc,uBAAuB,CAAC"}
|
package/dist/esm/utils/index.js
CHANGED
|
@@ -3,6 +3,8 @@ export * from './buildTickValues/buildTickValues';
|
|
|
3
3
|
export * from './classNames/classNames';
|
|
4
4
|
export * from './cssGradientToSvg/cssGradientToSvg';
|
|
5
5
|
export * from './cursorNear/isNear';
|
|
6
|
+
export * from './logger';
|
|
6
7
|
export * from './shadowSvg/shadowSvg';
|
|
7
8
|
export * from './shadowSvg/shadowSvg.types';
|
|
9
|
+
export * from './ssr';
|
|
8
10
|
export * from './textBound/textBound';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/logger/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { logger, configureLogger, resetLogger } from './logger';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for @kubit/web-ui-charts
|
|
3
|
+
*
|
|
4
|
+
* Provides a centralized logging system that:
|
|
5
|
+
* - Respects NODE_ENV (disabled in production builds)
|
|
6
|
+
* - Supports different log levels
|
|
7
|
+
* - Can be configured/disabled by consumers
|
|
8
|
+
* - Will be stripped out in production builds via terser
|
|
9
|
+
*/
|
|
10
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
11
|
+
interface LoggerConfig {
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
minLevel: LogLevel;
|
|
14
|
+
prefix: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Configure the logger behavior
|
|
18
|
+
* @param newConfig - Partial configuration to merge with current settings
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Disable all logging
|
|
23
|
+
* configureLogger({ enabled: false });
|
|
24
|
+
*
|
|
25
|
+
* // Enable debug logs in development
|
|
26
|
+
* configureLogger({ minLevel: 'debug' });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const configureLogger: (newConfig: Partial<LoggerConfig>) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Reset logger to default configuration
|
|
32
|
+
*/
|
|
33
|
+
export declare const resetLogger: () => void;
|
|
34
|
+
/**
|
|
35
|
+
* Main logger object
|
|
36
|
+
* Export as singleton to ensure consistent configuration
|
|
37
|
+
*/
|
|
38
|
+
export declare const logger: {
|
|
39
|
+
debug: (message: string, ...args: unknown[]) => void;
|
|
40
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
41
|
+
info: (message: string, ...args: unknown[]) => void;
|
|
42
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
43
|
+
};
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../../src/utils/logger/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEpD,UAAU,YAAY;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AA+BD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,OAAO,CAAC,YAAY,CAAC,KAAG,IAElE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,QAAO,IAE9B,CAAC;AAkFF;;;GAGG;AACH,eAAO,MAAM,MAAM;qBA1DK,MAAM,WAAW,OAAO,EAAE,KAAG,IAAI;qBA+CjC,MAAM,WAAW,OAAO,EAAE,KAAG,IAAI;oBAhClC,MAAM,WAAW,OAAO,EAAE,KAAG,IAAI;oBAgBjC,MAAM,WAAW,OAAO,EAAE,KAAG,IAAI;CAgCvD,CAAC"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility for @kubit/web-ui-charts
|
|
3
|
+
*
|
|
4
|
+
* Provides a centralized logging system that:
|
|
5
|
+
* - Respects NODE_ENV (disabled in production builds)
|
|
6
|
+
* - Supports different log levels
|
|
7
|
+
* - Can be configured/disabled by consumers
|
|
8
|
+
* - Will be stripped out in production builds via terser
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Detect if we're in a production build
|
|
12
|
+
* Uses globalThis to be compatible with different environments (browser, Node, SSR)
|
|
13
|
+
*/
|
|
14
|
+
const isProduction = () => {
|
|
15
|
+
// Check if globalThis.process exists (Node/SSR environments)
|
|
16
|
+
if (typeof globalThis !== 'undefined' && 'process' in globalThis) {
|
|
17
|
+
const proc = globalThis.process;
|
|
18
|
+
return proc?.env?.NODE_ENV === 'production';
|
|
19
|
+
}
|
|
20
|
+
// In browser or other environments, assume development unless explicitly set
|
|
21
|
+
return false;
|
|
22
|
+
};
|
|
23
|
+
const DEFAULT_CONFIG = {
|
|
24
|
+
enabled: !isProduction(),
|
|
25
|
+
minLevel: 'info',
|
|
26
|
+
prefix: '[Kubit Charts]',
|
|
27
|
+
};
|
|
28
|
+
let config = { ...DEFAULT_CONFIG };
|
|
29
|
+
const LOG_LEVELS = {
|
|
30
|
+
debug: 0,
|
|
31
|
+
error: 3,
|
|
32
|
+
info: 1,
|
|
33
|
+
warn: 2,
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Configure the logger behavior
|
|
37
|
+
* @param newConfig - Partial configuration to merge with current settings
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* // Disable all logging
|
|
42
|
+
* configureLogger({ enabled: false });
|
|
43
|
+
*
|
|
44
|
+
* // Enable debug logs in development
|
|
45
|
+
* configureLogger({ minLevel: 'debug' });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export const configureLogger = (newConfig) => {
|
|
49
|
+
config = { ...config, ...newConfig };
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Reset logger to default configuration
|
|
53
|
+
*/
|
|
54
|
+
export const resetLogger = () => {
|
|
55
|
+
config = { ...DEFAULT_CONFIG };
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Check if a log level should be output based on configuration
|
|
59
|
+
*/
|
|
60
|
+
const shouldLog = (level) => {
|
|
61
|
+
if (!config.enabled) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[config.minLevel];
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Format log message with prefix
|
|
68
|
+
*/
|
|
69
|
+
const formatMessage = (message) => {
|
|
70
|
+
return `${config.prefix} ${message}`;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Log debug messages (development only)
|
|
74
|
+
* Useful for detailed debugging information
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* logger.debug('Chart dimensions calculated', { width: 400, height: 300 });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
const debug = (message, ...args) => {
|
|
82
|
+
if (shouldLog('debug')) {
|
|
83
|
+
// eslint-disable-next-line no-console
|
|
84
|
+
console.debug(formatMessage(message), ...args);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Log informational messages
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* logger.info('Chart rendered successfully');
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
const info = (message, ...args) => {
|
|
96
|
+
if (shouldLog('info')) {
|
|
97
|
+
// eslint-disable-next-line no-console
|
|
98
|
+
console.info(formatMessage(message), ...args);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Log warning messages
|
|
103
|
+
* Use for non-breaking issues that developers should be aware of
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* logger.warn('Invalid gradient angle, falling back to default', angle);
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
const warn = (message, ...args) => {
|
|
111
|
+
if (shouldLog('warn')) {
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.warn(formatMessage(message), ...args);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Log error messages
|
|
118
|
+
* Use for errors that don't prevent execution but indicate problems
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* logger.error('Failed to calculate text bounds, using fallback', error);
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
const error = (message, ...args) => {
|
|
126
|
+
if (shouldLog('error')) {
|
|
127
|
+
// eslint-disable-next-line no-console
|
|
128
|
+
console.error(formatMessage(message), ...args);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Main logger object
|
|
133
|
+
* Export as singleton to ensure consistent configuration
|
|
134
|
+
*/
|
|
135
|
+
export const logger = {
|
|
136
|
+
debug,
|
|
137
|
+
error,
|
|
138
|
+
info,
|
|
139
|
+
warn,
|
|
140
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/utils/ssr/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,WAAW,EACX,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { isBrowser, isServer, safeWindow, safeDocument, safeExecute, safeExecuteWithFallback, createSVGElement, safeGetComputedStyle, safeQuerySelector, } from './ssr';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR (Server-Side Rendering) utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides safe access to browser APIs when rendering on the server.
|
|
5
|
+
* Compatible with Next.js, Remix, Gatsby, and other SSR frameworks.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check if code is running in a browser environment
|
|
9
|
+
* @returns true if window is defined (browser), false otherwise (SSR)
|
|
10
|
+
*/
|
|
11
|
+
export declare const isBrowser: () => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Check if code is running in a server environment
|
|
14
|
+
* @returns true if running on server (no window), false otherwise
|
|
15
|
+
*/
|
|
16
|
+
export declare const isServer: () => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Safely access window object
|
|
19
|
+
* @returns window object if in browser, undefined if on server
|
|
20
|
+
*/
|
|
21
|
+
export declare const safeWindow: () => Window | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Safely access document object
|
|
24
|
+
* @returns document object if in browser, undefined if on server
|
|
25
|
+
*/
|
|
26
|
+
export declare const safeDocument: () => Document | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Safely execute code that requires browser APIs
|
|
29
|
+
* Returns undefined on server, executes callback in browser
|
|
30
|
+
*
|
|
31
|
+
* @param callback - Function to execute in browser environment
|
|
32
|
+
* @returns Result of callback if in browser, undefined if on server
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* const width = safeExecute(() => window.innerWidth) ?? 0;
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare const safeExecute: <T>(callback: () => T) => T | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Safely execute code with a fallback value for SSR
|
|
42
|
+
*
|
|
43
|
+
* @param callback - Function to execute in browser environment
|
|
44
|
+
* @param fallback - Value to return if on server or if callback fails
|
|
45
|
+
* @returns Result of callback if in browser, fallback otherwise
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const fontSize = safeExecuteWithFallback(
|
|
50
|
+
* () => parseFloat(getComputedStyle(document.documentElement).fontSize),
|
|
51
|
+
* 16
|
|
52
|
+
* );
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare const safeExecuteWithFallback: <T>(callback: () => T, fallback: T) => T;
|
|
56
|
+
/**
|
|
57
|
+
* Create an SVG element safely (browser-only)
|
|
58
|
+
* Returns undefined on server
|
|
59
|
+
*
|
|
60
|
+
* @param tagName - SVG element tag name
|
|
61
|
+
* @returns SVG element if in browser, undefined if on server
|
|
62
|
+
*/
|
|
63
|
+
export declare const createSVGElement: <K extends keyof SVGElementTagNameMap>(tagName: K) => SVGElementTagNameMap[K] | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Get computed style safely
|
|
66
|
+
* Returns undefined on server
|
|
67
|
+
*
|
|
68
|
+
* @param element - Element to get computed style for
|
|
69
|
+
* @returns CSSStyleDeclaration if in browser, undefined if on server
|
|
70
|
+
*/
|
|
71
|
+
export declare const safeGetComputedStyle: (element: Element) => CSSStyleDeclaration | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Query selector safely
|
|
74
|
+
* Returns null on server or if not found
|
|
75
|
+
*
|
|
76
|
+
* @param selector - CSS selector string
|
|
77
|
+
* @returns Element if found in browser, null otherwise
|
|
78
|
+
*/
|
|
79
|
+
export declare const safeQuerySelector: <T extends Element = Element>(selector: string) => T | null;
|
|
80
|
+
//# sourceMappingURL=ssr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../../../../src/utils/ssr/ssr.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,SAAS,QAAO,OAE5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,QAAO,OAE3B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,QAAO,MAAM,GAAG,SAEtC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,QAAQ,GAAG,SAE1C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,UAAU,MAAM,CAAC,KAAG,CAAC,GAAG,SAStD,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,EAAE,UAAU,MAAM,CAAC,EAAE,UAAU,CAAC,KAAG,CAE3E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,oBAAoB,EACnE,SAAS,CAAC,KACT,oBAAoB,CAAC,CAAC,CAAC,GAAG,SAM5B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,SAAS,OAAO,KACf,mBAAmB,GAAG,SAMxB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,OAAO,GAAG,OAAO,EAC3D,UAAU,MAAM,KACf,CAAC,GAAG,IAMN,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR (Server-Side Rendering) utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides safe access to browser APIs when rendering on the server.
|
|
5
|
+
* Compatible with Next.js, Remix, Gatsby, and other SSR frameworks.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check if code is running in a browser environment
|
|
9
|
+
* @returns true if window is defined (browser), false otherwise (SSR)
|
|
10
|
+
*/
|
|
11
|
+
export const isBrowser = () => {
|
|
12
|
+
return typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Check if code is running in a server environment
|
|
16
|
+
* @returns true if running on server (no window), false otherwise
|
|
17
|
+
*/
|
|
18
|
+
export const isServer = () => {
|
|
19
|
+
return !isBrowser();
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Safely access window object
|
|
23
|
+
* @returns window object if in browser, undefined if on server
|
|
24
|
+
*/
|
|
25
|
+
export const safeWindow = () => {
|
|
26
|
+
return isBrowser() ? window : undefined;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Safely access document object
|
|
30
|
+
* @returns document object if in browser, undefined if on server
|
|
31
|
+
*/
|
|
32
|
+
export const safeDocument = () => {
|
|
33
|
+
return isBrowser() ? document : undefined;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Safely execute code that requires browser APIs
|
|
37
|
+
* Returns undefined on server, executes callback in browser
|
|
38
|
+
*
|
|
39
|
+
* @param callback - Function to execute in browser environment
|
|
40
|
+
* @returns Result of callback if in browser, undefined if on server
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const width = safeExecute(() => window.innerWidth) ?? 0;
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const safeExecute = (callback) => {
|
|
48
|
+
if (!isBrowser()) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return callback();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Safely execute code with a fallback value for SSR
|
|
60
|
+
*
|
|
61
|
+
* @param callback - Function to execute in browser environment
|
|
62
|
+
* @param fallback - Value to return if on server or if callback fails
|
|
63
|
+
* @returns Result of callback if in browser, fallback otherwise
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const fontSize = safeExecuteWithFallback(
|
|
68
|
+
* () => parseFloat(getComputedStyle(document.documentElement).fontSize),
|
|
69
|
+
* 16
|
|
70
|
+
* );
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export const safeExecuteWithFallback = (callback, fallback) => {
|
|
74
|
+
return safeExecute(callback) ?? fallback;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Create an SVG element safely (browser-only)
|
|
78
|
+
* Returns undefined on server
|
|
79
|
+
*
|
|
80
|
+
* @param tagName - SVG element tag name
|
|
81
|
+
* @returns SVG element if in browser, undefined if on server
|
|
82
|
+
*/
|
|
83
|
+
export const createSVGElement = (tagName) => {
|
|
84
|
+
const doc = safeDocument();
|
|
85
|
+
if (!doc) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return doc.createElementNS('http://www.w3.org/2000/svg', tagName);
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Get computed style safely
|
|
92
|
+
* Returns undefined on server
|
|
93
|
+
*
|
|
94
|
+
* @param element - Element to get computed style for
|
|
95
|
+
* @returns CSSStyleDeclaration if in browser, undefined if on server
|
|
96
|
+
*/
|
|
97
|
+
export const safeGetComputedStyle = (element) => {
|
|
98
|
+
const win = safeWindow();
|
|
99
|
+
if (!win) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
return win.getComputedStyle(element);
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Query selector safely
|
|
106
|
+
* Returns null on server or if not found
|
|
107
|
+
*
|
|
108
|
+
* @param selector - CSS selector string
|
|
109
|
+
* @returns Element if found in browser, null otherwise
|
|
110
|
+
*/
|
|
111
|
+
export const safeQuerySelector = (selector) => {
|
|
112
|
+
const doc = safeDocument();
|
|
113
|
+
if (!doc) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return doc.querySelector(selector);
|
|
117
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textBound.d.ts","sourceRoot":"","sources":["../../../../src/utils/textBound/textBound.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"textBound.d.ts","sourceRoot":"","sources":["../../../../src/utils/textBound/textBound.ts"],"names":[],"mappings":"AAEA,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,SAAS,GAAI,0DAOvB,cAAc,KAAG,MAwCnB,CAAC"}
|
|
@@ -1,15 +1,27 @@
|
|
|
1
|
+
import { createSVGElement, isBrowser, safeDocument } from '../ssr/ssr';
|
|
1
2
|
export const textBound = ({ bound, data, fontSize, svgHeight, svgWidth, viewBox, }) => {
|
|
2
|
-
if
|
|
3
|
+
// SSR-safe: Return 0 if not in browser or no data
|
|
4
|
+
if (!isBrowser() || !data.length) {
|
|
5
|
+
return 0;
|
|
6
|
+
}
|
|
7
|
+
const doc = safeDocument();
|
|
8
|
+
if (!doc) {
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
const svgContainer = createSVGElement('svg');
|
|
12
|
+
if (!svgContainer) {
|
|
3
13
|
return 0;
|
|
4
14
|
}
|
|
5
|
-
const svgContainer = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
6
15
|
svgContainer.setAttribute('style', 'position: absolute; visibility: hidden; top: -9999px; left: -9999px;');
|
|
7
16
|
svgContainer.setAttribute('viewBox', viewBox);
|
|
8
17
|
svgContainer.setAttribute('width', svgWidth);
|
|
9
18
|
svgContainer.setAttribute('height', svgHeight);
|
|
10
|
-
|
|
19
|
+
doc.body.appendChild(svgContainer);
|
|
11
20
|
const sizes = data.map((d) => {
|
|
12
|
-
const text =
|
|
21
|
+
const text = createSVGElement('text');
|
|
22
|
+
if (!text) {
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
13
25
|
text.setAttribute('font-size', fontSize);
|
|
14
26
|
text.textContent = d;
|
|
15
27
|
svgContainer.appendChild(text);
|
|
@@ -18,5 +30,5 @@ export const textBound = ({ bound, data, fontSize, svgHeight, svgWidth, viewBox,
|
|
|
18
30
|
return size;
|
|
19
31
|
});
|
|
20
32
|
svgContainer.remove();
|
|
21
|
-
return Math.max(...sizes);
|
|
33
|
+
return Math.max(...sizes, 0); // Ensure at least 0 is returned
|
|
22
34
|
};
|