This commit is contained in:
seb
2026-07-31 18:36:13 +02:00
parent ce8d7d04da
commit 083e48f621
15 changed files with 179 additions and 47 deletions

View File

@@ -8,6 +8,7 @@ import CircularProgress from '@mui/material/CircularProgress';
import IconButton from '@mui/material/IconButton';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import { injectMuiTheme } from './injectMuiTheme';
import { enqueueSnackbar } from 'notistack';
import { backendErrorFrom } from '../../utils/backendError';
import { panelTilePaperSx } from './panelTileLayout';
@@ -20,7 +21,7 @@ function valuesEqual(a, b) {
* Panel tile with centralized inline-edit chrome.
* Pass `onSave` to enable edit UI; omit it for read-only tiles (no edit icon).
*/
export class EditablePanelTile extends Component {
class EditablePanelTileBase extends Component {
constructor(props) {
super(props);
this.inputRef = createRef();
@@ -186,9 +187,11 @@ export class EditablePanelTile extends Component {
render() {
const {
theme,
wide = 1,
sx,
minHeight = 120,
tileKey,
renderDisplay,
renderEdit,
} = this.props;
@@ -198,8 +201,15 @@ export class EditablePanelTile extends Component {
return (
<Paper
variant="outlined"
sx={panelTilePaperSx({ wide, sx, minHeight, pending })}
elevation={0}
sx={panelTilePaperSx({
wide,
sx,
minHeight,
pending,
tileKey,
theme,
})}
>
{this.renderActions()}
{this.renderTitle()}
@@ -220,3 +230,5 @@ export class EditablePanelTile extends Component {
);
}
}
export const EditablePanelTile = injectMuiTheme(EditablePanelTileBase);

View File

@@ -2,9 +2,10 @@ import { Component } from 'react';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import { injectMuiTheme } from './injectMuiTheme';
import { GRID_COLUMNS, panelTilePaperSx } from './panelTileLayout';
export class PanelTile extends Component {
class PanelTileBase extends Component {
renderTitle() {
const { title } = this.props;
if (!title) return null;
@@ -20,12 +21,18 @@ export class PanelTile extends Component {
}
render() {
const { wide = 1, children, sx, minHeight = 120 } = this.props;
const { theme, wide = 1, children, sx, minHeight = 120, tileKey } = this.props;
return (
<Paper
variant="outlined"
sx={panelTilePaperSx({ wide, sx, minHeight })}
elevation={0}
sx={panelTilePaperSx({
wide,
sx,
minHeight,
tileKey,
theme,
})}
>
{this.renderTitle()}
<Box sx={{ flex: 1, minWidth: 0 }}>{children}</Box>
@@ -34,6 +41,8 @@ export class PanelTile extends Component {
}
}
export const PanelTile = injectMuiTheme(PanelTileBase);
export function PanelTileGrid({ children, sx }) {
return (
<Box

View File

@@ -0,0 +1,13 @@
import { useTheme } from '@mui/material/styles';
/** Injects MUI theme into class components (replaces removed withTheme HOC). */
export function injectMuiTheme(Wrapped) {
function ComponentWithTheme(props) {
const theme = useTheme();
return <Wrapped {...props} theme={theme} />;
}
const name = Wrapped.displayName || Wrapped.name || 'Component';
ComponentWithTheme.displayName = `injectMuiTheme(${name})`;
return ComponentWithTheme;
}

View File

@@ -17,7 +17,21 @@ export function responsiveColumnSpan(wide) {
export const PENDING_EDIT_RING_PX = 4;
export function panelTilePaperSx({ wide, sx, minHeight = 120, pending = false }) {
export function panelTileBackground(theme, tileKey) {
if (!tileKey || !theme?.panelTiles) return undefined;
return theme.panelTiles[tileKey];
}
export function panelTilePaperSx({
wide,
sx,
minHeight = 120,
pending = false,
tileKey,
theme,
}) {
const tileBg = panelTileBackground(theme, tileKey);
return {
gridColumn: responsiveColumnSpan(wide),
position: 'relative',
@@ -25,6 +39,9 @@ export function panelTilePaperSx({ wide, sx, minHeight = 120, pending = false })
minHeight,
display: 'flex',
flexDirection: 'column',
border: 'none',
boxShadow: 'none',
...(tileBg ? { bgcolor: tileBg } : {}),
...(pending
? {
boxShadow: `inset 0 0 0 ${PENDING_EDIT_RING_PX}px ${PENDING_EDIT_BORDER}`,