mirror of
https://github.com/traccar/traccar-web.git
synced 2025-01-07 03:26:42 +08:00
Theme and styles RTL support
This commit is contained in:
parent
393651524b
commit
79c6ac5e2c
43
package-lock.json
generated
43
package-lock.json
generated
@ -37,6 +37,8 @@
|
||||
"react-window": "^1.8.10",
|
||||
"recharts": "^2.12.4",
|
||||
"redux": "^5.0.1",
|
||||
"stylis": "^4.3.1",
|
||||
"stylis-plugin-rtl": "^2.1.1",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-pwa": "^0.19.8",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
@ -1687,6 +1689,11 @@
|
||||
"stylis": "4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin/node_modules/stylis": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
||||
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
|
||||
},
|
||||
"node_modules/@emotion/cache": {
|
||||
"version": "11.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
|
||||
@ -1699,6 +1706,11 @@
|
||||
"stylis": "4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/cache/node_modules/stylis": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
||||
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
|
||||
},
|
||||
"node_modules/@emotion/hash": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
|
||||
@ -5198,9 +5210,9 @@
|
||||
"integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
|
||||
},
|
||||
"node_modules/@types/pbf": {
|
||||
"version": "3.0.5",
|
||||
@ -6129,6 +6141,14 @@
|
||||
"resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
|
||||
"integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
|
||||
},
|
||||
"node_modules/cssjanus": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cssjanus/-/cssjanus-2.1.0.tgz",
|
||||
"integrity": "sha512-kAijbny3GmdOi9k+QT6DGIXqFvL96aksNlGr4Rhk9qXDZYWUojU4bRc3IHWxdaLNOqgEZHuXoe5Wl2l7dxLW5g==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
@ -10820,9 +10840,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
||||
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz",
|
||||
"integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ=="
|
||||
},
|
||||
"node_modules/stylis-plugin-rtl": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stylis-plugin-rtl/-/stylis-plugin-rtl-2.1.1.tgz",
|
||||
"integrity": "sha512-q6xIkri6fBufIO/sV55md2CbgS5c6gg9EhSVATtHHCdOnbN/jcI0u3lYhNVeuI65c4lQPo67g8xmq5jrREvzlg==",
|
||||
"dependencies": {
|
||||
"cssjanus": "^2.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"stylis": "4.x"
|
||||
}
|
||||
},
|
||||
"node_modules/subtag": {
|
||||
"version": "0.5.0",
|
||||
|
@ -33,6 +33,8 @@
|
||||
"react-window": "^1.8.10",
|
||||
"recharts": "^2.12.4",
|
||||
"redux": "^5.0.1",
|
||||
"stylis": "^4.3.1",
|
||||
"stylis-plugin-rtl": "^2.1.1",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-pwa": "^0.19.8",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
|
@ -1,21 +1,40 @@
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { ThemeProvider, useMediaQuery } from '@mui/material';
|
||||
import { CacheProvider } from '@emotion/react';
|
||||
import createCache from '@emotion/cache';
|
||||
import { prefixer } from 'stylis';
|
||||
import rtlPlugin from 'stylis-plugin-rtl';
|
||||
import theme from './common/theme';
|
||||
import { useLocalization } from './common/components/LocalizationProvider';
|
||||
|
||||
const cache = {
|
||||
ltr: createCache({
|
||||
key: 'muiltr',
|
||||
stylisPlugins: [prefixer],
|
||||
}),
|
||||
rtl: createCache({
|
||||
key: 'muirtl',
|
||||
stylisPlugins: [prefixer, rtlPlugin],
|
||||
}),
|
||||
};
|
||||
|
||||
const AppThemeProvider = ({ children }) => {
|
||||
const server = useSelector((state) => state.session.server);
|
||||
const { direction } = useLocalization();
|
||||
|
||||
const serverDarkMode = server?.attributes?.darkMode;
|
||||
const preferDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
|
||||
const darkMode = serverDarkMode !== undefined ? serverDarkMode : preferDarkMode;
|
||||
|
||||
const themeInstance = theme(server, darkMode);
|
||||
const themeInstance = theme(server, darkMode, direction);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={themeInstance}>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
<CacheProvider value={cache[direction]}>
|
||||
<ThemeProvider theme={themeInstance}>
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
</CacheProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -152,8 +152,9 @@ const LocalizationContext = createContext({
|
||||
|
||||
export const LocalizationProvider = ({ children }) => {
|
||||
const [language, setLanguage] = usePersistedState('language', getDefaultLanguage());
|
||||
const direction = /^(ar|he|fa)$/.test(language) ? 'rtl' : 'ltr';
|
||||
|
||||
const value = useMemo(() => ({ languages, language, setLanguage }), [languages, language, setLanguage]);
|
||||
const value = useMemo(() => ({ languages, language, setLanguage, direction }), [languages, language, setLanguage, direction]);
|
||||
|
||||
useEffect(() => {
|
||||
let selected;
|
||||
@ -163,8 +164,8 @@ export const LocalizationProvider = ({ children }) => {
|
||||
selected = language;
|
||||
}
|
||||
dayjs.locale(selected);
|
||||
document.dir = /^(ar|he|fa)$/.test(language) ? 'rtl' : 'ltr';
|
||||
}, [language]);
|
||||
document.dir = direction;
|
||||
}, [language, direction]);
|
||||
|
||||
return (
|
||||
<LocalizationContext.Provider value={value}>
|
||||
|
@ -4,8 +4,9 @@ import palette from './palette';
|
||||
import dimensions from './dimensions';
|
||||
import components from './components';
|
||||
|
||||
export default (server, darkMode) => useMemo(() => createTheme({
|
||||
export default (server, darkMode, direction) => useMemo(() => createTheme({
|
||||
palette: palette(server, darkMode),
|
||||
direction,
|
||||
dimensions,
|
||||
components,
|
||||
}), [server, darkMode]);
|
||||
}), [server, darkMode, direction]);
|
||||
|
Loading…
Reference in New Issue
Block a user