@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
393 lines (392 loc) • 12.3 kB
JavaScript
import { createTheme } from '@mui/material';
import { blue, green, grey, orange, red } from '@mui/material/colors';
import deepmerge from 'deepmerge';
const refTheme = createTheme();
const midnight = refTheme.palette.augmentColor({ color: { main: '#0D233F' } });
const grape = refTheme.palette.augmentColor({ color: { main: '#721E63' } });
const forest = refTheme.palette.augmentColor({ color: { main: '#135560' } });
const mandarin = refTheme.palette.augmentColor({ color: { main: '#FFB11D' } });
const lightgrey = refTheme.palette.augmentColor({ color: { main: '#aaa' } });
const bases = {
A: refTheme.palette.augmentColor({ color: green }),
C: refTheme.palette.augmentColor({ color: blue }),
G: refTheme.palette.augmentColor({ color: orange }),
T: refTheme.palette.augmentColor({ color: red }),
};
const framesCDS = [
null,
refTheme.palette.augmentColor({ color: { main: '#FF8080' } }),
refTheme.palette.augmentColor({ color: { main: '#80FF80' } }),
refTheme.palette.augmentColor({ color: { main: '#8080FF' } }),
refTheme.palette.augmentColor({ color: { main: '#8080FF' } }),
refTheme.palette.augmentColor({ color: { main: '#80FF80' } }),
refTheme.palette.augmentColor({ color: { main: '#FF8080' } }),
];
const frames = [
null,
refTheme.palette.augmentColor({ color: { main: '#8f8f8f' } }),
refTheme.palette.augmentColor({ color: { main: '#adadad' } }),
refTheme.palette.augmentColor({ color: { main: '#d8d8d8' } }),
refTheme.palette.augmentColor({ color: { main: '#d8d8d8' } }),
refTheme.palette.augmentColor({ color: { main: '#adadad' } }),
refTheme.palette.augmentColor({ color: { main: '#8f8f8f' } }),
];
const stopCodon = '#e22';
const startCodon = '#3e3';
const insertion = '#800080';
const deletion = '#808080';
const hardclip = '#f00';
const softclip = '#00f';
const skip = '#97b8c9';
const defaults = {
primary: midnight,
secondary: grape,
tertiary: forest,
quaternary: mandarin,
highlight: mandarin,
stopCodon,
startCodon,
insertion,
deletion,
softclip,
hardclip,
bases,
frames,
framesCDS,
skip,
};
function stockTheme() {
return {
palette: {
...defaults,
mode: undefined,
},
components: {
MuiLink: {
styleOverrides: {
root: ({ theme }) => ({
color: theme.palette.tertiary.main,
}),
},
},
},
};
}
function getDefaultTheme() {
return {
...stockTheme(),
name: 'Default (from config)',
};
}
function getLightStockTheme() {
return {
...stockTheme(),
name: 'Light (stock)',
};
}
function getDarkStockTheme() {
return {
name: 'Dark (stock)',
palette: {
...defaults,
mode: 'dark',
},
components: {
MuiAppBar: {
defaultProps: {
enableColorOnDark: true,
},
styleOverrides: {
root: ({ theme }) => theme.palette.primary.main,
},
},
},
};
}
function getDarkMinimalTheme() {
return {
name: 'Dark (minimal)',
palette: {
...defaults,
mode: 'dark',
primary: { main: grey[700] },
secondary: { main: grey[800] },
tertiary: refTheme.palette.augmentColor({ color: { main: grey[900] } }),
},
};
}
function getMinimalTheme() {
return {
name: 'Light (minimal)',
palette: {
...defaults,
primary: { main: grey[900] },
secondary: { main: grey[800] },
tertiary: refTheme.palette.augmentColor({ color: { main: grey[900] } }),
},
};
}
export const defaultThemes = {
default: getDefaultTheme(),
lightStock: getLightStockTheme(),
lightMinimal: getMinimalTheme(),
darkMinimal: getDarkMinimalTheme(),
darkStock: getDarkStockTheme(),
};
function overwriteArrayMerge(_, sourceArray) {
return sourceArray;
}
export function createJBrowseBaseTheme(theme) {
const themeP = {
palette: theme?.palette,
typography: {
fontSize: 12,
},
spacing: 4,
components: {
MuiTooltip: {
styleOverrides: {
tooltip: {
fontSize: 12,
},
},
},
MuiButton: {
defaultProps: {
size: 'small',
},
styleOverrides: {
root: ({ theme }) => theme.palette.mode === 'dark'
? {
color: theme.palette.text.primary,
}
: undefined,
},
},
MuiAccordion: {
defaultProps: {
disableGutters: true,
slotProps: {
transition: {
timeout: 150,
unmountOnExit: true,
},
},
},
},
MuiFilledInput: {
defaultProps: {
margin: 'dense',
},
},
MuiFormControl: {
defaultProps: {
margin: 'dense',
size: 'small',
},
},
MuiFormHelperText: {
defaultProps: {
margin: 'dense',
},
},
MuiIconButton: {
defaultProps: {
size: 'small',
},
},
MuiInputBase: {
defaultProps: {
margin: 'dense',
},
},
MuiAutocomplete: {
defaultProps: {
size: 'small',
},
},
MuiInputLabel: {
defaultProps: {
margin: 'dense',
},
},
MuiToolbar: {
defaultProps: {
variant: 'dense',
},
},
MuiListItem: {
defaultProps: {
dense: true,
},
},
MuiOutlinedInput: {
defaultProps: {
margin: 'dense',
},
},
MuiFab: {
defaultProps: {
size: 'small',
},
styleOverrides: {
secondary: {
backgroundColor: theme?.palette?.quaternary?.main,
},
},
},
MuiTable: {
defaultProps: {
size: 'small',
},
},
MuiPopover: {
defaultProps: {
transitionDuration: 0,
},
},
MuiMenu: {
defaultProps: {
transitionDuration: 0,
},
},
MuiMenuItem: {
defaultProps: {
dense: true,
},
},
MuiTextField: {
defaultProps: {
margin: 'dense',
variant: 'standard',
},
},
MuiLink: {
styleOverrides: {
root: ({ theme }) => ({
color: theme.palette.text.secondary,
}),
},
},
MuiCheckbox: {
styleOverrides: {
root: ({ theme }) => theme.palette.mode === 'dark'
? {
color: theme.palette.text.secondary,
'&.Mui-checked': {
color: theme.palette.text.secondary,
},
}
: undefined,
},
},
MuiRadio: {
styleOverrides: {
root: ({ theme }) => theme.palette.mode === 'dark'
? {
color: theme.palette.text.secondary,
'&.Mui-checked': {
color: theme.palette.text.secondary,
},
}
: undefined,
},
},
MuiFormLabel: {
styleOverrides: {
root: ({ theme }) => theme.palette.mode === 'dark'
? {
color: theme.palette.text.secondary,
'&.Mui-focused': {
color: theme.palette.text.secondary,
},
}
: undefined,
},
},
MuiAccordionSummary: {
styleOverrides: {
root: {
backgroundColor: theme?.palette?.tertiary?.main,
},
content: {
color: theme?.palette?.tertiary?.contrastText,
},
},
},
MuiToggleButtonGroup: {
defaultProps: {
size: 'small',
},
},
MuiButtonBase: {
styleOverrides: {
root: {
'& .MuiTouchRipple-ripple': {
animationDuration: '50ms !important',
},
'& .MuiTouchRipple-child': {
animationDuration: '50ms !important',
},
},
},
},
},
};
return deepmerge(themeP, theme || {}, { arrayMerge: overwriteArrayMerge });
}
const themeCache = new Map();
function getThemeCacheKey(configTheme, themeName) {
return JSON.stringify({ configTheme, themeName });
}
export function createJBrowseTheme(configTheme = {}, themes = defaultThemes, themeName = 'default') {
const cacheKey = getThemeCacheKey(configTheme, themeName);
const cached = themeCache.get(cacheKey);
if (cached) {
return cached;
}
const theme = createTheme(createJBrowseBaseTheme(themeName === 'default'
? deepmerge(themes.default, augmentThemeColors(configTheme), {
arrayMerge: overwriteArrayMerge,
})
: addMissingColors(themes[themeName])));
themeCache.set(cacheKey, theme);
return theme;
}
function augmentThemeColors(theme = {}) {
const augmentedPalette = Object.create(null);
for (const entry of [
'primary',
'secondary',
'tertiary',
'quaternary',
'highlight',
]) {
const paletteEntry = theme.palette?.[entry];
if (paletteEntry) {
augmentedPalette[entry] = refTheme.palette.augmentColor('color' in paletteEntry
? paletteEntry
: { color: paletteEntry });
}
}
return Object.keys(augmentedPalette).length > 0
? deepmerge(theme, { palette: augmentedPalette })
: theme;
}
function addMissingColors(theme = {}) {
const { palette } = theme;
return augmentThemeColors(deepmerge(theme, {
palette: {
quaternary: palette?.quaternary || lightgrey,
tertiary: palette?.tertiary || lightgrey,
highlight: palette?.highlight || mandarin,
insertion: palette?.insertion || insertion,
softclip: palette?.softclip || softclip,
skip: palette?.skip || skip,
hardclip: palette?.hardclip || hardclip,
deletion: palette?.deletion || deletion,
startCodon: palette?.startCodon || startCodon,
stopCodon: palette?.stopCodon || stopCodon,
},
}));
}