Skip to content

Commit 194bac4

Browse files
lixl39505july
andauthored
fix(react): color mode control was not working (#13)
* fix(react): color mode control was not working --------- Co-authored-by: july <[email protected]>
1 parent 251ae80 commit 194bac4

File tree

12 files changed

+146
-127
lines changed

12 files changed

+146
-127
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.4.5 (July 25, 2025)
2+
3+
- fix(react): color mode control was not working
4+
15
## 0.4.4 (July 24, 2025)
26

37
- feat(react): supports colorMode configuration

packages/react/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@blocklet/theme-builder-react",
33
"description": "React component library for Blocklet Theme Builder",
4-
"version": "0.4.4",
4+
"version": "0.4.5",
55
"license": "0BSD",
66
"keywords": [
77
"MUI",
@@ -53,12 +53,12 @@
5353
},
5454
"dependencies": {
5555
"@abtnode/constant": "^1.16.46",
56-
"@arcblock/did-connect": "^3.0.27",
57-
"@arcblock/icons": "^3.0.27",
58-
"@arcblock/ux": "^3.0.27",
56+
"@arcblock/did-connect": "^3.0.32",
57+
"@arcblock/icons": "^3.0.32",
58+
"@arcblock/ux": "^3.0.32",
5959
"@babel/eslint-parser": "^7.28.0",
60-
"@blocklet/theme": "^3.0.27",
61-
"@blocklet/ui-react": "^3.0.27",
60+
"@blocklet/theme": "^3.0.32",
61+
"@blocklet/ui-react": "^3.0.32",
6262
"@emotion/react": "^11.14.0",
6363
"@emotion/styled": "^11.14.1",
6464
"@iconify/react": "^5.2.1",

packages/react/src/components/Editor/ColorsSection/ColorsSection.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@ function ColorsSection() {
4242
const { t } = useLocaleContext();
4343
const theme = useTheme();
4444
const concept = useThemeBuilder((s) => s.getCurrentConcept());
45-
const showColorMode = useThemeBuilder((s) => s.showColorMode);
46-
const { mode, prefer } = concept;
45+
const themeMode = useThemeBuilder((s) => s.themeMode);
46+
const mode = useThemeBuilder((s) => s.getThemeMode());
47+
const isShowThemeMode = useThemeBuilder((s) => s.shouldShowThemeMode());
48+
const { prefer } = concept;
4749
const isMobile = useMobile();
4850
const containerRef = useRef<HTMLDivElement>(null);
4951
const { width: containerWidth } = useDomSize(containerRef);
@@ -166,7 +168,7 @@ function ColorsSection() {
166168
{/* 工具栏 */}
167169
<Box sx={{ display: 'flex', gap: 1, justifyContent: 'flex-end', alignItems: 'center' }}>
168170
{/* 模式切换 */}
169-
{showColorMode && (
171+
{isShowThemeMode && (
170172
<Box
171173
sx={{
172174
display: 'flex',

packages/react/src/components/Editor/ColorsSection/ColorsSettingMenu.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { ThemePrefer } from 'src/types/theme';
88

99
export function ColorsSettingMenu() {
1010
const { t } = useLocaleContext();
11-
const showColorMode = useThemeBuilder((s) => s.showColorMode);
11+
const isShowThemeMode = useThemeBuilder((s) => s.shouldShowThemeMode());
1212
const prefer = useThemeBuilder((s) => s.getCurrentConcept().prefer);
1313
const setThemePrefer = useThemeBuilder((s) => s.setThemePrefer);
1414
const resetColors = useThemeBuilder((s) => s.resetColors);
@@ -65,7 +65,7 @@ export function ColorsSettingMenu() {
6565
sx: { minWidth: 120 },
6666
},
6767
}}>
68-
{showColorMode && (
68+
{isShowThemeMode && (
6969
<>
7070
<MenuItem onClick={() => handleOptionSelect('system')} selected={prefer === 'system'}>
7171
<Typography variant="body2">{t('editor.colorSection.modeDisable.none')}</Typography>

packages/react/src/index.tsx

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ export interface BaseThemeBuilderProps extends Omit<BoxProps, 'onChange'> {
6767
showPreview?: boolean;
6868
showEditor?: boolean;
6969
showHeader?: boolean;
70-
showColorMode?: boolean;
71-
colorMode?: Mode;
70+
themeMode?: Mode;
7271
locale?: Locale;
7372
themeOptions?: ThemeOptions;
7473
themeData?: ThemeData | null;
@@ -81,8 +80,7 @@ export function BaseThemeBuilder({
8180
showPreview = false,
8281
showEditor = true,
8382
showHeader = true,
84-
showColorMode = true,
85-
colorMode = undefined,
83+
themeMode = undefined,
8684
locale = 'en',
8785
themeOptions = {},
8886
themeData = undefined,
@@ -142,19 +140,10 @@ export function BaseThemeBuilder({
142140
useEffect(() => {
143141
const { setThemeMode } = store.getState();
144142

145-
if (colorMode === 'light' || colorMode === 'dark') {
146-
setThemeMode(colorMode);
143+
if (themeMode === 'light' || themeMode === 'dark') {
144+
setThemeMode(themeMode, { root: true });
147145
}
148-
}, [colorMode, store]);
149-
150-
// 隐藏/显示颜色模式切换
151-
useEffect(() => {
152-
const { setColorModeVisible } = store.getState();
153-
154-
if (showColorMode === true || showColorMode === false) {
155-
setColorModeVisible(showColorMode);
156-
}
157-
}, [showColorMode, store]);
146+
}, [themeMode, store]);
158147

159148
// 监听 store 数据变化
160149
useEffect(() => {
@@ -220,7 +209,7 @@ export function ThemeBuilder({
220209
let result: ThemeData | null = null;
221210

222211
// 无需拉取
223-
if (fetchTheme === false || themeData) {
212+
if (fetchTheme === false || outerThemeData) {
224213
setLoading(false);
225214
onLoad?.(null);
226215
return;
@@ -238,7 +227,7 @@ export function ThemeBuilder({
238227
} finally {
239228
setLoading(false);
240229
}
241-
}, [fetchTheme, setThemeData]);
230+
}, [fetchTheme, setThemeData, outerThemeData]);
242231

243232
return <BaseThemeBuilder themeData={outerThemeData || themeData} loading={loading} onSave={handleSave} {...rest} />;
244233
}

packages/react/src/state/createStore.ts

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ const getDefaultState = () => ({
8585
selectedComponentId: 'Website',
8686
themeObject: createPreviewMuiTheme(deepmerge({ palette: { mode: 'light' } }, getDefaultThemeConfig().light), false),
8787
saving: false,
88-
showColorMode: true,
8988
// 历史记录相关
9089
history: [],
9190
currentHistoryIndex: -1,
@@ -124,15 +123,6 @@ export default function createStore() {
124123
saveToHistory();
125124
},
126125
setSaving: (saving) => set({ saving }),
127-
getThemeData: () => {
128-
const { concepts, currentConceptId } = get();
129-
130-
return {
131-
concepts: cloneDeep(concepts),
132-
currentConceptId,
133-
};
134-
},
135-
setColorModeVisible: (visible) => set({ showColorMode: visible }),
136126

137127
// # 历史记录管理
138128
saveToHistory: () => {
@@ -519,12 +509,12 @@ export default function createStore() {
519509

520510
// # ThemeOptions 编辑
521511
setThemeOption: (path, value) => {
522-
const { saveToHistory } = get();
512+
const { saveToHistory, getThemeMode } = get();
523513

524514
set((state) => {
525515
const current = state.concepts.find((c) => c.id === state.currentConceptId);
526516
if (!current || !path) return {};
527-
const { mode } = current;
517+
const mode = getThemeMode();
528518

529519
const fieldName = getThemeFieldName(path, mode);
530520
const themeOptions = setByPath(current.themeConfig[fieldName], path, value);
@@ -541,12 +531,12 @@ export default function createStore() {
541531
saveToHistory();
542532
},
543533
setThemeOptions: (configs) => {
544-
const { saveToHistory } = get();
534+
const { saveToHistory, getThemeMode } = get();
545535

546536
set((state) => {
547537
const current = state.concepts.find((c) => c.id === state.currentConceptId);
548538
if (!current) return {};
549-
const { mode } = current;
539+
const mode = getThemeMode();
550540

551541
let newThemeOptions = { ...current.themeConfig };
552542

@@ -566,12 +556,12 @@ export default function createStore() {
566556
saveToHistory();
567557
},
568558
removeThemeOption: (path) => {
569-
const { saveToHistory } = get();
559+
const { saveToHistory, getThemeMode } = get();
570560

571561
set((state) => {
572562
const current = state.concepts.find((c) => c.id === state.currentConceptId);
573563
if (!current || !path) return {};
574-
const { mode } = current;
564+
const mode = getThemeMode();
575565

576566
const fieldName = getThemeFieldName(path, mode);
577567
const themeOptions = removeByPath(current.themeConfig[fieldName], path);
@@ -588,12 +578,12 @@ export default function createStore() {
588578
saveToHistory();
589579
},
590580
removeThemeOptions: (paths) => {
591-
const { saveToHistory } = get();
581+
const { saveToHistory, getThemeMode } = get();
592582

593583
set((state) => {
594584
const current = state.concepts.find((c) => c.id === state.currentConceptId);
595585
if (!current) return {};
596-
const { mode } = current;
586+
const mode = getThemeMode();
597587

598588
let newThemeOptions = { ...current.themeConfig };
599589
paths.forEach((p) => {
@@ -639,10 +629,17 @@ export default function createStore() {
639629
// 保存到历史记录
640630
saveToHistory();
641631
},
642-
setThemeMode: (mode) => {
632+
setThemeMode: (mode, { root = false } = {}) => {
643633
const { saveToHistory } = get();
644634

645635
set((state) => {
636+
// 修改根状态
637+
if (root === true) {
638+
return {
639+
themeMode: mode,
640+
};
641+
}
642+
646643
const current = state.concepts.find((c) => c.id === state.currentConceptId);
647644
if (!current) return {};
648645
return { concepts: state.concepts.map((c) => (c.id === state.currentConceptId ? { ...c, mode } : c)) };
@@ -651,6 +648,25 @@ export default function createStore() {
651648
// 保存到历史记录
652649
saveToHistory();
653650
},
651+
getThemeMode: () => {
652+
const { themeMode, getCurrentConcept } = get();
653+
654+
// 全局 themeMode 优先
655+
if (themeMode) {
656+
return themeMode;
657+
}
658+
659+
const concept = getCurrentConcept();
660+
if (concept) {
661+
return concept.mode;
662+
}
663+
return 'light';
664+
},
665+
shouldShowThemeMode: () => {
666+
const { themeMode } = get();
667+
668+
return themeMode === undefined;
669+
},
654670
updateThemeConfig: (themeConfig) => {
655671
const { saveToHistory } = get();
656672

@@ -664,8 +680,19 @@ export default function createStore() {
664680
saveToHistory();
665681
},
666682
getCurrentThemeOptions: () => {
667-
const concept = get().getCurrentConcept();
668-
return concept.themeConfig[concept.mode];
683+
const { getCurrentConcept, getThemeMode } = get();
684+
const concept = getCurrentConcept();
685+
const mode = getThemeMode();
686+
687+
return concept.themeConfig[mode];
688+
},
689+
getThemeData: () => {
690+
const { concepts, currentConceptId } = get();
691+
692+
return {
693+
concepts: cloneDeep(concepts),
694+
currentConceptId,
695+
};
669696
},
670697

671698
// # Colors 编辑
@@ -787,20 +814,18 @@ export default function createStore() {
787814

788815
// 实时更新 themeObject
789816
store.subscribe(
790-
(state) => [state.concepts, state.currentConceptId, state.previewSize],
817+
(state) => [state.concepts, state.currentConceptId, state.previewSize, state.themeMode],
791818
() => {
792819
const state = store.getState();
793820
const concept = state.getCurrentConcept();
794821

795822
let themeObject: Theme;
796823

797824
if (concept) {
825+
const mode = state.getThemeMode();
826+
798827
themeObject = createPreviewMuiTheme(
799-
deepmergeAll([
800-
{ palette: { mode: concept.mode } },
801-
concept.themeConfig.common,
802-
concept.themeConfig[concept.mode],
803-
]),
828+
deepmergeAll([{ palette: { mode } }, concept.themeConfig.common, concept.themeConfig[mode]]),
804829
state.previewSize,
805830
);
806831
} else {

packages/react/src/types/theme.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export interface ThemeStoreState {
6464
selectedComponentId: string;
6565
themeObject: Theme;
6666
saving: boolean;
67-
showColorMode: boolean;
67+
themeMode?: Mode;
6868
history: {
6969
concepts: Concept[];
7070
currentConceptId: string;
@@ -77,8 +77,6 @@ export interface ThemeStoreModel extends ThemeStoreState {
7777
// # 整体设置
7878
resetStore: () => void;
7979
setSaving: (saving: boolean) => void;
80-
getThemeData: () => ThemeData;
81-
setColorModeVisible: (visible: boolean) => void;
8280

8381
// # 历史记录管理
8482
undo: () => void;
@@ -112,9 +110,12 @@ export interface ThemeStoreModel extends ThemeStoreState {
112110
removeThemeOption: (path: string) => void;
113111
removeThemeOptions: (paths: string[]) => void;
114112
setThemePrefer: (prefer: ThemePrefer) => void;
115-
setThemeMode: (mode: Mode) => void;
116-
updateThemeConfig: (themeConfig: Concept['themeConfig']) => void;
113+
setThemeMode: (mode: Mode, options?: { root?: boolean }) => void;
114+
getThemeMode: () => Mode;
115+
shouldShowThemeMode: () => boolean;
117116
getCurrentThemeOptions: () => ThemeOptions;
117+
updateThemeConfig: (themeConfig: Concept['themeConfig']) => void;
118+
getThemeData: () => ThemeData;
118119

119120
// # Colors 编辑
120121
setColorLock: (colorKey: string, isLocked: boolean) => void;

packages/theme-builder/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@blocklet/theme-builder",
33
"description": "A comprehensive tool to customize themes for Material-UI",
4-
"version": "0.4.4",
4+
"version": "0.4.5",
55
"keywords": [
66
"MUI",
77
"MUI v5",

packages/theme-builder/src/hooks/useRemoteThemeSync.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ export default function useRemoteThemeSync() {
1717
getTheme({
1818
url: schemaKey,
1919
headers: getAuthHeaders(),
20-
}).finally(() => {
21-
setLoading(false);
22-
});
20+
})
21+
.then((data) => {
22+
setThemeData(data);
23+
})
24+
.finally(() => {
25+
setLoading(false);
26+
});
2327
}, [setThemeData, schemaKey]);
2428

2529
return { loading, themeData };

packages/theme-builder/src/pages/index.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,7 @@ function Index() {
6868
return (
6969
<ErrorBoundary>
7070
<ThemeProvider theme={siteTheme} injectFirst>
71-
<ThemeBuilder
72-
showPreview
73-
locale={locale}
74-
colorMode={parentTheme?.palette?.mode}
75-
themeData={themeData}
76-
onSave={saveTheme}
77-
/>
71+
<ThemeBuilder showPreview locale={locale} themeData={themeData} fetchTheme={false} onSave={saveTheme} />
7872
</ThemeProvider>
7973
</ErrorBoundary>
8074
);

0 commit comments

Comments
 (0)