From cdf8be7e749e42ca5fb908af6a80b1b10a536e24 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 18 Sep 2025 18:13:53 +0200 Subject: [PATCH 1/7] Fix custom theme variables used --- demo/src/equipment-search.tsx | 2 +- .../customAGGrid/customAggrid.style.ts | 6 +- src/components/customAGGrid/customAggrid.tsx | 3 +- .../agGridTable/CustomAgGridTable.tsx | 125 +++++++++--------- src/index.ts | 4 +- src/module-mui.d.ts | 38 ++++-- src/utils/styles.ts | 4 +- 7 files changed, 104 insertions(+), 78 deletions(-) diff --git a/demo/src/equipment-search.tsx b/demo/src/equipment-search.tsx index 76f1d1db6..107934e74 100644 --- a/demo/src/equipment-search.tsx +++ b/demo/src/equipment-search.tsx @@ -15,7 +15,7 @@ import { equipmentStyles, EquipmentType, useElementSearch, -} from '../../src/index'; +} from '../../src'; interface AnyElementInterface { id: string; diff --git a/src/components/customAGGrid/customAggrid.style.ts b/src/components/customAGGrid/customAggrid.style.ts index 74a7fada4..7b0d9962b 100644 --- a/src/components/customAGGrid/customAggrid.style.ts +++ b/src/components/customAGGrid/customAggrid.style.ts @@ -15,9 +15,9 @@ export const styles = { position: 'relative', [`&.${CUSTOM_AGGRID_THEME}`]: { - '--ag-value-change-value-highlight-background-color': theme.aggrid.valueChangeHighlightBackgroundColor, - '--ag-selected-row-background-color': theme.aggrid.highlightColor, - '--ag-row-hover-color': theme.aggrid.highlightColor, + '--ag-value-change-value-highlight-background-color': theme.agGrid.valueChangeHighlightBackgroundColor, + '--ag-selected-row-background-color': theme.agGrid.highlightColor, + '--ag-row-hover-color': theme.agGrid.highlightColor, }, '& .ag-checkbox-input': { diff --git a/src/components/customAGGrid/customAggrid.tsx b/src/components/customAGGrid/customAggrid.tsx index 1df51e84c..5215bcf93 100644 --- a/src/components/customAGGrid/customAggrid.tsx +++ b/src/components/customAGGrid/customAggrid.tsx @@ -53,6 +53,7 @@ function onColumnResized({ api, column, finished, source }: ColumnResizedEvent) } } +// TODO try to expose of props that forwardRef don't permit export const CustomAGGrid = forwardRef( ({ overrideLocales, sx, ...agGridReactProps }, ref) => { const theme = useTheme(); @@ -61,7 +62,7 @@ export const CustomAGGrid = forwardRef( ({ - grid: (theme: any) => ({ - width: 'auto', - height: '100%', - position: 'relative', - - // - AG Grid colors override - - // It shouldn't be exactly like this, but I couldn't make it works otherwise - // https://www.ag-grid.com/react-data-grid/global-style-customisation/ - '--ag-alpine-active-color': `${theme.palette.primary.main} !important`, - '--ag-checkbox-indeterminate-color': `${theme.palette.primary.main} !important`, - '--ag-background-color': `${theme.agGridBackground.color} !important`, - '--ag-header-background-color': `${theme.agGridBackground.color} !important`, - '--ag-odd-row-background-color': `${theme.agGridBackground.color} !important`, - '--ag-modal-overlay-background-color': `${theme.agGridBackground.color} !important`, - '--ag-selected-row-background-color': 'transparent !important', - '--ag-range-selection-border-color': 'transparent !important', - - // overrides the default computed max height for ag grid default selector editor to make it more usable - // can be removed if a custom selector editor is implemented - '& .ag-select-list': { - maxHeight: '300px !important', - }, - '& .ag-root-wrapper-body': { - maxHeight: '500px', - }, - '& .ag-cell': { - boxShadow: 'none', - }, - '& .ag-cell-edit-wrapper': { - height: 'inherit', - }, - '& .ag-row-hover': { - cursor: 'text', - }, - '& .ag-overlay-loading-center': { - border: 'none', - boxShadow: 'none', - }, - '& .numeric-input': { - fontSize: 'calc(var(--ag-font-size) + 1px)', - paddingLeft: 'calc(var(--ag-cell-horizontal-padding) - 1px)', - width: '100%', +const style = (customProps: CSSObject) => + ({ + grid: (theme) => ({ + width: 'auto', height: '100%', - border: 'inherit', - outline: 'inherit', - backgroundColor: theme.agGridBackground.color, - }, - '& .Mui-focused .MuiOutlinedInput-root': { - // borders moves row height - outline: 'var(--ag-borders-input) var(--ag-input-focus-border-color)', - outlineOffset: '-1px', - backgroundColor: theme.agGridBackground.color, - }, - ...customProps, - }), -}); + position: 'relative', + + // - AG Grid colors override - + // It shouldn't be exactly like this, but I couldn't make it works otherwise + // https://www.ag-grid.com/react-data-grid/global-style-customisation/ + '--ag-alpine-active-color': `${theme.palette.primary.main} !important`, + '--ag-checkbox-indeterminate-color': `${theme.palette.primary.main} !important`, + '--ag-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-header-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-odd-row-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-modal-overlay-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-selected-row-background-color': 'transparent !important', + '--ag-range-selection-border-color': 'transparent !important', + + // overrides the default computed max height for ag grid default selector editor to make it more usable + // can be removed if a custom selector editor is implemented + '& .ag-select-list': { + maxHeight: '300px !important', + }, + '& .ag-root-wrapper-body': { + maxHeight: '500px', + }, + '& .ag-cell': { + boxShadow: 'none', + }, + '& .ag-cell-edit-wrapper': { + height: 'inherit', + }, + '& .ag-row-hover': { + cursor: 'text', + }, + '& .ag-overlay-loading-center': { + border: 'none', + boxShadow: 'none', + }, + '& .numeric-input': { + fontSize: 'calc(var(--ag-font-size) + 1px)', + paddingLeft: 'calc(var(--ag-cell-horizontal-padding) - 1px)', + width: '100%', + height: '100%', + border: 'inherit', + outline: 'inherit', + backgroundColor: theme.agGrid.backgroundColor, + }, + '& .Mui-focused .MuiOutlinedInput-root': { + // borders moves row height + outline: 'var(--ag-borders-input) var(--ag-input-focus-border-color)', + outlineOffset: '-1px', + backgroundColor: theme.agGrid.backgroundColor, + }, + ...customProps, + }), + }) as const satisfies MuiStyles; export type CustomAgGridTableProps = Required< Pick< @@ -86,7 +88,7 @@ export type CustomAgGridTableProps = Required< name: string; makeDefaultRowData: any; csvProps: unknown; - cssProps: unknown; + cssProps: CSSObject; }; export function CustomAgGridTable({ @@ -97,8 +99,7 @@ export function CustomAgGridTable({ rowSelection, ...props }: Readonly) { - // FIXME: right type => Theme --> not defined there ( gridStudy and gridExplore definition not the same ) - const theme: any = useTheme(); + const theme = useTheme(); const [gridApi, setGridApi] = useState(null); const [selectedRows, setSelectedRows] = useState([]); const [newRowAdded, setNewRowAdded] = useState(false); @@ -208,7 +209,7 @@ export function CustomAgGridTable({ return ( <> - + style(cssProps).grid, [cssProps])}> | undefined): sx is SxProps => { export const mergeSx = (...allSx: (SxProps | undefined)[]) => allSx.filter(isSxProps).flat(); export type SxStyle = SxProps; +export type SxStyleObject = SystemStyleObject; export type MuiStyles = Record; From 37e353d534f95f3d8cbc36ddd45ed92329cc162b Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Thu, 18 Sep 2025 22:50:58 +0200 Subject: [PATCH 2/7] fix dts problem --- src/index.ts | 3 --- vite.config.ts | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index d5f087bed..21ccbb33f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,9 +4,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// Ensure the module augmentation is loaded whenever a project imports '@gridsuite/commons-ui' -import './module-mui'; - export * from './components'; export * from './hooks'; export * from './redux'; diff --git a/vite.config.ts b/vite.config.ts index 83cec47b5..d52516e88 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -16,6 +16,8 @@ import { globSync } from 'glob'; import * as path from 'node:path'; import * as url from 'node:url'; +const outDir = path.join(__dirname, 'dist'); + export default defineConfig((config) => ({ plugins: [ react(), @@ -27,7 +29,18 @@ export default defineConfig((config) => ({ libInjectCss(), dts({ include: ['src'], - exclude: '**/*.test.{ts,tsx}', + exclude: ['**/*.test.{ts,tsx}'], + copyDtsFiles: true, // copy existing .d.ts files from src to outDir + beforeWriteFile: (filePath, content) => { + if (filePath === `${outDir}/index.d.ts`) { + // vite doesn't support "import './f.d.ts'" and dts plugin doesn't keep "import type {}", so we inject it manually + return { + filePath, + content: `${content}\n// Ensure the module augmentation is loaded whenever a project imports '@gridsuite/commons-ui'\nimport './module-mui';\n`, + }; + } + return undefined; + }, }), ], build: { @@ -41,7 +54,7 @@ export default defineConfig((config) => ({ // from https://rollupjs.org/configuration-options/#input input: Object.fromEntries( globSync('src/**/*.{js,jsx,ts,tsx}', { - ignore: ['src/vite-env.d.ts', 'src/**/*.test.{js,jsx,ts,tsx}'], + ignore: ['src/vite-env.d.ts', 'src/**/*.test.{js,jsx,ts,tsx}', 'src/**/*.d.ts'], }).map((file) => [ // This remove `src/` as well as the file extension from each // file, so e.g. src/nested/foo.js becomes nested/foo From 61b6ca9a90bf211cf9a199ab9e6180a514e41d78 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Sep 2025 14:06:07 +0200 Subject: [PATCH 3/7] update (a little) demo --- ...izable-box.jsx => right-resizable-box.tsx} | 41 ++++++++++--------- src/index.ts | 2 + 2 files changed, 23 insertions(+), 20 deletions(-) rename demo/src/{right-resizable-box.jsx => right-resizable-box.tsx} (73%) diff --git a/demo/src/right-resizable-box.jsx b/demo/src/right-resizable-box.tsx similarity index 73% rename from demo/src/right-resizable-box.jsx rename to demo/src/right-resizable-box.tsx index e68301673..6f2c31ad3 100644 --- a/demo/src/right-resizable-box.jsx +++ b/demo/src/right-resizable-box.tsx @@ -4,15 +4,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* eslint-disable import/no-extraneous-dependencies */ -import { useState } from 'react'; +import { type PropsWithChildren, useState } from 'react'; import { MoreVert as ResizePanelHandleIcon } from '@mui/icons-material'; -import { ResizableBox } from 'react-resizable'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { ResizableBox, type ResizableBoxProps } from 'react-resizable'; +// eslint-disable-next-line import/no-extraneous-dependencies import { useWindowWidth } from '@react-hook/window-size'; -import PropTypes from 'prop-types'; import { Box, styled } from '@mui/material'; -import { mergeSx } from '../../src/utils/styles'; +import { mergeSx, type MuiStyles } from '../../src/utils/styles'; const styles = { panel: { @@ -47,25 +47,35 @@ const styles = { color: theme.palette.text.disabled, transform: 'scale(0.5, 1.5)', }), -}; +} as const satisfies MuiStyles; // TODO can we avoid to define a component just to add sx support ? const ResizableBoxSx = styled(ResizableBox)({}); -function RightResizableBox(props) { - const { children, disableResize = false, fullscreen = false, hide = false } = props; +export type RightResizableBoxProps = PropsWithChildren<{ + disableResize?: boolean; + fullscreen?: boolean; + hide?: boolean; +}>; + +export default function RightResizableBox({ + children, + disableResize = false, + fullscreen = false, + hide = false, +}: Readonly) { const windowWidth = useWindowWidth(); const [resizedTreePercentage, setResizedTreePercentage] = useState(0.5); - const updateResizedTreePercentage = (treePanelWidth, totalWidth) => { + const updateResizedTreePercentage = (treePanelWidth: number, totalWidth: number) => { if (totalWidth > 0) { const newPercentage = treePanelWidth / totalWidth; setResizedTreePercentage(newPercentage); } }; // eslint-disable-next-line @typescript-eslint/no-unused-vars - const onResize = (event, { element, size }) => { + const onResize: NonNullable = (_event, { size }) => { updateResizedTreePercentage(size.width, windowWidth); }; @@ -73,7 +83,7 @@ function RightResizableBox(props) { ); } - -RightResizableBox.propTypes = { - children: PropTypes.node, - disableResize: PropTypes.bool, - fullscreen: PropTypes.bool, - hide: PropTypes.bool, -}; - -export default RightResizableBox; diff --git a/src/index.ts b/src/index.ts index 21ccbb33f..e2fecd034 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +import type {} from './module-mui'; // here for demo + export * from './components'; export * from './hooks'; export * from './redux'; From e987982b0a169601800e52debb66efd028748f80 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Sep 2025 18:00:23 +0200 Subject: [PATCH 4/7] Exclude unwanted dts from build --- vite.config.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/vite.config.ts b/vite.config.ts index d52516e88..6367a1b48 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -32,14 +32,19 @@ export default defineConfig((config) => ({ exclude: ['**/*.test.{ts,tsx}'], copyDtsFiles: true, // copy existing .d.ts files from src to outDir beforeWriteFile: (filePath, content) => { - if (filePath === `${outDir}/index.d.ts`) { - // vite doesn't support "import './f.d.ts'" and dts plugin doesn't keep "import type {}", so we inject it manually - return { - filePath, - content: `${content}\n// Ensure the module augmentation is loaded whenever a project imports '@gridsuite/commons-ui'\nimport './module-mui';\n`, - }; + switch (filePath) { + case `${outDir}/index.d.ts`: + // vite doesn't support "import './f.d.ts'" and dts plugin doesn't keep "import type {}", so we inject it manually + return { + filePath, + content: `${content}\n// Ensure the module augmentation is loaded whenever a project imports '@gridsuite/commons-ui'\nimport './module-mui';\n`, + }; + case `${outDir}/module-localized-countries.d.ts`: + case `${outDir}/vite-env.d.ts`: + return false; + default: + return undefined; } - return undefined; }, }), ], From aa9d26c19ec38583c5b759200fbd55791dfe90f8 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Sep 2025 18:01:58 +0200 Subject: [PATCH 5/7] Update Mui augmentation with common code from fronts --- src/module-mui.d.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/module-mui.d.ts b/src/module-mui.d.ts index c04c3a39e..6f3a9c180 100644 --- a/src/module-mui.d.ts +++ b/src/module-mui.d.ts @@ -4,27 +4,43 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* eslint-disable no-restricted-imports */ // noinspection ES6UnusedImports import type {} from '@mui/material'; // dunno why we need to import like that for module augmentation to work import type { Property } from 'csstype'; +// https://mui.com/x/react-charts/quickstart/#typescript +// import type {} from '@mui/x-charts/themeAugmentation'; + +// https://mui.com/x/react-date-pickers/quickstart/#typescript +// import type {} from '@mui/x-date-pickers/themeAugmentation'; +// import type {} from '@mui/x-date-pickers/AdapterDayjs'; // replace `AdapterDayjs` with the adapter you're using + +// https://mui.com/x/react-tree-view/quickstart/#typescript +import type {} from '@mui/x-tree-view/themeAugmentation'; + +// https://mui.com/material-ui/about-the-lab/#typescript +import type {} from '@mui/lab/themeAugmentation'; + // used to customize mui theme & colors declare module '@mui/material/styles' { // https://mui.com/material-ui/customization/theming/#typescript interface Theme { agGrid: { - theme: string; + theme: 'ag-theme-alpine' | 'ag-theme-alpine-dark'; highlightColor: Property.Color; valueChangeHighlightBackgroundColor: Property.BackgroundColor; backgroundColor: Property.BackgroundColor; }; } + + // options of createTheme({...}) interface ThemeOptions { // do you use AgGrid component(s)? agGrid?: { // There is no default/fallback values, so all variables must be specified - theme: string; + theme: 'ag-theme-alpine' | 'ag-theme-alpine-dark'; highlightColor: Property.Color; valueChangeHighlightBackgroundColor: Property.BackgroundColor; backgroundColor: Property.BackgroundColor; @@ -40,4 +56,8 @@ declare module '@mui/material/styles' { // interface SimplePaletteColorOptions {} } +declare module '@mui/utils/capitalize' { + export default function capitalize(string: S): Capitalize; +} + export {}; // keep this file a module From f602647209ee67bb3922c95e3f9c017a3915eaab Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 19 Sep 2025 18:03:22 +0200 Subject: [PATCH 6/7] Pass aggrid extensions as optional as each apps set only some of them --- .../customAGGrid/customAggrid.style.ts | 10 +++- src/components/customAGGrid/customAggrid.tsx | 2 +- .../agGridTable/CustomAgGridTable.tsx | 58 +++++++++---------- src/module-mui.d.ts | 14 ++--- 4 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/components/customAGGrid/customAggrid.style.ts b/src/components/customAGGrid/customAggrid.style.ts index 7b0d9962b..b277e12a9 100644 --- a/src/components/customAGGrid/customAggrid.style.ts +++ b/src/components/customAGGrid/customAggrid.style.ts @@ -15,9 +15,13 @@ export const styles = { position: 'relative', [`&.${CUSTOM_AGGRID_THEME}`]: { - '--ag-value-change-value-highlight-background-color': theme.agGrid.valueChangeHighlightBackgroundColor, - '--ag-selected-row-background-color': theme.agGrid.highlightColor, - '--ag-row-hover-color': theme.agGrid.highlightColor, + ...(theme.agGrid?.valueChangeHighlightBackgroundColor && { + '--ag-value-change-value-highlight-background-color': theme.agGrid.valueChangeHighlightBackgroundColor, + }), + ...(theme.agGrid?.highlightColor && { + '--ag-selected-row-background-color': theme.agGrid.highlightColor, + '--ag-row-hover-color': theme.agGrid.highlightColor, + }), }, '& .ag-checkbox-input': { diff --git a/src/components/customAGGrid/customAggrid.tsx b/src/components/customAGGrid/customAggrid.tsx index 5215bcf93..e206fcdac 100644 --- a/src/components/customAGGrid/customAggrid.tsx +++ b/src/components/customAGGrid/customAggrid.tsx @@ -62,7 +62,7 @@ export const CustomAGGrid = forwardRef( // https://www.ag-grid.com/react-data-grid/global-style-customisation/ '--ag-alpine-active-color': `${theme.palette.primary.main} !important`, '--ag-checkbox-indeterminate-color': `${theme.palette.primary.main} !important`, - '--ag-background-color': `${theme.agGrid.backgroundColor} !important`, - '--ag-header-background-color': `${theme.agGrid.backgroundColor} !important`, - '--ag-odd-row-background-color': `${theme.agGrid.backgroundColor} !important`, - '--ag-modal-overlay-background-color': `${theme.agGrid.backgroundColor} !important`, + ...(theme.agGrid?.backgroundColor && { + '--ag-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-header-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-odd-row-background-color': `${theme.agGrid.backgroundColor} !important`, + '--ag-modal-overlay-background-color': `${theme.agGrid.backgroundColor} !important`, + }), '--ag-selected-row-background-color': 'transparent !important', '--ag-range-selection-border-color': 'transparent !important', @@ -61,13 +63,13 @@ const style = (customProps: CSSObject) => height: '100%', border: 'inherit', outline: 'inherit', - backgroundColor: theme.agGrid.backgroundColor, + ...(theme.agGrid?.backgroundColor && { backgroundColor: theme.agGrid.backgroundColor }), }, '& .Mui-focused .MuiOutlinedInput-root': { // borders moves row height outline: 'var(--ag-borders-input) var(--ag-input-focus-border-color)', outlineOffset: '-1px', - backgroundColor: theme.agGrid.backgroundColor, + ...(theme.agGrid?.backgroundColor && { backgroundColor: theme.agGrid.backgroundColor }), }, ...customProps, }), @@ -99,7 +101,6 @@ export function CustomAgGridTable({ rowSelection, ...props }: Readonly) { - const theme = useTheme(); const [gridApi, setGridApi] = useState(null); const [selectedRows, setSelectedRows] = useState([]); const [newRowAdded, setNewRowAdded] = useState(false); @@ -209,27 +210,26 @@ export function CustomAgGridTable({ return ( <> - style(cssProps).grid, [cssProps])}> - move(getIndex(e.node.data), e.overIndex)} - detailRowAutoHeight - onSelectionChanged={() => { - setSelectedRows(gridApi.api.getSelectedRows()); - }} - onRowDataUpdated={newRowAdded ? onRowDataUpdated : undefined} - onCellEditingStopped={onCellEditingStopped} - onSortChanged={onSortChanged} - getRowId={(row) => row.data[FieldConstants.AG_GRID_ROW_UUID]} - theme="legacy" - {...props} - /> - + move(getIndex(e.node.data), e.overIndex)} + detailRowAutoHeight + onSelectionChanged={() => { + setSelectedRows(gridApi.api.getSelectedRows()); + }} + onRowDataUpdated={newRowAdded ? onRowDataUpdated : undefined} + onCellEditingStopped={onCellEditingStopped} + onSortChanged={onSortChanged} + getRowId={(row) => row.data[FieldConstants.AG_GRID_ROW_UUID]} + theme="legacy" + sx={useMemo(() => style(cssProps).grid, [cssProps])} + {...props} + /> Date: Fri, 19 Sep 2025 19:31:13 +0200 Subject: [PATCH 7/7] `CancelButton` wans't declared correctly --- .../reactHookForm/utils/CancelButton.tsx | 4 +++- src/module-mui.d.ts | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/reactHookForm/utils/CancelButton.tsx b/src/components/inputs/reactHookForm/utils/CancelButton.tsx index b9a7ce5d6..886cc2439 100644 --- a/src/components/inputs/reactHookForm/utils/CancelButton.tsx +++ b/src/components/inputs/reactHookForm/utils/CancelButton.tsx @@ -8,7 +8,9 @@ import { Button, type ButtonProps, useThemeProps } from '@mui/material'; import { FormattedMessage } from 'react-intl'; -export function CancelButton(inProps: Readonly>) { +export type CancelButtonProps = Omit; + +export function CancelButton(inProps: Readonly) { const props = useThemeProps({ props: inProps, name: 'CancelButton' }); return (