From 412016bf49384b383cdbc9aed62b557ca149da3a Mon Sep 17 00:00:00 2001 From: Arun Philip Date: Wed, 12 Jun 2024 09:50:10 -0400 Subject: [PATCH 1/4] ensure getComputedStyle always has a valid canvas provided --- src/helpers/helpers.dom.ts | 29 +++++++++++++++++++++-------- src/platform/platform.base.js | 7 ++++--- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/helpers/helpers.dom.ts b/src/helpers/helpers.dom.ts index e06fefe94a6..c19c9793639 100644 --- a/src/helpers/helpers.dom.ts +++ b/src/helpers/helpers.dom.ts @@ -53,7 +53,12 @@ function parseMaxStyle(styleValue: string | number, node: HTMLElement, parentPro const getComputedStyle = (element: HTMLElement): CSSStyleDeclaration => element.ownerDocument.defaultView.getComputedStyle(element, null); -export function getStyle(el: HTMLElement, property: string): string { +// @ts-ignore +export function getStyle(el?: HTMLElement, property: string): string { + if (!el) { + return ''; + } + return getComputedStyle(el).getPropertyValue(property); } @@ -105,20 +110,22 @@ function getCanvasPosition( /** * Gets an event's x, y coordinates, relative to the chart area - * @param event - * @param chart * @returns x and y coordinates of the event */ export function getRelativePosition( event: Event | ChartEvent | TouchEvent | MouseEvent, - chart: Chart + chart?: Chart ): { x: number; y: number } { if ('native' in event) { return event; } const {canvas, currentDevicePixelRatio} = chart; + if (!canvas) { + return {x: 0, y: 0}; + } + const style = getComputedStyle(canvas); const borderBox = style.boxSizing === 'border-box'; const paddings = getPositionedStyle(style, 'padding'); @@ -138,19 +145,21 @@ export function getRelativePosition( }; } -function getContainerSize(canvas: HTMLCanvasElement, width: number, height: number): Partial { +// @ts-ignore +function getContainerSize(canvas?: HTMLCanvasElement, width: number, height: number): Partial { let maxWidth: number, maxHeight: number; if (width === undefined || height === undefined) { const container = canvas && _getParentNode(canvas); if (!container) { - width = canvas.clientWidth; - height = canvas.clientHeight; + width = canvas?.clientWidth ?? 0; + height = canvas?.clientHeight ?? 0; } else { const rect = container.getBoundingClientRect(); // this is the border box of the container const containerStyle = getComputedStyle(container); const containerBorder = getPositionedStyle(containerStyle, 'border', 'width'); const containerPadding = getPositionedStyle(containerStyle, 'padding'); + width = rect.width - containerPadding.width - containerBorder.width; height = rect.height - containerPadding.height - containerBorder.height; maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth'); @@ -169,11 +178,15 @@ const round1 = (v: number) => Math.round(v * 10) / 10; // eslint-disable-next-line complexity export function getMaximumSize( - canvas: HTMLCanvasElement, + canvas?: HTMLCanvasElement, bbWidth?: number, bbHeight?: number, aspectRatio?: number ): { width: number; height: number } { + if (!canvas) { + return {width: 0, height: 0}; + } + const style = getComputedStyle(canvas); const margins = getPositionedStyle(style, 'margin'); const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY; diff --git a/src/platform/platform.base.js b/src/platform/platform.base.js index 298e4088342..f1c93fdbad9 100644 --- a/src/platform/platform.base.js +++ b/src/platform/platform.base.js @@ -51,14 +51,15 @@ export default class BasePlatform { /** * Returns the maximum size in pixels of given canvas element. - * @param {HTMLCanvasElement} element + * @param {?HTMLCanvasElement} element * @param {number} [width] - content width of parent element * @param {number} [height] - content height of parent element * @param {number} [aspectRatio] - aspect ratio to maintain */ getMaximumSize(element, width, height, aspectRatio) { - width = Math.max(0, width || element.width); - height = height || element.height; + width = Math.max(0, width || (element?.width ?? 0)); + height = height || (element?.height ?? 0); + return { width, height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height) From ea5403de5fb73b944330f215ddaac7605de9e105 Mon Sep 17 00:00:00 2001 From: Arun Philip Date: Wed, 12 Jun 2024 14:40:44 -0400 Subject: [PATCH 2/4] fix jsdoc for getMaximumSize --- src/platform/platform.base.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/platform.base.js b/src/platform/platform.base.js index f1c93fdbad9..97e518cff88 100644 --- a/src/platform/platform.base.js +++ b/src/platform/platform.base.js @@ -51,7 +51,7 @@ export default class BasePlatform { /** * Returns the maximum size in pixels of given canvas element. - * @param {?HTMLCanvasElement} element + * @param {HTMLCanvasElement} [element] * @param {number} [width] - content width of parent element * @param {number} [height] - content height of parent element * @param {number} [aspectRatio] - aspect ratio to maintain From e50c4c5bdef34b031cd9f2cc23ee768243e03a9c Mon Sep 17 00:00:00 2001 From: Arun Philip Date: Wed, 12 Jun 2024 14:42:26 -0400 Subject: [PATCH 3/4] rearrange parameters to fix typescript error --- src/helpers/helpers.dom.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/helpers/helpers.dom.ts b/src/helpers/helpers.dom.ts index c19c9793639..0d100dbb5c4 100644 --- a/src/helpers/helpers.dom.ts +++ b/src/helpers/helpers.dom.ts @@ -53,8 +53,7 @@ function parseMaxStyle(styleValue: string | number, node: HTMLElement, parentPro const getComputedStyle = (element: HTMLElement): CSSStyleDeclaration => element.ownerDocument.defaultView.getComputedStyle(element, null); -// @ts-ignore -export function getStyle(el?: HTMLElement, property: string): string { +export function getStyle(property: string, el?: HTMLElement): string { if (!el) { return ''; } @@ -145,8 +144,7 @@ export function getRelativePosition( }; } -// @ts-ignore -function getContainerSize(canvas?: HTMLCanvasElement, width: number, height: number): Partial { +function getContainerSize(width: number, height: number, canvas?: HTMLCanvasElement): Partial { let maxWidth: number, maxHeight: number; if (width === undefined || height === undefined) { @@ -191,7 +189,7 @@ export function getMaximumSize( const margins = getPositionedStyle(style, 'margin'); const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY; const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY; - const containerSize = getContainerSize(canvas, bbWidth, bbHeight); + const containerSize = getContainerSize(bbWidth, bbHeight, canvas); let {width, height} = containerSize; if (style.boxSizing === 'content-box') { @@ -299,7 +297,7 @@ export function readUsedSize( element: HTMLElement, property: 'width' | 'height' ): number | undefined { - const value = getStyle(element, property); + const value = getStyle(property, element); const matches = value && value.match(/^(\d+)(\.\d+)?px$/); return matches ? +matches[1] : undefined; } From 41d203f71d2713d8acc1279fc18ca6b49c4bf65f Mon Sep 17 00:00:00 2001 From: Arun Philip Date: Wed, 12 Jun 2024 14:46:21 -0400 Subject: [PATCH 4/4] allow optional chaining and null coalescing operators --- .eslintrc.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintrc.yml b/.eslintrc.yml index d4a2057ca13..d9dde94ff8f 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -36,6 +36,8 @@ rules: es/no-regexp-s-flag: "error" es/no-regexp-unicode-property-escapes: "error" es/no-dynamic-import: "off" + es/no-optional-chaining: "off" + es/no-nullish-coalescing-operators: "off" overrides: - files: ['**/*.ts']