Compare commits

...
Author SHA1 Message Date
Mehmet Salih Yavuz 884516043f chore(deps): upgrade React 18 to 19 2026-08-28 17:40:15 +03:00
188 changed files with 1126 additions and 884 deletions
@@ -17,7 +17,14 @@
* under the License.
*/
import { useState, useEffect, useCallback, useRef, ReactNode } from 'react';
import {
useState,
useEffect,
useCallback,
useRef,
ReactNode,
type ReactElement,
} from 'react';
import { t } from '@apache-superset/core/translation';
import {
SupersetClient,
@@ -54,7 +61,7 @@ export default function VerifyCORS({
host,
method,
postPayload,
}: Props): JSX.Element {
}: Props): ReactElement {
const [didVerify, setDidVerify] = useState(false);
const [error, setError] = useState<Error | SupersetApiError | undefined>(
undefined,
+1 -1
View File
@@ -77,7 +77,7 @@ module.exports = {
// @ant-design/colors and @ant-design/fast-color are allowed through because
// @ant-design/icons >= 6.3 deep-imports the ESM build of @ant-design/colors
// from its CJS output, so babel-jest must transform those files.
'node_modules/(?!@ant-design/(colors|fast-color)|@formatjs/.*|d3-(array|interpolate|color|time|scale|time-format|format|selection)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|@x0k/.*|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|hastscript|refractor|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|character-reference-invalid|is-alphanumerical|is-alphabetical|is-decimal|is-hexadecimal|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|(?!geostyler)lodash|react-error-boundary|react-json-tree|react-base16-styling|lodash-es|rbush|quickselect|react-diff-viewer-continued|storybook/*.|json-stringify-pretty-compact|@x0k/json-schema-merge)',
'node_modules/(?!@ant-design/(colors|fast-color)|@formatjs/.*|d3-(array|interpolate|color|time|scale|time-format|format|selection)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|@x0k/.*|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|hastscript|refractor|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|character-reference-invalid|is-alphanumerical|is-alphabetical|is-decimal|is-hexadecimal|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|(?!geostyler)lodash|react-error-boundary|react-json-tree|react-base16-styling|lodash-es|rbush|quickselect|react-diff-viewer-continued|storybook/*.|json-stringify-pretty-compact|@x0k/json-schema-merge|react-resize-detector|react-markdown|vfile|vfile-message|trim-lines|trough|is-plain-obj)',
],
preset: 'ts-jest',
transform: {
+154 -260
View File
@@ -118,20 +118,19 @@
"ol": "^10.10.0",
"query-string": "9.5.0",
"re-resizable": "^6.11.2",
"react": "^18.3.0",
"react": "^19.2.0",
"react-arborist": "^3.16.0",
"react-checkbox-tree": "^1.8.0",
"react-checkbox-tree": "^2.0.1",
"react-diff-viewer-continued": "^4.4.0",
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^18.3.0",
"react-dom": "^19.2.0",
"react-google-recaptcha": "^3.1.0",
"react-intersection-observer": "^11.0.0",
"react-json-tree": "^0.20.0",
"react-lines-ellipsis": "^0.16.1",
"react-loadable": "^5.5.0",
"react-redux": "^7.2.9",
"react-resize-detector": "^9.1.1",
"react-resize-detector": "^12.3.0",
"react-reverse-portal": "^2.3.0",
"react-router-dom": "^5.3.4",
"react-search-input": "^0.11.3",
@@ -190,7 +189,7 @@
"@swc/plugin-transform-imports": "^13.0.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^12.8.3",
"@types/content-disposition": "^0.5.9",
"@types/dom-to-image": "^2.6.7",
@@ -201,9 +200,8 @@
"@types/lodash-es": "^4.17.12",
"@types/mousetrap": "^1.6.15",
"@types/node": "^26.2.0",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"@types/react-loadable": "^5.5.11",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"@types/react-redux": "^7.1.10",
"@types/react-router-dom": "^5.3.3",
"@types/react-transition-group": "^4.4.12",
@@ -292,7 +290,7 @@
"ace-builds": "^1.41.0",
"core-js": "^3.38.1",
"handlebars": "^4.7.8",
"react-ace": "^10.1.0",
"react-ace": "^14.0.1",
"regenerator-runtime": "^0.14.1"
}
},
@@ -11947,26 +11945,29 @@
"license": "MIT"
},
"node_modules/@testing-library/react": {
"version": "15.0.7",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz",
"integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==",
"version": "16.3.3",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.3.tgz",
"integrity": "sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@testing-library/dom": "^10.0.0",
"@types/react-dom": "^18.0.0"
"@babel/runtime": "^7.12.5"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@types/react": "^18.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
"@testing-library/dom": "^10.0.0",
"@types/react": "^18.0.0 || ^19.0.0",
"@types/react-dom": "^18.0.0 || ^19.0.0",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
@@ -12836,6 +12837,7 @@
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/qs": {
@@ -12866,22 +12868,21 @@
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.3.28",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
"version": "19.2.18",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz",
"integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.3.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"version": "19.2.5",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.5.tgz",
"integrity": "sha512-fMPwH9v7r/pp43yUd2/Mbiex5KouJwwR3dzHkhLREUC6764VyDsqxhAxv6OFEYR1RhjOyD1naqba8ECDBe7ZQg==",
"license": "MIT",
"peerDependencies": {
"@types/react": "^18.0.0"
"@types/react": "^19.2.0"
}
},
"node_modules/@types/react-google-recaptcha": {
@@ -12893,20 +12894,11 @@
"@types/react": "*"
}
},
"node_modules/@types/react-loadable": {
"version": "5.5.11",
"resolved": "https://registry.npmjs.org/@types/react-loadable/-/react-loadable-5.5.11.tgz",
"integrity": "sha512-/tq2IJ853MoIFRBmqVOxnGsRRjER5TmEKzsZtaAkiXAWoDeKgR/QNOT1vd9k0p9h/F616X21cpNh3hu4RutzRQ==",
"license": "MIT",
"dependencies": {
"@types/react": "*",
"@types/webpack": "^4"
}
},
"node_modules/@types/react-loadable/node_modules/@types/webpack": {
"version": "4.41.40",
"resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.40.tgz",
"integrity": "sha512-u6kMFSBM9HcoTpUXnL6mt2HSzftqb3JgYV6oxIgL2dl6sX6aCa5k6SOkzv5DuZjBTPUE/dJltKtwwuqrkZHpfw==",
"extraneous": true,
"license": "MIT",
"dependencies": {
"@types/node": "*",
@@ -12921,6 +12913,7 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"extraneous": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
@@ -13093,12 +13086,6 @@
"@types/node": "*"
}
},
"node_modules/@types/source-list-map": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.6.tgz",
"integrity": "sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==",
"license": "MIT"
},
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
@@ -13115,12 +13102,6 @@
"@types/geojson": "*"
}
},
"node_modules/@types/tapable": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.12.tgz",
"integrity": "sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==",
"license": "MIT"
},
"node_modules/@types/tinycolor2": {
"version": "1.4.6",
"resolved": "https://registry.npmjs.org/@types/tinycolor2/-/tinycolor2-1.4.6.tgz",
@@ -13141,24 +13122,6 @@
"license": "MIT",
"optional": true
},
"node_modules/@types/uglify-js": {
"version": "3.17.5",
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.5.tgz",
"integrity": "sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==",
"license": "MIT",
"dependencies": {
"source-map": "^0.6.1"
}
},
"node_modules/@types/uglify-js/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@types/unist": {
"version": "2.0.11",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
@@ -13203,26 +13166,6 @@
"@types/node": "*"
}
},
"node_modules/@types/webpack-sources": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw==",
"license": "MIT",
"dependencies": {
"@types/node": "*",
"@types/source-list-map": "*",
"source-map": "^0.7.3"
}
},
"node_modules/@types/webpack-sources/node_modules/source-map": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz",
"integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">= 12"
}
},
"node_modules/@types/yargs": {
"version": "17.0.33",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
@@ -15070,6 +15013,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
@@ -19750,6 +19694,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es-toolkit": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.52.0.tgz",
"integrity": "sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==",
"license": "MIT",
"workspaces": [
"docs",
"benchmarks",
"tests/types",
"tests/browser-compat"
]
},
"node_modules/es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
@@ -28199,24 +28155,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/lodash.get": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
"license": "MIT"
},
"node_modules/lodash.isempty": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
"integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==",
"license": "MIT"
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
"license": "MIT"
},
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
@@ -28228,7 +28172,6 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
"dev": true,
"license": "MIT"
},
"node_modules/lodash.merge": {
@@ -34520,33 +34463,37 @@
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"version": "19.2.8",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz",
"integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-ace": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/react-ace/-/react-ace-10.1.0.tgz",
"integrity": "sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA==",
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/react-ace/-/react-ace-14.1.0.tgz",
"integrity": "sha512-H+Tuw1oa3uP6zRoLBOayPVaMy5Le4G33OpEmLOfSVks75ajmrmFGbyWWEHfBYLCCpu5KfyFlod9jCEUc7i5ekw==",
"license": "MIT",
"peer": true,
"dependencies": {
"ace-builds": "^1.4.14",
"ace-builds": "^1.36.3",
"diff-match-patch": "^1.0.5",
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
"prop-types": "^15.7.2"
"fast-equals": "^5.3.3",
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0"
"react": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-ace/node_modules/fast-equals": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.1.tgz",
"integrity": "sha512-DjlFSM5Pk9cGcL0q5QXl66eGzx0N6szNgaswwc5ZphlBohjTVJSnGgI+rJVOgOi65qUoQnDZN4nDqi33udtydQ==",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/react-arborist": {
@@ -34680,36 +34627,18 @@
}
},
"node_modules/react-checkbox-tree": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/react-checkbox-tree/-/react-checkbox-tree-1.8.0.tgz",
"integrity": "sha512-ufC4aorihOvjLpvY1beab2hjVLGZbDTFRzw62foG0+th+KX7e/sdmWu/nD1ZS/U5Yr0rWGwedGH5GOtR0IkUXw==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/react-checkbox-tree/-/react-checkbox-tree-2.0.2.tgz",
"integrity": "sha512-6cywFB8PgvQD4V9hXMbOKV5F2MPzepix73aevgRZMqkwcqKHD/ulkueCP2ptQYBa43iU7X7YmYxRABKRg77R6Q==",
"license": "MIT",
"dependencies": {
"classnames": "^2.2.5",
"lodash": "^4.17.10",
"nanoid": "^3.0.0",
"fast-equals": "^6.0.0",
"lodash.memoize": "^4.1.2",
"prop-types": "^15.5.8"
},
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-checkbox-tree/node_modules/nanoid": {
"version": "3.3.18",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-diff-viewer-continued": {
@@ -34865,18 +34794,23 @@
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"version": "19.2.8",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz",
"integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==",
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
"scheduler": "^0.27.0"
},
"peerDependencies": {
"react": "^18.3.1"
"react": "^19.2.8"
}
},
"node_modules/react-dom/node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
"license": "MIT"
},
"node_modules/react-draggable": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.5.0.tgz",
@@ -34995,18 +34929,6 @@
"react-dom": "*"
}
},
"node_modules/react-loadable": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-loadable/-/react-loadable-5.5.0.tgz",
"integrity": "sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg==",
"license": "MIT",
"dependencies": {
"prop-types": "^15.5.0"
},
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-map-gl": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-8.1.2.tgz",
@@ -35115,16 +35037,15 @@
}
},
"node_modules/react-resize-detector": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-9.1.1.tgz",
"integrity": "sha512-siLzop7i4xIvZIACE/PHTvRegA8QRCEt0TfmvJ/qCIFQJ4U+3NuYcF8tNDmDWxfIn+X1eNCyY2rauH4KRxge8w==",
"version": "12.3.0",
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-12.3.0.tgz",
"integrity": "sha512-mIDOVrTHKGnKe6qEUWi8dFdfHM5CPyTOpqoHctdMQf89Ljm/0qqDIzkP3vTRZZJi9/raaMiRxDEOqO4you5x+A==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21"
"es-toolkit": "^1.39.6"
},
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
"react": "^18.0.0 || ^19.0.0"
}
},
"node_modules/react-reverse-portal": {
@@ -35304,20 +35225,6 @@
"react-dom": ">=16.6.0"
}
},
"node_modules/react-ultimate-pagination": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/react-ultimate-pagination/-/react-ultimate-pagination-1.3.2.tgz",
"integrity": "sha512-TDrUFR0hcI4nx9/EK3Gj4nlbhNQ5cXi6/7CGuF3j7k0vur7NUFOczm3POlGnuhTku2KUnpoM4Jf7E0l8Fpi2/Q==",
"license": "MIT",
"dependencies": {
"prop-types": "^15.0.0",
"ultimate-pagination": "1.0.0"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-use-measure": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz",
@@ -36411,6 +36318,7 @@
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
@@ -40106,12 +40014,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ultimate-pagination": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/ultimate-pagination/-/ultimate-pagination-1.0.0.tgz",
"integrity": "sha512-bJNroO5GM11McB9RJ1rHZGiXV/jU89Qwc6U5wR8jZuk0uFVajIvUDGPiROVvNMApvh7Ij3cPoeG5V3UlF4GvOA==",
"license": "MIT"
},
"node_modules/un-eval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/un-eval/-/un-eval-1.2.0.tgz",
@@ -41618,6 +41520,33 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/webpack-visualizer-plugin2/node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/webpack-visualizer-plugin2/node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.3.1"
}
},
"node_modules/webpack/node_modules/acorn": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
@@ -42914,11 +42843,10 @@
"@emotion/styled": "^11.14.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/lodash": "^4.17.25",
"@types/react": "*",
"@types/react-loadable": "*",
"@types/tinycolor2": "*",
"typescript": "^5.0.0"
},
@@ -42932,9 +42860,8 @@
"jed": "^1.1.1",
"lodash": "^4.18.1",
"nanoid": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-loadable": "^5.5.0",
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0",
"tinycolor2": "*"
}
},
@@ -42955,14 +42882,14 @@
"@superset-ui/core": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"ace-builds": "^1.4.14",
"brace": "^0.11.1",
"memoize-one": "^6.0.0",
"react": "^18.3.0",
"react-ace": "^10.1.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-ace": "^14.0.1",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"packages/superset-ui-core": {
@@ -43003,9 +42930,8 @@
"react-error-boundary": "^6.1.3",
"react-js-cron": "^6.0.2",
"react-markdown": "^10.1.0",
"react-resize-detector": "^7.1.2",
"react-resize-detector": "^12.3.0",
"react-syntax-highlighter": "^16.1.1",
"react-ultimate-pagination": "^1.3.2",
"regenerator-runtime": "^0.14.1",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
@@ -43040,16 +42966,14 @@
"@emotion/styled": "^11.14.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/react": "*",
"@types/react-loadable": "*",
"@types/tinycolor2": "*",
"antd": "^6.0.0",
"nanoid": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-loadable": "^5.5.0",
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0",
"tinycolor2": "*"
}
},
@@ -43099,23 +43023,6 @@
"node": ">=12"
}
},
"packages/superset-ui-core/node_modules/react-ace": {
"version": "14.0.1",
"resolved": "https://registry.npmjs.org/react-ace/-/react-ace-14.0.1.tgz",
"integrity": "sha512-z6YAZ20PNf/FqmYEic//G/UK6uw0rn21g58ASgHJHl9rfE4nITQLqthr9rHMVQK4ezwohJbp2dGrZpkq979PYQ==",
"license": "MIT",
"dependencies": {
"ace-builds": "^1.36.3",
"diff-match-patch": "^1.0.5",
"lodash.get": "^4.4.2",
"lodash.isequal": "^4.5.0",
"prop-types": "^15.8.1"
},
"peerDependencies": {
"react": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"packages/superset-ui-core/node_modules/react-draggable": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.7.1.tgz",
@@ -43130,19 +43037,6 @@
"react-dom": ">= 16.3.0"
}
},
"packages/superset-ui-core/node_modules/react-resize-detector": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-7.1.2.tgz",
"integrity": "sha512-zXnPJ2m8+6oq9Nn8zsep/orts9vQv3elrpA+R8XTcW7DVVUJ9vwDwMXaBtykAYjMnkCIaOoK9vObyR7ZgFNlOw==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21"
},
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"packages/superset-ui-switchboard": {
"name": "@superset-ui/switchboard",
"version": "0.20.3",
@@ -43171,11 +43065,11 @@
"@superset-ui/core": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/react": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-ag-grid-table/node_modules/d3-array": {
@@ -43205,7 +43099,7 @@
"@emotion/react": "^11.4.1",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-calendar/node_modules/d3-array": {
@@ -43253,8 +43147,8 @@
"geostyler-wfs-parser": "^3.0.1",
"ol": "^10.8.0",
"polished": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-chord": {
@@ -43269,7 +43163,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-country-map": {
@@ -43285,7 +43179,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-country-map/node_modules/d3-array": {
@@ -43320,7 +43214,7 @@
"dayjs": "^1.11.21",
"echarts": "*",
"memoize-one": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-echarts/node_modules/acorn": {
@@ -43370,9 +43264,9 @@
"dayjs": "^1.11.21",
"handlebars": "^4.7.8",
"lodash": "^4.18.1",
"react": "^18.3.0",
"react-ace": "^10.1.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-ace": "^14.0.1",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-handlebars/node_modules/just-handlebars-helpers": {
@@ -43400,7 +43294,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-horizon/node_modules/d3-array": {
@@ -43423,7 +43317,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-parallel-coordinates": {
@@ -43438,7 +43332,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-partition": {
@@ -43455,9 +43349,9 @@
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"@testing-library/react": "^16.3.2",
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-pivot-table": {
@@ -43468,7 +43362,7 @@
"@babel/types": "^7.29.8",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/jest": "^30.0.0",
"jest": "^30.4.2"
@@ -43480,8 +43374,8 @@
"@superset-ui/core": "*",
"lodash": "^4.18.1",
"prop-types": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-point-cluster-map": {
@@ -43499,8 +43393,8 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-point-cluster-map/node_modules/supercluster": {
@@ -43535,12 +43429,12 @@
"@superset-ui/core": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/react": "*",
"match-sorter": "^8.2.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-table/node_modules/d3-array": {
@@ -43574,7 +43468,7 @@
"@superset-ui/core": "*",
"@types/lodash": "^4.17.25",
"@types/react": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-world-map": {
@@ -43592,7 +43486,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
},
"plugins/plugin-chart-world-map/node_modules/d3-array": {
@@ -43654,8 +43548,8 @@
"@superset-ui/core": "*",
"dayjs": "^1.11.21",
"mapbox-gl": ">=1.0.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"mapbox-gl": {
+49 -11
View File
@@ -195,20 +195,19 @@
"ol": "^10.10.0",
"query-string": "9.5.0",
"re-resizable": "^6.11.2",
"react": "^18.3.0",
"react": "^19.2.0",
"react-arborist": "^3.16.0",
"react-checkbox-tree": "^1.8.0",
"react-checkbox-tree": "^2.0.1",
"react-diff-viewer-continued": "^4.4.0",
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^18.3.0",
"react-dom": "^19.2.0",
"react-google-recaptcha": "^3.1.0",
"react-intersection-observer": "^11.0.0",
"react-json-tree": "^0.20.0",
"react-lines-ellipsis": "^0.16.1",
"react-loadable": "^5.5.0",
"react-redux": "^7.2.9",
"react-resize-detector": "^9.1.1",
"react-resize-detector": "^12.3.0",
"react-reverse-portal": "^2.3.0",
"react-router-dom": "^5.3.4",
"react-search-input": "^0.11.3",
@@ -267,7 +266,7 @@
"@swc/plugin-transform-imports": "^13.0.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^12.8.3",
"@types/content-disposition": "^0.5.9",
"@types/dom-to-image": "^2.6.7",
@@ -278,9 +277,8 @@
"@types/lodash-es": "^4.17.12",
"@types/mousetrap": "^1.6.15",
"@types/node": "^26.2.0",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"@types/react-loadable": "^5.5.11",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"@types/react-redux": "^7.1.10",
"@types/react-router-dom": "^5.3.3",
"@types/react-transition-group": "^4.4.12",
@@ -365,7 +363,7 @@
"ace-builds": "^1.41.0",
"core-js": "^3.38.1",
"handlebars": "^4.7.8",
"react-ace": "^10.1.0",
"react-ace": "^14.0.1",
"regenerator-runtime": "^0.14.1"
},
"overrides": {
@@ -381,7 +379,9 @@
"@deck.gl/react": "~9.2.5",
"@deck.gl/widgets": "~9.2.5",
"@great-expectations/jsonforms-antd-renderers": {
"antd": "$antd"
"antd": "$antd",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"@jest/globals": "^30.4.0",
"@jest/types": "^30.4.0",
@@ -391,6 +391,29 @@
"@luma.gl/gltf": "~9.2.5",
"@luma.gl/shadertools": "~9.2.5",
"@luma.gl/webgl": "~9.2.5",
"@reduxjs/toolkit": {
"react": "^19.2.0"
},
"@visx/axis": {
"react": "^19.2.0"
},
"@visx/grid": {
"react": "^19.2.0"
},
"@visx/responsive": {
"react": "^19.2.0"
},
"@visx/scale": {
"react": "^19.2.0"
},
"@visx/tooltip": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"@visx/xychart": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"core-js": "^3.38.1",
"dompurify": "^3.4.11",
"esbuild": "^0.28.1",
@@ -418,6 +441,21 @@
"nanoid@>=3 <4": "3.3.18",
"nwsapi": "^2.2.13",
"puppeteer": "^22.4.1",
"react-redux": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"react-router-dom": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"react-table": {
"react": "^19.2.0"
},
"react-virtualized-auto-sizer": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"tar": "^7.5.16",
"typescript-json-schema": "^0.68.0",
"underscore": "^1.13.7",
@@ -104,11 +104,10 @@
"@emotion/styled": "^11.14.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/lodash": "^4.17.25",
"@types/react": "*",
"@types/react-loadable": "*",
"@types/tinycolor2": "*",
"typescript": "^5.0.0"
},
@@ -122,9 +121,8 @@
"jed": "^1.1.1",
"lodash": "^4.18.1",
"nanoid": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-loadable": "^5.5.0",
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0",
"tinycolor2": "*"
}
}
@@ -39,13 +39,13 @@
"@superset-ui/core": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"ace-builds": "^1.4.14",
"brace": "^0.11.1",
"memoize-one": "^6.0.0",
"react": "^18.3.0",
"react-ace": "^10.1.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-ace": "^14.0.1",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -36,7 +36,7 @@ import { SQLPopover } from './SQLPopover';
export type ColumnOptionProps = {
column: ColumnMeta;
showType?: boolean;
labelRef?: RefObject<any>;
labelRef?: RefObject<any | null>;
};
const StyleOverrides = styled.span`
@@ -47,7 +47,7 @@ export interface MetricOptionProps {
showFormula?: boolean;
showType?: boolean;
url?: string;
labelRef?: RefObject<any>;
labelRef?: RefObject<any | null>;
shouldShowTooltip?: boolean;
}
@@ -58,7 +58,7 @@ const TooltipSection = ({
</TooltipSectionWrapper>
);
export const isLabelTruncated = (labelRef?: RefObject<any>): boolean =>
export const isLabelTruncated = (labelRef?: RefObject<any | null>): boolean =>
!!(labelRef?.current?.scrollWidth > labelRef?.current?.clientWidth);
export const getColumnLabelText = (column: ColumnMeta): string =>
@@ -92,7 +92,7 @@ export const getColumnTypeTooltipNode = (column: ColumnMeta): ReactNode => {
export const getColumnTooltipNode = (
column: ColumnMeta,
labelRef?: RefObject<any>,
labelRef?: RefObject<any | null>,
): ReactNode => {
if (
(!column.column_name || !column.verbose_name) &&
@@ -121,7 +121,7 @@ type MetricType = Omit<Metric, 'id' | 'uuid'> & { label?: string };
export const getMetricTooltipNode = (
metric: MetricType,
labelRef?: RefObject<any>,
labelRef?: RefObject<any | null>,
): ReactNode => {
if (
!metric.verbose_name &&
@@ -17,7 +17,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ReactElement, ReactNode, ReactText, ComponentType } from 'react';
import { ReactElement, ReactNode, ComponentType } from 'react';
import type {
AdhocColumn,
@@ -40,6 +40,9 @@ import { type RGBColor } from '@superset-ui/core/components';
import { GenericDataType } from '@apache-superset/core/common';
import { sharedControls, sharedControlComponents } from './shared-controls';
// React 19 removed the ReactText type.
type ReactText = string | number;
export type { Metric } from '@superset-ui/core';
export type { ControlComponentProps } from './shared-controls/components/types';
@@ -82,9 +82,8 @@
"react-error-boundary": "^6.1.3",
"react-js-cron": "^6.0.2",
"react-markdown": "^10.1.0",
"react-resize-detector": "^7.1.2",
"react-resize-detector": "^12.3.0",
"react-syntax-highlighter": "^16.1.1",
"react-ultimate-pagination": "^1.3.2",
"regenerator-runtime": "^0.14.1",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
@@ -119,16 +118,14 @@
"@emotion/styled": "^11.14.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/react": "*",
"@types/react-loadable": "*",
"@types/tinycolor2": "*",
"antd": "^6.0.0",
"nanoid": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0",
"react-loadable": "^5.5.0",
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0",
"tinycolor2": "*"
}
}
@@ -17,7 +17,14 @@
* under the License.
*/
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
import {
ReactNode,
useCallback,
useEffect,
useMemo,
useState,
ReactElement,
} from 'react';
import {
SupersetClientInterface,
RequestConfig,
@@ -77,7 +84,7 @@ function ChartDataProvider({
formDataRequestOptions,
datasourceRequestOptions,
queryRequestOptions,
}: ChartDataProviderProps): JSX.Element | null {
}: ChartDataProviderProps): ReactElement | null {
const [state, setState] = useState<ChartDataProviderState>({
status: 'uninitialized',
});
@@ -159,7 +166,7 @@ function ChartDataProvider({
const { status, payload, error } = state;
// Wrap the children result in a Fragment so the component's return type
// stays `JSX.Element | null` (which TypeScript requires for JSX components)
// stays `ReactElement | null` (which TypeScript requires for JSX components)
// while still letting consumers return any ReactNode (strings, fragments,
// arrays, null, etc.) from the render prop.
switch (status) {
@@ -187,8 +187,8 @@ export default function StatefulChart(props: StatefulChartProps) {
const [error, setError] = useState<Error>();
const [formData, setFormData] = useState<QueryFormData>();
const chartClientRef = useRef<ChartClient>();
const abortControllerRef = useRef<AbortController>();
const chartClientRef = useRef<ChartClient | null>(null);
const abortControllerRef = useRef<AbortController | null>(null);
// fetchData is memoized with an empty dep list, so it would otherwise close
// over the first render's props. Keep the latest props in a ref so refetches
@@ -433,7 +433,7 @@ export default function StatefulChart(props: StatefulChartProps) {
}, []);
// Combined effect for all prop changes and lifecycle
const prevPropsRef = useRef<StatefulChartProps>();
const prevPropsRef = useRef<StatefulChartProps | null>(null);
useEffect(() => {
const currentProps = props;
const prevProps = prevPropsRef.current;
@@ -26,6 +26,7 @@ import {
useCallback,
useMemo,
useRef,
ReactElement,
} from 'react';
import {
@@ -76,9 +77,9 @@ export type Props = Omit<SuperChartCoreProps, 'chartProps'> &
/** Prop for form plugins using superchart */
showOverflow?: boolean;
/** Prop for popovercontainer ref */
parentRef?: RefObject<any>;
parentRef?: RefObject<any | null>;
/** Prop for chart ref */
inputRef?: RefObject<any>;
inputRef?: RefObject<any | null>;
/** Chart width */
height?: number | string;
/** Chart height */
@@ -125,7 +126,7 @@ function SuperChart({
height = 400,
width = '100%',
...rest
}: Props): JSX.Element {
}: Props): ReactElement {
/**
* SuperChart's core ref
*/
@@ -264,7 +265,7 @@ function SuperChart({
({ data }) => !data || (Array.isArray(data) && data.length === 0),
));
let chart: JSX.Element;
let chart: ReactElement;
if (noResultQueries) {
chart = noResults ? (
<>{noResults}</>
@@ -42,10 +42,10 @@ function IDENTITY<T>(x: T) {
return x;
}
const EMPTY = () => null;
const EMPTY = Object.assign(() => null, { preload: () => Promise.resolve() });
interface LoadingProps {
error: { toString(): string };
error?: unknown;
}
interface LoadedModules {
@@ -204,7 +204,7 @@ const SuperChartCore = forwardRef<SuperChartCoreRef, Props>(
<div className="alert alert-warning" role="alert">
<strong>{t('ERROR')}</strong>&nbsp;
<code>chartType=&quot;{loadingChartType}&quot;</code> &mdash;
{error.toString()}
{String(error)}
</div>
);
}
@@ -26,11 +26,21 @@ import {
} from 'react';
import type {
ComponentType,
WeakValidationMap,
ForwardRefExoticComponent,
PropsWithoutRef,
RefAttributes,
} from 'react';
import type { Validator } from 'prop-types';
// React 19 dropped `WeakValidationMap` from its type exports; keep the original
// shape so `renderFn.propTypes` still type-checks.
type WeakValidationMap<T> = {
[K in keyof T]?: null extends T[K]
? Validator<T[K] | null | undefined>
: undefined extends T[K]
? Validator<T[K] | null | undefined>
: Validator<T[K]>;
};
// TODO: Note that id and className can collide between Props and ReactifyProps
// leading to (likely) unexpected behaviors. We should either require Props to not
@@ -74,6 +84,24 @@ export type ReactifiedComponent<Props> = ForwardRefExoticComponent<
PropsWithoutRef<Props & ReactifyProps> & RefAttributes<ReactifiedComponentRef>
>;
// Mirrors React's own `defaultProps` rule: a default fills in only where the
// caller passed `undefined`.
function applyDefaultProps<P extends object>(
props: P,
defaultProps?: object,
): P {
if (!defaultProps) {
return props;
}
const merged = { ...props } as Record<string, unknown>;
Object.entries(defaultProps).forEach(([key, value]) => {
if (merged[key] === undefined) {
merged[key] = value;
}
});
return merged as P;
}
// Return the widest public type that covers "use it as a React component" so
// TypeScript JSX callers and `ComponentType<...>`-typed variables still compile;
// callers with explicit `ComponentClass<...>` annotations must widen to
@@ -82,11 +110,18 @@ export type ReactifiedComponent<Props> = ForwardRefExoticComponent<
export default function reactify<Props extends object>(
renderFn: RenderFuncType<Props>,
callbacks?: LifeCycleCallbacks<Props>,
): ComponentType<Props & ReactifyProps> {
): ComponentType<Props & ReactifyProps> & {
// Copied off `renderFn` for introspection. React 19 no longer applies these
// itself — `applyDefaultProps` does.
defaultProps?: Partial<Props & ReactifyProps>;
} {
const ReactifiedComponent = forwardRef<
ReactifiedComponentRef,
Props & ReactifyProps
>(function ReactifiedComponent(props, ref) {
>(function ReactifiedComponent(incomingProps, ref) {
// React 19 no longer applies `defaultProps` to function components, so the
// defaults declared on `renderFn` are merged here instead.
const props = applyDefaultProps(incomingProps, renderFn.defaultProps);
const containerRef = useRef<HTMLDivElement>(null);
// Keep the latest props available to the unmount callback — legacy
// consumers read values off `this.props` (e.g. ReactNVD3 uses id).
@@ -94,7 +129,7 @@ export default function reactify<Props extends object>(
// assignment only happens for committed renders (safe under Concurrent
// Mode) and is in place before the passive unmount effect reads it.
const propsRef = useRef(props);
const committedContainerRef = useRef<HTMLDivElement>();
const committedContainerRef = useRef<HTMLDivElement | undefined>(undefined);
useLayoutEffect(() => {
propsRef.current = props;
committedContainerRef.current = containerRef.current ?? undefined;
@@ -112,7 +112,7 @@ export interface ChartPropsConfig {
/** is the chart refreshing its contents */
isRefreshing?: boolean;
/** chart ref */
inputRef?: RefObject<any>;
inputRef?: RefObject<any | null>;
/** Theme object */
theme: SupersetTheme;
/* legend index */
@@ -163,7 +163,7 @@ export default class ChartProps<FormData extends RawFormData = RawFormData> {
isRefreshing?: boolean;
inputRef?: RefObject<any>;
inputRef?: RefObject<any | null>;
inContextMenu?: boolean;
@@ -263,8 +263,8 @@ export function AsyncAceEditor(
// Move autocomplete popup to the nearest parent container with data-ace-container
useEffect(() => {
const editorInstance = (ref as React.RefObject<AceEditor>)?.current
?.editor;
const editorInstance = (ref as React.RefObject<AceEditor | null>)
?.current?.editor;
if (!editorInstance) return;
const editorContainer = editorInstance.container;
@@ -16,7 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Children, ReactElement, Fragment, forwardRef, Ref } from 'react';
import {
Children,
ReactElement,
ReactNode,
Fragment,
forwardRef,
Ref,
} from 'react';
import cx from 'classnames';
import { Button as AntdButton } from 'antd';
import { useTheme } from '@apache-superset/core/theme';
@@ -164,7 +171,9 @@ function ButtonInner(props: ButtonProps, ref: Ref<HTMLElement>) {
color,
} = resolvedStyleMap[buttonStyle ?? 'primary'] ?? BUTTON_STYLE_MAP.primary;
const element = children as ReactElement;
// React 19 types `ReactElement['props']` as `unknown`, so spell out the
// shape read below.
const element = children as ReactElement<{ children?: ReactNode }>;
let renderedChildren = [];
@@ -28,13 +28,14 @@ test('Should send correct props to ReactCronPicker', () => {
myCustomProp: 'myCustomProp',
};
render(<CronPicker {...(props as any)} />);
expect(spy).toHaveBeenCalledWith(
// React 19 calls function components with a single props argument, so assert
// on the props rather than the whole call signature.
expect(spy.mock.calls.at(-1)?.[0]).toEqual(
expect.objectContaining({
className: expect.any(String),
locale: expect.anything(),
myCustomProp: 'myCustomProp',
}),
expect.anything(),
);
});
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import type { ComponentType } from 'react';
import { DatePicker as AntdDatePicker } from 'antd';
import { css } from '@apache-superset/core/theme';
import type { DatePickerProps, RangePickerProps } from './types';
@@ -29,6 +30,7 @@ export const DatePicker = (props: DatePickerProps) => (
/>
);
export const { RangePicker } = AntdDatePicker;
export const RangePicker: ComponentType<RangePickerProps> =
AntdDatePicker.RangePicker;
export type { DatePickerProps, RangePickerProps };
@@ -16,7 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ReactElement, cloneElement, forwardRef } from 'react';
import {
cloneElement,
forwardRef,
type FocusEventHandler,
type KeyboardEventHandler,
type ReactElement,
} from 'react';
import { Dropdown as AntdDropdown, DropdownProps } from 'antd';
import { styled } from '@apache-superset/core/theme';
@@ -108,10 +114,16 @@ MenuDotsDropdown.displayName = 'MenuDotsDropdown';
export const NoAnimationDropdown = (props: NoAnimationDropdownProps) => {
const { children, onBlur, onKeyDown, ...rest } = props;
const childrenWithProps = cloneElement(children as ReactElement, {
onBlur,
onKeyDown,
});
const childrenWithProps = cloneElement(
children as ReactElement<{
onBlur?: FocusEventHandler;
onKeyDown?: KeyboardEventHandler;
}>,
{
onBlur,
onKeyDown,
},
);
return (
<AntdDropdown autoFocus overlayStyle={props.overlayStyle} {...rest}>
@@ -57,7 +57,7 @@ export interface DropdownContainerProps {
/**
* Dropdown ref.
*/
dropdownRef?: RefObject<HTMLDivElement>;
dropdownRef?: RefObject<HTMLDivElement | null>;
/**
* Dropdown additional style properties.
*/
@@ -24,7 +24,9 @@ import { BaseIconComponent } from './BaseIcon';
const AsyncIcon = forwardRef<HTMLSpanElement, IconType>((props, ref) => {
const [, setLoaded] = useState(false);
const ImportedSVG = useRef<FC<SVGProps<SVGSVGElement>>>();
const ImportedSVG = useRef<FC<SVGProps<SVGSVGElement>> | undefined>(
undefined,
);
const { fileName, customIcons, iconSize, iconColor, viewBox, ...restProps } =
props;
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import type React from 'react';
import { fireEvent, render } from '@superset-ui/core/spec';
import { Icons } from '../Icons';
@@ -76,7 +77,11 @@ test('does not add the icon gap to an icon-less label (#42139)', () => {
// test stories from the storybook!
test('renders all the storybook gallery variants', () => {
const { container } = render(<LabelGallery />);
// Cast the storybook fn — its render signature changed in storybook 8
const GalleryComponent = LabelGallery as unknown as React.FC<
Record<string, never>
>;
const { container } = render(<GalleryComponent />);
const nonInteractiveLabelCount = 4;
const renderedLabelCount = options.length * 2 + nonInteractiveLabelCount;
expect(container.querySelectorAll('.ant-tag')).toHaveLength(
@@ -17,7 +17,6 @@
* under the License.
*/
import { render, screen, userEvent, within } from '@superset-ui/core/spec';
import * as resizeDetector from 'react-resize-detector';
import { hexToRgb } from '@superset-ui/core';
import { supersetTheme } from '@apache-superset/core/theme';
import MetadataBar, {
@@ -41,18 +40,32 @@ const TAGS = ['management', 'research', 'poc'];
const A_WEEK_AGO = 'a week ago';
const TWO_DAYS_AGO = '2 days ago';
// react-resize-detector's ESM export is non-configurable, so jest.spyOn can't
// replace it; swap the implementation through the module mock instead.
let mockResizeImpl: ((props: any) => unknown) | null = null;
jest.mock('react-resize-detector', () => {
const actual = jest.requireActual('react-resize-detector');
return {
...actual,
useResizeDetector: (props: any) =>
mockResizeImpl ? mockResizeImpl(props) : actual.useResizeDetector(props),
};
});
const runWithBarCollapsed = async (func: Function) => {
const spy = jest.spyOn(resizeDetector, 'useResizeDetector');
let width: number;
spy.mockImplementation(props => {
let width = 0;
mockResizeImpl = (props: any) => {
if (props?.onResize && !width) {
width = 80;
props.onResize(width);
props.onResize({ width, height: 0, entry: null });
}
return { ref: { current: undefined } };
});
await func();
spy.mockRestore();
return { ref: () => {} };
};
try {
await func();
} finally {
mockResizeImpl = null;
}
};
const ITEMS: ContentType[] = [
@@ -17,7 +17,10 @@
* under the License.
*/
import { useCallback, useEffect, useRef, useState } from 'react';
import { useResizeDetector } from 'react-resize-detector';
import {
useResizeDetector,
type OnResizeCallback,
} from 'react-resize-detector';
import { uniqWith } from 'lodash-es';
import { styled } from '@apache-superset/core/theme';
import { Tooltip } from '../Tooltip';
@@ -182,7 +185,7 @@ export interface MetadataBarProps {
* This process is important to make sure the new type is reviewed by the design team, improving Superset consistency.
*/
const MetadataBar = ({ items, tooltipPlacement = 'top' }: MetadataBarProps) => {
const [width, setWidth] = useState<number>();
const [width, setWidth] = useState<number | undefined>(undefined);
const [collapsed, setCollapsed] = useState(false);
const uniqueItems = uniqWith(items, (a, b) => a.type === b.type);
const sortedItems = uniqueItems.sort((a, b) => ORDER[a.type] - ORDER[b.type]);
@@ -194,8 +197,9 @@ const MetadataBar = ({ items, tooltipPlacement = 'top' }: MetadataBarProps) => {
throw new Error('The maximum number of items for the metadata bar is 6.');
}
const onResize = useCallback(
(width: number | undefined) => {
const onResize = useCallback<OnResizeCallback>(
payload => {
const width = payload.width ?? undefined;
// Calculates the breakpoint width to collapse the bar.
// The last item does not have a space, so we subtract SPACE_BETWEEN_ITEMS from the total.
const breakpoint =
@@ -54,7 +54,7 @@ export interface ModalProps {
/** @deprecated Use styles.body instead */
bodyStyle?: CSSProperties;
styles?: { body?: CSSProperties; [key: string]: CSSProperties | undefined };
openerRef?: React.RefObject<HTMLElement>;
openerRef?: React.RefObject<HTMLElement | null>;
}
export interface StyledModalProps {
@@ -17,13 +17,14 @@
* under the License.
*/
import { ModalTrigger } from '.';
import type { ReactElement } from 'react';
interface IModalTriggerProps {
triggerNode: JSX.Element;
triggerNode: ReactElement;
dialogClassName?: string;
modalTitle?: string;
modalBody?: JSX.Element;
modalFooter?: JSX.Element;
modalBody?: ReactElement;
modalFooter?: ReactElement;
beforeOpen?: () => void;
onExit?: () => void;
isButton?: boolean;
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Key } from 'react';
import { Key, ReactElement } from 'react';
import cx from 'classnames';
import { css, useTheme } from '@apache-superset/core/theme';
import { Icons } from '@superset-ui/core/components/Icons';
@@ -29,7 +29,7 @@ export interface OptionProps {
}
export type OnChangeHandler = (key: Key) => void;
export type RenderElementHandler = (option: OptionProps) => JSX.Element;
export type RenderElementHandler = (option: OptionProps) => ReactElement;
export interface PopoverDropdownProps {
id: string;
@@ -653,7 +653,7 @@ const AsyncSelect = forwardRef(
originNode: ReactElement & { ref?: RefObject<HTMLElement> },
) =>
dropDownRenderHelper(
originNode,
originNode as Parameters<typeof dropDownRenderHelper>[0],
isDropdownVisible,
isLoading,
fullSelectOptions.length,
@@ -685,10 +685,10 @@ const Select = forwardRef(
const isLoading = loading ?? false;
const popupRender = (
originNode: ReactElement & { ref?: RefObject<HTMLElement> },
originNode: ReactElement & { ref?: RefObject<HTMLElement | null> },
) =>
dropDownRenderHelper(
originNode,
originNode as Parameters<typeof dropDownRenderHelper>[0],
isDropdownVisible,
isLoading,
fullSelectOptions.length,
@@ -165,14 +165,20 @@ export const getSuffixIcon = (
return <Icons.DownOutlined iconSize="s" aria-label="down" />;
};
type FlattenOptionsProps = {
flattenOptions?: Array<Record<string, any>>;
};
export const dropDownRenderHelper = (
originNode: ReactElement & { ref?: RefObject<HTMLElement> },
originNode: ReactElement<FlattenOptionsProps> & {
ref?: RefObject<HTMLElement | null>;
},
isDropdownVisible: boolean,
isLoading: boolean | undefined,
optionsLength: number,
helperText: string | undefined,
errorComponent?: JSX.Element,
bulkSelectComponents?: JSX.Element,
errorComponent?: ReactElement,
bulkSelectComponents?: ReactElement,
) => {
if (!isDropdownVisible) {
originNode.ref?.current?.scrollTo({ top: 0 });
@@ -184,17 +190,19 @@ export const dropDownRenderHelper = (
return errorComponent;
}
const originProps = originNode.props;
// remap for accessibility for proper item count
const accessibilityNode = {
...originNode,
props: {
...originNode.props,
flattenOptions: ensureIsArray(originNode.props.flattenOptions).map(
...originProps,
flattenOptions: ensureIsArray(originProps.flattenOptions).map(
(opt: Record<string, any>, idx: number) => ({
...opt,
data: {
...opt.data,
'aria-setsize': originNode.props.flattenOptions?.length || 0,
'aria-setsize': originProps.flattenOptions?.length || 0,
'aria-posinset': idx + 1,
},
}),
@@ -23,7 +23,10 @@ import {
TableProps as AntTableProps,
} from 'antd/es/table';
import classNames from 'classnames';
import { useResizeDetector } from 'react-resize-detector';
import {
useResizeDetector,
type OnResizeCallback,
} from 'react-resize-detector';
import { useRef, useState, useCallback, type UIEvent } from 'react';
import {
Grid,
@@ -141,7 +144,7 @@ const VirtualTable = <RecordType extends object>(
allowHTML = false,
} = props;
const [tableWidth, setTableWidth] = useState<number>(0);
const onResize = useCallback((width?: number) => {
const onResize = useCallback<OnResizeCallback>(({ width }) => {
setTableWidth(width ?? 0);
}, []);
const { ref } = useResizeDetector({ onResize });
@@ -17,7 +17,7 @@
* under the License.
*/
import { fireEvent, render } from '@superset-ui/core/spec';
import { fireEvent, render, screen } from '@superset-ui/core/spec';
import Tabs, { EditableTabs, LineEditableTabs } from './Tabs';
const defaultItems = [
@@ -163,12 +163,14 @@ describe('Tabs', () => {
expect(onEditMock).toHaveBeenCalledWith(expect.any(String), 'remove');
});
test('should have default props set correctly', () => {
expect(EditableTabs.defaultProps?.type).toBe('editable-card');
expect(EditableTabs.defaultProps?.animated).toEqual({
inkBar: true,
tabPane: false,
});
test('renders with editable-card defaults', () => {
render(
<EditableTabs
items={[{ key: '1', label: 'Tab 1', children: 'one' }]}
/>,
);
const container = screen.getByText('Tab 1').closest('.ant-tabs');
expect(container).toHaveClass('ant-tabs-editable-card');
});
});
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import type { FC } from 'react';
import type { ComponentProps, FC } from 'react';
import { css, styled } from '@apache-superset/core/theme';
import { Tabs as AntdTabs, TabsProps as AntdTabsProps } from 'antd';
import { Icons } from '@superset-ui/core/components/Icons';
@@ -132,20 +132,24 @@ const StyledEditableTabs = styled(StyledTabs)`
const StyledCloseOutlined = styled(Icons.CloseOutlined)`
color: ${({ theme }) => theme.colorIcon};
`;
export const EditableTabs = Object.assign(StyledEditableTabs, {
TabPane: StyledTabPane,
});
const EditableTabsBase: FC<TabsProps> = ({
type = 'editable-card',
animated = { inkBar: true, tabPane: false },
...rest
}: TabsProps) => (
<StyledEditableTabs type={type} animated={animated} {...rest} />
);
EditableTabs.defaultProps = {
type: 'editable-card',
animated: { inkBar: true, tabPane: false },
};
EditableTabs.TabPane.defaultProps = {
const EditableTabPane: FC<ComponentProps<typeof StyledTabPane>> = ({
// rc-tabs already wraps closeIcon in its own <button role="tab"
// aria-label="remove">; this is just decorative content inside it.
closeIcon: <StyledCloseOutlined iconSize="s" />,
};
closeIcon = <StyledCloseOutlined iconSize="s" />,
...rest
}) => <StyledTabPane closeIcon={closeIcon} {...rest} />;
export const EditableTabs = Object.assign(EditableTabsBase, {
TabPane: EditableTabPane,
});
export const StyledLineEditableTabs = styled(EditableTabs)`
&.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab {
@@ -42,7 +42,7 @@ interface TelemetryPixelProps {
* @param {string} props.sha - The SHA of Superset that's currently in use.
* @param {string} props.build - The build of Superset that's currently in use.
* @param {boolean} props.enabled - Runtime opt-out switch; when false the pixel is not rendered.
* @returns {JSX.Element | null} The rendered TelemetryPixel component.
* @returns {ReactElement | null} The rendered TelemetryPixel component.
*/
const PIXEL_ID = '0d3461e1-abb1-4691-a0aa-5ed50de66af0';
@@ -122,6 +122,10 @@ test('applies dark theme when background is dark', () => {
expect(theme.foregroundColor).toBe('#ffffff');
});
// The props AgGridReact was last rendered with.
const agGridProps = () =>
(AgGridReact as unknown as jest.Mock).mock.calls.at(-1)?.[0];
test('forwards ref to AgGridReact', () => {
const ref = createRef<AgGridReact>();
@@ -133,13 +137,14 @@ test('forwards ref to AgGridReact', () => {
/>,
);
// Check that AgGridReact was called with the ref
expect(AgGridReact).toHaveBeenCalledWith(
// React 19 hands `ref` to the component as a regular prop rather than as a
// second argument, so assert on the props object itself.
expect(agGridProps()).toEqual(
expect.objectContaining({
rowData: mockRowData,
columnDefs: mockColumnDefs,
ref,
}),
expect.any(Object), // ref is passed as second argument
);
});
@@ -160,7 +165,7 @@ test('passes all props through to AgGridReact', () => {
// onGridReady and onFirstDataRendered are intercepted by the component to expose
// the grid API on the container element; the wrapped function is passed instead.
expect(AgGridReact).toHaveBeenCalledWith(
expect(agGridProps()).toEqual(
expect.objectContaining({
rowData: mockRowData,
columnDefs: mockColumnDefs,
@@ -169,7 +174,6 @@ test('passes all props through to AgGridReact', () => {
pagination: true,
paginationPageSize: 10,
}),
expect.any(Object),
);
});
@@ -38,7 +38,7 @@ export function Timer({
const [clockStr, setClockStr] = useState(
startTime && endTime ? fDuration(startTime, endTime) : '00:00:00.00',
);
const timer = useRef<ReturnType<typeof setInterval>>();
const timer = useRef<ReturnType<typeof setInterval> | undefined>(undefined);
useEffect(() => {
const stopTimer = () => {
@@ -20,8 +20,8 @@ import { useEffect, useRef, useState, RefObject } from 'react';
export function useElementOnScreen<T extends Element>(
options: IntersectionObserverInit,
): [RefObject<T>, boolean] {
const containerRef = useRef<T>(null);
): [RefObject<T | null>, boolean] {
const containerRef = useRef<T | null>(null);
const [isSticky, setIsSticky] = useState(false);
const callback = (entries: IntersectionObserverEntry[]) => {
@@ -38,9 +38,9 @@ export const truncationCSS = css`
*/
const useCSSTextTruncation = <T extends HTMLElement>(
{ isVertical, isHorizontal } = { isVertical: false, isHorizontal: true },
): [RefObject<T>, boolean] => {
): [RefObject<T | null>, boolean] => {
const [isTruncated, setIsTruncated] = useState(true);
const ref = useRef<T>(null);
const ref = useRef<T | null>(null);
const [offsetWidth, setOffsetWidth] = useState(0);
const [scrollWidth, setScrollWidth] = useState(0);
const [offsetHeight, setOffsetHeight] = useState(0);
@@ -30,10 +30,10 @@ const genElements = (
offsetWidth: number | undefined,
childNodes: any = [],
) => {
const elementRef: RefObject<Partial<HTMLElement>> = {
const elementRef: RefObject<Partial<HTMLElement> | null> = {
current: { scrollWidth, clientWidth, childNodes },
};
const plusRef: RefObject<Partial<HTMLElement>> = {
const plusRef: RefObject<Partial<HTMLElement> | null> = {
current: { offsetWidth },
};
return [elementRef, plusRef];
@@ -18,7 +18,7 @@
*/
import '@testing-library/jest-dom';
import { ComponentType } from 'react';
import { ComponentType, ReactElement } from 'react';
import { render as renderTestComponent, screen } from '@testing-library/react';
import createLoadableRenderer, {
LoadableRenderer as LoadableRendererType,
@@ -29,8 +29,8 @@ describe('createLoadableRenderer', () => {
return <div className="test-component">test</div>;
}
let loadChartSuccess = jest.fn(() => Promise.resolve(TestComponent));
let render: (loaded: { Chart: ComponentType }) => JSX.Element;
let loading: () => JSX.Element;
let render: (loaded: { Chart: ComponentType }) => ReactElement;
let loading: () => ReactElement;
let LoadableRenderer: LoadableRendererType<{}>;
beforeEach(() => {
@@ -45,10 +45,10 @@
"@superset-ui/core": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/react": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -67,7 +67,7 @@ const getSortIcon = (sortState: SortState[], colId: string | null) => {
const autoOpenFilterAndFocus = async (
column: Column,
api: GridApi,
filterRef: React.RefObject<HTMLDivElement>,
filterRef: React.RefObject<HTMLDivElement | null>,
setFilterVisible: (visible: boolean) => void,
lastFilteredInputPosition?: FilterInputPosition,
) => {
@@ -16,12 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
import { useEffect, useRef, useState, cloneElement } from 'react';
import {
useEffect,
useRef,
useState,
cloneElement,
type ReactElement,
type Ref,
} from 'react';
import { PopoverContainer, PopoverWrapper } from '../../styles';
interface Props {
content: React.ReactNode;
children: React.ReactElement;
children: ReactElement<{ ref?: Ref<HTMLElement> }>;
isOpen: boolean;
onClose: () => void;
}
@@ -24,9 +24,10 @@ import {
memo,
FunctionComponent,
useState,
ChangeEvent,
FormEvent,
useEffect,
type RefObject,
ReactElement,
} from 'react';
import { Constants, ThemedAgGridReact } from '@superset-ui/core/components';
@@ -102,14 +103,14 @@ export interface AgGridTableProps {
handleCellClicked: (event: CellClickedEvent) => void;
handleSelectionChanged: (event: SelectionChangedEvent) => void;
filters?: Record<string, DataRecordValue[]> | null;
renderTimeComparisonDropdown: () => JSX.Element | null;
renderTimeComparisonDropdown: () => ReactElement | null;
cleanedTotals: DataRecord;
showTotals: boolean;
width: number;
onColumnStateChange?: (state: AgGridChartStateWithMetadata) => void;
onFilterChanged?: (filterModel: Record<string, any>) => void;
metricColumns?: string[];
gridRef?: RefObject<AgGridReact>;
gridRef?: RefObject<AgGridReact | null>;
chartState?: AgGridChartState;
}
@@ -246,7 +247,8 @@ const AgGridDataTable: FunctionComponent<AgGridTableProps> = memo(
}, []);
const onFilterTextBoxChanged = useCallback(
({ target: { value } }: ChangeEvent<HTMLInputElement>) => {
(event: FormEvent<HTMLInputElement>) => {
const { value } = event.target as HTMLInputElement;
if (serverPagination) {
setSearchValue(value);
debouncedSearch(value);
@@ -23,7 +23,14 @@ import {
getTimeFormatterForGranularity,
} from '@superset-ui/core';
import { GenericDataType } from '@apache-superset/core/common';
import { useCallback, useEffect, useRef, useState, useMemo } from 'react';
import {
useCallback,
useEffect,
useRef,
useState,
useMemo,
type ReactElement,
} from 'react';
import { isEqual } from 'lodash-es';
import {
@@ -439,7 +446,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
[setDataMask, serverPagination],
);
const renderTimeComparisonVisibility = (): JSX.Element => (
const renderTimeComparisonVisibility = (): ReactElement => (
<TimeComparisonVisibility
comparisonColumns={comparisonColumns}
selectedComparisonColumns={selectedComparisonColumns}
@@ -120,7 +120,7 @@ async function detectLastFilteredInput(
* Gets complete filter state including SQL conversion and input position detection.
*/
export async function getCompleteFilterState(
gridRef: RefObject<AgGridReact>,
gridRef: RefObject<AgGridReact | null>,
metricColumns: string[],
): Promise<FilterState> {
// Capture activeElement before any async operations to detect which input
@@ -24,7 +24,7 @@ import { FILTER_INPUT_POSITIONS } from '../../src/consts';
describe('filterStateManager', () => {
describe('getCompleteFilterState', () => {
test('should return empty state when gridRef.current is null', async () => {
const gridRef = { current: null } as RefObject<AgGridReact>;
const gridRef = { current: null } as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -41,7 +41,7 @@ describe('filterStateManager', () => {
test('should return empty state when gridRef.current.api is undefined', async () => {
const gridRef = {
current: { api: undefined } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -68,7 +68,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -103,7 +103,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, ['SUM(revenue)']);
@@ -138,7 +138,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
// Mock activeElement
Object.defineProperty(document, 'activeElement', {
@@ -182,7 +182,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
// Mock activeElement
Object.defineProperty(document, 'activeElement', {
@@ -217,7 +217,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
// Mock activeElement as something outside the filter
const outsideElement = document.createElement('div');
@@ -272,7 +272,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
// Mock activeElement in age filter
Object.defineProperty(document, 'activeElement', {
@@ -306,7 +306,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -324,7 +324,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -356,7 +356,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -378,7 +378,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -422,7 +422,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
Object.defineProperty(document, 'activeElement', {
writable: true,
@@ -449,7 +449,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -469,7 +469,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
const result = await getCompleteFilterState(gridRef, []);
@@ -509,7 +509,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
// Mock activeElement in join AND operator
Object.defineProperty(document, 'activeElement', {
@@ -556,7 +556,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
// Mock activeElement in join OR operator
Object.defineProperty(document, 'activeElement', {
@@ -598,7 +598,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
Object.defineProperty(document, 'activeElement', {
writable: true,
@@ -641,7 +641,7 @@ describe('filterStateManager', () => {
const gridRef = {
current: { api: mockApi } as any,
} as RefObject<AgGridReact>;
} as RefObject<AgGridReact | null>;
Object.defineProperty(document, 'activeElement', {
writable: true,
@@ -36,6 +36,6 @@
"@emotion/react": "^11.4.1",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -48,7 +48,7 @@
"geostyler-wfs-parser": "^3.0.1",
"ol": "^10.8.0",
"polished": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -36,6 +36,6 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -34,6 +34,6 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -42,6 +42,6 @@
"dayjs": "^1.11.21",
"echarts": "*",
"memoize-one": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -108,7 +108,9 @@ export default function EchartsTimeseries({
const echartRef = useRef<EchartsHandler | null>(null);
// eslint-disable-next-line no-param-reassign
refs.echartRef = echartRef;
const clickTimer = useRef<ReturnType<typeof setTimeout>>();
const clickTimer = useRef<ReturnType<typeof setTimeout> | undefined>(
undefined,
);
// Draggable percent-change baseline: when the rebase view is active, a
// vertical line is drawn on the plot; dragging it re-indexes every series
@@ -168,7 +168,7 @@ function Echart(
refs.divRef = divRef;
}
const [didMount, setDidMount] = useState(false);
const chartRef = useRef<EChartsType>();
const chartRef = useRef<EChartsType | null>(null);
const previousQueryEventHandlers = useRef<QueryEventHandlers>([]);
const currentSelection = useMemo(
() => Object.keys(selectedValues) || [],
@@ -177,7 +177,7 @@ function Echart(
const previousSelection = useRef<string[]>([]);
useImperativeHandle(ref, () => ({
getEchartInstance: () => chartRef.current,
getEchartInstance: () => chartRef.current ?? undefined,
}));
const locale = useSelector(
@@ -44,7 +44,7 @@ export type EchartsStylesProps = {
export type Refs = {
echartRef?: Ref<EchartsHandler>;
divRef?: RefObject<HTMLDivElement>;
divRef?: RefObject<HTMLDivElement | null>;
};
export interface EchartsProps {
@@ -45,8 +45,8 @@
"dayjs": "^1.11.21",
"handlebars": "^4.7.8",
"lodash": "^4.18.1",
"react": "^18.3.0",
"react-ace": "^10.1.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-ace": "^14.0.1",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ReactNode } from 'react';
import { ReactNode, ReactElement } from 'react';
interface ControlHeaderProps {
children: ReactNode;
@@ -24,7 +24,7 @@ interface ControlHeaderProps {
export const ControlHeader = ({
children,
}: ControlHeaderProps): JSX.Element => (
}: ControlHeaderProps): ReactElement => (
<div className="ControlHeader">
<div className="pull-left">{children}</div>
</div>
@@ -34,6 +34,6 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -29,6 +29,6 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -36,6 +36,6 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -35,8 +35,8 @@
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"@testing-library/react": "^16.3.2",
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -30,7 +30,7 @@
"@babel/types": "^7.29.8",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/jest": "^30.0.0",
"jest": "^30.4.2"
@@ -42,7 +42,7 @@
"@superset-ui/core": "*",
"lodash": "^4.18.1",
"prop-types": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -1527,4 +1527,3 @@ TableRenderer.propTypes = {
tableOptions: PropTypes.object,
onContextMenu: PropTypes.func,
};
TableRenderer.defaultProps = { ...PivotData.defaultProps, tableOptions: {} };
@@ -39,7 +39,7 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -45,11 +45,11 @@
"@superset-ui/core": "*",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "*",
"@testing-library/react": "^15.0.0",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "*",
"@types/react": "*",
"match-sorter": "^8.2.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
}
}
@@ -27,6 +27,7 @@ import {
DragEvent,
useEffect,
useMemo,
ReactElement,
} from 'react';
import { typedMemo, usePrevious } from '@superset-ui/core';
import { t } from '@apache-superset/core/translation';
@@ -79,10 +80,10 @@ export interface DataTableProps<D extends object> extends TableOptions<D> {
noResults?: string | ((filterString: string) => ReactNode);
sticky?: boolean;
rowCount: number;
wrapperRef?: MutableRefObject<HTMLDivElement>;
wrapperRef?: MutableRefObject<HTMLDivElement | null>;
onColumnOrderChange?: () => void;
renderGroupingHeaders?: () => JSX.Element;
renderTimeComparisonDropdown?: () => JSX.Element;
renderGroupingHeaders?: () => ReactElement;
renderTimeComparisonDropdown?: () => ReactElement;
handleSortByChange: (sortBy: SortByItem[]) => void;
sortByFromParent: SortByItem[];
manualSearch?: boolean;
@@ -138,7 +139,7 @@ export default typedMemo(function DataTable<D extends object>({
onFilteredDataChange,
onFilteredRowsChange,
...moreUseTableOptions
}: DataTableProps<D>): JSX.Element {
}: DataTableProps<D>): ReactElement {
const tableHooks: PluginHook<D>[] = [
useGlobalFilter,
useSortBy,
@@ -344,7 +345,7 @@ export default typedMemo(function DataTable<D extends object>({
if (!columns || columns.length === 0) {
return (
wrapStickyTable ? wrapStickyTable(getNoResults) : getNoResults()
) as JSX.Element;
) as ReactElement;
}
const shouldRenderFooter = columns.some(x => !!x.Footer);
@@ -28,6 +28,7 @@ import {
ComponentPropsWithRef,
CSSProperties,
UIEventHandler,
type JSX,
} from 'react';
import { TableInstance, Hooks } from 'react-table';
import { useTheme, css } from '@apache-superset/core/theme';
@@ -26,7 +26,7 @@ export default function useMountedMemo<T>(
factory: () => T,
deps?: unknown[],
): T | undefined {
const mounted = useRef<typeof factory>();
const mounted = useRef<typeof factory | null>(null);
useLayoutEffect(() => {
mounted.current = factory;
});
@@ -26,6 +26,7 @@ import {
KeyboardEvent as ReactKeyboardEvent,
useEffect,
useRef,
ReactElement,
} from 'react';
import {
@@ -764,7 +765,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
[comparisonLabels],
);
const renderTimeComparisonDropdown = (): JSX.Element => {
const renderTimeComparisonDropdown = (): ReactElement => {
const allKey = comparisonColumns[0].key;
const handleOnClick = (data: any) => {
const { key } = data;
@@ -871,7 +872,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
[visibleColumnsMeta, getHeaderColumns, isUsingTimeComparison],
);
const renderGroupingHeaders = (): JSX.Element => {
const renderGroupingHeaders = (): ReactElement => {
// TODO: Make use of ColumnGroup to render the aditional headers
const headers: any = [];
let currentColumnIndex = 0;
@@ -43,6 +43,6 @@
"@superset-ui/core": "*",
"@types/lodash": "^4.17.25",
"@types/react": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -18,7 +18,7 @@
*/
import { isCustomControlItem } from '@superset-ui/chart-controls';
import controlPanel from '../src/plugin/controlPanel';
import React, { ReactElement } from 'react';
import React, { type ReactElement } from 'react';
const isNameControl = (
item: unknown,
@@ -39,6 +39,6 @@
"@apache-superset/core": "*",
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^18.3.0"
"react": "^18.3.0 || ^19.0.0"
}
}
@@ -69,8 +69,8 @@
"@superset-ui/core": "*",
"dayjs": "^1.11.21",
"mapbox-gl": ">=1.0.0",
"react": "^18.3.0",
"react-dom": "^18.3.0"
"react": "^18.3.0 || ^19.0.0",
"react-dom": "^18.3.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"mapbox-gl": {
@@ -112,7 +112,7 @@ export const DeckGLContainer = memo(
}, [props.layers]);
const isCustomTooltip = (content: ReactNode): boolean =>
isValidElement(content) &&
isValidElement<{ 'data-tooltip-type'?: string }>(content) &&
content.props?.['data-tooltip-type'] === 'custom';
const renderTooltip = (tooltipState: TooltipProps['tooltip']) => {
@@ -142,7 +142,7 @@ const selectDataMask = createSelector(
);
const DeckMulti = (props: DeckMultiProps) => {
const containerRef = useRef<DeckGLContainerHandle>();
const containerRef = useRef<DeckGLContainerHandle | null>(null);
const theme = useTheme();
const dataMask = useSelector(selectDataMask);
@@ -93,7 +93,7 @@ export function createDeckGLComponent(
) {
// Higher order component
return memo((props: DeckGLComponentProps) => {
const containerRef = useRef<DeckGLContainerHandle>();
const containerRef = useRef<DeckGLContainerHandle | null>(null);
const prevFormData = usePrevious(props.formData);
const prevFilterState = usePrevious(props.filterState);
const prevPayload = usePrevious(props.payload);
@@ -167,7 +167,7 @@ export const getLayer: GetLayerType<ContourLayer> = function ({
cellSize: safeCellSize,
aggregation: aggregation.toUpperCase(),
getPosition: (d: { position: number[]; weight: number }) =>
d.position as Position,
d.position as unknown as Position,
getWeight: (d: { weight: number }) => d.weight || 0,
...commonLayerProps({
formData: fd,
@@ -294,7 +294,7 @@ export function getPoints(data?: Point[]) {
}
const DeckGLGeoJson = (props: DeckGLGeoJsonProps) => {
const containerRef = useRef<DeckGLContainerHandle>();
const containerRef = useRef<DeckGLContainerHandle | null>(null);
const setTooltip = useCallback((tooltip: TooltipProps['tooltip']) => {
const { current } = containerRef;
if (current) {
@@ -19,7 +19,9 @@
import { HeatmapLayer } from '@deck.gl/aggregation-layers';
import { Position } from '@deck.gl/core';
import { t } from '@apache-superset/core/translation';
import type { ScaleLinear } from 'd3-scale';
import {
CategoricalColorScale,
getSequentialSchemeRegistry,
JsonObject,
QueryFormData,
@@ -123,7 +125,10 @@ export const getLayer: GetLayerType<HeatmapLayer> = ({
colorBreakpoints: fd.color_breakpoints,
fixedColor: fd.color_picker,
colorSchemeType,
colorScale,
colorScale: colorScale as
| CategoricalColorScale
| ScaleLinear<string, string, never>
| undefined,
})?.reverse();
const tooltipContent = setTooltipContent(fd);
@@ -259,7 +259,7 @@ export function getPoints(data: JsonObject[]) {
}
const DeckGLPolygon = (props: DeckGLPolygonProps) => {
const containerRef = useRef<DeckGLContainerHandle>();
const containerRef = useRef<DeckGLContainerHandle | null>(null);
const getAdjustedViewport = useCallback(() => {
let viewport = { ...props.viewport };
@@ -231,7 +231,7 @@ export const getColorRange = ({
defaultBreakpointsColor: { r: number; g: number; b: number; a: number };
fixedColor?: { r: number; g: number; b: number; a: number };
colorBreakpoints?: ColorBreakpointType[];
colorScale?: CategoricalColorScale | ScaleLinear<string, string>;
colorScale?: CategoricalColorScale | ScaleLinear<string, string, never>;
}) => {
let colorRange: Color[] | undefined;
switch (colorSchemeType) {
@@ -19,7 +19,7 @@
import { t } from '@apache-superset/core/translation';
import { JsonObject, QueryFormData } from '@superset-ui/core';
import { useMemo, memo } from 'react';
import { useMemo, memo, ReactElement } from 'react';
import { HandlebarsRenderer } from './HandlebarsRenderer';
import TooltipRow from '../TooltipRow';
import { createDefaultTemplateWithLimits } from './multiValueUtils';
@@ -126,8 +126,8 @@ function formatValue(value: any): string {
function buildFieldBasedTooltipItems(
o: JsonObject,
formData: QueryFormData,
): JSX.Element[] {
const tooltipItems: JSX.Element[] = [];
): ReactElement[] {
const tooltipItems: ReactElement[] = [];
formData.tooltip_contents.forEach((item: any, index: number) => {
let label = '';
@@ -360,7 +360,7 @@ export function generateEnhancedDefaultTemplate(
export function useTooltipContent(
formData: QueryFormData,
defaultTooltipGenerator: (o: JsonObject) => JSX.Element,
defaultTooltipGenerator: (o: JsonObject) => ReactElement,
) {
const tooltipContentGenerator = useMemo(
() => (o: JsonObject) => {
@@ -401,7 +401,7 @@ export function useTooltipContent(
export function createTooltipContent(
formData: QueryFormData,
defaultTooltipGenerator: (o: JsonObject) => JSX.Element,
defaultTooltipGenerator: (o: JsonObject) => ReactElement,
) {
return (o: JsonObject) => {
if (
@@ -136,7 +136,9 @@ export function getBreakPointColorScaler(
if (!colorScheme) {
return () => TRANSPARENT_COLOR_ARRAY;
}
let scaler: ScaleLinear<string, string> | ScaleThreshold<number, string>;
let scaler:
| ScaleLinear<string, string, never>
| ScaleThreshold<number, string>;
let maskPoint: (v: number | undefined) => boolean;
if (breakPoints !== null) {
// bucket colors into discrete colors
@@ -164,11 +166,15 @@ export function getBreakPointColorScaler(
// interpolate colors linearly
const linearScaleDomain = extent(features, accessor);
if (!linearScaleDomain.some(i => typeof i === 'number')) {
scaler = colorScheme.createLinearScale();
scaler = colorScheme.createLinearScale() as ScaleLinear<
string,
string,
never
>;
} else {
scaler = colorScheme.createLinearScale(
extent(features, accessor) as number[],
);
) as ScaleLinear<string, string, never>;
}
maskPoint = () => false;
}
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { type ReactChild } from 'react';
import { type ReactNode } from 'react';
import {
render,
screen,
@@ -96,7 +96,7 @@ jest.mock('src/components/StreamingExportModal/useStreamingExport', () => ({
jest.mock(
'react-virtualized-auto-sizer',
() =>
({ children }: { children: (params: { height: number }) => ReactChild }) =>
({ children }: { children: (params: { height: number }) => ReactNode }) =>
children({ height: 500 }),
);
const applicationRootMock = jest.spyOn(getBootstrapData, 'applicationRoot');
@@ -233,14 +233,15 @@ describe('ResultSet', () => {
const table = getByTestId('table-container');
expect(table).toBeInTheDocument();
const firstColumn = queryAllByText(
query.results?.columns[0].column_name ?? '',
)[0];
const secondColumn = queryAllByText(
query.results?.columns[1].column_name ?? '',
)[0];
expect(firstColumn).toBeInTheDocument();
expect(secondColumn).toBeInTheDocument();
// AG Grid commits its header row after the initial render under React 19.
await waitFor(() => {
expect(
queryAllByText(query.results?.columns[0].column_name ?? '')[0],
).toBeInTheDocument();
expect(
queryAllByText(query.results?.columns[1].column_name ?? '')[0],
).toBeInTheDocument();
});
const exploreButton = getByTestId('explore-results-button');
expect(exploreButton).toBeInTheDocument();
@@ -26,7 +26,7 @@ import { styled } from '@apache-superset/core/theme';
import { parseDate } from 'chrono-node';
import {
ModalTrigger,
ModalTriggerRef,
type ModalTriggerRef,
} from '@superset-ui/core/components/ModalTrigger';
import {
Input,
@@ -158,7 +158,7 @@ const ScheduleQueryButton: FunctionComponent<ScheduleQueryButtonProps> = ({
const [description, setDescription] = useState('');
const [label, setLabel] = useState(defaultLabel);
const [showSchedule, setShowSchedule] = useState(false);
const saveModal: ModalTriggerRef | null = useRef() as ModalTriggerRef;
const saveModal = useRef<ModalTriggerRef['current']>(null);
const onScheduleSubmit = ({
formData,
@@ -174,7 +174,7 @@ const ScheduleQueryButton: FunctionComponent<ScheduleQueryButtonProps> = ({
extra_json: JSON.stringify({ schedule_info: formData }),
};
onSchedule(query);
saveModal?.current?.close();
saveModal?.current?.close?.();
};
const renderModalBody = () => (
@@ -51,7 +51,7 @@ jest.mock(
({
children,
}: {
children: (params: { height: number }) => React.ReactChild;
children: (params: { height: number }) => React.ReactNode;
}) =>
children({ height: 500 }),
);
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import type { ReactChild } from 'react';
import type { ReactNode } from 'react';
import fetchMock from 'fetch-mock';
import {
act,
@@ -40,7 +40,7 @@ import TableExploreTree from '.';
jest.mock(
'react-virtualized-auto-sizer',
() =>
({ children }: { children: (params: { height: number }) => ReactChild }) =>
({ children }: { children: (params: { height: number }) => ReactNode }) =>
children({ height: 500 }),
);
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { type ReactChild } from 'react';
import { type ReactNode } from 'react';
import fetchMock from 'fetch-mock';
import { ErrorTypeEnum } from '@superset-ui/core';
import { table, initialState } from 'src/SqlLab/fixtures';
@@ -44,7 +44,7 @@ jest.mock('src/components/FilterableTable', () => ({
jest.mock(
'react-virtualized-auto-sizer',
() =>
({ children }: { children: (params: { height: number }) => ReactChild }) =>
({ children }: { children: (params: { height: number }) => ReactNode }) =>
children({ height: 500 }),
);
jest.mock('@superset-ui/core/components/IconTooltip', () => ({
@@ -36,5 +36,5 @@ export type PluginDeckglLayerVisibilityProps = PluginFilterStylesProps & {
data: (ColumnOption | ColumnData)[];
filterState: FilterState;
formData: DeckglLayerVisibilityFormData;
inputRef: RefObject<RefSelectProps>;
inputRef: RefObject<RefSelectProps | null>;
} & PluginFilterHooks;
@@ -52,7 +52,7 @@ interface PluginFilterGroupByCustomizeProps {
canSelectMultiple?: boolean;
aggregation?: string;
enableEmptyFilter?: boolean;
inputRef?: RefObject<HTMLInputElement>;
inputRef?: RefObject<HTMLInputElement | null>;
}
export type PluginFilterGroupByQueryFormData = QueryFormData &
@@ -69,7 +69,7 @@ export type PluginFilterGroupByProps = PluginFilterStylesProps & {
data: (ColumnOption | ColumnData)[];
filterState: FilterState;
formData: PluginFilterGroupByQueryFormData;
inputRef: RefObject<RefSelectProps>;
inputRef: RefObject<RefSelectProps | null>;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterGroupByCustomizeProps = {
@@ -28,7 +28,7 @@ import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
interface PluginFilterTimeColumnCustomizeProps {
defaultValue?: string[] | null;
inputRef?: RefObject<HTMLInputElement>;
inputRef?: RefObject<HTMLInputElement | null>;
}
export type PluginFilterTimeColumnQueryFormData = QueryFormData &
@@ -40,7 +40,7 @@ export type PluginFilterTimeColumnProps = PluginFilterStylesProps & {
data: DataRecord[];
filterState: FilterState;
formData: PluginFilterTimeColumnQueryFormData;
inputRef: RefObject<RefSelectProps>;
inputRef: RefObject<RefSelectProps | null>;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterTimeColumnCustomizeProps = {
@@ -23,7 +23,7 @@ import { PluginFilterHooks, PluginFilterStylesProps } from '../types';
interface PluginFilterTimeGrainCustomizeProps {
defaultValue?: string[] | null;
inputRef?: RefObject<HTMLInputElement>;
inputRef?: RefObject<HTMLInputElement | null>;
timeGrains?: string[];
}
@@ -35,7 +35,7 @@ export type PluginFilterTimeGrainProps = PluginFilterStylesProps & {
data: DataRecord[];
filterState: FilterState;
formData: PluginFilterTimeGrainQueryFormData;
inputRef: RefObject<RefSelectProps>;
inputRef: RefObject<RefSelectProps | null>;
} & PluginFilterHooks;
export const DEFAULT_FORM_DATA: PluginFilterTimeGrainCustomizeProps = {
@@ -16,7 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ErrorInfo, useCallback, useEffect, useRef } from 'react';
import {
ErrorInfo,
useCallback,
useEffect,
useRef,
type ReactElement,
} from 'react';
import { t } from '@apache-superset/core/translation';
import { logging } from '@apache-superset/core/utils';
import {
@@ -185,7 +191,7 @@ function Chart({
force = false,
isInView = true,
...restProps
}: ChartProps): JSX.Element {
}: ChartProps): ReactElement {
const {
actions,
chartId,
@@ -93,7 +93,7 @@ const ChartContextMenu = (
displayedItems = ContextMenuItem.All,
additionalConfig,
}: ChartContextMenuProps,
ref: RefObject<ChartContextMenuRef>,
ref: RefObject<ChartContextMenuRef | null>,
) => {
const dispatch = useDispatch();
const theme = useTheme();
@@ -26,6 +26,7 @@ import {
MouseEvent,
ReactNode,
memo,
type ReactElement,
} from 'react';
import {
SuperChart,
@@ -193,7 +194,7 @@ function ChartRendererComponent({
initialValues = BLANK,
setControlValue = () => {},
...restProps
}: ChartRendererProps): JSX.Element | null {
}: ChartRendererProps): ReactElement | null {
const {
annotationData,
actions,
@@ -73,13 +73,15 @@ const MOCK_CHART_DATA_RESULT = [
},
];
test('Displays results table for 1 query', () => {
test('Displays results table for 1 query', async () => {
const { result } = renderHook(() =>
useResultsTableView(MOCK_CHART_DATA_RESULT.slice(0, 1), '1__table', true),
);
render(result.current, { useRedux: true });
// AG Grid commits its header and rows after the initial render, which React
// 19 defers.
expect(await screen.findByText('name')).toBeInTheDocument();
expect(screen.queryByRole('tablist')).not.toBeInTheDocument();
expect(screen.getByText('name')).toBeInTheDocument();
expect(screen.getByText('sum__num')).toBeInTheDocument();
expect(screen.getByText('Michael')).toBeInTheDocument();
});
@@ -95,12 +97,12 @@ test('Displays results for 2 queries', async () => {
expect(within(tablistElement).getByText('Results 1')).toBeInTheDocument();
expect(within(tablistElement).getByText('Results 2')).toBeInTheDocument();
expect(screen.getByText('Michael')).toBeInTheDocument();
expect(await screen.findByText('Michael')).toBeInTheDocument();
userEvent.click(screen.getByText('Results 2'));
await waitFor(() => {
expect(screen.getByText('gender')).toBeInTheDocument();
});
expect(screen.getByText('boy')).toBeInTheDocument();
expect(await screen.findByText('boy')).toBeInTheDocument();
});
@@ -69,7 +69,11 @@ interface DataType {
// Must be outside of the main component due to problems in
// react-resize-detector with conditional rendering
// https://github.com/maslianok/react-resize-detector/issues/178
function Resizable({ children }: { children: ReactElement }) {
function Resizable({
children,
}: {
children: ReactElement<{ height?: number }>;
}) {
const { ref, height } = useResizeDetector();
return (
<div ref={ref} css={{ flex: 1 }}>

Some files were not shown because too many files have changed in this diff Show More