monorepo/apps/web2/admin/_components/reducer/reduce.tsx

91 lines
2.9 KiB
TypeScript

import type { FC, PropsWithChildren } from 'react';
import { Switch } from 'antd';
import { createContext, useContext, useEffect, useReducer } from 'react';
import type { ThemeAction, ThemeContextType, ThemeState } from './types';
import { ThemeMode } from './types';
const initialState: ThemeState = {
mode: ThemeMode.LIGHT,
compact: false,
};
const ThemeContext = createContext<ThemeContextType>({
state: initialState,
dispatch: () => null,
});
const ThemeReducer = (state: ThemeState, action: ThemeAction) => {
switch (action.type) {
case 'change_mode':
return { ...state, mode: action.value };
case 'change_compact':
return { ...state, compact: action.value };
default:
throw new Error(`Unhandled action type`);
}
};
export const Theme: FC<PropsWithChildren> = ({ children }) => {
const [state, dispatch] = useReducer(ThemeReducer, initialState);
useEffect(() => {
const html = document.getElementsByTagName('html');
console.log(html[0], 'html');
if (html.length > 0) {
html[0].classList.remove('light', 'dark');
html[0].classList.add(state.mode);
}
}, [state.mode]);
return <ThemeContext value={{ state, dispatch }}>{children}</ThemeContext>;
};
export const ThemeConfig = () => {
const { state, dispatch } = useContext(ThemeContext);
const handleModeChange = () =>
dispatch({
type: 'change_mode',
value: state.mode === ThemeMode.LIGHT ? ThemeMode.DARK : ThemeMode.LIGHT,
});
const handleCompactChange = () =>
dispatch({
type: 'change_compact',
value: !state.compact,
});
return (
<>
<Switch
checkedChildren="🌛"
unCheckedChildren="🌞"
onChange={handleModeChange}
checked={state.mode === ThemeMode.DARK}
defaultChecked={state.mode === ThemeMode.DARK}
></Switch>
<Switch
checkedChildren="紧凑"
unCheckedChildren="正常"
onChange={handleCompactChange}
checked={state.compact}
defaultChecked={state.compact}
></Switch>
</>
);
};
export const ReducerDemo = () => {
const {
state: { mode, compact },
} = useContext(ThemeContext);
return (
<div className="tw-container">
<h2 className="tw-text-center dark:tw-text-white ">useReducer Demo</h2>
<div className="tw-flex tw-flex-col tw-items-center">
<p>: {mode === 'dark' ? '暗黑' : '明亮'}</p>
<p>: {compact ? '是' : '否'}</p>
<div className="tw-mb-5 tw-flex-auto">
<ThemeConfig />
</div>
</div>
</div>
);
};