From 3cf2b7b6f35077c142737703fa1c53b26817b543 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Fri, 21 Nov 2025 12:51:51 +0100 Subject: [PATCH 1/8] fix: Prevent wrong component type on error (null) --- app/components/chart-with-filters.tsx | 55 ++++++--------------------- 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/app/components/chart-with-filters.tsx b/app/components/chart-with-filters.tsx index 0b4407e0c6..eb08b1a37f 100644 --- a/app/components/chart-with-filters.tsx +++ b/app/components/chart-with-filters.tsx @@ -13,70 +13,37 @@ import { } from "@/config-types"; const ChartAreasVisualization = dynamic( - import("@/charts/area/chart-area").then( - (mod) => mod.ChartAreasVisualization, - () => null as never - ) + () => import("@/charts/area/chart-area").then((mod) => ({ default: mod.ChartAreasVisualization })) ); const ChartColumnsVisualization = dynamic( - import("@/charts/column/chart-column").then( - (mod) => mod.ChartColumnsVisualization, - () => null as never - ) + () => import("@/charts/column/chart-column").then((mod) => ({ default: mod.ChartColumnsVisualization })) ); const ChartBarsVisualization = dynamic( - import("@/charts/bar/chart-bar").then( - (mod) => mod.ChartBarsVisualization, - () => null as never - ) + () => import("@/charts/bar/chart-bar").then((mod) => ({ default: mod.ChartBarsVisualization })) ); const ChartComboLineSingleVisualization = dynamic( - import("@/charts/combo/chart-combo-line-single").then( - (mod) => mod.ChartComboLineSingleVisualization, - () => null as never - ) + () => import("@/charts/combo/chart-combo-line-single").then((mod) => ({ default: mod.ChartComboLineSingleVisualization })) ); const ChartComboLineDualVisualization = dynamic( - import("@/charts/combo/chart-combo-line-dual").then( - (mod) => mod.ChartComboLineDualVisualization, - () => null as never - ) + () => import("@/charts/combo/chart-combo-line-dual").then((mod) => ({ default: mod.ChartComboLineDualVisualization })) ); const ChartComboLineColumnVisualization = dynamic( - import("@/charts/combo/chart-combo-line-column").then( - (mod) => mod.ChartComboLineColumnVisualization, - () => null as never - ) + () => import("@/charts/combo/chart-combo-line-column").then((mod) => ({ default: mod.ChartComboLineColumnVisualization })) ); const ChartLinesVisualization = dynamic( - import("@/charts/line/chart-lines").then( - (mod) => mod.ChartLinesVisualization, - () => null as never - ) + () => import("@/charts/line/chart-lines").then((mod) => ({ default: mod.ChartLinesVisualization })) ); const ChartMapVisualization = dynamic( - import("@/charts/map/chart-map").then( - (mod) => mod.ChartMapVisualization, - () => null as never - ) + () => import("@/charts/map/chart-map").then((mod) => ({ default: mod.ChartMapVisualization })) ); const ChartPieVisualization = dynamic( - import("@/charts/pie/chart-pie").then( - (mod) => mod.ChartPieVisualization, - () => null as never - ) + () => import("@/charts/pie/chart-pie").then((mod) => ({ default: mod.ChartPieVisualization })) ); const ChartScatterplotVisualization = dynamic( - import("@/charts/scatterplot/chart-scatterplot").then( - (mod) => mod.ChartScatterplotVisualization, - () => null as never - ) + () => import("@/charts/scatterplot/chart-scatterplot").then((mod) => ({ default: mod.ChartScatterplotVisualization })) ); const ChartTableVisualization = dynamic( - import("@/charts/table/chart-table").then( - (mod) => mod.ChartTableVisualization, - () => null as never - ) + () => import("@/charts/table/chart-table").then((mod) => ({ default: mod.ChartTableVisualization })) ); type GenericChartProps = { From ef282b267d64286af954e73676bf3f32a141fc84 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Fri, 21 Nov 2025 12:52:26 +0100 Subject: [PATCH 2/8] chore: Install @open-iframe-resizer/core --- app/package.json | 1 + yarn.lock | 106 ++++------------------------------------------- 2 files changed, 8 insertions(+), 99 deletions(-) diff --git a/app/package.json b/app/package.json index d178138121..8baec41a51 100644 --- a/app/package.json +++ b/app/package.json @@ -46,6 +46,7 @@ "@mui/utils": "^5.17.1", "@next/bundle-analyzer": "^11.0.1", "@next/mdx": "^11.0.1", + "@open-iframe-resizer/core": "1.6.0", "@preconstruct/next": "^3.0.1", "@prisma/client": "^4.10.1", "@rdfjs/data-model": "^2.0.2", diff --git a/yarn.lock b/yarn.lock index e4df412c0a..3518a65714 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,14 +7,6 @@ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.2.tgz#c836b1bd81e6d62cd6cdf3ee4948bcdce8ea79c8" integrity sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A== -"@ampproject/remapping@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - "@apollo/client@^3.2.5", "@apollo/client@~3.2.5 || ~3.3.0": version "3.3.20" resolved "https://registry.npmjs.org/@apollo/client/-/client-3.3.20.tgz" @@ -405,28 +397,6 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/generator@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.3.tgz#ef1c0f7cfe3b5fc8cbb9f6cc69f93441a68edefc" - integrity sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q== - dependencies: - "@babel/parser" "^7.27.3" - "@babel/types" "^7.27.3" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^3.0.2" - -"@babel/generator@^7.28.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.0.tgz#9cc2f7bd6eb054d77dc66c2664148a0c5118acd2" - integrity sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg== - dependencies: - "@babel/parser" "^7.28.0" - "@babel/types" "^7.28.0" - "@jridgewell/gen-mapping" "^0.3.12" - "@jridgewell/trace-mapping" "^0.3.28" - jsesc "^3.0.2" - "@babel/generator@^7.28.5": version "7.28.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.5.tgz#712722d5e50f44d07bc7ac9fe84438742dd61298" @@ -750,15 +720,6 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/helper-module-transforms@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz#db0bbcfba5802f9ef7870705a7ef8788508ede02" - integrity sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg== - dependencies: - "@babel/helper-module-imports" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - "@babel/traverse" "^7.27.3" - "@babel/helper-module-transforms@^7.28.3": version "7.28.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" @@ -1031,14 +992,6 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.22.19" -"@babel/helpers@^7.27.6": - version "7.28.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.2.tgz#80f0918fecbfebea9af856c419763230040ee850" - integrity sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw== - dependencies: - "@babel/template" "^7.27.2" - "@babel/types" "^7.28.2" - "@babel/helpers@^7.28.4": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.4.tgz#fe07274742e95bdf7cf1443593eeb8926ab63827" @@ -1084,7 +1037,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@7.12.16", "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.6", "@babel/parser@^7.15.4", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4", "@babel/parser@^7.22.0", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5", "@babel/parser@^7.25.9", "@babel/parser@^7.26.2", "@babel/parser@^7.27.0", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2", "@babel/parser@^7.27.3", "@babel/parser@^7.28.0", "@babel/parser@^7.28.3", "@babel/parser@^7.28.5": +"@babel/parser@7.12.16", "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.6", "@babel/parser@^7.15.4", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4", "@babel/parser@^7.22.0", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5", "@babel/parser@^7.25.9", "@babel/parser@^7.26.2", "@babel/parser@^7.27.0", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2", "@babel/parser@^7.28.3", "@babel/parser@^7.28.5": version "7.28.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== @@ -2435,32 +2388,6 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.3.tgz#8b62a6c2d10f9d921ba7339c90074708509cffae" - integrity sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.27.3" - "@babel/parser" "^7.27.3" - "@babel/template" "^7.27.2" - "@babel/types" "^7.27.3" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/traverse@^7.28.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.0.tgz#518aa113359b062042379e333db18380b537e34b" - integrity sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg== - dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.28.0" - "@babel/helper-globals" "^7.28.0" - "@babel/parser" "^7.28.0" - "@babel/template" "^7.27.2" - "@babel/types" "^7.28.0" - debug "^4.3.1" - "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.5": version "7.28.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.5.tgz#450cab9135d21a7a2ca9d2d35aa05c20e68c360b" @@ -2585,22 +2512,6 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" -"@babel/types@^7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.3.tgz#c0257bedf33aad6aad1f406d35c44758321eb3ec" - integrity sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - -"@babel/types@^7.28.0": - version "7.28.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.1.tgz#2aaf3c10b31ba03a77ac84f52b3912a0edef4cf9" - integrity sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ== - dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.27.1" - "@babel/types@^7.28.4", "@babel/types@^7.28.5": version "7.28.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" @@ -4891,14 +4802,6 @@ resolved "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz" integrity sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg== -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/gen-mapping@^0.3.0": version "0.3.3" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" @@ -4957,7 +4860,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": +"@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== @@ -6484,6 +6387,11 @@ resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== +"@open-iframe-resizer/core@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@open-iframe-resizer/core/-/core-1.6.0.tgz#fdcd8104e35a24f81fe2a04b0004421ba75d521d" + integrity sha512-qv4jo06YQP1qYzhUKeaBBA5r172n0zSmRCKvm9lom8e8mZEPZj4i6SBisKrhK0sUQttWKUfNQQDVxsik7gDzug== + "@panva/hkdf@^1.0.2": version "1.1.1" resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.1.1.tgz#ab9cd8755d1976e72fc77a00f7655a64efe6cd5d" From 44427a8ec35dc821b39d76b8ada512388d4e1d90 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Fri, 21 Nov 2025 13:30:04 +0100 Subject: [PATCH 3/8] fix: Client-side issues when executed on the server --- app/charts/bar/rendering-utils.ts | 2 +- app/charts/column/rendering-utils.ts | 2 +- app/components/text-block.tsx | 63 +++++++++---------- .../chart-controls/color-picker.tsx | 3 +- app/configurator/components/color-picker.tsx | 18 +++--- app/utils/color-utils.ts | 15 +++++ app/utils/get-text-size.ts | 14 +++++ 7 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 app/utils/color-utils.ts diff --git a/app/charts/bar/rendering-utils.ts b/app/charts/bar/rendering-utils.ts index 07f7655dda..368a927995 100644 --- a/app/charts/bar/rendering-utils.ts +++ b/app/charts/bar/rendering-utils.ts @@ -1,4 +1,3 @@ -import { getContrastingColor } from "@uiw/react-color"; import { select, Selection } from "d3-selection"; import { Series } from "d3-shape"; import { useCallback } from "react"; @@ -18,6 +17,7 @@ import { import { getChartConfig, useDefinitiveFilters } from "@/config-utils"; import { useConfiguratorState } from "@/configurator/configurator-state"; import { Observation } from "@/domain/data"; +import { getContrastingColor } from "@/utils/color-utils"; import { getTextWidth } from "@/utils/get-text-width"; export type RenderBarDatum = { diff --git a/app/charts/column/rendering-utils.ts b/app/charts/column/rendering-utils.ts index e5d8996498..eb57b3f1f8 100644 --- a/app/charts/column/rendering-utils.ts +++ b/app/charts/column/rendering-utils.ts @@ -1,4 +1,3 @@ -import { getContrastingColor } from "@uiw/react-color"; import { select, Selection } from "d3-selection"; import { Series } from "d3-shape"; import { useCallback } from "react"; @@ -18,6 +17,7 @@ import { import { getChartConfig, useDefinitiveFilters } from "@/config-utils"; import { useConfiguratorState } from "@/configurator/configurator-state"; import { Observation } from "@/domain/data"; +import { getContrastingColor } from "@/utils/color-utils"; export type RenderColumnDatum = { key: string; diff --git a/app/components/text-block.tsx b/app/components/text-block.tsx index 0e8eddd43b..b90f321795 100644 --- a/app/components/text-block.tsx +++ b/app/components/text-block.tsx @@ -3,7 +3,6 @@ import { t } from "@lingui/macro"; import { Theme } from "@mui/material"; import { makeStyles } from "@mui/styles"; import clsx from "clsx"; -import { selectAll } from "d3-selection"; import isEqual from "lodash/isEqual"; import { ComponentProps, @@ -186,39 +185,39 @@ export const useSyncTextBlockHeight = () => { return; } - selectAll(`.${TEXT_BLOCK_WRAPPER_CLASS}`).each( - function () { - const wrapperEl = this; - const contentEl = wrapperEl.querySelector( - `.${TEXT_BLOCK_CONTENT_CLASS}` - ); + const elements = document.querySelectorAll( + `.${TEXT_BLOCK_WRAPPER_CLASS}` + ); + elements.forEach((wrapperEl) => { + const contentEl = wrapperEl.querySelector( + `.${TEXT_BLOCK_CONTENT_CLASS}` + ); - if (!contentEl) { - return; - } + if (!contentEl) { + return; + } - const key = wrapperEl.id; - const h = Math.ceil(contentEl.clientHeight / ROW_HEIGHT) || 1; - - const newLayouts = Object.fromEntries( - Object.entries(layout.layouts).map(([bp, layouts]) => [ - bp, - layouts.map((b) => { - return b.i === key ? { ...b, h, minH: h } : b; - }), - ]) - ); - - if (!isEqual(newLayouts, layout.layouts)) { - dispatch({ - type: "LAYOUT_CHANGED", - value: { - ...layout, - layouts: newLayouts, - }, - }); - } + const key = wrapperEl.id; + const h = Math.ceil(contentEl.clientHeight / ROW_HEIGHT) || 1; + + const newLayouts = Object.fromEntries( + Object.entries(layout.layouts).map(([bp, layouts]) => [ + bp, + layouts.map((b) => { + return b.i === key ? { ...b, h, minH: h } : b; + }), + ]) + ); + + if (!isEqual(newLayouts, layout.layouts)) { + dispatch({ + type: "LAYOUT_CHANGED", + value: { + ...layout, + layouts: newLayouts, + }, + }); } - ); + }); }, [dispatch, layout, isFreeCanvas]); }; diff --git a/app/configurator/components/chart-controls/color-picker.tsx b/app/configurator/components/chart-controls/color-picker.tsx index 7d69ebc1b1..b5c1231d8d 100644 --- a/app/configurator/components/chart-controls/color-picker.tsx +++ b/app/configurator/components/chart-controls/color-picker.tsx @@ -12,10 +12,9 @@ import { Icon } from "@/icons"; import { ColorItem } from "@/palettes"; import { createColorId } from "@/utils/color-palette-utils"; -//have to import dynamically to avoid @uiw/react-color dependency issues with the server const CustomColorPicker = dynamic( () => - import("../../components/color-picker").then( + import("@/configurator/components/color-picker").then( (mod) => mod.CustomColorPicker ), { ssr: false } diff --git a/app/configurator/components/color-picker.tsx b/app/configurator/components/color-picker.tsx index 848d64837d..bac45c5a52 100644 --- a/app/configurator/components/color-picker.tsx +++ b/app/configurator/components/color-picker.tsx @@ -1,12 +1,6 @@ import { Input } from "@mui/material"; import { makeStyles } from "@mui/styles"; -import { - hexToHsva, - HsvaColor, - hsvaToHex, - Hue, - Saturation, -} from "@uiw/react-color"; +import { hexToHsva, HsvaColor, hsvaToHex } from "@uiw/react-color"; import dynamic from "next/dynamic"; import { ChangeEvent, useCallback, useEffect, useState } from "react"; @@ -20,6 +14,16 @@ const ChromePicker = dynamic( { ssr: false } ); +const Hue = dynamic( + () => import("@uiw/react-color").then((mod) => ({ default: mod.Hue })), + { ssr: false } +); + +const Saturation = dynamic( + () => import("@uiw/react-color").then((mod) => ({ default: mod.Saturation })), + { ssr: false } +); + const useColorPickerStyles = makeStyles({ swatches: { display: "grid", diff --git a/app/utils/color-utils.ts b/app/utils/color-utils.ts new file mode 100644 index 0000000000..b94ee3b186 --- /dev/null +++ b/app/utils/color-utils.ts @@ -0,0 +1,15 @@ +export const getContrastingColor = (color: string): string => { + if (!color) { + return "#ffffff"; + } + + const hex = color.replace("#", ""); + + const r = parseInt(hex.substring(0, 2), 16); + const g = parseInt(hex.substring(2, 4), 16); + const b = parseInt(hex.substring(4, 6), 16); + + const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255; + + return luminance >= 0.5 ? "#000000" : "#ffffff"; +}; diff --git a/app/utils/get-text-size.ts b/app/utils/get-text-size.ts index b67b26f4c7..942385498a 100644 --- a/app/utils/get-text-size.ts +++ b/app/utils/get-text-size.ts @@ -25,6 +25,20 @@ export const getTextSize = ( paddingRight = 0, paddingBottom = 0, } = options ?? {}; + + if (typeof document === "undefined") { + return { + x: 0, + y: 0, + width: 0, + height: 0, + top: 0, + right: 0, + bottom: 0, + left: 0, + } as DOMRect; + } + const root = select("body") .append("div") .attr("aria-hidden", "true") From 23be869900b4b34a963ff02e8bc0739aa5d71926 Mon Sep 17 00:00:00 2001 From: Bartosz Prusinowski Date: Fri, 21 Nov 2025 13:31:27 +0100 Subject: [PATCH 4/8] fix: Embed iFrame resizing --- app/pages/embed/[chartId].tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/pages/embed/[chartId].tsx b/app/pages/embed/[chartId].tsx index 832ba2ed4a..ad72b224a4 100644 --- a/app/pages/embed/[chartId].tsx +++ b/app/pages/embed/[chartId].tsx @@ -3,7 +3,7 @@ import "iframe-resizer/js/iframeResizer.contentWindow.js"; import { GetServerSideProps } from "next"; import ErrorPage from "next/error"; import Head from "next/head"; -import Script from "next/script"; +import "@open-iframe-resizer/core"; import { ChartPublished } from "@/components/chart-published"; import { useEmbedQueryParams } from "@/components/embed-params"; @@ -66,13 +66,9 @@ const EmbedPage = (props: PageProps) => { -