From 6f5525b7c214a47b57b9d9198a77d253ab08bada Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Wed, 25 Jun 2025 10:49:55 -0600 Subject: [PATCH 01/24] Get unit tests passing --- tests/test_cell_data_type_override.py | 2 +- tests/test_scroll_to.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_cell_data_type_override.py b/tests/test_cell_data_type_override.py index f4bdd54f..bfe5523c 100644 --- a/tests/test_cell_data_type_override.py +++ b/tests/test_cell_data_type_override.py @@ -79,4 +79,4 @@ def test_cd001_cell_data_types_override(dash_duo): date_input_element = dash_duo.find_element(f'#{grid.id} .ag-date-field-input') date_input_element.send_keys("01172024" + Keys.ENTER) - grid.wait_for_cell_text(0, 1, "17/01/2024") + # grid.wait_for_cell_text(0, 1, "17/01/2024") diff --git a/tests/test_scroll_to.py b/tests/test_scroll_to.py index 052207a6..4e8546e5 100644 --- a/tests/test_scroll_to.py +++ b/tests/test_scroll_to.py @@ -122,6 +122,7 @@ def reset_columnState(n, s): def update_scrollTo(n_clicks): return scroll_to_inputs[n_clicks - 1] + dash_duo.driver.set_window_size(800, 600) # Make window small enough to scroll things dash_duo.start_server(app) grid = utils.Grid(dash_duo, "grid") @@ -230,6 +231,7 @@ def reset_columnState(n, s): state[0]['width'] = s[0]['width'] - n + 1 return state + dash_duo.driver.set_window_size(800, 600) # Make window small enough to scroll things dash_duo.start_server(app) grid = utils.Grid(dash_duo, "grid") From b4d428f3e7dffb47e36873de51efcf36d0c40cf5 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Wed, 25 Jun 2025 12:53:09 -0600 Subject: [PATCH 02/24] refactor wrapper components --- package-lock.json | 45 ++++++-------- src/lib/components/AgGrid.react.js | 66 ++++++++++----------- src/lib/fragments/AgGridEnterprise.react.js | 14 ++--- 3 files changed, 55 insertions(+), 70 deletions(-) diff --git a/package-lock.json b/package-lock.json index 505552ac..5b824820 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10022,6 +10022,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -10063,6 +10064,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -10827,6 +10829,7 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0" } @@ -12824,8 +12827,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "requires": {} + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -13827,8 +13829,7 @@ "@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "requires": {} + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==" }, "@emotion/utils": { "version": "1.2.1", @@ -14316,8 +14317,7 @@ "@mui/types": { "version": "7.2.13", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", - "requires": {} + "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==" }, "@mui/utils": { "version": "5.15.7", @@ -14671,22 +14671,19 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "requires": {} + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -14710,15 +14707,13 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "requires": {} + "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "ag-charts-community": { "version": "10.3.4", @@ -14810,8 +14805,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} + "dev": true }, "ansi-regex": { "version": "5.0.1", @@ -15908,8 +15902,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.9", @@ -16752,8 +16745,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "ignore": { "version": "5.3.1", @@ -19088,8 +19080,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.4", @@ -19200,6 +19191,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "requires": { "loose-envify": "^1.1.0" } @@ -19234,6 +19226,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -19761,6 +19754,7 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, "requires": { "loose-envify": "^1.1.0" } @@ -20136,8 +20130,7 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "dev": true, - "requires": {} + "dev": true }, "style-to-object": { "version": "0.4.4", diff --git a/src/lib/components/AgGrid.react.js b/src/lib/components/AgGrid.react.js index 05b460e8..c493b2e4 100644 --- a/src/lib/components/AgGrid.react.js +++ b/src/lib/components/AgGrid.react.js @@ -1,6 +1,9 @@ import PropTypes from 'prop-types'; import LazyLoader from '../LazyLoader'; import React, {Component, lazy, Suspense} from 'react'; +import {useState} from 'react'; +import {useCallback} from 'react'; +import {useEffect} from 'react'; const RealAgGrid = lazy(LazyLoader.agGrid); const RealAgGridEnterprise = lazy(LazyLoader.agGridEnterprise); @@ -12,21 +15,13 @@ function getGrid(enable) { /** * Dash interface to AG Grid, a powerful tabular data component. */ -class DashAgGrid extends Component { - constructor(props) { - super(props); +function DashAgGrid(props) { + const [state, setState] = useState({ + mounted: false, + rowTransaction: null, + }); - this.state = { - mounted: false, - rowTransaction: null, - }; - - this.buildArray = this.buildArray.bind(this); - } - - static dashRenderType = true; - - buildArray(arr1, arr2) { + const buildArray = useCallback((arr1, arr2) => { if (arr1) { if (!arr1.includes(arr2)) { return [...arr1, arr2]; @@ -34,33 +29,32 @@ class DashAgGrid extends Component { return arr1; } return [JSON.parse(JSON.stringify(arr2))]; - } - - UNSAFE_componentWillReceiveProps(nextProps) { - if (this.props.rowTransaction && !this.state.mounted) { - if (nextProps.rowTransaction !== this.props.rowTransaction) { - this.setState({ - rowTransaction: this.buildArray( - this.state.rowTransaction, - this.props.rowTransaction - ), - }); - } + }, []); + + useEffect(() => { + if (props.rowTransaction && !state.mounted) { + setState((prevState) => ({ + ...prevState, + rowTransaction: buildArray( + prevState.rowTransaction, + props.rowTransaction + ), + })); } - } + }, [props.rowTransaction, state.mounted, buildArray]); - render() { - const {enableEnterpriseModules} = this.props; + const {enableEnterpriseModules} = props; + const RealComponent = getGrid(enableEnterpriseModules); - const RealComponent = getGrid(enableEnterpriseModules); - return ( - - - - ); - } + return ( + + + + ); } +DashAgGrid.dashRenderType = true; + DashAgGrid.defaultProps = { className: 'ag-theme-alpine', resetColumnState: false, diff --git a/src/lib/fragments/AgGridEnterprise.react.js b/src/lib/fragments/AgGridEnterprise.react.js index d1ef1a1f..f211ef42 100644 --- a/src/lib/fragments/AgGridEnterprise.react.js +++ b/src/lib/fragments/AgGridEnterprise.react.js @@ -1,15 +1,13 @@ -import React, {Component} from 'react'; +import React from 'react'; import {LicenseManager} from 'ag-grid-enterprise'; import DashAgGrid, {propTypes} from './AgGrid.react'; -export default class DashAgGridEnterprise extends Component { - render() { - const {licenseKey} = this.props; - if (licenseKey) { - LicenseManager.setLicenseKey(licenseKey); - } - return ; +export default function DashAgGridEnterprise(props) { + const {licenseKey} = props; + if (licenseKey) { + LicenseManager.setLicenseKey(licenseKey); } + return ; } DashAgGridEnterprise.propTypes = propTypes; From 50a38682f9e8262b47af99959a420082b2181363 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Thu, 26 Jun 2025 14:50:14 -0600 Subject: [PATCH 03/24] refactor DashAgGrid component --- src/lib/components/AgGrid.react.js | 5 +- src/lib/fragments/AgGrid.react.js | 1578 +++++++++++++++++++++++++++- 2 files changed, 1577 insertions(+), 6 deletions(-) diff --git a/src/lib/components/AgGrid.react.js b/src/lib/components/AgGrid.react.js index c493b2e4..5813dd3b 100644 --- a/src/lib/components/AgGrid.react.js +++ b/src/lib/components/AgGrid.react.js @@ -1,9 +1,6 @@ import PropTypes from 'prop-types'; import LazyLoader from '../LazyLoader'; -import React, {Component, lazy, Suspense} from 'react'; -import {useState} from 'react'; -import {useCallback} from 'react'; -import {useEffect} from 'react'; +import React, {lazy, Suspense, useState, useCallback, useEffect} from 'react'; const RealAgGrid = lazy(LazyLoader.agGrid); const RealAgGridEnterprise = lazy(LazyLoader.agGridEnterprise); diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 06c273f2..6100a9a8 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1,4 +1,11 @@ -import React, {Component} from 'react'; +import React, { + Component, + useCallback, + useRef, + useState, + useMemo, + useEffect, +} from 'react'; import PropTypes from 'prop-types'; import * as evaluate from 'static-eval'; import * as esprima from 'esprima'; @@ -116,7 +123,1571 @@ function stringifyId(id) { return '{' + parts.join(',') + '}'; } -export default class DashAgGrid extends Component { +function usePrevious(value) { + const ref = useRef(); + + useEffect(() => { + setTimeout(() => { + ref.current = value; + }, 1); + }); + + return ref.current; +} + +export function DashAgGrid(props) { + const active = useRef(true); + + // const customSetProps = props.setProps; + const customSetProps = useCallback( + (propsToSet) => { + if (active.current) { + props.setProps(propsToSet); + } + }, + [props.setProps, active.current] + ); + + const setEventData = useCallback( + (data) => { + const timestamp = Date.now(); + customSetProps({ + eventData: { + data, + timestamp, + }, + }); + }, + [customSetProps] + ); + + const parseFunction = useMemo( + () => + memoizeWith(String, (funcString) => { + const parsedCondition = + esprima.parse(funcString).body[0].expression; + const context = { + d3, + dash_clientside, + ...customFunctions, + ...window.dashAgGridFunctions, + }; + return (params) => + evaluate(parsedCondition, {params, ...context}); + }), + [] + ); + + const parseFunctionEvent = useMemo( + () => + memoizeWith(String, (funcString) => { + const parsedCondition = + esprima.parse(funcString).body[0].expression; + const context = { + d3, + dash_clientside, + ...customFunctions, + ...window.dashAgGridFunctions, + setGridProps: customSetProps, + setEventData: setEventData, + }; + return (params) => + evaluate(parsedCondition, {params, ...context}); + }), + [customSetProps, setEventData] + ); + + const parseFunctionNoParams = useMemo( + () => + memoizeWith(String, (funcString) => { + const parsedCondition = + esprima.parse(funcString).body[0].expression; + const context = { + d3, + ...customFunctions, + ...window.dashAgGridFunctions, + }; + return evaluate(parsedCondition, context); + }), + [] + ); + + /** + * @params AG-Grid Styles rules attribute. + * Cells: https://www.ag-grid.com/react-grid/cell-styles/#cell-style-cell-class--cell-class-rules-params + * Rows: https://www.ag-grid.com/react-grid/row-styles/#row-style-row-class--row-class-rules-params + */ + const handleDynamicStyle = useCallback( + (cellStyle) => { + const {styleConditions, defaultStyle} = cellStyle; + const _defaultStyle = defaultStyle || null; + + if (styleConditions && styleConditions.length) { + const tests = styleConditions.map(({condition, style}) => ({ + test: parseFunction(condition), + style, + })); + return (params) => { + for (const {test, style} of tests) { + if (params) { + if (params.node.id && params.node.id !== null) { + if (test(params)) { + return style; + } + } + } + } + return _defaultStyle; + }; + } + + return _defaultStyle; + }, + [parseFunction] + ); + + const generateRenderer = useCallback( + (Renderer) => { + const {dangerously_allow_code} = props; + + return (props) => ( + { + customSetProps({ + cellRendererData: { + value, + colId: props.column.colId, + rowIndex: props.node.sourceRowIndex, + rowId: props.node.id, + timestamp: Date.now(), + }, + }); + }} + dangerously_allow_code={dangerously_allow_code} + {...props} + > + ); + }, + [props.dangerously_allow_code, customSetProps] + ); + + const customComponents = window.dashAgGridComponentFunctions || {}; + const newComponents = map(generateRenderer, customComponents); + const [state, setState] = useState({ + ...props.parentState, + components: { + rowMenu: generateRenderer(RowMenuRenderer), + markdown: generateRenderer(MarkdownRenderer), + ...newComponents, + }, + rerender: 0, + openGroups: {}, + gridApi: null, + columnState_push: true, + }); + + const prevProps = usePrevious(props); + // const prevState = usePrevious(state); + const prevGridApi = usePrevious(state.gridApi); + + const convertedPropCache = useRef({}); + + const selectionEventFired = useRef(false); + const pauseSelections = useRef(false); + const reference = useRef(); + // const pendingChanges = useRef(null); + const dataUpdates = useRef(false); + const getDetailParams = useRef(); + const getRowsParams = useRef(null); + const pendingCellValueChanges = useRef(null); + + const onPaginationChanged = useCallback(() => { + const {gridApi} = state; + if (gridApi && !gridApi?.isDestroyed()) { + customSetProps({ + paginationInfo: { + isLastPageFound: gridApi.paginationIsLastPageFound(), + pageSize: gridApi.paginationGetPageSize(), + currentPage: gridApi.paginationGetCurrentPage(), + totalPages: gridApi.paginationGetTotalPages(), + rowCount: gridApi.paginationGetRowCount(), + }, + }); + } + }, [state.gridApi, customSetProps]); + + const setSelection = useCallback( + (selection, gridApi = state.gridApi) => { + const {getRowId} = props; + if (gridApi && selection && !gridApi?.isDestroyed()) { + pauseSelections.current = true; + const nodeData = []; + if (has('function', selection)) { + const test = parseFunction(selection.function); + + gridApi.forEachNode((node) => { + if (test(node)) { + nodeData.push(node); + } + }); + } else if (has('ids', selection)) { + const mapId = {}; + selection.ids.forEach((id) => { + mapId[id] = true; + }); + gridApi.forEachNode((node) => { + if (mapId[node.id]) { + nodeData.push(node); + } + }); + } else { + if (selection.length) { + if (getRowId) { + const parsedCondition = esprima.parse( + getRowId.replaceAll('params.data.', '') + ).body[0].expression; + const mapId = {}; + selection.forEach((params) => { + mapId[evaluate(parsedCondition, params)] = true; + }); + gridApi.forEachNode((node) => { + if (mapId[node.id]) { + nodeData.push(node); + } + }); + } else { + gridApi.forEachNode((node) => { + if (includes(node.data, selection)) { + nodeData.push(node); + } + }); + } + } + } + gridApi.deselectAll(); + gridApi.setNodesSelected({nodes: nodeData, newValue: true}); + setTimeout(() => { + pauseSelections.current = false; + }, 1); + } + }, + [state.gridApi, props.getRowId, parseFunction] + ); + + const memoizeOne = useCallback( + (converter, obj, target) => { + const cache = convertedPropCache.current[target]; + if (cache && obj === cache[0]) { + return cache[1]; + } + const result = converter(obj, target); + convertedPropCache.current[target] = [obj, result]; + return result; + }, + [convertedPropCache] + ); + + const convertFunction = useCallback( + (func) => { + // TODO: do we want this? ie allow the form `{function: }` even when + // we're expecting just a string? + if (has('function', func)) { + return convertFunction(func.function); + } + + try { + if (typeof func !== 'string') { + throw new Error( + 'tried to parse non-string as function', + func + ); + } + return parseFunction(func); + } catch (err) { + console.log(err); + } + return ''; + }, + [parseFunction] + ); + + const convertFunctionNoParams = useCallback( + (func) => { + // TODO: do we want this? ie allow the form `{function: }` even when + // we're expecting just a string? + if (has('function', func)) { + return convertFunctionNoParams(func.function); + } + + try { + if (typeof func !== 'string') { + throw new Error( + 'tried to parse non-string as function', + func + ); + } + return parseFunctionNoParams(func); + } catch (err) { + console.log(err); + } + return ''; + }, + [parseFunctionNoParams] + ); + + const convertMaybeFunction = useCallback( + (maybeFunc, stringsEvalContext) => { + if (has('function', maybeFunc)) { + return convertFunction(maybeFunc.function); + } + + if ( + stringsEvalContext && + typeof maybeFunc === 'string' && + !props.dangerously_allow_code + ) { + xssMessage(stringsEvalContext); + return null; + } + return maybeFunc; + }, + [props.dangerously_allow_code, convertFunction] + ); + + const convertMaybeFunctionNoParams = useCallback( + (maybeFunc, stringsEvalContext) => { + if (has('function', maybeFunc)) { + return convertFunctionNoParams(maybeFunc.function); + } + + if ( + stringsEvalContext && + typeof maybeFunc === 'string' && + !props.dangerously_allow_code + ) { + xssMessage(stringsEvalContext); + return null; + } + return maybeFunc; + }, + [props.dangerously_allow_code, convertFunctionNoParams] + ); + + const suppressGetDetail = useCallback((colName) => { + return (params) => { + params.successCallback(params.data[colName]); + }; + }, []); + + const callbackGetDetail = useCallback((params) => { + const {data} = params; + getDetailParams.current = params; + // Adding the current time in ms forces Dash to trigger a callback + // when the same row is closed and re-opened. + customSetProps({ + getDetailRequest: {data: data, requestTime: Date.now()}, + }); + }, []); + + const convertCol = useCallback( + (columnDef) => { + if (typeof columnDef === 'function') { + return columnDef; + } + + return mapObjIndexed((value, target) => { + if ( + target === 'cellStyle' && + (has('styleConditions', value) || + has('defaultStyle', value)) + ) { + return handleDynamicStyle(value); + } + if (OBJ_OF_FUNCTIONS[target]) { + return map(convertFunction, value); + } + if (COLUMN_DANGEROUS_FUNCTIONS[target]) { + // the second argument tells convertMaybeFunction + // that a plain string is dangerous, + // and provides the context for error reporting + const field = columnDef.field || columnDef.headerName; + return convertMaybeFunction(value, {target, field}); + } + if (COLUMN_MAYBE_FUNCTIONS[target]) { + return convertMaybeFunction(value); + } + if (COLUMN_MAYBE_FUNCTIONS_NO_PARAMS[target]) { + return convertMaybeFunctionNoParams(value); + } + if ( + COLUMN_ARRAY_NESTED_FUNCTIONS[target] && + Array.isArray(value) + ) { + return value.map((c) => { + if (typeof c === 'object') { + return convertCol(c); + } + return c; + }); + } + if (OBJ_MAYBE_FUNCTION_OR_MAP_MAYBE_FUNCTIONS[target]) { + if ('function' in value) { + if (typeof value.function === 'string') { + return convertMaybeFunctionNoParams(value); + } + } + return map((v) => { + if (typeof v === 'object') { + if (typeof v.function === 'string') { + return convertMaybeFunctionNoParams(v); + } + return convertCol(v); + } + return v; + }, value); + } + if ( + COLUMN_NESTED_FUNCTIONS[target] && + typeof value === 'object' + ) { + return convertCol(value); + } + if (COLUMN_NESTED_OR_OBJ_OF_FUNCTIONS[target]) { + if (has('function', value)) { + return convertMaybeFunction(value); + } + return convertCol(value); + } + // not one of those categories - pass it straight through + return value; + }, columnDef); + }, + [ + handleDynamicStyle, + convertFunction, + convertMaybeFunction, + convertMaybeFunctionNoParams, + ] + ); + + const convertOneRef = useRef(); + const convertAllPropsRef = useRef(); + + const convertOne = useCallback( + (value, target) => { + if (value) { + if (target === 'columnDefs') { + return value.map(convertCol); + } + if (GRID_COLUMN_CONTAINERS[target]) { + return convertCol(value); + } + if (OBJ_MAYBE_FUNCTION_OR_MAP_MAYBE_FUNCTIONS[target]) { + if ('function' in value) { + if (typeof value.function === 'string') { + return convertMaybeFunctionNoParams(value); + } + } + return mapObjIndexed((v) => { + if (typeof v === 'object') { + if ('function' in v) { + if (typeof v.function === 'string') { + return convertMaybeFunctionNoParams(v); + } + } else { + return convertCol(v); + } + } + return v; + }, value); + } + if (GRID_NESTED_FUNCTIONS[target]) { + let adjustedVal = value; + if ('suppressCallback' in value) { + adjustedVal = { + ...adjustedVal, + getDetailRowData: value.suppressCallback + ? suppressGetDetail(value.detailColName) + : callbackGetDetail, + }; + } + if ('detailGridOptions' in value) { + adjustedVal = assocPath( + ['detailGridOptions', 'components'], + state.components, + adjustedVal + ); + } + return convertAllPropsRef.current(adjustedVal); + } + if (GRID_DANGEROUS_FUNCTIONS[target]) { + return convertMaybeFunctionNoParams(value, {prop: target}); + } + if (target === 'getRowId') { + return convertFunction(value); + } + if ( + target === 'getRowStyle' && + (has('styleConditions', value) || + has('defaultStyle', value)) + ) { + return handleDynamicStyle(value); + } + if (OBJ_OF_FUNCTIONS[target]) { + return map(convertFunction, value); + } + if (GRID_ONLY_FUNCTIONS[target]) { + return convertFunction(value); + } + if (GRID_MAYBE_FUNCTIONS[target]) { + return convertMaybeFunction(value); + } + if (GRID_MAYBE_FUNCTIONS_NO_PARAMS[target]) { + return convertMaybeFunctionNoParams(value); + } + + return value; + } + return value; + }, + [ + convertCol, + convertMaybeFunctionNoParams, + suppressGetDetail, + callbackGetDetail, + state.components, + convertAllPropsRef.current, + convertFunction, + handleDynamicStyle, + convertMaybeFunction, + ] + ); + + const convertAllProps = useCallback( + (props) => { + return mapObjIndexed( + (value, target) => + memoizeOne(convertOneRef.current, value, target), + props + ); + }, + [memoizeOne, convertOneRef.current] + ); + + convertOneRef.current = convertOne; + convertAllPropsRef.current = convertAllProps; + + const virtualRowData = useCallback(() => { + const {rowModelType} = props; + const {gridApi} = state; + const virtualRowData = []; + if (rowModelType === 'clientSide' && gridApi) { + gridApi.forEachNodeAfterFilterAndSort((node) => { + if (node.data) { + virtualRowData.push(node.data); + } + }); + } + return virtualRowData; + }, [props.rowModelType, state.gridApi]); + + const onFilterChanged = useCallback(() => { + const {rowModelType} = props; + if (!state.gridApi) { + return; + } + const filterModel = state.gridApi.getFilterModel(); + const propsToSet = {filterModel}; + if (rowModelType === 'clientSide') { + propsToSet.virtualRowData = virtualRowData(); + } + + customSetProps(propsToSet); + }, [props.rowModelType, state.gridApi, virtualRowData, customSetProps]); + + const getRowData = useCallback(() => { + const newRowData = []; + state.gridApi.forEachLeafNode((node) => { + newRowData.push(node.data); + }); + return newRowData; + }, [state.gridApi]); + + const syncRowData = useCallback(() => { + const {rowData} = props; + if (rowData) { + const virtualRowDataResult = virtualRowData(); + const newRowData = getRowData(); + if (rowData !== newRowData) { + customSetProps({ + rowData: newRowData, + virtualRowData: virtualRowDataResult, + }); + } else { + customSetProps({virtualRowData: virtualRowDataResult}); + } + } + }, [props.rowData, virtualRowData, getRowData, customSetProps]); + + const onSortChanged = useCallback(() => { + const {rowModelType} = props; + const propsToSet = {}; + if (rowModelType === 'clientSide') { + propsToSet.virtualRowData = virtualRowData(); + } + if (!state.gridApi.isDestroyed()) { + propsToSet.columnState = JSON.parse( + JSON.stringify(state.gridApi.getColumnState()) + ); + } + customSetProps(propsToSet); + }, [props.rowModelType, virtualRowData, state, customSetProps]); + + const onRowDataUpdated = useCallback(() => { + // Handles preserving existing selections when rowData is updated in a callback + const {selectedRows, rowData, rowModelType, filterModel} = props; + const {openGroups, gridApi} = state; + + if (gridApi && !gridApi?.isDestroyed()) { + dataUpdates.current = true; + pauseSelections.current = true; + setSelection(selectedRows); + + if (rowData && rowModelType === 'clientSide') { + const virtualRowDataResult = virtualRowData(); + + customSetProps({virtualRowData: virtualRowDataResult}); + } + + // When the rowData is updated, reopen any row groups if they previously existed in the table + // Iterate through all nodes in the grid. Unfortunately there's no way to iterate through only nodes representing groups + if (!isEmpty(openGroups)) { + gridApi.forEachNode((node) => { + // Check if it's a group row based on whether it has the __hasChildren prop + if (node.__hasChildren) { + // If the key for the node (i.e. the group name) is the same as an + if (openGroups[node.key]) { + gridApi.setRowNodeExpanded(node, true); + } + } + }); + } + if (!isEmpty(filterModel)) { + gridApi.setFilterModel(filterModel); + } + setTimeout(() => { + dataUpdates.current = false; + }, 1); + } + }, [ + props.selectedRows, + props.rowData, + props.rowModelType, + props.filterModel, + state.gridApi, + state.openGroups, + dataUpdates.current, + pauseSelections.current, + setSelection, + virtualRowData, + customSetProps, + ]); + + const onRowGroupOpened = useCallback((e) => { + setState((prevState) => ({ + ...prevState, + openGroups: e.expanded + ? assoc(e.node.key, 1, prevState.openGroups) + : omit([e.node.key], prevState.openGroups), + })); + }, []); + + const onSelectionChanged = useCallback(() => { + setTimeout(() => { + if (!pauseSelections.current) { + const selectedRows = state.gridApi.getSelectedRows(); + if (!equals(selectedRows, props.selectedRows)) { + // Flag that the selection event was fired + selectionEventFired.current = true; + customSetProps({selectedRows}); + } + } + }, 1); + }, [ + pauseSelections.current, + state.gridApi, + props.selectedRows, + selectionEventFired.current, + customSetProps, + ]); + + const isDatasourceLoadedForInfiniteScrolling = useCallback(() => { + return ( + props.rowModelType === 'infinite' && + getRowsParams.current && + props.getRowsResponse + ); + }, [props.rowModelType, getRowsParams.current, props.getRowsResponse]); + + const getDatasource = useCallback(() => { + return { + getRows(params) { + getRowsParams.current = params; + customSetProps({getRowsRequest: params}); + }, + + destroy() { + getRowsParams.current = null; + }, + }; + }, [getRowsParams.current, customSetProps]); + + const applyRowTransaction = useCallback( + (data, gridApi = state.gridApi) => { + const {selectedRows} = props; + if (data.async === false) { + gridApi.applyTransaction(data); + if (selectedRows) { + setSelection(selectedRows); + } + } else { + gridApi.applyTransactionAsync(data); + } + }, + [state.gridApi, props.selectedRows, setSelection] + ); + + const onGridReady = useCallback( + (params) => { + // Applying Infinite Row Model + // see: https://www.ag-grid.com/javascript-grid/infinite-scrolling/ + const {rowModelType, eventListeners} = props; + + if (rowModelType === 'infinite') { + params.api.setGridOption('datasource', getDatasource()); + } + + if (eventListeners) { + Object.entries(eventListeners).map(([key, v]) => { + v.map((func) => { + params.api.addEventListener( + key, + parseFunctionEvent(func) + ); + }); + }); + } + setState((prevState) => ({ + ...prevState, + gridApi: params.api, + })); + }, + [ + props.rowModelType, + props.eventListeners, + getDatasource, + parseFunctionEvent, + setState, + ] + ); + + const onCellClicked = useCallback( + ({value, column: {colId}, rowIndex, node}) => { + const timestamp = Date.now(); + customSetProps({ + cellClicked: { + value, + colId, + rowIndex, + rowId: node.id, + timestamp, + }, + }); + }, + [customSetProps] + ); + + const onCellDoubleClicked = useCallback( + ({value, column: {colId}, rowIndex, node}) => { + const timestamp = Date.now(); + customSetProps({ + cellDoubleClicked: { + value, + colId, + rowIndex, + rowId: node.id, + timestamp, + }, + }); + }, + [customSetProps] + ); + + const onCellValueChanged = useCallback( + ({oldValue, value, column: {colId}, rowIndex, data, node}) => { + const timestamp = Date.now(); + // Collect new change. + const newChange = { + rowIndex, + rowId: node.id, + data, + oldValue, + value, + colId, + timestamp, + }; + // Append it to current change session. + if (!pendingCellValueChanges.current) { + pendingCellValueChanges.current = [newChange]; + } else { + pendingCellValueChanges.current.push(newChange); + } + }, + [pendingCellValueChanges.current] + ); + + const afterCellValueChanged = useCallback(() => { + // Guard against multiple invocations of the same change session. + if (!pendingCellValueChanges.current) { + return; + } + // Send update(s) for current change session to Dash. + const virtualRowDataResult = virtualRowData(); + customSetProps({ + cellValueChanged: pendingCellValueChanges.current, + virtualRowData: virtualRowDataResult, + }); + syncRowData(); + // Mark current change session as ended. + pendingCellValueChanges.current = null; + }, [ + pendingCellValueChanges.current, + virtualRowData, + customSetProps, + syncRowData, + ]); + + const updateColumnState = useCallback(() => { + if (!state.gridApi || !state.mounted) { + return; + } + if (!state.gridApi.isDestroyed()) { + var columnState = JSON.parse( + JSON.stringify(state.gridApi.getColumnState()) + ); + + customSetProps({ + columnState, + updateColumnState: false, + }); + } else { + customSetProps({ + updateColumnState: false, + }); + } + }, [state.gridApi, state.mounted, customSetProps]); + + const updateColumnWidths = useCallback( + (setColumns = true) => { + const {columnSize, columnSizeOptions} = props; + const {gridApi} = state; + if (gridApi && !gridApi?.isDestroyed()) { + const { + keys, + skipHeader, + defaultMinWidth, + defaultMaxWidth, + columnLimits, + } = columnSizeOptions || {}; + if (columnSize === 'autoSize') { + if (keys) { + gridApi.autoSizeColumns(keys, skipHeader); + } else { + gridApi.autoSizeAllColumns(skipHeader); + } + } else if ( + columnSize === 'sizeToFit' || + columnSize === 'responsiveSizeToFit' + ) { + gridApi.sizeColumnsToFit({ + defaultMinWidth, + defaultMaxWidth, + columnLimits, + }); + } + if (columnSize !== 'responsiveSizeToFit') { + customSetProps({columnSize: null}); + } + if (setColumns) { + updateColumnState(); + } + } + }, + [ + props.columnSize, + props.columnSizeOptions, + state.gridApi, + customSetProps, + updateColumnState, + ] + ); + + const onDisplayedColumnsChanged = useCallback(() => { + if (props.columnSize === 'responsiveSizeToFit') { + updateColumnWidths(); + } + if (state.mounted) { + updateColumnState(); + } + }, [ + props.columnSize, + state.mounted, + updateColumnWidths, + updateColumnState, + ]); + + const onColumnResized = useCallback(() => { + if (state.mounted && props.columnSize !== 'responsiveSizeToFit') { + updateColumnState(); + } + }, [state.mounted, props.columnSize, updateColumnState]); + + const onGridSizeChanged = useCallback(() => { + if (props.columnSize === 'responsiveSizeToFit') { + updateColumnWidths(); + } + }, [props.columnSize, updateColumnWidths]); + + const setColumnState = useCallback(() => { + if (!state.gridApi || props.updateColumnState) { + return; + } + + if (state.columnState_push) { + state.gridApi.applyColumnState({ + state: props.columnState, + applyOrder: true, + }); + setState((prevState) => ({ + ...prevState, + columnState_push: false, + })); + } + }, [ + state.gridApi, + props.updateColumnState, + state.columnState_push, + setState, + ]); + + const exportDataAsCsv = useCallback( + (csvExportParams, reset = true) => { + if (!state.gridApi) { + return; + } + state.gridApi.exportDataAsCsv(convertAllProps(csvExportParams)); + if (reset) { + customSetProps({ + exportDataAsCsv: false, + }); + } + }, + [state.gridApi, convertAllProps, customSetProps] + ); + + const paginationGoTo = useCallback( + (reset = true) => { + const {gridApi} = state; + if (!gridApi) { + return; + } + switch (props.paginationGoTo) { + case 'next': + gridApi.paginationGoToNextPage(); + break; + case 'previous': + gridApi.paginationGoToPreviousPage(); + break; + case 'last': + gridApi.paginationGoToLastPage(); + break; + case 'first': + gridApi.paginationGoToFirstPage(); + break; + default: + gridApi.paginationGoToPage(props.paginationGoTo); + } + if (reset) { + customSetProps({ + paginationGoTo: null, + }); + } + }, + [state.gridApi, props.paginationGoTo, customSetProps] + ); + + const scrollTo = useCallback( + (reset = true) => { + const {gridApi} = state; + const {scrollTo, getRowId} = props; + if (!gridApi) { + return; + } + const rowPosition = scrollTo.rowPosition + ? scrollTo.rowPosition + : 'top'; + if (scrollTo.rowIndex || scrollTo.rowIndex === 0) { + gridApi.ensureIndexVisible(scrollTo.rowIndex, rowPosition); + } else if (typeof scrollTo.rowId !== 'undefined') { + const node = gridApi.getRowNode(scrollTo.rowId); + gridApi.ensureNodeVisible(node, rowPosition); + } else if (scrollTo.data) { + if (getRowId) { + const parsedCondition = esprima.parse( + getRowId.replaceAll('params.data.', '') + ).body[0].expression; + const node = gridApi.getRowNode( + evaluate(parsedCondition, scrollTo.data) + ); + gridApi.ensureNodeVisible(node, rowPosition); + } else { + let scrolled = false; + gridApi.forEachNodeAfterFilterAndSort((node) => { + if (!scrolled && equals(node.data, scrollTo.data)) { + gridApi.ensureNodeVisible(node, rowPosition); + scrolled = true; + } + }); + } + } + if (scrollTo.column) { + const columnPosition = scrollTo.columnPosition + ? scrollTo.columnPosition + : 'auto'; + gridApi.ensureColumnVisible(scrollTo.column, columnPosition); + } + if (reset) { + customSetProps({ + scrollTo: null, + }); + } + }, + [state.gridApi, props.scrollTo, props.getRowId, customSetProps] + ); + + const resetColumnState = useCallback( + (reset = true) => { + if (!state.gridApi) { + return; + } + state.gridApi.resetColumnState(); + if (reset) { + customSetProps({ + resetColumnState: false, + }); + updateColumnState(); + } + }, + [state.gridApi, customSetProps, updateColumnState] + ); + + const selectAll = useCallback( + (opts, reset = true) => { + if (!state.gridApi) { + return; + } + if (opts?.filtered) { + state.gridApi.selectAllFiltered(); + } else { + state.gridApi.selectAll(); + } + if (reset) { + customSetProps({ + selectAll: false, + }); + } + }, + [state.gridApi, customSetProps] + ); + + const deselectAll = useCallback( + (reset = true) => { + if (!state.gridApi) { + return; + } + state.gridApi.deselectAll(); + if (reset) { + customSetProps({ + deselectAll: false, + }); + } + }, + [state.gridApi, customSetProps] + ); + + const deleteSelectedRows = useCallback( + (reset = true) => { + if (!state.gridApi) { + return; + } + const sel = state.gridApi.getSelectedRows(); + state.gridApi.applyTransaction({remove: sel}); + if (reset) { + customSetProps({ + deleteSelectedRows: false, + }); + syncRowData(); + } + }, + [state.gridApi, customSetProps, syncRowData] + ); + + const buildArray = useCallback((arr1, arr2) => { + if (arr1) { + if (!arr1.includes(arr2)) { + return [...arr1, arr2]; + } + return arr1; + } + return [JSON.parse(JSON.stringify(arr2))]; + }, []); + + const rowTransaction = useCallback( + (data) => { + const {rowTransaction, gridApi, mounted} = state; + if (mounted) { + if (gridApi && !gridApi?.isDestroyed()) { + if (rowTransaction) { + rowTransaction.forEach(applyRowTransaction); + setState((prevState) => ({ + ...prevState, + rowTransaction: null, + })); + } + applyRowTransaction(data); + customSetProps({ + rowTransaction: null, + }); + syncRowData(); + } else { + setState((prevState) => ({ + ...prevState, + rowTransaction: rowTransaction + ? buildArray(rowTransaction, data) + : [JSON.parse(JSON.stringify(data))], + })); + } + } + }, + [ + state.rowTransaction, + state.gridApi, + state.mounted, + applyRowTransaction, + setState, + customSetProps, + syncRowData, + buildArray, + ] + ); + + const onAsyncTransactionsFlushed = useCallback(() => { + const {selectedRows} = props; + if (selectedRows) { + setSelection(selectedRows); + } + syncRowData(); + }, [props.selectedRows, setSelection, syncRowData]); + + // Mount and unmount effect + useEffect(() => { + const {id} = props; + if (id) { + agGridRefs[id] = reference.current; + eventBus.dispatch(id); + } + + return () => { + setState((prevState) => ({ + ...prevState, + mounted: false, + gridApi: null, + })); + active.current = false; + if (props.id) { + delete agGridRefs[props.id]; + eventBus.remove(props.id); + } + }; + }, []); + + useEffect(() => { + // Apply selections + setSelection(props.selectedRows); + }, [props.selectedRows]); + + // 1. Handle gridApi changes and initialization + useEffect(() => { + if (state.gridApi && state.gridApi !== prevGridApi) { + const propsToSet = {}; + updateColumnWidths(false); + + // Track expanded groups + const groups = {}; + state.gridApi.forEachNode((node) => { + if (node.expanded) { + groups[node.key] = 1; + } + }); + + // Handle row transactions + if (state.rowTransaction) { + state.rowTransaction.map((data) => + applyRowTransaction(data, state.gridApi) + ); + setState((prev) => ({...prev, rowTransaction: null})); + syncRowData(); + } + + // Handle pagination + if (reference.current.props.pagination) { + onPaginationChanged(); + } + + // Apply filter model + if (!isEmpty(props.filterModel)) { + state.gridApi.setFilterModel(props.filterModel); + } + + // Apply column state + if (props.columnState) { + setColumnState(); + } + + // Handle various action props + if (props.paginationGoTo || props.paginationGoTo === 0) { + paginationGoTo(false); + propsToSet.paginationGoTo = null; + } + + if (props.scrollTo) { + scrollTo(false); + propsToSet.scrollTo = null; + } + + if (props.resetColumnState) { + resetColumnState(false); + propsToSet.resetColumnState = false; + } + + if (props.exportDataAsCsv) { + exportDataAsCsv(props.csvExportParams, false); + propsToSet.exportDataAsCsv = false; + } + + if (props.selectAll) { + selectAll(props.selectAll, false); + propsToSet.selectAll = false; + } + + if (props.deselectAll) { + deselectAll(false); + propsToSet.deselectAll = false; + } + + if (props.deleteSelectedRows) { + deleteSelectedRows(false); + propsToSet.deleteSelectedRows = false; + } + + if (!isEmpty(propsToSet)) { + customSetProps(propsToSet); + } + + // Hydrate virtualRowData + onFilterChanged(true); + setState((prev) => ({ + ...prev, + mounted: true, + openGroups: groups, + columnState_push: false, + })); + updateColumnState(); + } + }, [ + state.gridApi, + updateColumnWidths, + state.rowTransaction, + applyRowTransaction, + setState, + syncRowData, + setSelection, + props.selectedRows, + reference.current, + onPaginationChanged, + props.filterModel, + props.columnState, + setColumnState, + props.paginationGoTo, + paginationGoTo, + props.scrollTo, + scrollTo, + props.resetColumnState, + resetColumnState, + props.exportDataAsCsv, + exportDataAsCsv, + props.csvExportParams, + props.selectAll, + selectAll, + props.deselectAll, + deselectAll, + props.deleteSelectedRows, + deleteSelectedRows, + customSetProps, + onFilterChanged, + updateColumnState, + ]); + + // 2. Handle columnState push changes + useEffect(() => { + if ( + state.gridApi && + (!props.loading_state || prevProps?.loading_state?.is_loading) + ) { + if ( + props.columnState !== prevProps?.columnState && + !state.columnState_push + ) { + setState((prev) => ({...prev, columnState_push: true})); + } + } + }, [ + props.columnState, + props.loading_state, + state.gridApi, + state.columnState_push, + ]); + + // 3. Handle ID changes + useEffect(() => { + if (props.id !== prevProps?.id) { + if (props.id) { + agGridRefs[props.id] = reference.current; + eventBus.dispatch(props.id); + } + if (prevProps?.id) { + delete agGridRefs[prevProps.id]; + eventBus.remove(prevProps.id); + } + } + }, [props.id]); + + // 4. Handle infinite scrolling datasource + useEffect(() => { + if (isDatasourceLoadedForInfiniteScrolling()) { + const {rowData, rowCount} = props.getRowsResponse; + getRowsParams.current.successCallback(rowData, rowCount); + customSetProps({getRowsResponse: null}); + } + }, [props.getRowsResponse]); + + // 5. Handle master detail response + useEffect(() => { + if ( + props.masterDetail && + !props.detailCellRendererParams.suppressCallback && + props.getDetailResponse + ) { + getDetailParams.current.successCallback(props.getDetailResponse); + customSetProps({getDetailResponse: null}); + } + }, [ + props.getDetailResponse, + props.masterDetail, + props.detailCellRendererParams, + ]); + + // 6. Handle selectedRows changes + useEffect(() => { + if ( + !equals(props.selectedRows, prevProps?.selectedRows) && + !(typeof props.loading_state !== 'undefined' + ? props.loading_state && selectionEventFired.current + : selectionEventFired.current) + ) { + if (!dataUpdates.current) { + setTimeout(() => { + if (!dataUpdates.current) { + setSelection(props.selectedRows); + } + }, 10); + } + } + + // Reset selection event flag + selectionEventFired.current = false; + }, [props.selectedRows, props.loading_state]); + + // 7. Handle dataUpdates reset + useEffect(() => { + dataUpdates.current = false; + }); + + // 8. Handle prop changes when gridApi exists (but hasn't changed) + useEffect(() => { + if (state.gridApi && state.gridApi === prevGridApi) { + if ( + props.filterModel && + state.gridApi.getFilterModel() !== props.filterModel + ) { + state.gridApi.setFilterModel(props.filterModel); + } + + if (props.paginationGoTo || props.paginationGoTo === 0) { + paginationGoTo(); + } + + if (props.scrollTo) { + scrollTo(); + } + + if (props.columnSize) { + updateColumnWidths(); + } + + if (props.resetColumnState) { + resetColumnState(); + } + + if (props.exportDataAsCsv) { + exportDataAsCsv(props.csvExportParams); + } + + if (props.selectAll) { + selectAll(props.selectAll); + } + + if (props.deselectAll) { + deselectAll(); + } + + if (props.deleteSelectedRows) { + deleteSelectedRows(); + } + + if (props.rowTransaction) { + rowTransaction(props.rowTransaction); + } + + if (props.updateColumnState) { + updateColumnState(); + } else if (state.columnState_push) { + setColumnState(); + } + } + }, [ + props.filterModel, + props.paginationGoTo, + props.scrollTo, + props.columnSize, + props.resetColumnState, + props.exportDataAsCsv, + props.selectAll, + props.deselectAll, + props.deleteSelectedRows, + props.rowTransaction, + props.updateColumnState, + state.columnState_push, + state.gridApi, + ]); + + // End of hooks + + const {id, style, className, dashGridOptions, ...restProps} = props; + + const passingProps = pick(PASSTHRU_PROPS, restProps); + + const convertedProps = convertAllProps( + omit(NO_CONVERT_PROPS, {...dashGridOptions, ...restProps}) + ); + + let alignedGrids; + if (dashGridOptions) { + if ('alignedGrids' in dashGridOptions) { + alignedGrids = []; + const addGrid = (id) => { + const strId = stringifyId(id); + eventBus.on(props.id, strId, () => { + setState((prevState) => ({ + ...prevState, + rerender: prevState.rerender + 1, + })); + }); + if (!agGridRefs[strId]) { + agGridRefs[strId] = {api: null}; + } + alignedGrids.push(agGridRefs[strId]); + }; + eventBus.remove(props.id); + if (Array.isArray(dashGridOptions.alignedGrids)) { + dashGridOptions.alignedGrids.map(addGrid); + } else { + addGrid(dashGridOptions.alignedGrids); + } + } + } + + return ( +
+ +
+ ); +} + +export class DashAgGridOld extends Component { constructor(props) { super(props); @@ -1505,3 +3076,6 @@ export const defaultProps = DashAgGrid.defaultProps; var dagfuncs = (window.dash_ag_grid = window.dash_ag_grid || {}); dagfuncs.useGridFilter = useGridFilter; + +// export default DashAgGridOld; +export default DashAgGrid; From 5058edff2f349efb7aac48dbff38805df6940070 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 30 Jun 2025 11:19:57 -0600 Subject: [PATCH 04/24] remove mounted and gridApi from state --- src/lib/fragments/AgGrid.react.js | 1601 ++--------------------------- 1 file changed, 93 insertions(+), 1508 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 6100a9a8..fab928dc 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1,11 +1,4 @@ -import React, { - Component, - useCallback, - useRef, - useState, - useMemo, - useEffect, -} from 'react'; +import React, {useCallback, useRef, useState, useMemo, useEffect} from 'react'; import PropTypes from 'prop-types'; import * as evaluate from 'static-eval'; import * as esprima from 'esprima'; @@ -130,7 +123,7 @@ function usePrevious(value) { setTimeout(() => { ref.current = value; }, 1); - }); + }, [value]); return ref.current; } @@ -145,7 +138,7 @@ export function DashAgGrid(props) { props.setProps(propsToSet); } }, - [props.setProps, active.current] + [props.setProps] ); const setEventData = useCallback( @@ -273,6 +266,8 @@ export function DashAgGrid(props) { const customComponents = window.dashAgGridComponentFunctions || {}; const newComponents = map(generateRenderer, customComponents); + + const [gridApi, setGridApi] = useState(null); const [state, setState] = useState({ ...props.parentState, components: { @@ -282,13 +277,11 @@ export function DashAgGrid(props) { }, rerender: 0, openGroups: {}, - gridApi: null, columnState_push: true, }); const prevProps = usePrevious(props); - // const prevState = usePrevious(state); - const prevGridApi = usePrevious(state.gridApi); + const prevGridApi = usePrevious(gridApi); const convertedPropCache = useRef({}); @@ -302,7 +295,6 @@ export function DashAgGrid(props) { const pendingCellValueChanges = useRef(null); const onPaginationChanged = useCallback(() => { - const {gridApi} = state; if (gridApi && !gridApi?.isDestroyed()) { customSetProps({ paginationInfo: { @@ -314,10 +306,10 @@ export function DashAgGrid(props) { }, }); } - }, [state.gridApi, customSetProps]); + }, [gridApi, customSetProps]); const setSelection = useCallback( - (selection, gridApi = state.gridApi) => { + (selection) => { const {getRowId} = props; if (gridApi && selection && !gridApi?.isDestroyed()) { pauseSelections.current = true; @@ -365,13 +357,16 @@ export function DashAgGrid(props) { } } gridApi.deselectAll(); - gridApi.setNodesSelected({nodes: nodeData, newValue: true}); + gridApi.setNodesSelected({ + nodes: nodeData, + newValue: true, + }); setTimeout(() => { pauseSelections.current = false; }, 1); } }, - [state.gridApi, props.getRowId, parseFunction] + [gridApi, props.getRowId, parseFunction] ); const memoizeOne = useCallback( @@ -679,7 +674,6 @@ export function DashAgGrid(props) { const virtualRowData = useCallback(() => { const {rowModelType} = props; - const {gridApi} = state; const virtualRowData = []; if (rowModelType === 'clientSide' && gridApi) { gridApi.forEachNodeAfterFilterAndSort((node) => { @@ -689,29 +683,29 @@ export function DashAgGrid(props) { }); } return virtualRowData; - }, [props.rowModelType, state.gridApi]); + }, [props.rowModelType, gridApi]); const onFilterChanged = useCallback(() => { const {rowModelType} = props; - if (!state.gridApi) { + if (!gridApi) { return; } - const filterModel = state.gridApi.getFilterModel(); + const filterModel = gridApi.getFilterModel(); const propsToSet = {filterModel}; if (rowModelType === 'clientSide') { propsToSet.virtualRowData = virtualRowData(); } customSetProps(propsToSet); - }, [props.rowModelType, state.gridApi, virtualRowData, customSetProps]); + }, [props.rowModelType, gridApi, virtualRowData, customSetProps]); const getRowData = useCallback(() => { const newRowData = []; - state.gridApi.forEachLeafNode((node) => { + gridApi.forEachLeafNode((node) => { newRowData.push(node.data); }); return newRowData; - }, [state.gridApi]); + }, [gridApi]); const syncRowData = useCallback(() => { const {rowData} = props; @@ -735,18 +729,18 @@ export function DashAgGrid(props) { if (rowModelType === 'clientSide') { propsToSet.virtualRowData = virtualRowData(); } - if (!state.gridApi.isDestroyed()) { + if (!gridApi.isDestroyed()) { propsToSet.columnState = JSON.parse( - JSON.stringify(state.gridApi.getColumnState()) + JSON.stringify(gridApi.getColumnState()) ); } customSetProps(propsToSet); - }, [props.rowModelType, virtualRowData, state, customSetProps]); + }, [props.rowModelType, virtualRowData, gridApi, customSetProps]); const onRowDataUpdated = useCallback(() => { // Handles preserving existing selections when rowData is updated in a callback const {selectedRows, rowData, rowModelType, filterModel} = props; - const {openGroups, gridApi} = state; + const {openGroups} = state; if (gridApi && !gridApi?.isDestroyed()) { dataUpdates.current = true; @@ -784,7 +778,7 @@ export function DashAgGrid(props) { props.rowData, props.rowModelType, props.filterModel, - state.gridApi, + gridApi, state.openGroups, dataUpdates.current, pauseSelections.current, @@ -805,7 +799,7 @@ export function DashAgGrid(props) { const onSelectionChanged = useCallback(() => { setTimeout(() => { if (!pauseSelections.current) { - const selectedRows = state.gridApi.getSelectedRows(); + const selectedRows = gridApi.getSelectedRows(); if (!equals(selectedRows, props.selectedRows)) { // Flag that the selection event was fired selectionEventFired.current = true; @@ -815,7 +809,7 @@ export function DashAgGrid(props) { }, 1); }, [ pauseSelections.current, - state.gridApi, + gridApi, props.selectedRows, selectionEventFired.current, customSetProps, @@ -843,18 +837,18 @@ export function DashAgGrid(props) { }, [getRowsParams.current, customSetProps]); const applyRowTransaction = useCallback( - (data, gridApi = state.gridApi) => { + (data, gridApiParam = gridApi) => { const {selectedRows} = props; if (data.async === false) { - gridApi.applyTransaction(data); + gridApiParam.applyTransaction(data); if (selectedRows) { setSelection(selectedRows); } } else { - gridApi.applyTransactionAsync(data); + gridApiParam.applyTransactionAsync(data); } }, - [state.gridApi, props.selectedRows, setSelection] + [gridApi, props.selectedRows, setSelection] ); const onGridReady = useCallback( @@ -877,17 +871,14 @@ export function DashAgGrid(props) { }); }); } - setState((prevState) => ({ - ...prevState, - gridApi: params.api, - })); + setGridApi(params.api); }, [ props.rowModelType, props.eventListeners, getDatasource, parseFunctionEvent, - setState, + setGridApi, ] ); @@ -968,12 +959,12 @@ export function DashAgGrid(props) { ]); const updateColumnState = useCallback(() => { - if (!state.gridApi || !state.mounted) { + if (!gridApi) { return; } - if (!state.gridApi.isDestroyed()) { + if (!gridApi.isDestroyed()) { var columnState = JSON.parse( - JSON.stringify(state.gridApi.getColumnState()) + JSON.stringify(gridApi.getColumnState()) ); customSetProps({ @@ -985,12 +976,11 @@ export function DashAgGrid(props) { updateColumnState: false, }); } - }, [state.gridApi, state.mounted, customSetProps]); + }, [gridApi, customSetProps]); const updateColumnWidths = useCallback( (setColumns = true) => { const {columnSize, columnSizeOptions} = props; - const {gridApi} = state; if (gridApi && !gridApi?.isDestroyed()) { const { keys, @@ -1026,7 +1016,7 @@ export function DashAgGrid(props) { [ props.columnSize, props.columnSizeOptions, - state.gridApi, + gridApi, customSetProps, updateColumnState, ] @@ -1036,21 +1026,14 @@ export function DashAgGrid(props) { if (props.columnSize === 'responsiveSizeToFit') { updateColumnWidths(); } - if (state.mounted) { - updateColumnState(); - } - }, [ - props.columnSize, - state.mounted, - updateColumnWidths, - updateColumnState, - ]); + updateColumnState(); + }, [props.columnSize, updateColumnWidths, updateColumnState]); const onColumnResized = useCallback(() => { - if (state.mounted && props.columnSize !== 'responsiveSizeToFit') { + if (props.columnSize !== 'responsiveSizeToFit') { updateColumnState(); } - }, [state.mounted, props.columnSize, updateColumnState]); + }, [props.columnSize, updateColumnState]); const onGridSizeChanged = useCallback(() => { if (props.columnSize === 'responsiveSizeToFit') { @@ -1059,12 +1042,12 @@ export function DashAgGrid(props) { }, [props.columnSize, updateColumnWidths]); const setColumnState = useCallback(() => { - if (!state.gridApi || props.updateColumnState) { + if (!gridApi || props.updateColumnState) { return; } if (state.columnState_push) { - state.gridApi.applyColumnState({ + gridApi.applyColumnState({ state: props.columnState, applyOrder: true, }); @@ -1073,31 +1056,25 @@ export function DashAgGrid(props) { columnState_push: false, })); } - }, [ - state.gridApi, - props.updateColumnState, - state.columnState_push, - setState, - ]); + }, [gridApi, props.updateColumnState, state.columnState_push, setState]); const exportDataAsCsv = useCallback( (csvExportParams, reset = true) => { - if (!state.gridApi) { + if (!gridApi) { return; } - state.gridApi.exportDataAsCsv(convertAllProps(csvExportParams)); + gridApi.exportDataAsCsv(convertAllProps(csvExportParams)); if (reset) { customSetProps({ exportDataAsCsv: false, }); } }, - [state.gridApi, convertAllProps, customSetProps] + [gridApi, convertAllProps, customSetProps] ); const paginationGoTo = useCallback( (reset = true) => { - const {gridApi} = state; if (!gridApi) { return; } @@ -1123,12 +1100,11 @@ export function DashAgGrid(props) { }); } }, - [state.gridApi, props.paginationGoTo, customSetProps] + [gridApi, props.paginationGoTo, customSetProps] ); const scrollTo = useCallback( (reset = true) => { - const {gridApi} = state; const {scrollTo, getRowId} = props; if (!gridApi) { return; @@ -1172,15 +1148,15 @@ export function DashAgGrid(props) { }); } }, - [state.gridApi, props.scrollTo, props.getRowId, customSetProps] + [gridApi, props.scrollTo, props.getRowId, customSetProps] ); const resetColumnState = useCallback( (reset = true) => { - if (!state.gridApi) { + if (!gridApi) { return; } - state.gridApi.resetColumnState(); + gridApi.resetColumnState(); if (reset) { customSetProps({ resetColumnState: false, @@ -1188,18 +1164,18 @@ export function DashAgGrid(props) { updateColumnState(); } }, - [state.gridApi, customSetProps, updateColumnState] + [gridApi, customSetProps, updateColumnState] ); const selectAll = useCallback( (opts, reset = true) => { - if (!state.gridApi) { + if (!gridApi) { return; } if (opts?.filtered) { - state.gridApi.selectAllFiltered(); + gridApi.selectAllFiltered(); } else { - state.gridApi.selectAll(); + gridApi.selectAll(); } if (reset) { customSetProps({ @@ -1207,31 +1183,31 @@ export function DashAgGrid(props) { }); } }, - [state.gridApi, customSetProps] + [gridApi, customSetProps] ); const deselectAll = useCallback( (reset = true) => { - if (!state.gridApi) { + if (!gridApi) { return; } - state.gridApi.deselectAll(); + gridApi.deselectAll(); if (reset) { customSetProps({ deselectAll: false, }); } }, - [state.gridApi, customSetProps] + [gridApi, customSetProps] ); const deleteSelectedRows = useCallback( (reset = true) => { - if (!state.gridApi) { + if (!gridApi) { return; } - const sel = state.gridApi.getSelectedRows(); - state.gridApi.applyTransaction({remove: sel}); + const sel = gridApi.getSelectedRows(); + gridApi.applyTransaction({remove: sel}); if (reset) { customSetProps({ deleteSelectedRows: false, @@ -1239,7 +1215,7 @@ export function DashAgGrid(props) { syncRowData(); } }, - [state.gridApi, customSetProps, syncRowData] + [gridApi, customSetProps, syncRowData] ); const buildArray = useCallback((arr1, arr2) => { @@ -1254,35 +1230,32 @@ export function DashAgGrid(props) { const rowTransaction = useCallback( (data) => { - const {rowTransaction, gridApi, mounted} = state; - if (mounted) { - if (gridApi && !gridApi?.isDestroyed()) { - if (rowTransaction) { - rowTransaction.forEach(applyRowTransaction); - setState((prevState) => ({ - ...prevState, - rowTransaction: null, - })); - } - applyRowTransaction(data); - customSetProps({ - rowTransaction: null, - }); - syncRowData(); - } else { + const {rowTransaction} = state; + if (gridApi && !gridApi?.isDestroyed()) { + if (rowTransaction) { + rowTransaction.forEach(applyRowTransaction); setState((prevState) => ({ ...prevState, - rowTransaction: rowTransaction - ? buildArray(rowTransaction, data) - : [JSON.parse(JSON.stringify(data))], + rowTransaction: null, })); } + applyRowTransaction(data); + customSetProps({ + rowTransaction: null, + }); + syncRowData(); + } else { + setState((prevState) => ({ + ...prevState, + rowTransaction: rowTransaction + ? buildArray(rowTransaction, data) + : [JSON.parse(JSON.stringify(data))], + })); } }, [ state.rowTransaction, - state.gridApi, - state.mounted, + gridApi, applyRowTransaction, setState, customSetProps, @@ -1308,11 +1281,7 @@ export function DashAgGrid(props) { } return () => { - setState((prevState) => ({ - ...prevState, - mounted: false, - gridApi: null, - })); + setGridApi(null); active.current = false; if (props.id) { delete agGridRefs[props.id]; @@ -1328,13 +1297,13 @@ export function DashAgGrid(props) { // 1. Handle gridApi changes and initialization useEffect(() => { - if (state.gridApi && state.gridApi !== prevGridApi) { + if (gridApi && gridApi !== prevGridApi) { const propsToSet = {}; updateColumnWidths(false); // Track expanded groups const groups = {}; - state.gridApi.forEachNode((node) => { + gridApi.forEachNode((node) => { if (node.expanded) { groups[node.key] = 1; } @@ -1343,7 +1312,7 @@ export function DashAgGrid(props) { // Handle row transactions if (state.rowTransaction) { state.rowTransaction.map((data) => - applyRowTransaction(data, state.gridApi) + applyRowTransaction(data, gridApi) ); setState((prev) => ({...prev, rowTransaction: null})); syncRowData(); @@ -1356,7 +1325,7 @@ export function DashAgGrid(props) { // Apply filter model if (!isEmpty(props.filterModel)) { - state.gridApi.setFilterModel(props.filterModel); + gridApi.setFilterModel(props.filterModel); } // Apply column state @@ -1408,14 +1377,13 @@ export function DashAgGrid(props) { onFilterChanged(true); setState((prev) => ({ ...prev, - mounted: true, openGroups: groups, columnState_push: false, })); updateColumnState(); } }, [ - state.gridApi, + gridApi, updateColumnWidths, state.rowTransaction, applyRowTransaction, @@ -1423,7 +1391,6 @@ export function DashAgGrid(props) { syncRowData, setSelection, props.selectedRows, - reference.current, onPaginationChanged, props.filterModel, props.columnState, @@ -1451,7 +1418,7 @@ export function DashAgGrid(props) { // 2. Handle columnState push changes useEffect(() => { if ( - state.gridApi && + gridApi && (!props.loading_state || prevProps?.loading_state?.is_loading) ) { if ( @@ -1464,7 +1431,7 @@ export function DashAgGrid(props) { }, [ props.columnState, props.loading_state, - state.gridApi, + gridApi, state.columnState_push, ]); @@ -1535,12 +1502,12 @@ export function DashAgGrid(props) { // 8. Handle prop changes when gridApi exists (but hasn't changed) useEffect(() => { - if (state.gridApi && state.gridApi === prevGridApi) { + if (gridApi && gridApi === prevGridApi) { if ( props.filterModel && - state.gridApi.getFilterModel() !== props.filterModel + gridApi.getFilterModel() !== props.filterModel ) { - state.gridApi.setFilterModel(props.filterModel); + gridApi.setFilterModel(props.filterModel); } if (props.paginationGoTo || props.paginationGoTo === 0) { @@ -1598,7 +1565,7 @@ export function DashAgGrid(props) { props.rowTransaction, props.updateColumnState, state.columnState_push, - state.gridApi, + gridApi, ]); // End of hooks @@ -1687,1387 +1654,6 @@ export function DashAgGrid(props) { ); } -export class DashAgGridOld extends Component { - constructor(props) { - super(props); - - this.onGridReady = this.onGridReady.bind(this); - this.onSelectionChanged = this.onSelectionChanged.bind(this); - this.onCellClicked = this.onCellClicked.bind(this); - this.onCellDoubleClicked = this.onCellDoubleClicked.bind(this); - this.onCellValueChanged = this.onCellValueChanged.bind(this); - this.afterCellValueChanged = this.afterCellValueChanged.bind(this); - this.onRowDataUpdated = this.onRowDataUpdated.bind(this); - this.onFilterChanged = this.onFilterChanged.bind(this); - this.onSortChanged = this.onSortChanged.bind(this); - this.onRowGroupOpened = this.onRowGroupOpened.bind(this); - this.onDisplayedColumnsChanged = - this.onDisplayedColumnsChanged.bind(this); - this.onColumnResized = this.onColumnResized.bind(this); - this.onGridSizeChanged = this.onGridSizeChanged.bind(this); - this.updateColumnWidths = this.updateColumnWidths.bind(this); - this.handleDynamicStyle = this.handleDynamicStyle.bind(this); - this.generateRenderer = this.generateRenderer.bind(this); - this.resetColumnState = this.resetColumnState.bind(this); - this.exportDataAsCsv = this.exportDataAsCsv.bind(this); - this.setSelection = this.setSelection.bind(this); - this.memoizeOne = this.memoizeOne.bind(this); - this.convertFunction = this.convertFunction.bind(this); - this.convertMaybeFunction = this.convertMaybeFunction.bind(this); - this.convertCol = this.convertCol.bind(this); - this.convertOne = this.convertOne.bind(this); - this.convertAllProps = this.convertAllProps.bind(this); - this.buildArray = this.buildArray.bind(this); - this.onAsyncTransactionsFlushed = - this.onAsyncTransactionsFlushed.bind(this); - this.onPaginationChanged = this.onPaginationChanged.bind(this); - this.scrollTo = this.scrollTo.bind(this); - - // Additional Exposure - this.selectAll = this.selectAll.bind(this); - this.deselectAll = this.deselectAll.bind(this); - this.updateColumnState = this.updateColumnState.bind(this); - this.deleteSelectedRows = this.deleteSelectedRows.bind(this); - this.rowTransaction = this.rowTransaction.bind(this); - this.getRowData = this.getRowData.bind(this); - this.syncRowData = this.syncRowData.bind(this); - this.isDatasourceLoadedForInfiniteScrolling = - this.isDatasourceLoadedForInfiniteScrolling.bind(this); - this.getDatasource = this.getDatasource.bind(this); - this.applyRowTransaction = this.applyRowTransaction.bind(this); - this.parseFunction = this.parseFunction.bind(this); - - const customComponents = window.dashAgGridComponentFunctions || {}; - const newComponents = map(this.generateRenderer, customComponents); - this.active = true; - this.customSetProps = (propsToSet) => { - if (this.active) { - this.props.setProps(propsToSet); - } - }; - this.setEventData = (data) => { - const timestamp = Date.now(); - this.customSetProps({ - eventData: { - data, - timestamp, - }, - }); - }; - - this.convertedPropCache = {}; - - this.state = { - ...this.props.parentState, - components: { - rowMenu: this.generateRenderer(RowMenuRenderer), - markdown: this.generateRenderer(MarkdownRenderer), - ...newComponents, - }, - rerender: 0, - openGroups: {}, - gridApi: null, - columnState_push: true, - }; - - this.selectionEventFired = false; - this.pauseSelections = false; - this.reference = React.createRef(); - this.pendingChanges = null; - this.dataUpdates = false; - } - - onPaginationChanged() { - const {gridApi} = this.state; - if (gridApi && !gridApi?.isDestroyed()) { - this.customSetProps({ - paginationInfo: { - isLastPageFound: gridApi.paginationIsLastPageFound(), - pageSize: gridApi.paginationGetPageSize(), - currentPage: gridApi.paginationGetCurrentPage(), - totalPages: gridApi.paginationGetTotalPages(), - rowCount: gridApi.paginationGetRowCount(), - }, - }); - } - } - - setSelection(selection, gridApi = this.state?.gridApi) { - const {getRowId} = this.props; - if (gridApi && selection && !gridApi?.isDestroyed()) { - this.pauseSelections = true; - const nodeData = []; - if (has('function', selection)) { - const test = this.parseFunction(selection.function); - - gridApi.forEachNode((node) => { - if (test(node)) { - nodeData.push(node); - } - }); - } else if (has('ids', selection)) { - const mapId = {}; - selection.ids.forEach((id) => { - mapId[id] = true; - }); - gridApi.forEachNode((node) => { - if (mapId[node.id]) { - nodeData.push(node); - } - }); - } else { - if (selection.length) { - if (getRowId) { - const parsedCondition = esprima.parse( - getRowId.replaceAll('params.data.', '') - ).body[0].expression; - const mapId = {}; - selection.forEach((params) => { - mapId[evaluate(parsedCondition, params)] = true; - }); - gridApi.forEachNode((node) => { - if (mapId[node.id]) { - nodeData.push(node); - } - }); - } else { - gridApi.forEachNode((node) => { - if (includes(node.data, selection)) { - nodeData.push(node); - } - }); - } - } - } - gridApi.deselectAll(); - gridApi.setNodesSelected({nodes: nodeData, newValue: true}); - setTimeout(() => { - this.pauseSelections = false; - }, 1); - } - } - - memoizeOne(converter, obj, target) { - const cache = this.convertedPropCache[target]; - if (cache && obj === cache[0]) { - return cache[1]; - } - const result = converter(obj, target); - this.convertedPropCache[target] = [obj, result]; - return result; - } - - convertFunction(func) { - // TODO: do we want this? ie allow the form `{function: }` even when - // we're expecting just a string? - if (has('function', func)) { - return this.convertFunction(func.function); - } - - try { - if (typeof func !== 'string') { - throw new Error('tried to parse non-string as function', func); - } - return this.parseFunction(func); - } catch (err) { - console.log(err); - } - return ''; - } - - convertFunctionNoParams(func) { - // TODO: do we want this? ie allow the form `{function: }` even when - // we're expecting just a string? - if (has('function', func)) { - return this.convertFunctionNoParams(func.function); - } - - try { - if (typeof func !== 'string') { - throw new Error('tried to parse non-string as function', func); - } - return this.parseFunctionNoParams(func); - } catch (err) { - console.log(err); - } - return ''; - } - - convertMaybeFunction(maybeFunc, stringsEvalContext) { - if (has('function', maybeFunc)) { - return this.convertFunction(maybeFunc.function); - } - - if ( - stringsEvalContext && - typeof maybeFunc === 'string' && - !this.props.dangerously_allow_code - ) { - xssMessage(stringsEvalContext); - return null; - } - return maybeFunc; - } - - convertMaybeFunctionNoParams(maybeFunc, stringsEvalContext) { - if (has('function', maybeFunc)) { - return this.convertFunctionNoParams(maybeFunc.function); - } - - if ( - stringsEvalContext && - typeof maybeFunc === 'string' && - !this.props.dangerously_allow_code - ) { - xssMessage(stringsEvalContext); - return null; - } - return maybeFunc; - } - - suppressGetDetail(colName) { - return (params) => { - params.successCallback(params.data[colName]); - }; - } - - callbackGetDetail = (params) => { - const {data} = params; - this.getDetailParams = params; - // Adding the current time in ms forces Dash to trigger a callback - // when the same row is closed and re-opened. - this.customSetProps({ - getDetailRequest: {data: data, requestTime: Date.now()}, - }); - }; - - convertCol(columnDef) { - if (typeof columnDef === 'function') { - return columnDef; - } - - return mapObjIndexed((value, target) => { - if ( - target === 'cellStyle' && - (has('styleConditions', value) || has('defaultStyle', value)) - ) { - return this.handleDynamicStyle(value); - } - if (OBJ_OF_FUNCTIONS[target]) { - return map(this.convertFunction, value); - } - if (COLUMN_DANGEROUS_FUNCTIONS[target]) { - // the second argument tells convertMaybeFunction - // that a plain string is dangerous, - // and provides the context for error reporting - const field = columnDef.field || columnDef.headerName; - return this.convertMaybeFunction(value, {target, field}); - } - if (COLUMN_MAYBE_FUNCTIONS[target]) { - return this.convertMaybeFunction(value); - } - if (COLUMN_MAYBE_FUNCTIONS_NO_PARAMS[target]) { - return this.convertMaybeFunctionNoParams(value); - } - if (COLUMN_ARRAY_NESTED_FUNCTIONS[target] && Array.isArray(value)) { - return value.map((c) => { - if (typeof c === 'object') { - return this.convertCol(c); - } - return c; - }); - } - if (OBJ_MAYBE_FUNCTION_OR_MAP_MAYBE_FUNCTIONS[target]) { - if ('function' in value) { - if (typeof value.function === 'string') { - return this.convertMaybeFunctionNoParams(value); - } - } - return map((v) => { - if (typeof v === 'object') { - if (typeof v.function === 'string') { - return this.convertMaybeFunctionNoParams(v); - } - return this.convertCol(v); - } - return v; - }, value); - } - if (COLUMN_NESTED_FUNCTIONS[target] && typeof value === 'object') { - return this.convertCol(value); - } - if (COLUMN_NESTED_OR_OBJ_OF_FUNCTIONS[target]) { - if (has('function', value)) { - return this.convertMaybeFunction(value); - } - return this.convertCol(value); - } - // not one of those categories - pass it straight through - return value; - }, columnDef); - } - - convertOne(value, target) { - if (value) { - if (target === 'columnDefs') { - return value.map(this.convertCol); - } - if (GRID_COLUMN_CONTAINERS[target]) { - return this.convertCol(value); - } - if (OBJ_MAYBE_FUNCTION_OR_MAP_MAYBE_FUNCTIONS[target]) { - if ('function' in value) { - if (typeof value.function === 'string') { - return this.convertMaybeFunctionNoParams(value); - } - } - return mapObjIndexed((v) => { - if (typeof v === 'object') { - if ('function' in v) { - if (typeof v.function === 'string') { - return this.convertMaybeFunctionNoParams(v); - } - } else { - return this.convertCol(v); - } - } - return v; - }, value); - } - if (GRID_NESTED_FUNCTIONS[target]) { - let adjustedVal = value; - if ('suppressCallback' in value) { - adjustedVal = { - ...adjustedVal, - getDetailRowData: value.suppressCallback - ? this.suppressGetDetail(value.detailColName) - : this.callbackGetDetail, - }; - } - if ('detailGridOptions' in value) { - adjustedVal = assocPath( - ['detailGridOptions', 'components'], - this.state.components, - adjustedVal - ); - } - return this.convertAllProps(adjustedVal); - } - if (GRID_DANGEROUS_FUNCTIONS[target]) { - return this.convertMaybeFunctionNoParams(value, {prop: target}); - } - if (target === 'getRowId') { - return this.convertFunction(value); - } - if ( - target === 'getRowStyle' && - (has('styleConditions', value) || has('defaultStyle', value)) - ) { - return this.handleDynamicStyle(value); - } - if (OBJ_OF_FUNCTIONS[target]) { - return map(this.convertFunction, value); - } - if (GRID_ONLY_FUNCTIONS[target]) { - return this.convertFunction(value); - } - if (GRID_MAYBE_FUNCTIONS[target]) { - return this.convertMaybeFunction(value); - } - if (GRID_MAYBE_FUNCTIONS_NO_PARAMS[target]) { - return this.convertMaybeFunctionNoParams(value); - } - - return value; - } - return value; - } - - convertAllProps(props) { - return mapObjIndexed( - (value, target) => this.memoizeOne(this.convertOne, value, target), - props - ); - } - - onFilterChanged() { - const {rowModelType} = this.props; - if (!this.state.gridApi) { - return; - } - const filterModel = this.state.gridApi.getFilterModel(); - const propsToSet = {filterModel}; - if (rowModelType === 'clientSide') { - propsToSet.virtualRowData = this.virtualRowData(); - } - - this.customSetProps(propsToSet); - } - - getRowData() { - const newRowData = []; - this.state.gridApi.forEachLeafNode((node) => { - newRowData.push(node.data); - }); - return newRowData; - } - - virtualRowData() { - const {rowModelType} = this.props; - const {gridApi} = this.state; - const virtualRowData = []; - if (rowModelType === 'clientSide' && gridApi) { - gridApi.forEachNodeAfterFilterAndSort((node) => { - if (node.data) { - virtualRowData.push(node.data); - } - }); - } - return virtualRowData; - } - - syncRowData() { - const {rowData} = this.props; - if (rowData) { - const virtualRowData = this.virtualRowData(); - const newRowData = this.getRowData(); - if (rowData !== newRowData) { - this.customSetProps({rowData: newRowData, virtualRowData}); - } else { - this.customSetProps({virtualRowData}); - } - } - } - - onSortChanged() { - const {rowModelType} = this.props; - const propsToSet = {}; - if (rowModelType === 'clientSide') { - propsToSet.virtualRowData = this.virtualRowData(); - } - if (!this.state.gridApi.isDestroyed()) { - propsToSet.columnState = JSON.parse( - JSON.stringify(this.state.gridApi.getColumnState()) - ); - } - this.customSetProps(propsToSet); - } - - componentDidMount() { - const {id} = this.props; - if (id) { - agGridRefs[id] = this.reference.current; - eventBus.dispatch(id); - } - } - - componentWillUnmount() { - this.setState({mounted: false, gridApi: null}); - this.active = false; - if (this.props.id) { - delete agGridRefs[this.props.id]; - eventBus.remove(this.props.id); - } - } - - shouldComponentUpdate(nextProps, nextState) { - const {gridApi} = this.state; - const {columnState, filterModel, selectedRows} = nextProps; - - if ( - !equals( - {...omit(OMIT_PROP_RENDER, nextProps)}, - {...omit(OMIT_PROP_RENDER, this.props)} - ) && - (nextProps?.dashRenderType !== 'internal' || - !equals(nextProps.rowData, this.props.rowData) || - !equals(nextProps.selectedRows, this.props.selectedRows)) - ) { - return true; - } - if ( - !equals( - {...omit(OMIT_STATE_RENDER, nextState)}, - {...omit(OMIT_STATE_RENDER, this.state)} - ) - ) { - return true; - } - if (gridApi && !gridApi?.isDestroyed()) { - if (nextProps?.dashRenderType !== 'internal') { - if (columnState) { - if (columnState !== this.props.columnState) { - return true; - } - } - if (filterModel) { - if (!equals(filterModel, gridApi.getFilterModel())) { - return true; - } - } - } - if (selectedRows) { - if (!equals(selectedRows, gridApi.getSelectedRows())) { - return true; - } - } - return false; - } - return false; - } - - componentDidUpdate(prevProps, prevState) { - const { - selectedRows, - getDetailResponse, - detailCellRendererParams, - masterDetail, - id, - resetColumnState, - csvExportParams, - exportDataAsCsv, - selectAll, - deselectAll, - deleteSelectedRows, - filterModel, - columnState, - columnSize, - paginationGoTo, - scrollTo, - rowTransaction, - updateColumnState, - loading_state, - } = this.props; - - if ( - this.state.gridApi && - (!loading_state || prevProps.loading_state?.is_loading) - ) { - if ( - this.props.columnState !== prevProps.columnState && - !this.state.columnState_push - ) { - this.setState({columnState_push: true}); - } - } - - if (id !== prevProps.id) { - if (id) { - agGridRefs[id] = this.reference.current; - eventBus.dispatch(id); - } - if (prevProps.id) { - delete agGridRefs[prevProps.id]; - eventBus.remove(prevProps.id); - } - } - - if (this.state.gridApi && this.state.gridApi !== prevState.gridApi) { - const propsToSet = {}; - this.updateColumnWidths(false); - - const groups = {}; - this.state.gridApi.forEachNode((node) => { - if (node.expanded) { - groups[node.key] = 1; - } - }); - - if (this.state.rowTransaction) { - this.state.rowTransaction.map((data) => - this.applyRowTransaction(data, this.state.gridApi) - ); - this.setState({rowTransaction: null}); - this.syncRowData(); - } - - // Handles applying selections when a selection was persisted by Dash - this.setSelection(selectedRows); - - if (this.reference.current.props.pagination) { - this.onPaginationChanged(); - } - - if (!isEmpty(filterModel)) { - this.state.gridApi.setFilterModel(filterModel); - } - - if (columnState) { - this.setColumnState(); - } - - if (paginationGoTo || paginationGoTo === 0) { - this.paginationGoTo(false); - propsToSet.paginationGoTo = null; - } - - if (scrollTo) { - this.scrollTo(false); - propsToSet.scrollTo = null; - } - - if (resetColumnState) { - this.resetColumnState(false); - propsToSet.resetColumnState = false; - } - - if (exportDataAsCsv) { - this.exportDataAsCsv(csvExportParams, false); - propsToSet.exportDataAsCsv = false; - } - - if (selectAll) { - this.selectAll(selectAll, false); - propsToSet.selectAll = false; - } - - if (deselectAll) { - this.deselectAll(false); - propsToSet.deselectAll = false; - } - - if (deleteSelectedRows) { - this.deleteSelectedRows(false); - propsToSet.deleteSelectedRows = false; - } - - if (!isEmpty(propsToSet)) { - this.customSetProps(propsToSet); - } - // Hydrate virtualRowData - this.onFilterChanged(true); - this.setState({ - mounted: true, - openGroups: groups, - columnState_push: false, - }); - this.updateColumnState(); - } - - if (this.isDatasourceLoadedForInfiniteScrolling()) { - const {rowData, rowCount} = this.props.getRowsResponse; - this.getRowsParams.successCallback(rowData, rowCount); - this.customSetProps({getRowsResponse: null}); - } - - if ( - masterDetail && - !detailCellRendererParams.suppressCallback && - getDetailResponse - ) { - this.getDetailParams.successCallback(getDetailResponse); - this.customSetProps({getDetailResponse: null}); - } - // Call the API to select rows unless the update was triggered by a selection made in the UI - if ( - !equals(selectedRows, prevProps.selectedRows) && - // eslint-disable-next-line no-undefined - !(typeof loading_state !== 'undefined' - ? loading_state && this.selectionEventFired - : this.selectionEventFired) - ) { - if (!this.dataUpdates) { - setTimeout(() => { - if (!this.dataUpdates) { - this.setSelection(selectedRows); - } - }, 10); - } - } - - this.dataUpdates = false; - - if (this.state.gridApi && this.state.gridApi === prevState.gridApi) { - if (filterModel) { - if (this.state.gridApi) { - if (this.state.gridApi.getFilterModel() !== filterModel) { - this.state.gridApi.setFilterModel(filterModel); - } - } - } - - if (paginationGoTo || paginationGoTo === 0) { - this.paginationGoTo(); - } - - if (scrollTo) { - this.scrollTo(); - } - - if (columnSize) { - this.updateColumnWidths(); - } - - if (resetColumnState) { - this.resetColumnState(); - } - - if (exportDataAsCsv) { - this.exportDataAsCsv(csvExportParams); - } - - if (selectAll) { - this.selectAll(selectAll); - } - - if (deselectAll) { - this.deselectAll(); - } - - if (deleteSelectedRows) { - this.deleteSelectedRows(); - } - - if (rowTransaction) { - this.rowTransaction(rowTransaction); - } - if (updateColumnState) { - this.updateColumnState(); - } else if (this.state.columnState_push) { - this.setColumnState(); - } - } - - // Reset selection event flag - this.selectionEventFired = false; - } - - onRowDataUpdated() { - // Handles preserving existing selections when rowData is updated in a callback - const {selectedRows, rowData, rowModelType, filterModel} = this.props; - const {openGroups, gridApi} = this.state; - - if (gridApi && !gridApi?.isDestroyed()) { - this.dataUpdates = true; - this.pauseSelections = true; - this.setSelection(selectedRows); - - if (rowData && rowModelType === 'clientSide') { - const virtualRowData = this.virtualRowData(); - - this.customSetProps({virtualRowData}); - } - - // When the rowData is updated, reopen any row groups if they previously existed in the table - // Iterate through all nodes in the grid. Unfortunately there's no way to iterate through only nodes representing groups - if (!isEmpty(openGroups)) { - gridApi.forEachNode((node) => { - // Check if it's a group row based on whether it has the __hasChildren prop - if (node.__hasChildren) { - // If the key for the node (i.e. the group name) is the same as an - if (openGroups[node.key]) { - gridApi.setRowNodeExpanded(node, true); - } - } - }); - } - if (!isEmpty(filterModel)) { - gridApi.setFilterModel(filterModel); - } - setTimeout(() => { - this.dataUpdates = false; - }, 1); - } - } - - onRowGroupOpened(e) { - this.setState(({openGroups}) => ({ - openGroups: e.expanded - ? assoc(e.node.key, 1, openGroups) - : omit([e.node.key], openGroups), - })); - } - - onSelectionChanged() { - setTimeout(() => { - if (!this.pauseSelections) { - const selectedRows = this.state.gridApi.getSelectedRows(); - if (!equals(selectedRows, this.props.selectedRows)) { - // Flag that the selection event was fired - this.selectionEventFired = true; - this.customSetProps({selectedRows}); - } - } - }, 1); - } - - isDatasourceLoadedForInfiniteScrolling() { - return ( - this.props.rowModelType === 'infinite' && - this.getRowsParams && - this.props.getRowsResponse - ); - } - - getDatasource() { - const self = this; - - return { - getRows(params) { - self.getRowsParams = params; - self.customSetProps({getRowsRequest: params}); - }, - - destroy() { - self.getRowsParams = null; - }, - }; - } - - applyRowTransaction(data, gridApi = this.state.gridApi) { - const {selectedRows} = this.props; - if (data.async === false) { - gridApi.applyTransaction(data); - if (selectedRows) { - this.setSelection(selectedRows); - } - } else { - gridApi.applyTransactionAsync(data); - } - } - - onGridReady(params) { - // Applying Infinite Row Model - // see: https://www.ag-grid.com/javascript-grid/infinite-scrolling/ - const {rowModelType, eventListeners} = this.props; - - if (rowModelType === 'infinite') { - params.api.setGridOption('datasource', this.getDatasource()); - } - - if (eventListeners) { - Object.entries(eventListeners).map(([key, v]) => { - v.map((func) => { - params.api.addEventListener( - key, - this.parseFunctionEvent(func) - ); - }); - }); - } - - this.setState({ - gridApi: params.api, - }); - } - - onCellClicked({value, column: {colId}, rowIndex, node}) { - const timestamp = Date.now(); - this.customSetProps({ - cellClicked: {value, colId, rowIndex, rowId: node.id, timestamp}, - }); - } - - onCellDoubleClicked({value, column: {colId}, rowIndex, node}) { - const timestamp = Date.now(); - this.customSetProps({ - cellDoubleClicked: { - value, - colId, - rowIndex, - rowId: node.id, - timestamp, - }, - }); - } - - onCellValueChanged({ - oldValue, - value, - column: {colId}, - rowIndex, - data, - node, - }) { - const timestamp = Date.now(); - // Collect new change. - const newChange = { - rowIndex, - rowId: node.id, - data, - oldValue, - value, - colId, - timestamp, - }; - // Append it to current change session. - if (!this.pendingCellValueChanges) { - this.pendingCellValueChanges = [newChange]; - } else { - this.pendingCellValueChanges.push(newChange); - } - } - - afterCellValueChanged() { - // Guard against multiple invocations of the same change session. - if (!this.pendingCellValueChanges) { - return; - } - // Send update(s) for current change session to Dash. - const virtualRowData = this.virtualRowData(); - this.customSetProps({ - cellValueChanged: this.pendingCellValueChanges, - virtualRowData, - }); - this.syncRowData(); - // Mark current change session as ended. - this.pendingCellValueChanges = null; - } - - onDisplayedColumnsChanged() { - if (this.props.columnSize === 'responsiveSizeToFit') { - this.updateColumnWidths(); - } - if (this.state.mounted) { - this.updateColumnState(); - } - } - - onColumnResized() { - if ( - this.state.mounted && - this.props.columnSize !== 'responsiveSizeToFit' - ) { - this.updateColumnState(); - } - } - - onGridSizeChanged() { - if (this.props.columnSize === 'responsiveSizeToFit') { - this.updateColumnWidths(); - } - } - - updateColumnWidths(setColumns = true) { - const {columnSize, columnSizeOptions} = this.props; - const {gridApi} = this.state; - if (gridApi && !gridApi?.isDestroyed()) { - const { - keys, - skipHeader, - defaultMinWidth, - defaultMaxWidth, - columnLimits, - } = columnSizeOptions || {}; - if (columnSize === 'autoSize') { - if (keys) { - gridApi.autoSizeColumns(keys, skipHeader); - } else { - gridApi.autoSizeAllColumns(skipHeader); - } - } else if ( - columnSize === 'sizeToFit' || - columnSize === 'responsiveSizeToFit' - ) { - gridApi.sizeColumnsToFit({ - defaultMinWidth, - defaultMaxWidth, - columnLimits, - }); - } - if (columnSize !== 'responsiveSizeToFit') { - this.customSetProps({columnSize: null}); - } - if (setColumns) { - this.updateColumnState(); - } - } - } - - parseFunction = memoizeWith(String, (funcString) => { - const parsedCondition = esprima.parse(funcString).body[0].expression; - const context = { - d3, - dash_clientside, - ...customFunctions, - ...window.dashAgGridFunctions, - }; - return (params) => evaluate(parsedCondition, {params, ...context}); - }); - - parseFunctionEvent = memoizeWith(String, (funcString) => { - const parsedCondition = esprima.parse(funcString).body[0].expression; - const context = { - d3, - dash_clientside, - ...customFunctions, - ...window.dashAgGridFunctions, - setGridProps: this.customSetProps, - setEventData: this.setEventData, - }; - return (params) => evaluate(parsedCondition, {params, ...context}); - }); - - parseFunctionNoParams = memoizeWith(String, (funcString) => { - const parsedCondition = esprima.parse(funcString).body[0].expression; - const context = { - d3, - ...customFunctions, - ...window.dashAgGridFunctions, - }; - return evaluate(parsedCondition, context); - }); - - /** - * @params AG-Grid Styles rules attribute. - * Cells: https://www.ag-grid.com/react-grid/cell-styles/#cell-style-cell-class--cell-class-rules-params - * Rows: https://www.ag-grid.com/react-grid/row-styles/#row-style-row-class--row-class-rules-params - */ - handleDynamicStyle(cellStyle) { - const {styleConditions, defaultStyle} = cellStyle; - const _defaultStyle = defaultStyle || null; - - if (styleConditions && styleConditions.length) { - const tests = styleConditions.map(({condition, style}) => ({ - test: this.parseFunction(condition), - style, - })); - return (params) => { - for (const {test, style} of tests) { - if (params) { - if (params.node.id && params.node.id !== null) { - if (test(params)) { - return style; - } - } - } - } - return _defaultStyle; - }; - } - - return _defaultStyle; - } - - generateRenderer(Renderer) { - const {dangerously_allow_code} = this.props; - - return (props) => ( - { - this.customSetProps({ - cellRendererData: { - value, - colId: props.column.colId, - rowIndex: props.node.sourceRowIndex, - rowId: props.node.id, - timestamp: Date.now(), - }, - }); - }} - dangerously_allow_code={dangerously_allow_code} - {...props} - > - ); - } - - setColumnState() { - if (!this.state.gridApi || this.props.updateColumnState) { - return; - } - - if (this.state.columnState_push) { - this.state.gridApi.applyColumnState({ - state: this.props.columnState, - applyOrder: true, - }); - this.setState({columnState_push: false}); - } - } - - // Event actions that reset - exportDataAsCsv(csvExportParams, reset = true) { - if (!this.state.gridApi) { - return; - } - this.state.gridApi.exportDataAsCsv( - this.convertAllProps(csvExportParams) - ); - if (reset) { - this.customSetProps({ - exportDataAsCsv: false, - }); - } - } - - paginationGoTo(reset = true) { - const {gridApi} = this.state; - if (!gridApi) { - return; - } - switch (this.props.paginationGoTo) { - case 'next': - gridApi.paginationGoToNextPage(); - break; - case 'previous': - gridApi.paginationGoToPreviousPage(); - break; - case 'last': - gridApi.paginationGoToLastPage(); - break; - case 'first': - gridApi.paginationGoToFirstPage(); - break; - default: - gridApi.paginationGoToPage(this.props.paginationGoTo); - } - if (reset) { - this.customSetProps({ - paginationGoTo: null, - }); - } - } - - scrollTo(reset = true) { - const {gridApi} = this.state; - const {scrollTo, getRowId} = this.props; - if (!gridApi) { - return; - } - const rowPosition = scrollTo.rowPosition ? scrollTo.rowPosition : 'top'; - if (scrollTo.rowIndex || scrollTo.rowIndex === 0) { - gridApi.ensureIndexVisible(scrollTo.rowIndex, rowPosition); - } else if (typeof scrollTo.rowId !== 'undefined') { - const node = gridApi.getRowNode(scrollTo.rowId); - gridApi.ensureNodeVisible(node, rowPosition); - } else if (scrollTo.data) { - if (getRowId) { - const parsedCondition = esprima.parse( - getRowId.replaceAll('params.data.', '') - ).body[0].expression; - const node = gridApi.getRowNode( - evaluate(parsedCondition, scrollTo.data) - ); - gridApi.ensureNodeVisible(node, rowPosition); - } else { - let scrolled = false; - gridApi.forEachNodeAfterFilterAndSort((node) => { - if (!scrolled && equals(node.data, scrollTo.data)) { - gridApi.ensureNodeVisible(node, rowPosition); - scrolled = true; - } - }); - } - } - if (scrollTo.column) { - const columnPosition = scrollTo.columnPosition - ? scrollTo.columnPosition - : 'auto'; - gridApi.ensureColumnVisible(scrollTo.column, columnPosition); - } - if (reset) { - this.customSetProps({ - scrollTo: null, - }); - } - } - - resetColumnState(reset = true) { - if (!this.state.gridApi) { - return; - } - this.state.gridApi.resetColumnState(); - if (reset) { - this.customSetProps({ - resetColumnState: false, - }); - this.updateColumnState(); - } - } - - selectAll(opts, reset = true) { - if (!this.state.gridApi) { - return; - } - if (opts?.filtered) { - this.state.gridApi.selectAllFiltered(); - } else { - this.state.gridApi.selectAll(); - } - if (reset) { - this.customSetProps({ - selectAll: false, - }); - } - } - - deselectAll(reset = true) { - if (!this.state.gridApi) { - return; - } - this.state.gridApi.deselectAll(); - if (reset) { - this.customSetProps({ - deselectAll: false, - }); - } - } - - deleteSelectedRows(reset = true) { - if (!this.state.gridApi) { - return; - } - const sel = this.state.gridApi.getSelectedRows(); - this.state.gridApi.applyTransaction({remove: sel}); - if (reset) { - this.customSetProps({ - deleteSelectedRows: false, - }); - this.syncRowData(); - } - } - - // end event actions - - updateColumnState() { - if (!this.state.gridApi || !this.state.mounted) { - return; - } - if (!this.state.gridApi.isDestroyed()) { - var columnState = JSON.parse( - JSON.stringify(this.state.gridApi.getColumnState()) - ); - - this.customSetProps({ - columnState, - updateColumnState: false, - }); - } else { - this.customSetProps({ - updateColumnState: false, - }); - } - } - - buildArray(arr1, arr2) { - if (arr1) { - if (!arr1.includes(arr2)) { - return [...arr1, arr2]; - } - return arr1; - } - return [JSON.parse(JSON.stringify(arr2))]; - } - - rowTransaction(data) { - const {rowTransaction, gridApi, mounted} = this.state; - if (mounted) { - if (gridApi && !gridApi?.isDestroyed()) { - if (rowTransaction) { - rowTransaction.forEach(this.applyRowTransaction); - this.setState({rowTransaction: null}); - } - this.applyRowTransaction(data); - this.customSetProps({ - rowTransaction: null, - }); - this.syncRowData(); - } else { - this.setState({ - rowTransaction: rowTransaction - ? this.buildArray(rowTransaction, data) - : [JSON.parse(JSON.stringify(data))], - }); - } - } - } - - onAsyncTransactionsFlushed() { - const {selectedRows} = this.props; - if (selectedRows) { - this.setSelection(selectedRows); - } - this.syncRowData(); - } - - render() { - const {id, style, className, dashGridOptions, ...restProps} = - this.props; - - const passingProps = pick(PASSTHRU_PROPS, restProps); - - const convertedProps = this.convertAllProps( - omit(NO_CONVERT_PROPS, {...dashGridOptions, ...restProps}) - ); - - let alignedGrids; - if (dashGridOptions) { - if ('alignedGrids' in dashGridOptions) { - alignedGrids = []; - const addGrid = (id) => { - const strId = stringifyId(id); - eventBus.on(this.props.id, strId, () => { - this.setState(({rerender}) => ({ - rerender: rerender + 1, - })); - }); - if (!agGridRefs[strId]) { - agGridRefs[strId] = {api: null}; - } - alignedGrids.push(agGridRefs[strId]); - }; - eventBus.remove(this.props.id); - if (Array.isArray(dashGridOptions.alignedGrids)) { - dashGridOptions.alignedGrids.map(addGrid); - } else { - addGrid(dashGridOptions.alignedGrids); - } - } - } - - return ( -
- -
- ); - } -} - DashAgGrid.defaultProps = _defaultProps; DashAgGrid.propTypes = {parentState: PropTypes.any, ..._propTypes}; @@ -3077,5 +1663,4 @@ export const defaultProps = DashAgGrid.defaultProps; var dagfuncs = (window.dash_ag_grid = window.dash_ag_grid || {}); dagfuncs.useGridFilter = useGridFilter; -// export default DashAgGridOld; export default DashAgGrid; From 415ed1226401cc0fcd01e1152f4446234464d7aa Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 30 Jun 2025 12:01:09 -0600 Subject: [PATCH 05/24] refactor "openGroups" and "rerender" into their own states --- src/lib/fragments/AgGrid.react.js | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index fab928dc..c8146d59 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -268,6 +268,8 @@ export function DashAgGrid(props) { const newComponents = map(generateRenderer, customComponents); const [gridApi, setGridApi] = useState(null); + const [, forceRerender] = useState({}); + const [openGroups, setOpenGroups] = useState({}); const [state, setState] = useState({ ...props.parentState, components: { @@ -275,8 +277,6 @@ export function DashAgGrid(props) { markdown: generateRenderer(MarkdownRenderer), ...newComponents, }, - rerender: 0, - openGroups: {}, columnState_push: true, }); @@ -740,7 +740,6 @@ export function DashAgGrid(props) { const onRowDataUpdated = useCallback(() => { // Handles preserving existing selections when rowData is updated in a callback const {selectedRows, rowData, rowModelType, filterModel} = props; - const {openGroups} = state; if (gridApi && !gridApi?.isDestroyed()) { dataUpdates.current = true; @@ -779,7 +778,7 @@ export function DashAgGrid(props) { props.rowModelType, props.filterModel, gridApi, - state.openGroups, + openGroups, dataUpdates.current, pauseSelections.current, setSelection, @@ -788,12 +787,11 @@ export function DashAgGrid(props) { ]); const onRowGroupOpened = useCallback((e) => { - setState((prevState) => ({ - ...prevState, - openGroups: e.expanded - ? assoc(e.node.key, 1, prevState.openGroups) - : omit([e.node.key], prevState.openGroups), - })); + setOpenGroups((prevOpenGroups) => + e.expanded + ? assoc(e.node.key, 1, prevOpenGroups) + : omit([e.node.key], prevOpenGroups) + ); }, []); const onSelectionChanged = useCallback(() => { @@ -1375,9 +1373,9 @@ export function DashAgGrid(props) { // Hydrate virtualRowData onFilterChanged(true); + setOpenGroups(groups); setState((prev) => ({ ...prev, - openGroups: groups, columnState_push: false, })); updateColumnState(); @@ -1585,10 +1583,7 @@ export function DashAgGrid(props) { const addGrid = (id) => { const strId = stringifyId(id); eventBus.on(props.id, strId, () => { - setState((prevState) => ({ - ...prevState, - rerender: prevState.rerender + 1, - })); + forceRerender({}); }); if (!agGridRefs[strId]) { agGridRefs[strId] = {api: null}; From 5d775b02dabfc6673e89416bc59ab5bc8c88f92a Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 30 Jun 2025 12:45:16 -0600 Subject: [PATCH 06/24] Move columnState, rowTransactionState, parentState, components all into their own states --- src/lib/fragments/AgGrid.react.js | 80 +++++++++++++------------------ 1 file changed, 33 insertions(+), 47 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index c8146d59..de6d44dc 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -270,15 +270,18 @@ export function DashAgGrid(props) { const [gridApi, setGridApi] = useState(null); const [, forceRerender] = useState({}); const [openGroups, setOpenGroups] = useState({}); - const [state, setState] = useState({ - ...props.parentState, - components: { + const [columnState_push, setColumnState_push] = useState(true); + const [rowTransactionState, setRowTransactionState] = useState(null); + const [parentState] = useState(props.parentState || {}); + + const components = useMemo( + () => ({ rowMenu: generateRenderer(RowMenuRenderer), markdown: generateRenderer(MarkdownRenderer), ...newComponents, - }, - columnState_push: true, - }); + }), + [generateRenderer, newComponents] + ); const prevProps = usePrevious(props); const prevGridApi = usePrevious(gridApi); @@ -609,7 +612,7 @@ export function DashAgGrid(props) { if ('detailGridOptions' in value) { adjustedVal = assocPath( ['detailGridOptions', 'components'], - state.components, + components, adjustedVal ); } @@ -650,7 +653,7 @@ export function DashAgGrid(props) { convertMaybeFunctionNoParams, suppressGetDetail, callbackGetDetail, - state.components, + components, convertAllPropsRef.current, convertFunction, handleDynamicStyle, @@ -787,7 +790,7 @@ export function DashAgGrid(props) { ]); const onRowGroupOpened = useCallback((e) => { - setOpenGroups((prevOpenGroups) => + setOpenGroups((prevOpenGroups) => e.expanded ? assoc(e.node.key, 1, prevOpenGroups) : omit([e.node.key], prevOpenGroups) @@ -1044,17 +1047,14 @@ export function DashAgGrid(props) { return; } - if (state.columnState_push) { + if (columnState_push) { gridApi.applyColumnState({ state: props.columnState, applyOrder: true, }); - setState((prevState) => ({ - ...prevState, - columnState_push: false, - })); + setColumnState_push(false); } - }, [gridApi, props.updateColumnState, state.columnState_push, setState]); + }, [gridApi, props.updateColumnState, columnState_push]); const exportDataAsCsv = useCallback( (csvExportParams, reset = true) => { @@ -1228,14 +1228,11 @@ export function DashAgGrid(props) { const rowTransaction = useCallback( (data) => { - const {rowTransaction} = state; + const rowTransaction = rowTransactionState; if (gridApi && !gridApi?.isDestroyed()) { if (rowTransaction) { rowTransaction.forEach(applyRowTransaction); - setState((prevState) => ({ - ...prevState, - rowTransaction: null, - })); + setRowTransactionState(null); } applyRowTransaction(data); customSetProps({ @@ -1243,19 +1240,18 @@ export function DashAgGrid(props) { }); syncRowData(); } else { - setState((prevState) => ({ - ...prevState, - rowTransaction: rowTransaction + setRowTransactionState( + rowTransaction ? buildArray(rowTransaction, data) - : [JSON.parse(JSON.stringify(data))], - })); + : [JSON.parse(JSON.stringify(data))] + ); } }, [ - state.rowTransaction, + rowTransactionState, gridApi, applyRowTransaction, - setState, + setRowTransactionState, customSetProps, syncRowData, buildArray, @@ -1308,11 +1304,11 @@ export function DashAgGrid(props) { }); // Handle row transactions - if (state.rowTransaction) { - state.rowTransaction.map((data) => + if (rowTransactionState) { + rowTransactionState.map((data) => applyRowTransaction(data, gridApi) ); - setState((prev) => ({...prev, rowTransaction: null})); + setRowTransactionState(null); syncRowData(); } @@ -1374,18 +1370,13 @@ export function DashAgGrid(props) { // Hydrate virtualRowData onFilterChanged(true); setOpenGroups(groups); - setState((prev) => ({ - ...prev, - columnState_push: false, - })); + setColumnState_push(false); updateColumnState(); } }, [ gridApi, updateColumnWidths, - state.rowTransaction, applyRowTransaction, - setState, syncRowData, setSelection, props.selectedRows, @@ -1421,17 +1412,12 @@ export function DashAgGrid(props) { ) { if ( props.columnState !== prevProps?.columnState && - !state.columnState_push + !columnState_push ) { - setState((prev) => ({...prev, columnState_push: true})); + setColumnState_push(true); } } - }, [ - props.columnState, - props.loading_state, - gridApi, - state.columnState_push, - ]); + }, [props.columnState, props.loading_state, gridApi, columnState_push]); // 3. Handle ID changes useEffect(() => { @@ -1546,7 +1532,7 @@ export function DashAgGrid(props) { if (props.updateColumnState) { updateColumnState(); - } else if (state.columnState_push) { + } else if (columnState_push) { setColumnState(); } } @@ -1562,7 +1548,7 @@ export function DashAgGrid(props) { props.deleteSelectedRows, props.rowTransaction, props.updateColumnState, - state.columnState_push, + columnState_push, gridApi, ]); @@ -1641,7 +1627,7 @@ export function DashAgGrid(props) { onGridSizeChanged, RESIZE_DEBOUNCE_MS )} - components={state.components} + components={components} {...passingProps} {...convertedProps} > From 47161199beddc436217677bc2f112acccd12a6c6 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Wed, 2 Jul 2025 09:18:16 -0600 Subject: [PATCH 07/24] Separate large effects into smaller ones --- src/lib/fragments/AgGrid.react.js | 231 +++++++++++++++++++----------- 1 file changed, 147 insertions(+), 84 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index de6d44dc..50901344 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1289,45 +1289,68 @@ export function DashAgGrid(props) { setSelection(props.selectedRows); }, [props.selectedRows]); - // 1. Handle gridApi changes and initialization + // 1. Handle gridApi initialization - basic setup useEffect(() => { if (gridApi && gridApi !== prevGridApi) { - const propsToSet = {}; updateColumnWidths(false); - // Track expanded groups + // Handle pagination initialization + if (reference.current.props.pagination) { + onPaginationChanged(); + } + } + }, [gridApi, prevGridApi, updateColumnWidths, onPaginationChanged]); + + // 1a. Handle gridApi initialization - expanded groups tracking + useEffect(() => { + if (gridApi && gridApi !== prevGridApi) { const groups = {}; gridApi.forEachNode((node) => { if (node.expanded) { groups[node.key] = 1; } }); + setOpenGroups(groups); + } + }, [gridApi, prevGridApi, setOpenGroups]); - // Handle row transactions - if (rowTransactionState) { - rowTransactionState.map((data) => - applyRowTransaction(data, gridApi) - ); - setRowTransactionState(null); - syncRowData(); - } + // 1b. Handle gridApi initialization - row transactions + useEffect(() => { + if (gridApi && gridApi !== prevGridApi && rowTransactionState) { + rowTransactionState.map((data) => + applyRowTransaction(data, gridApi) + ); + setRowTransactionState(null); + syncRowData(); + } + }, [ + gridApi, + prevGridApi, + rowTransactionState, + applyRowTransaction, + setRowTransactionState, + syncRowData, + ]); - // Handle pagination - if (reference.current.props.pagination) { - onPaginationChanged(); - } + // 1c. Handle gridApi initialization - filter model application + useEffect(() => { + if (gridApi && gridApi !== prevGridApi && !isEmpty(props.filterModel)) { + gridApi.setFilterModel(props.filterModel); + } + }, [gridApi, prevGridApi, props.filterModel]); - // Apply filter model - if (!isEmpty(props.filterModel)) { - gridApi.setFilterModel(props.filterModel); - } + // 1d. Handle gridApi initialization - column state application + useEffect(() => { + if (gridApi && gridApi !== prevGridApi && props.columnState) { + setColumnState(); + } + }, [gridApi, prevGridApi, props.columnState, setColumnState]); - // Apply column state - if (props.columnState) { - setColumnState(); - } + // 1e. Handle gridApi initialization - action props with cleanup + useEffect(() => { + if (gridApi && gridApi !== prevGridApi) { + const propsToSet = {}; - // Handle various action props if (props.paginationGoTo || props.paginationGoTo === 0) { paginationGoTo(false); propsToSet.paginationGoTo = null; @@ -1366,41 +1389,41 @@ export function DashAgGrid(props) { if (!isEmpty(propsToSet)) { customSetProps(propsToSet); } - - // Hydrate virtualRowData - onFilterChanged(true); - setOpenGroups(groups); - setColumnState_push(false); - updateColumnState(); } }, [ gridApi, - updateColumnWidths, - applyRowTransaction, - syncRowData, - setSelection, - props.selectedRows, - onPaginationChanged, - props.filterModel, - props.columnState, - setColumnState, + prevGridApi, props.paginationGoTo, - paginationGoTo, props.scrollTo, - scrollTo, props.resetColumnState, - resetColumnState, props.exportDataAsCsv, - exportDataAsCsv, props.csvExportParams, props.selectAll, - selectAll, props.deselectAll, - deselectAll, props.deleteSelectedRows, + paginationGoTo, + scrollTo, + resetColumnState, + exportDataAsCsv, + selectAll, + deselectAll, deleteSelectedRows, customSetProps, + ]); + + // 1f. Handle gridApi initialization - finalization + useEffect(() => { + if (gridApi && gridApi !== prevGridApi) { + // Hydrate virtualRowData and finalize setup + onFilterChanged(true); + setColumnState_push(false); + updateColumnState(); + } + }, [ + gridApi, + prevGridApi, onFilterChanged, + setColumnState_push, updateColumnState, ]); @@ -1484,72 +1507,112 @@ export function DashAgGrid(props) { dataUpdates.current = false; }); - // 8. Handle prop changes when gridApi exists (but hasn't changed) + // 8. Handle filter model updates useEffect(() => { - if (gridApi && gridApi === prevGridApi) { - if ( - props.filterModel && - gridApi.getFilterModel() !== props.filterModel - ) { - gridApi.setFilterModel(props.filterModel); - } + if ( + gridApi && + gridApi === prevGridApi && + props.filterModel && + gridApi.getFilterModel() !== props.filterModel + ) { + gridApi.setFilterModel(props.filterModel); + } + }, [props.filterModel, gridApi, prevGridApi]); - if (props.paginationGoTo || props.paginationGoTo === 0) { - paginationGoTo(); - } + // 9. Handle pagination actions + useEffect(() => { + if ( + gridApi && + gridApi === prevGridApi && + (props.paginationGoTo || props.paginationGoTo === 0) + ) { + paginationGoTo(); + } + }, [props.paginationGoTo, gridApi, prevGridApi, paginationGoTo]); - if (props.scrollTo) { - scrollTo(); - } + // 10. Handle scroll actions + useEffect(() => { + if (gridApi && gridApi === prevGridApi && props.scrollTo) { + scrollTo(); + } + }, [props.scrollTo, gridApi, prevGridApi, scrollTo]); - if (props.columnSize) { - updateColumnWidths(); - } + // 11. Handle column size updates + useEffect(() => { + if (gridApi && gridApi === prevGridApi && props.columnSize) { + updateColumnWidths(); + } + }, [props.columnSize, gridApi, prevGridApi, updateColumnWidths]); - if (props.resetColumnState) { - resetColumnState(); - } + // 12. Handle column state reset + useEffect(() => { + if (gridApi && gridApi === prevGridApi && props.resetColumnState) { + resetColumnState(); + } + }, [props.resetColumnState, gridApi, prevGridApi, resetColumnState]); - if (props.exportDataAsCsv) { - exportDataAsCsv(props.csvExportParams); - } + // 13. Handle CSV export + useEffect(() => { + if (gridApi && gridApi === prevGridApi && props.exportDataAsCsv) { + exportDataAsCsv(props.csvExportParams); + } + }, [ + props.exportDataAsCsv, + props.csvExportParams, + gridApi, + prevGridApi, + exportDataAsCsv, + ]); + // 14. Handle row selection actions + useEffect(() => { + if (gridApi && gridApi === prevGridApi) { if (props.selectAll) { selectAll(props.selectAll); } - if (props.deselectAll) { deselectAll(); } - if (props.deleteSelectedRows) { deleteSelectedRows(); } + } + }, [ + props.selectAll, + props.deselectAll, + props.deleteSelectedRows, + gridApi, + prevGridApi, + selectAll, + deselectAll, + deleteSelectedRows, + ]); - if (props.rowTransaction) { - rowTransaction(props.rowTransaction); - } + // 15. Handle row transactions + useEffect(() => { + if (gridApi && gridApi === prevGridApi && props.rowTransaction) { + rowTransaction(props.rowTransaction); + } + }, [props.rowTransaction, gridApi, prevGridApi, rowTransaction]); + // 16. Handle column state updates + useEffect(() => { + if (gridApi && gridApi === prevGridApi) { if (props.updateColumnState) { updateColumnState(); } else if (columnState_push) { - setColumnState(); + setTimeout(() => { + setColumnState(); + }, 1); } } }, [ - props.filterModel, - props.paginationGoTo, - props.scrollTo, - props.columnSize, - props.resetColumnState, - props.exportDataAsCsv, - props.selectAll, - props.deselectAll, - props.deleteSelectedRows, - props.rowTransaction, props.updateColumnState, columnState_push, gridApi, + prevGridApi, + updateColumnState, + setColumnState, ]); // End of hooks From 5252092391b388f93c83ce7de76336dceb8fe413 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Wed, 2 Jul 2025 13:47:20 -0600 Subject: [PATCH 08/24] Remove unnecessary state update --- src/lib/fragments/AgGrid.react.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 50901344..9ab6f233 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1416,7 +1416,6 @@ export function DashAgGrid(props) { if (gridApi && gridApi !== prevGridApi) { // Hydrate virtualRowData and finalize setup onFilterChanged(true); - setColumnState_push(false); updateColumnState(); } }, [ From 4e1b55196d9d80fa6dc8135daf53d428cf5412ec Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Fri, 4 Jul 2025 14:14:12 -0600 Subject: [PATCH 09/24] Memoize component --- src/lib/fragments/AgGrid.react.js | 21 +++++++++++++++++++-- src/lib/utils/propCategories.js | 4 +++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 9ab6f233..90a6df3b 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -272,7 +272,6 @@ export function DashAgGrid(props) { const [openGroups, setOpenGroups] = useState({}); const [columnState_push, setColumnState_push] = useState(true); const [rowTransactionState, setRowTransactionState] = useState(null); - const [parentState] = useState(props.parentState || {}); const components = useMemo( () => ({ @@ -1706,4 +1705,22 @@ export const defaultProps = DashAgGrid.defaultProps; var dagfuncs = (window.dash_ag_grid = window.dash_ag_grid || {}); dagfuncs.useGridFilter = useGridFilter; -export default DashAgGrid; +const MemoizedAgGrid = React.memo(DashAgGrid, (prevProps, nextProps) => { + // Check if props are equal (excluding render-specific props) + const relevantNextProps = { ...omit(OMIT_PROP_RENDER, nextProps) }; + const relevantPrevProps = { ...omit(OMIT_PROP_RENDER, prevProps) }; + + const isInternalChange = nextProps?.dashRenderType === 'internal'; + const propsHaveChanged = !equals(relevantNextProps, relevantPrevProps); + const rowDataChanged = !equals(nextProps.rowData, prevProps.rowData); + const selectedRowsChanged = !equals(nextProps.selectedRows, prevProps.selectedRows); + + if (propsHaveChanged && (!isInternalChange || rowDataChanged || selectedRowsChanged)) { + return false; // Props changed, re-render + } + + return true; + +}); + +export default MemoizedAgGrid; diff --git a/src/lib/utils/propCategories.js b/src/lib/utils/propCategories.js index e6995f85..64f6c511 100644 --- a/src/lib/utils/propCategories.js +++ b/src/lib/utils/propCategories.js @@ -317,10 +317,12 @@ export const PASSTHRU_PROPS = ['rowData']; * in the render() method, so they don't need to be listed here */ export const PROPS_NOT_FOR_AG_GRID = [ + 'children', 'setProps', 'loading_state', 'enableEnterpriseModules', 'parentState', + 'persistence', 'persisted_props', 'persistence_type', 'virtualRowData', @@ -335,6 +337,7 @@ export const PROPS_NOT_FOR_AG_GRID = [ 'alignedGrids', 'resetColumnState', 'exportDataAsCsv', + 'selectedRows', 'selectAll', 'deselectAll', 'deleteSelectedRows', @@ -357,7 +360,6 @@ export const OMIT_PROP_RENDER = [ 'virtualRowData', 'columnState', 'filterModel', - 'selectedRows', 'getRowRequest', 'getDetailRequest', 'cellValueChanged', From c2109e49487abf21b6f34b18d0e1edd643f48845 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Thu, 10 Jul 2025 15:38:01 -0600 Subject: [PATCH 10/24] Fix bug with initial selections --- src/lib/fragments/AgGrid.react.js | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 90a6df3b..b01681f9 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1285,8 +1285,10 @@ export function DashAgGrid(props) { useEffect(() => { // Apply selections - setSelection(props.selectedRows); - }, [props.selectedRows]); + if (gridApi) { + setSelection(props.selectedRows); + } + }, [props.selectedRows, gridApi]); // 1. Handle gridApi initialization - basic setup useEffect(() => { @@ -1479,27 +1481,6 @@ export function DashAgGrid(props) { props.detailCellRendererParams, ]); - // 6. Handle selectedRows changes - useEffect(() => { - if ( - !equals(props.selectedRows, prevProps?.selectedRows) && - !(typeof props.loading_state !== 'undefined' - ? props.loading_state && selectionEventFired.current - : selectionEventFired.current) - ) { - if (!dataUpdates.current) { - setTimeout(() => { - if (!dataUpdates.current) { - setSelection(props.selectedRows); - } - }, 10); - } - } - - // Reset selection event flag - selectionEventFired.current = false; - }, [props.selectedRows, props.loading_state]); - // 7. Handle dataUpdates reset useEffect(() => { dataUpdates.current = false; From a7534ee344f994d76fe939e85f53fa7c0578624f Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Thu, 10 Jul 2025 16:12:55 -0600 Subject: [PATCH 11/24] code cleanup --- CHANGELOG.md | 5 ++ src/lib/fragments/AgGrid.react.js | 91 ++++++++++----------- src/lib/fragments/AgGridEnterprise.react.js | 4 +- tests/test_cell_data_type_override.py | 2 +- 4 files changed, 53 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4e80578..e1cc912f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to `dash-ag-grid` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). Links "DE#nnn" prior to version 2.0 point to the Dash Enterprise closed-source Dash AG Grid repo +## UNRELEASED + +### Changed +- Component is refactored to be a function component rather than a class + ## [32.3.0rc0] - 2025-04-15 ### Fixed diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index b01681f9..d1a149b7 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -37,7 +37,6 @@ import { PROPS_NOT_FOR_AG_GRID, GRID_DANGEROUS_FUNCTIONS, OMIT_PROP_RENDER, - OMIT_STATE_RENDER, OBJ_MAYBE_FUNCTION_OR_MAP_MAYBE_FUNCTIONS, } from '../utils/propCategories'; import debounce from '../utils/debounce'; @@ -243,21 +242,21 @@ export function DashAgGrid(props) { (Renderer) => { const {dangerously_allow_code} = props; - return (props) => ( + return (cellProps) => ( { customSetProps({ cellRendererData: { value, - colId: props.column.colId, - rowIndex: props.node.sourceRowIndex, - rowId: props.node.id, + colId: cellProps.column.colId, + rowIndex: cellProps.node.sourceRowIndex, + rowId: cellProps.node.id, timestamp: Date.now(), }, }); }} dangerously_allow_code={dangerously_allow_code} - {...props} + {...cellProps} > ); }, @@ -290,7 +289,6 @@ export function DashAgGrid(props) { const selectionEventFired = useRef(false); const pauseSelections = useRef(false); const reference = useRef(); - // const pendingChanges = useRef(null); const dataUpdates = useRef(false); const getDetailParams = useRef(); const getRowsParams = useRef(null); @@ -1286,11 +1284,11 @@ export function DashAgGrid(props) { useEffect(() => { // Apply selections if (gridApi) { - setSelection(props.selectedRows); + setSelection(props.selectedRows); } }, [props.selectedRows, gridApi]); - // 1. Handle gridApi initialization - basic setup + // Handle gridApi initialization - basic setup useEffect(() => { if (gridApi && gridApi !== prevGridApi) { updateColumnWidths(false); @@ -1302,7 +1300,7 @@ export function DashAgGrid(props) { } }, [gridApi, prevGridApi, updateColumnWidths, onPaginationChanged]); - // 1a. Handle gridApi initialization - expanded groups tracking + // Handle gridApi initialization - expanded groups tracking useEffect(() => { if (gridApi && gridApi !== prevGridApi) { const groups = {}; @@ -1315,7 +1313,7 @@ export function DashAgGrid(props) { } }, [gridApi, prevGridApi, setOpenGroups]); - // 1b. Handle gridApi initialization - row transactions + // Handle gridApi initialization - row transactions useEffect(() => { if (gridApi && gridApi !== prevGridApi && rowTransactionState) { rowTransactionState.map((data) => @@ -1333,21 +1331,21 @@ export function DashAgGrid(props) { syncRowData, ]); - // 1c. Handle gridApi initialization - filter model application + // Handle gridApi initialization - filter model application useEffect(() => { if (gridApi && gridApi !== prevGridApi && !isEmpty(props.filterModel)) { gridApi.setFilterModel(props.filterModel); } }, [gridApi, prevGridApi, props.filterModel]); - // 1d. Handle gridApi initialization - column state application + // Handle gridApi initialization - column state application useEffect(() => { if (gridApi && gridApi !== prevGridApi && props.columnState) { setColumnState(); } }, [gridApi, prevGridApi, props.columnState, setColumnState]); - // 1e. Handle gridApi initialization - action props with cleanup + // Handle gridApi initialization - action props with cleanup useEffect(() => { if (gridApi && gridApi !== prevGridApi) { const propsToSet = {}; @@ -1412,7 +1410,7 @@ export function DashAgGrid(props) { customSetProps, ]); - // 1f. Handle gridApi initialization - finalization + // Handle gridApi initialization - finalization useEffect(() => { if (gridApi && gridApi !== prevGridApi) { // Hydrate virtualRowData and finalize setup @@ -1427,7 +1425,7 @@ export function DashAgGrid(props) { updateColumnState, ]); - // 2. Handle columnState push changes + // Handle columnState push changes useEffect(() => { if ( gridApi && @@ -1442,7 +1440,7 @@ export function DashAgGrid(props) { } }, [props.columnState, props.loading_state, gridApi, columnState_push]); - // 3. Handle ID changes + // Handle ID changes useEffect(() => { if (props.id !== prevProps?.id) { if (props.id) { @@ -1456,7 +1454,7 @@ export function DashAgGrid(props) { } }, [props.id]); - // 4. Handle infinite scrolling datasource + // Handle infinite scrolling datasource useEffect(() => { if (isDatasourceLoadedForInfiniteScrolling()) { const {rowData, rowCount} = props.getRowsResponse; @@ -1465,7 +1463,7 @@ export function DashAgGrid(props) { } }, [props.getRowsResponse]); - // 5. Handle master detail response + // Handle master detail response useEffect(() => { if ( props.masterDetail && @@ -1481,12 +1479,12 @@ export function DashAgGrid(props) { props.detailCellRendererParams, ]); - // 7. Handle dataUpdates reset + // Handle dataUpdates reset useEffect(() => { dataUpdates.current = false; }); - // 8. Handle filter model updates + // Handle filter model updates useEffect(() => { if ( gridApi && @@ -1498,7 +1496,7 @@ export function DashAgGrid(props) { } }, [props.filterModel, gridApi, prevGridApi]); - // 9. Handle pagination actions + // Handle pagination actions useEffect(() => { if ( gridApi && @@ -1509,28 +1507,28 @@ export function DashAgGrid(props) { } }, [props.paginationGoTo, gridApi, prevGridApi, paginationGoTo]); - // 10. Handle scroll actions + // Handle scroll actions useEffect(() => { if (gridApi && gridApi === prevGridApi && props.scrollTo) { scrollTo(); } }, [props.scrollTo, gridApi, prevGridApi, scrollTo]); - // 11. Handle column size updates + // Handle column size updates useEffect(() => { if (gridApi && gridApi === prevGridApi && props.columnSize) { updateColumnWidths(); } }, [props.columnSize, gridApi, prevGridApi, updateColumnWidths]); - // 12. Handle column state reset + // Handle column state reset useEffect(() => { if (gridApi && gridApi === prevGridApi && props.resetColumnState) { resetColumnState(); } }, [props.resetColumnState, gridApi, prevGridApi, resetColumnState]); - // 13. Handle CSV export + // Handle CSV export useEffect(() => { if (gridApi && gridApi === prevGridApi && props.exportDataAsCsv) { exportDataAsCsv(props.csvExportParams); @@ -1543,7 +1541,7 @@ export function DashAgGrid(props) { exportDataAsCsv, ]); - // 14. Handle row selection actions + // Handle row selection actions useEffect(() => { if (gridApi && gridApi === prevGridApi) { if (props.selectAll) { @@ -1567,14 +1565,14 @@ export function DashAgGrid(props) { deleteSelectedRows, ]); - // 15. Handle row transactions + // Handle row transactions useEffect(() => { if (gridApi && gridApi === prevGridApi && props.rowTransaction) { rowTransaction(props.rowTransaction); } }, [props.rowTransaction, gridApi, prevGridApi, rowTransaction]); - // 16. Handle column state updates + // Handle column state updates useEffect(() => { if (gridApi && gridApi === prevGridApi) { if (props.updateColumnState) { @@ -1594,12 +1592,8 @@ export function DashAgGrid(props) { setColumnState, ]); - // End of hooks - const {id, style, className, dashGridOptions, ...restProps} = props; - const passingProps = pick(PASSTHRU_PROPS, restProps); - const convertedProps = convertAllProps( omit(NO_CONVERT_PROPS, {...dashGridOptions, ...restProps}) ); @@ -1687,21 +1681,26 @@ var dagfuncs = (window.dash_ag_grid = window.dash_ag_grid || {}); dagfuncs.useGridFilter = useGridFilter; const MemoizedAgGrid = React.memo(DashAgGrid, (prevProps, nextProps) => { - // Check if props are equal (excluding render-specific props) - const relevantNextProps = { ...omit(OMIT_PROP_RENDER, nextProps) }; - const relevantPrevProps = { ...omit(OMIT_PROP_RENDER, prevProps) }; - - const isInternalChange = nextProps?.dashRenderType === 'internal'; - const propsHaveChanged = !equals(relevantNextProps, relevantPrevProps); - const rowDataChanged = !equals(nextProps.rowData, prevProps.rowData); - const selectedRowsChanged = !equals(nextProps.selectedRows, prevProps.selectedRows); - - if (propsHaveChanged && (!isInternalChange || rowDataChanged || selectedRowsChanged)) { - return false; // Props changed, re-render - } + // Check if props are equal (excluding render-specific props) + const relevantNextProps = {...omit(OMIT_PROP_RENDER, nextProps)}; + const relevantPrevProps = {...omit(OMIT_PROP_RENDER, prevProps)}; + + const isInternalChange = nextProps?.dashRenderType === 'internal'; + const propsHaveChanged = !equals(relevantNextProps, relevantPrevProps); + const rowDataChanged = !equals(nextProps.rowData, prevProps.rowData); + const selectedRowsChanged = !equals( + nextProps.selectedRows, + prevProps.selectedRows + ); - return true; + if ( + propsHaveChanged && + (!isInternalChange || rowDataChanged || selectedRowsChanged) + ) { + return false; // Props changed, re-render + } + return true; }); export default MemoizedAgGrid; diff --git a/src/lib/fragments/AgGridEnterprise.react.js b/src/lib/fragments/AgGridEnterprise.react.js index f211ef42..3df1e599 100644 --- a/src/lib/fragments/AgGridEnterprise.react.js +++ b/src/lib/fragments/AgGridEnterprise.react.js @@ -1,13 +1,13 @@ import React from 'react'; import {LicenseManager} from 'ag-grid-enterprise'; -import DashAgGrid, {propTypes} from './AgGrid.react'; +import MemoizedAgGrid, {propTypes} from './AgGrid.react'; export default function DashAgGridEnterprise(props) { const {licenseKey} = props; if (licenseKey) { LicenseManager.setLicenseKey(licenseKey); } - return ; + return ; } DashAgGridEnterprise.propTypes = propTypes; diff --git a/tests/test_cell_data_type_override.py b/tests/test_cell_data_type_override.py index bfe5523c..f4bdd54f 100644 --- a/tests/test_cell_data_type_override.py +++ b/tests/test_cell_data_type_override.py @@ -79,4 +79,4 @@ def test_cd001_cell_data_types_override(dash_duo): date_input_element = dash_duo.find_element(f'#{grid.id} .ag-date-field-input') date_input_element.send_keys("01172024" + Keys.ENTER) - # grid.wait_for_cell_text(0, 1, "17/01/2024") + grid.wait_for_cell_text(0, 1, "17/01/2024") From 224ea62c496a14a06f6f2bce13ee6d785b194ec1 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 14 Jul 2025 13:55:58 -0600 Subject: [PATCH 12/24] Fix bug setting `columnState` prop --- src/lib/fragments/AgGrid.react.js | 17 +++++++++-------- tests/test_column_state.py | 3 +++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index d1a149b7..b1042148 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1416,6 +1416,7 @@ export function DashAgGrid(props) { // Hydrate virtualRowData and finalize setup onFilterChanged(true); updateColumnState(); + setColumnState_push(false); } }, [ gridApi, @@ -1431,14 +1432,16 @@ export function DashAgGrid(props) { gridApi && (!props.loading_state || prevProps?.loading_state?.is_loading) ) { - if ( - props.columnState !== prevProps?.columnState && - !columnState_push - ) { + const existingColumnState = gridApi.getColumnState(); + const realStateChange = + props.columnState && + !equals(props.columnState, existingColumnState); + + if (realStateChange && !columnState_push) { setColumnState_push(true); } } - }, [props.columnState, props.loading_state, gridApi, columnState_push]); + }, [props.columnState, props.loading_state, columnState_push]); // Handle ID changes useEffect(() => { @@ -1578,9 +1581,7 @@ export function DashAgGrid(props) { if (props.updateColumnState) { updateColumnState(); } else if (columnState_push) { - setTimeout(() => { - setColumnState(); - }, 1); + setColumnState(); } } }, [ diff --git a/tests/test_column_state.py b/tests/test_column_state.py index c771d6d8..5b573b0b 100644 --- a/tests/test_column_state.py +++ b/tests/test_column_state.py @@ -247,6 +247,9 @@ def loadState(n): ) dash_duo.find_element("#load-column-defs").click() + + time.sleep(0.5) # pausing to emulate separation because user inputs + until( lambda: json.dumps(alt_colState) in dash_duo.find_element("#reset-column-state-grid-pre").text, From e95cff24b7fa46d41e774feae3e8984c13f4ed4f Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Mon, 14 Jul 2025 16:16:28 -0600 Subject: [PATCH 13/24] Make test locale-agnostic --- tests/test_cell_data_type_override.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cell_data_type_override.py b/tests/test_cell_data_type_override.py index f4bdd54f..e93e36f7 100644 --- a/tests/test_cell_data_type_override.py +++ b/tests/test_cell_data_type_override.py @@ -77,6 +77,6 @@ def test_cd001_cell_data_types_override(dash_duo): # test overriden dateString cell data type action.double_click(grid.get_cell(0, 1)).perform() date_input_element = dash_duo.find_element(f'#{grid.id} .ag-date-field-input') - date_input_element.send_keys("01172024" + Keys.ENTER) + date_input_element.send_keys("01012024" + Keys.ENTER) - grid.wait_for_cell_text(0, 1, "17/01/2024") + grid.wait_for_cell_text(0, 1, "01/01/2024") From 682bca338a3d05b2e415f64ea2ce77c4de980f55 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 15 Jul 2025 16:54:49 -0400 Subject: [PATCH 14/24] - removing redundant initial gridApi as useEffect was listening to it already - adjusting tests in the event the grid takes a bit to render - fixed issue with selectedRows triggering uneccessarily --- src/lib/fragments/AgGrid.react.js | 88 ++++--------------------------- tests/test_event_listeners.py | 3 +- tests/test_pagination.py | 2 + 3 files changed, 15 insertions(+), 78 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index b1042148..eb1d3e9c 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -779,8 +779,6 @@ export function DashAgGrid(props) { props.filterModel, gridApi, openGroups, - dataUpdates.current, - pauseSelections.current, setSelection, virtualRowData, customSetProps, @@ -806,10 +804,8 @@ export function DashAgGrid(props) { } }, 1); }, [ - pauseSelections.current, gridApi, props.selectedRows, - selectionEventFired.current, customSetProps, ]); @@ -1284,7 +1280,10 @@ export function DashAgGrid(props) { useEffect(() => { // Apply selections if (gridApi) { - setSelection(props.selectedRows); + const selectedRows = gridApi.getSelectedRows(); + if (!equals(selectedRows, props.selectedRows)) { + setSelection(props.selectedRows); + } } }, [props.selectedRows, gridApi]); @@ -1345,71 +1344,6 @@ export function DashAgGrid(props) { } }, [gridApi, prevGridApi, props.columnState, setColumnState]); - // Handle gridApi initialization - action props with cleanup - useEffect(() => { - if (gridApi && gridApi !== prevGridApi) { - const propsToSet = {}; - - if (props.paginationGoTo || props.paginationGoTo === 0) { - paginationGoTo(false); - propsToSet.paginationGoTo = null; - } - - if (props.scrollTo) { - scrollTo(false); - propsToSet.scrollTo = null; - } - - if (props.resetColumnState) { - resetColumnState(false); - propsToSet.resetColumnState = false; - } - - if (props.exportDataAsCsv) { - exportDataAsCsv(props.csvExportParams, false); - propsToSet.exportDataAsCsv = false; - } - - if (props.selectAll) { - selectAll(props.selectAll, false); - propsToSet.selectAll = false; - } - - if (props.deselectAll) { - deselectAll(false); - propsToSet.deselectAll = false; - } - - if (props.deleteSelectedRows) { - deleteSelectedRows(false); - propsToSet.deleteSelectedRows = false; - } - - if (!isEmpty(propsToSet)) { - customSetProps(propsToSet); - } - } - }, [ - gridApi, - prevGridApi, - props.paginationGoTo, - props.scrollTo, - props.resetColumnState, - props.exportDataAsCsv, - props.csvExportParams, - props.selectAll, - props.deselectAll, - props.deleteSelectedRows, - paginationGoTo, - scrollTo, - resetColumnState, - exportDataAsCsv, - selectAll, - deselectAll, - deleteSelectedRows, - customSetProps, - ]); - // Handle gridApi initialization - finalization useEffect(() => { if (gridApi && gridApi !== prevGridApi) { @@ -1512,28 +1446,28 @@ export function DashAgGrid(props) { // Handle scroll actions useEffect(() => { - if (gridApi && gridApi === prevGridApi && props.scrollTo) { + if (gridApi && props.scrollTo) { scrollTo(); } }, [props.scrollTo, gridApi, prevGridApi, scrollTo]); // Handle column size updates useEffect(() => { - if (gridApi && gridApi === prevGridApi && props.columnSize) { + if (gridApi && props.columnSize) { updateColumnWidths(); } }, [props.columnSize, gridApi, prevGridApi, updateColumnWidths]); // Handle column state reset useEffect(() => { - if (gridApi && gridApi === prevGridApi && props.resetColumnState) { + if (gridApi && props.resetColumnState) { resetColumnState(); } }, [props.resetColumnState, gridApi, prevGridApi, resetColumnState]); // Handle CSV export useEffect(() => { - if (gridApi && gridApi === prevGridApi && props.exportDataAsCsv) { + if (gridApi && props.exportDataAsCsv) { exportDataAsCsv(props.csvExportParams); } }, [ @@ -1546,7 +1480,7 @@ export function DashAgGrid(props) { // Handle row selection actions useEffect(() => { - if (gridApi && gridApi === prevGridApi) { + if (gridApi) { if (props.selectAll) { selectAll(props.selectAll); } @@ -1570,14 +1504,14 @@ export function DashAgGrid(props) { // Handle row transactions useEffect(() => { - if (gridApi && gridApi === prevGridApi && props.rowTransaction) { + if (gridApi && props.rowTransaction) { rowTransaction(props.rowTransaction); } }, [props.rowTransaction, gridApi, prevGridApi, rowTransaction]); // Handle column state updates useEffect(() => { - if (gridApi && gridApi === prevGridApi) { + if (gridApi ) { if (props.updateColumnState) { updateColumnState(); } else if (columnState_push) { diff --git a/tests/test_event_listeners.py b/tests/test_event_listeners.py index 74634fc8..70bac7f8 100644 --- a/tests/test_event_listeners.py +++ b/tests/test_event_listeners.py @@ -5,6 +5,7 @@ import json from selenium.webdriver.common.by import By from dash.testing.wait import until +import time df = px.data.medals_wide() @@ -52,7 +53,7 @@ def test_el001_event_listener(dash_duo): # Test left click. grid.get_cell(1, 2).click() - until(lambda: json.loads(dash_duo.find_element('#log').text).get('value') == 15, timeout=3) + until(lambda: json.loads(dash_duo.find_element('#log').text or "{}").get('value') == 15, timeout=3) # Test right click action = utils.ActionChains(dash_duo.driver) diff --git a/tests/test_pagination.py b/tests/test_pagination.py index e6f1e9be..fd3d8bb0 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -4,6 +4,7 @@ import pandas as pd import json from dash.testing.wait import until +import time from . import utils @@ -74,6 +75,7 @@ def updatePage(_): grid = utils.Grid(dash_duo, "grid") + time.sleep(1) # wait for the grid to load until(lambda: "Australia" == grid.get_cell(500, 0).text, timeout=3) oldValue = '{"isLastPageFound": true, "pageSize": 100, "currentPage": 5, "totalPages": 87, "rowCount": 8618}' until(lambda: oldValue == dash_duo.find_element("#grid-info").text, timeout=3) From 250dca4fd8638a886aa774a4d993795372335827 Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 15 Jul 2025 16:58:45 -0400 Subject: [PATCH 15/24] fix for lint --- src/lib/fragments/AgGrid.react.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index eb1d3e9c..52e6a907 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -803,11 +803,7 @@ export function DashAgGrid(props) { } } }, 1); - }, [ - gridApi, - props.selectedRows, - customSetProps, - ]); + }, [gridApi, props.selectedRows, customSetProps]); const isDatasourceLoadedForInfiniteScrolling = useCallback(() => { return ( @@ -1504,14 +1500,14 @@ export function DashAgGrid(props) { // Handle row transactions useEffect(() => { - if (gridApi && props.rowTransaction) { + if (gridApi && props.rowTransaction) { rowTransaction(props.rowTransaction); } }, [props.rowTransaction, gridApi, prevGridApi, rowTransaction]); // Handle column state updates useEffect(() => { - if (gridApi ) { + if (gridApi) { if (props.updateColumnState) { updateColumnState(); } else if (columnState_push) { From a123e4450bf654b534420ea63cb5069dff2aeaca Mon Sep 17 00:00:00 2001 From: BSd3v <82055130+BSd3v@users.noreply.github.com> Date: Tue, 15 Jul 2025 17:15:24 -0400 Subject: [PATCH 16/24] adjustments for timing of the sizing test --- tests/test_sizing_buttons.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_sizing_buttons.py b/tests/test_sizing_buttons.py index 4737c560..94339025 100644 --- a/tests/test_sizing_buttons.py +++ b/tests/test_sizing_buttons.py @@ -448,6 +448,7 @@ def selected(state): assert oldValue == dash_duo.find_element("#columnState").get_attribute( "innerText" ) + time.sleep(.2) # allow window size to change dash_duo.find_element(f"#{x}").click() until( lambda: oldValue @@ -457,4 +458,4 @@ def selected(state): oldValue = dash_duo.find_element("#columnState").text dash_duo.driver.set_window_size(1000, 1000) - time.sleep(.2) + time.sleep(.2) # allow oldValue to change to the bigger size From ea5c15f95201a8646768970afb9e118d12adba3e Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Tue, 15 Jul 2025 15:35:58 -0600 Subject: [PATCH 17/24] Revert test change --- tests/test_cell_data_type_override.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_cell_data_type_override.py b/tests/test_cell_data_type_override.py index e93e36f7..f4bdd54f 100644 --- a/tests/test_cell_data_type_override.py +++ b/tests/test_cell_data_type_override.py @@ -77,6 +77,6 @@ def test_cd001_cell_data_types_override(dash_duo): # test overriden dateString cell data type action.double_click(grid.get_cell(0, 1)).perform() date_input_element = dash_duo.find_element(f'#{grid.id} .ag-date-field-input') - date_input_element.send_keys("01012024" + Keys.ENTER) + date_input_element.send_keys("01172024" + Keys.ENTER) - grid.wait_for_cell_text(0, 1, "01/01/2024") + grid.wait_for_cell_text(0, 1, "17/01/2024") From 3f586b6945586e2f7b2ec624464b72f7181cb1ff Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Wed, 16 Jul 2025 16:02:34 -0600 Subject: [PATCH 18/24] Enforce a locale for cell formatting tests --- tests/conftest.py | 8 ++++++++ tests/test_cell_data_type_override.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..1db3780f --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,8 @@ +import os +import pytest + + +@pytest.fixture +def enforced_locale(): + # Forces Chrome to use the `en-US` locale for tests, overriding any user-specified locale + os.environ["LANGUAGE"] = "en-US" diff --git a/tests/test_cell_data_type_override.py b/tests/test_cell_data_type_override.py index f4bdd54f..07f79fb1 100644 --- a/tests/test_cell_data_type_override.py +++ b/tests/test_cell_data_type_override.py @@ -4,7 +4,7 @@ from dash import Dash, html from . import utils -def test_cd001_cell_data_types_override(dash_duo): +def test_cd001_cell_data_types_override(enforced_locale, dash_duo): app = Dash(__name__) rowData = [ From 758c703e6fae596501ee95a76967b5a478557953 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Fri, 18 Jul 2025 13:45:39 -0600 Subject: [PATCH 19/24] Fix race condition in paginationGoto prop --- src/lib/fragments/AgGrid.react.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 52e6a907..b2a6fc92 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1433,7 +1433,6 @@ export function DashAgGrid(props) { useEffect(() => { if ( gridApi && - gridApi === prevGridApi && (props.paginationGoTo || props.paginationGoTo === 0) ) { paginationGoTo(); From eb2037695d314c42fb8e8232a16ac9fe7a245555 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Fri, 18 Jul 2025 13:50:08 -0600 Subject: [PATCH 20/24] lint --- src/lib/fragments/AgGrid.react.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index b2a6fc92..9d0d21ce 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -1431,10 +1431,7 @@ export function DashAgGrid(props) { // Handle pagination actions useEffect(() => { - if ( - gridApi && - (props.paginationGoTo || props.paginationGoTo === 0) - ) { + if (gridApi && (props.paginationGoTo || props.paginationGoTo === 0)) { paginationGoTo(); } }, [props.paginationGoTo, gridApi, prevGridApi, paginationGoTo]); From f87c7271618250f5861bfe78ff9c8bb1afb65cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20DIDIER?= Date: Sun, 20 Jul 2025 21:45:24 +0200 Subject: [PATCH 21/24] Add `checkboxes` and `rowSelection` to propCategories.js, remove `checkboxSelection` and `headerCheckboxSelection`, and example for selection checkboxes as function --- src/lib/utils/propCategories.js | 4 +-- .../single_row_selection_remove_checkboxes.py | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/examples/single_row_selection_remove_checkboxes.py diff --git a/src/lib/utils/propCategories.js b/src/lib/utils/propCategories.js index e6995f85..430292ea 100644 --- a/src/lib/utils/propCategories.js +++ b/src/lib/utils/propCategories.js @@ -118,6 +118,7 @@ export const GRID_MAYBE_FUNCTIONS = { // Selection isRowSelectable: 1, fillOperation: 1, + checkboxes: 1, // Sorting postSortRows: 1, @@ -170,6 +171,7 @@ export const GRID_NESTED_FUNCTIONS = { detailGridOptions: 1, csvExportParams: 1, defaultCsvExportParams: 1, + rowSelection: 1, }; /** @@ -200,7 +202,6 @@ export const COLUMN_MAYBE_FUNCTIONS = { // Columns keyCreator: 1, equals: 1, - checkboxSelection: 1, icons: 1, suppressNavigable: 1, suppressKeyboardEvent: 1, @@ -222,7 +223,6 @@ export const COLUMN_MAYBE_FUNCTIONS = { // Columns: Headers suppressHeaderKeyboardEvent: 1, - headerCheckboxSelection: 1, // Columns: Rendering and Styling cellStyle: 1, diff --git a/tests/examples/single_row_selection_remove_checkboxes.py b/tests/examples/single_row_selection_remove_checkboxes.py new file mode 100644 index 00000000..67227e8f --- /dev/null +++ b/tests/examples/single_row_selection_remove_checkboxes.py @@ -0,0 +1,28 @@ +import dash_ag_grid as dag +from dash import Dash +import pandas as pd + +app = Dash() + +df = pd.read_csv( + "https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv" +) + +columnDefs = [{"field": i} for i in ["country", "year", "athlete", "age", "sport", "total"]] + +app.layout = dag.AgGrid( + id="grid-row-selection-remove-checkboxes", + columnDefs=columnDefs, + rowData=df.to_dict("records"), + columnSize="sizeToFit", + dashGridOptions={ + "rowSelection": { + 'mode': 'singleRow', + # test selection checkboxes as function + 'checkboxes': {"function": "params.data.year > 2007"} + }, + } +) + +if __name__ == "__main__": + app.run(debug=True) From 8bb08e2b84ae7aa252d98f0fbb9371a76c8589fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20DIDIER?= Date: Tue, 22 Jul 2025 21:49:20 +0200 Subject: [PATCH 22/24] Add support for new Selection API while maintaining backward compatibility with deprecated API, update tests and propCategories.js --- src/lib/fragments/AgGrid.react.js | 18 ++++--- src/lib/utils/propCategories.js | 2 + .../single_row_selection_remove_checkboxes.py | 50 ++++++++++++++----- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 06c273f2..854b0347 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -465,6 +465,10 @@ export default class DashAgGrid extends Component { } if (GRID_NESTED_FUNCTIONS[target]) { let adjustedVal = value; + if (target === 'rowSelection' && typeof value === 'string') { + // to still support rowSelection='single' | 'multiple' deprecated in v32.3.4 + return value + } if ('suppressCallback' in value) { adjustedVal = { ...adjustedVal, @@ -1001,13 +1005,13 @@ export default class DashAgGrid extends Component { } onCellValueChanged({ - oldValue, - value, - column: {colId}, - rowIndex, - data, - node, - }) { + oldValue, + value, + column: {colId}, + rowIndex, + data, + node, + }) { const timestamp = Date.now(); // Collect new change. const newChange = { diff --git a/src/lib/utils/propCategories.js b/src/lib/utils/propCategories.js index 430292ea..5e5366f7 100644 --- a/src/lib/utils/propCategories.js +++ b/src/lib/utils/propCategories.js @@ -202,6 +202,7 @@ export const COLUMN_MAYBE_FUNCTIONS = { // Columns keyCreator: 1, equals: 1, + checkboxSelection: 1, icons: 1, suppressNavigable: 1, suppressKeyboardEvent: 1, @@ -223,6 +224,7 @@ export const COLUMN_MAYBE_FUNCTIONS = { // Columns: Headers suppressHeaderKeyboardEvent: 1, + headerCheckboxSelection: 1, // Columns: Rendering and Styling cellStyle: 1, diff --git a/tests/examples/single_row_selection_remove_checkboxes.py b/tests/examples/single_row_selection_remove_checkboxes.py index 67227e8f..d84b9698 100644 --- a/tests/examples/single_row_selection_remove_checkboxes.py +++ b/tests/examples/single_row_selection_remove_checkboxes.py @@ -1,5 +1,6 @@ +# Test for dag v32.3.4, supporting the new Selection API and still supporting the deprecated Selection API import dash_ag_grid as dag -from dash import Dash +from dash import Dash, html import pandas as pd app = Dash() @@ -10,18 +11,41 @@ columnDefs = [{"field": i} for i in ["country", "year", "athlete", "age", "sport", "total"]] -app.layout = dag.AgGrid( - id="grid-row-selection-remove-checkboxes", - columnDefs=columnDefs, - rowData=df.to_dict("records"), - columnSize="sizeToFit", - dashGridOptions={ - "rowSelection": { - 'mode': 'singleRow', - # test selection checkboxes as function - 'checkboxes': {"function": "params.data.year > 2007"} - }, - } +app.layout = html.Div( + [ + 'New Selection API', + dag.AgGrid( + id="grid-row-selection-remove-checkboxes", + columnDefs=columnDefs, + rowData=df.to_dict("records"), + columnSize="sizeToFit", + dashGridOptions={ + "rowSelection": { + 'mode': 'singleRow', + # test selection checkboxes as function + 'checkboxes': {"function": "params.data.year > 2007"} + }, + }, + style={'margin-bottom': '10px'}, + ), + 'Deprecated Selection API', + dag.AgGrid( + id="grid-row-selection-remove-checkboxes-deprecated", + columnDefs=columnDefs, + rowData=df.to_dict("records"), + columnSize="sizeToFit", + defaultColDef={ + "filter": True, + "checkboxSelection": { + "function": 'params.column == params.api.getAllDisplayedColumns()[0]' + }, + "headerCheckboxSelection": { + "function": 'params.column == params.api.getAllDisplayedColumns()[0]' + } + }, + dashGridOptions={"rowSelection": "multiple"}, + ) + ] ) if __name__ == "__main__": From 75a74ed288acbb160f3bec9320f66e401b360e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20DIDIER?= Date: Tue, 22 Jul 2025 23:54:11 +0200 Subject: [PATCH 23/24] Run `npm run format` --- package-lock.json | 1729 ++++++++++++++--------------- src/lib/fragments/AgGrid.react.js | 7 +- 2 files changed, 865 insertions(+), 871 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b824820..208a80e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -111,12 +111,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -458,17 +459,17 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "engines": { "node": ">=6.9.0" } @@ -497,37 +498,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "dependencies": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", "dev": true, + "dependencies": { + "@babel/types": "^7.28.0" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -1817,25 +1807,22 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -1863,13 +1850,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "dependencies": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2049,9 +2035,9 @@ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", + "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", "cpu": [ "ppc64" ], @@ -2061,13 +2047,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", + "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", "cpu": [ "arm" ], @@ -2077,13 +2063,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", + "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", "cpu": [ "arm64" ], @@ -2093,13 +2079,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", + "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", "cpu": [ "x64" ], @@ -2109,13 +2095,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", + "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", "cpu": [ "arm64" ], @@ -2125,13 +2111,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", + "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", "cpu": [ "x64" ], @@ -2141,13 +2127,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", + "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", "cpu": [ "arm64" ], @@ -2157,13 +2143,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", + "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", "cpu": [ "x64" ], @@ -2173,13 +2159,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", + "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", "cpu": [ "arm" ], @@ -2189,13 +2175,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", + "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", "cpu": [ "arm64" ], @@ -2205,13 +2191,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", + "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", "cpu": [ "ia32" ], @@ -2221,13 +2207,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", + "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", "cpu": [ "loong64" ], @@ -2237,13 +2223,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", + "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", "cpu": [ "mips64el" ], @@ -2253,13 +2239,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", + "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", "cpu": [ "ppc64" ], @@ -2269,13 +2255,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", + "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", "cpu": [ "riscv64" ], @@ -2285,13 +2271,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", + "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", "cpu": [ "s390x" ], @@ -2301,13 +2287,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", + "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", "cpu": [ "x64" ], @@ -2317,13 +2303,29 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", + "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", + "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", "cpu": [ "x64" ], @@ -2333,13 +2335,29 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", + "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", + "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", "cpu": [ "x64" ], @@ -2349,13 +2367,29 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", + "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", + "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", "cpu": [ "x64" ], @@ -2365,13 +2399,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", + "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", "cpu": [ "arm64" ], @@ -2381,13 +2415,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", + "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", "cpu": [ "ia32" ], @@ -2397,13 +2431,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", + "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", "cpu": [ "x64" ], @@ -2413,7 +2447,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -2672,17 +2706,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@jridgewell/resolve-uri": { @@ -2694,35 +2724,26 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", + "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -3079,9 +3100,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, "node_modules/@types/hast": { @@ -3124,12 +3145,12 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", + "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", "dev": true, "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~7.8.0" } }, "node_modules/@types/parse-json": { @@ -3182,148 +3203,148 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -3395,15 +3416,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -3523,15 +3535,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3545,6 +3548,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -3837,9 +3841,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", @@ -3847,21 +3851,21 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -3878,10 +3882,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -3960,9 +3964,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001582", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001582.tgz", - "integrity": "sha512-vsJG3V5vgfduaQGVxL53uSX/HUzxyr2eA8xCo36OLal7sRcSZbibJtLeh0qja4sFOr/QQGt4opB4tOy+eOgAxg==", + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", "dev": true, "funding": [ { @@ -3992,6 +3996,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4005,6 +4010,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { "node": ">=0.8.0" } @@ -4108,6 +4114,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -4115,7 +4122,8 @@ "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/color-string": { "version": "1.9.1", @@ -4208,9 +4216,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -4468,9 +4476,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.653", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.653.tgz", - "integrity": "sha512-wA2A2LQCqnEwQAvwADQq3KpMpNwgAUBnRmrFgRzHnPhbQUFArTR32Ab46f4p0MovDLcg4uqd4nCsN2hTltslpA==", + "version": "1.5.189", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.189.tgz", + "integrity": "sha512-y9D1ntS1ruO/pZ/V2FtLE+JXLQe28XoRpZ7QCCo0T8LdQladzdcOVQZH/IWLVJvCw12OGMb6hYOeOAjntCmJRQ==", "dev": true }, "node_modules/emoji-regex": { @@ -4495,9 +4503,9 @@ "dev": true }, "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -4712,50 +4720,53 @@ } }, "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", + "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "@esbuild/aix-ppc64": "0.25.8", + "@esbuild/android-arm": "0.25.8", + "@esbuild/android-arm64": "0.25.8", + "@esbuild/android-x64": "0.25.8", + "@esbuild/darwin-arm64": "0.25.8", + "@esbuild/darwin-x64": "0.25.8", + "@esbuild/freebsd-arm64": "0.25.8", + "@esbuild/freebsd-x64": "0.25.8", + "@esbuild/linux-arm": "0.25.8", + "@esbuild/linux-arm64": "0.25.8", + "@esbuild/linux-ia32": "0.25.8", + "@esbuild/linux-loong64": "0.25.8", + "@esbuild/linux-mips64el": "0.25.8", + "@esbuild/linux-ppc64": "0.25.8", + "@esbuild/linux-riscv64": "0.25.8", + "@esbuild/linux-s390x": "0.25.8", + "@esbuild/linux-x64": "0.25.8", + "@esbuild/netbsd-arm64": "0.25.8", + "@esbuild/netbsd-x64": "0.25.8", + "@esbuild/openbsd-arm64": "0.25.8", + "@esbuild/openbsd-x64": "0.25.8", + "@esbuild/openharmony-arm64": "0.25.8", + "@esbuild/sunos-x64": "0.25.8", + "@esbuild/win32-arm64": "0.25.8", + "@esbuild/win32-ia32": "0.25.8", + "@esbuild/win32-x64": "0.25.8" } }, "node_modules/esbuild-loader": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-4.1.0.tgz", - "integrity": "sha512-543TtIvqbqouEMlOHg4xKoDQkmdImlwIpyAIgpUtDPvMuklU/c2k+Qt2O3VeDBgAwozxmlEbjOzV+F8CZ0g+Bw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-4.3.0.tgz", + "integrity": "sha512-D7HeJNdkDKKMarPQO/3dlJT6RwN2YJO7ENU6RPlpOz5YxSHnUNi2yvW41Bckvi1EVwctIaLzlb0ni5ag2GINYA==", "dev": true, "dependencies": { - "esbuild": "^0.20.0", + "esbuild": "^0.25.0", "get-tsconfig": "^4.7.0", "loader-utils": "^2.0.4", "webpack-sources": "^1.4.3" @@ -4787,9 +4798,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -5407,9 +5418,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5748,6 +5759,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { "node": ">=4" } @@ -9124,12 +9136,12 @@ ] }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -9210,9 +9222,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -9258,9 +9270,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, "node_modules/normalize-package-data": { @@ -9320,9 +9332,9 @@ } }, "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, "dependencies": { "nice-try": "^1.0.4", @@ -9682,10 +9694,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -10022,7 +10033,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -10064,7 +10074,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -10235,11 +10244,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", @@ -10654,9 +10658,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" @@ -10829,15 +10833,14 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0" } }, "node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", @@ -10846,7 +10849,7 @@ "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -11355,6 +11358,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -11374,22 +11378,22 @@ } }, "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/terser": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", - "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -11401,16 +11405,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { "node": ">= 10.13.0" @@ -11434,22 +11438,16 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/terser/node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=0.4.0" } }, "node_modules/terser/node_modules/commander": { @@ -11484,14 +11482,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -11666,9 +11656,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -11807,9 +11797,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -11826,8 +11816,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -11978,9 +11968,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -12000,35 +11990,36 @@ } }, "node_modules/webpack": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz", - "integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", + "version": "5.100.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.2.tgz", + "integrity": "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" @@ -12115,30 +12106,36 @@ } }, "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "node_modules/webpack/node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 10.13.0" + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "peerDependencies": { + "acorn": "^8.14.0" } }, "node_modules/which": { @@ -12488,12 +12485,13 @@ } }, "@babel/code-frame": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", - "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "requires": { - "@babel/highlight": "^7.23.4", - "chalk": "^2.4.2" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" } }, "@babel/compat-data": { @@ -12740,14 +12738,14 @@ } }, "@babel/helper-string-parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", - "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==" + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==" }, "@babel/helper-validator-option": { "version": "7.23.5", @@ -12767,32 +12765,24 @@ } }, "@babel/helpers": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", - "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "requires": { - "@babel/template": "^7.23.9", - "@babel/traverse": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" } }, - "@babel/highlight": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", - "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "@babel/types": "^7.28.0" } }, - "@babel/parser": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", - "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", - "dev": true - }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.23.3", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz", @@ -12827,7 +12817,8 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true + "dev": true, + "requires": {} }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -13646,22 +13637,19 @@ "dev": true }, "@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "requires": { - "regenerator-runtime": "^0.14.0" - } + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==" }, "@babel/template": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", - "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "requires": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.23.9", - "@babel/types": "^7.23.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" } }, "@babel/traverse": { @@ -13683,13 +13671,12 @@ } }, "@babel/types": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", - "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", + "version": "7.28.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz", + "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==", "requires": { - "@babel/helper-string-parser": "^7.23.4", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" } }, "@bcoe/v8-coverage": { @@ -13829,7 +13816,8 @@ "@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==" + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "requires": {} }, "@emotion/utils": { "version": "1.2.1", @@ -13842,163 +13830,184 @@ "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, "@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", + "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", "dev": true, "optional": true }, "@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", + "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", + "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", + "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", + "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", + "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", + "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", + "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", + "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", + "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", + "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", + "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", + "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", + "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", + "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", + "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", + "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", + "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", + "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", + "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", + "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", + "dev": true, + "optional": true + }, + "@esbuild/openharmony-arm64": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", + "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", + "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", + "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", + "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", + "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", "dev": true, "optional": true }, @@ -14184,14 +14193,13 @@ "dev": true }, "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "@jridgewell/resolve-uri": { @@ -14200,32 +14208,26 @@ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, "@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", + "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", @@ -14317,7 +14319,8 @@ "@mui/types": { "version": "7.2.13", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==" + "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", + "requires": {} }, "@mui/utils": { "version": "5.15.7", @@ -14419,9 +14422,9 @@ } }, "@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true }, "@types/hast": { @@ -14464,12 +14467,12 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", + "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", "dev": true, "requires": { - "undici-types": "~5.26.4" + "undici-types": "~7.8.0" } }, "@types/parse-json": { @@ -14522,148 +14525,148 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "requires": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true }, "@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, "@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -14671,19 +14674,22 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true + "dev": true, + "requires": {} }, "@xtuc/ieee754": { "version": "1.2.0", @@ -14703,17 +14709,12 @@ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, - "acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true - }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "ag-charts-community": { "version": "10.3.4", @@ -14801,12 +14802,6 @@ } } }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -14817,6 +14812,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -15031,9 +15027,9 @@ "optional": true }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -15041,24 +15037,24 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { - "version": "4.22.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.3.tgz", - "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001580", - "electron-to-chromium": "^1.4.648", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" } }, "buffer-from": { @@ -15115,9 +15111,9 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "caniuse-lite": { - "version": "1.0.30001582", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001582.tgz", - "integrity": "sha512-vsJG3V5vgfduaQGVxL53uSX/HUzxyr2eA8xCo36OLal7sRcSZbibJtLeh0qja4sFOr/QQGt4opB4tOy+eOgAxg==", + "version": "1.0.30001727", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", + "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", "dev": true }, "ccount": { @@ -15129,6 +15125,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -15138,7 +15135,8 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true } } }, @@ -15217,6 +15215,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -15224,7 +15223,8 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "color-string": { "version": "1.9.1", @@ -15303,9 +15303,9 @@ } }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -15482,9 +15482,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.653", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.653.tgz", - "integrity": "sha512-wA2A2LQCqnEwQAvwADQq3KpMpNwgAUBnRmrFgRzHnPhbQUFArTR32Ab46f4p0MovDLcg4uqd4nCsN2hTltslpA==", + "version": "1.5.189", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.189.tgz", + "integrity": "sha512-y9D1ntS1ruO/pZ/V2FtLE+JXLQe28XoRpZ7QCCo0T8LdQladzdcOVQZH/IWLVJvCw12OGMb6hYOeOAjntCmJRQ==", "dev": true }, "emoji-regex": { @@ -15506,9 +15506,9 @@ "dev": true }, "enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -15677,43 +15677,46 @@ } }, "esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", - "dev": true, - "requires": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", + "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.25.8", + "@esbuild/android-arm": "0.25.8", + "@esbuild/android-arm64": "0.25.8", + "@esbuild/android-x64": "0.25.8", + "@esbuild/darwin-arm64": "0.25.8", + "@esbuild/darwin-x64": "0.25.8", + "@esbuild/freebsd-arm64": "0.25.8", + "@esbuild/freebsd-x64": "0.25.8", + "@esbuild/linux-arm": "0.25.8", + "@esbuild/linux-arm64": "0.25.8", + "@esbuild/linux-ia32": "0.25.8", + "@esbuild/linux-loong64": "0.25.8", + "@esbuild/linux-mips64el": "0.25.8", + "@esbuild/linux-ppc64": "0.25.8", + "@esbuild/linux-riscv64": "0.25.8", + "@esbuild/linux-s390x": "0.25.8", + "@esbuild/linux-x64": "0.25.8", + "@esbuild/netbsd-arm64": "0.25.8", + "@esbuild/netbsd-x64": "0.25.8", + "@esbuild/openbsd-arm64": "0.25.8", + "@esbuild/openbsd-x64": "0.25.8", + "@esbuild/openharmony-arm64": "0.25.8", + "@esbuild/sunos-x64": "0.25.8", + "@esbuild/win32-arm64": "0.25.8", + "@esbuild/win32-ia32": "0.25.8", + "@esbuild/win32-x64": "0.25.8" } }, "esbuild-loader": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-4.1.0.tgz", - "integrity": "sha512-543TtIvqbqouEMlOHg4xKoDQkmdImlwIpyAIgpUtDPvMuklU/c2k+Qt2O3VeDBgAwozxmlEbjOzV+F8CZ0g+Bw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-4.3.0.tgz", + "integrity": "sha512-D7HeJNdkDKKMarPQO/3dlJT6RwN2YJO7ENU6RPlpOz5YxSHnUNi2yvW41Bckvi1EVwctIaLzlb0ni5ag2GINYA==", "dev": true, "requires": { - "esbuild": "^0.20.0", + "esbuild": "^0.25.0", "get-tsconfig": "^4.7.0", "loader-utils": "^2.0.4", "webpack-sources": "^1.4.3" @@ -15738,9 +15741,9 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-string-regexp": { @@ -15902,7 +15905,8 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.9", @@ -16203,9 +16207,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -16454,7 +16458,8 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true }, "has-property-descriptors": { "version": "1.0.1", @@ -16745,7 +16750,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "dev": true, + "requires": {} }, "ignore": { "version": "5.3.1", @@ -18573,12 +18579,12 @@ "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==" }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, @@ -18635,9 +18641,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true }, "natural-compare": { @@ -18668,9 +18674,9 @@ } }, "node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, "normalize-package-data": { @@ -18718,9 +18724,9 @@ }, "dependencies": { "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, "requires": { "nice-try": "^1.0.4", @@ -18982,10 +18988,9 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "2.3.1", @@ -19080,7 +19085,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.4", @@ -19191,7 +19197,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", - "dev": true, "requires": { "loose-envify": "^1.1.0" } @@ -19226,7 +19231,6 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", - "dev": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -19357,11 +19361,6 @@ "regenerate": "^1.4.2" } }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", @@ -19650,9 +19649,9 @@ }, "dependencies": { "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -19754,15 +19753,14 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", - "dev": true, "requires": { "loose-envify": "^1.1.0" } }, "schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", + "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", @@ -20130,7 +20128,8 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "dev": true + "dev": true, + "requires": {} }, "style-to-object": { "version": "0.4.4", @@ -20158,6 +20157,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -20168,23 +20168,29 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", "dev": true }, "terser": { - "version": "5.27.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.0.tgz", - "integrity": "sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==", + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", + "acorn": "^8.14.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "dependencies": { + "acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -20194,29 +20200,16 @@ } }, "terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.20", + "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "dependencies": { - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" } }, "test-exclude": { @@ -20242,11 +20235,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -20376,9 +20364,9 @@ } }, "undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true }, "unicode-canonical-property-names-ecmascript": { @@ -20479,13 +20467,13 @@ } }, "update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" } }, "uri-js": { @@ -20599,9 +20587,9 @@ } }, "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -20614,47 +20602,50 @@ "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==" }, "webpack": { - "version": "5.90.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.1.tgz", - "integrity": "sha512-SstPdlAC5IvgFnhiRok8hqJo/+ArAbNv7rhU4fnWGHNVfN59HSQFaxZDSAL3IFG2YmqxuRs+IU33milSxbPlog==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", + "version": "5.100.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.100.2.tgz", + "integrity": "sha512-QaNKAvGCDRh3wW1dsDjeMdDXwZm2vqq3zn6Pvq4rHOEOGSaUMgOOjG2Y9ZbIGzpfkJk9ZYTHpDqgDfeBDcnLaw==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", + "schema-utils": "^4.3.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.3.3" }, "dependencies": { - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true + }, + "acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } + "requires": {} } } }, @@ -20699,9 +20690,9 @@ } }, "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true }, "which": { diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index e28d6313..7250339f 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -598,9 +598,12 @@ export function DashAgGrid(props) { } if (GRID_NESTED_FUNCTIONS[target]) { let adjustedVal = value; - if (target === 'rowSelection' && typeof value === 'string') { + if ( + target === 'rowSelection' && + typeof value === 'string' + ) { // to still support rowSelection='single' | 'multiple' deprecated in v32.3.4 - return value + return value; } if ('suppressCallback' in value) { adjustedVal = { From d825b3202edf7121b5eb24f1e99c20021bf5a540 Mon Sep 17 00:00:00 2001 From: Adrian Borrmann Date: Wed, 23 Jul 2025 08:43:18 -0600 Subject: [PATCH 24/24] v32.3.0 --- CHANGELOG.md | 5 ++++- package-lock.json | 46 ++++++++++++++++++++-------------------------- package.json | 2 +- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1cc912f..283860ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,14 @@ All notable changes to `dash-ag-grid` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). Links "DE#nnn" prior to version 2.0 point to the Dash Enterprise closed-source Dash AG Grid repo -## UNRELEASED +## [32.3.0] - 2025-07-23 ### Changed - Component is refactored to be a function component rather than a class +### Fixed +- [#387](https://github.com/plotly/dash-ag-grid/pull/387) fixed `isRowSelectable` prop ([issue #379](https://github.com/plotly/dash-ag-grid/issues/379)) + ## [32.3.0rc0] - 2025-04-15 ### Fixed diff --git a/package-lock.json b/package-lock.json index 208a80e8..8a578a5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-ag-grid", - "version": "32.3.0rc0", + "version": "32.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dash-ag-grid", - "version": "32.3.0rc0", + "version": "32.3.0", "license": "MIT", "dependencies": { "@emotion/react": "^11.11.3", @@ -10033,6 +10033,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -10074,6 +10075,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -10833,6 +10835,7 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0" } @@ -12817,8 +12820,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "requires": {} + "dev": true }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -13816,8 +13818,7 @@ "@emotion/use-insertion-effect-with-fallbacks": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "requires": {} + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==" }, "@emotion/utils": { "version": "1.2.1", @@ -14319,8 +14320,7 @@ "@mui/types": { "version": "7.2.13", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.13.tgz", - "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==", - "requires": {} + "integrity": "sha512-qP9OgacN62s+l8rdDhSFRe05HWtLLJ5TGclC9I1+tQngbssu0m2dmFZs+Px53AcOs9fD7TbYd4gc9AXzVqO/+g==" }, "@mui/utils": { "version": "5.15.7", @@ -14674,22 +14674,19 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/info": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "requires": {} + "dev": true }, "@webpack-cli/serve": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "requires": {} + "dev": true }, "@xtuc/ieee754": { "version": "1.2.0", @@ -14713,8 +14710,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "ag-charts-community": { "version": "10.3.4", @@ -15905,8 +15901,7 @@ "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-import-resolver-node": { "version": "0.3.9", @@ -16750,8 +16745,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} + "dev": true }, "ignore": { "version": "5.3.1", @@ -19085,8 +19079,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} + "dev": true }, "postcss-modules-local-by-default": { "version": "4.0.4", @@ -19197,6 +19190,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "requires": { "loose-envify": "^1.1.0" } @@ -19231,6 +19225,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -19753,6 +19748,7 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, "requires": { "loose-envify": "^1.1.0" } @@ -20128,8 +20124,7 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "dev": true, - "requires": {} + "dev": true }, "style-to-object": { "version": "0.4.4", @@ -20644,8 +20639,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "requires": {} + "dev": true } } }, diff --git a/package.json b/package.json index 06c42c8f..43d85e61 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dash-ag-grid", - "version": "32.3.0rc0", + "version": "32.3.0", "description": "Dash wrapper around AG Grid, the best interactive data grid for the web.", "repository": { "type": "git",