From 00d1e425c0559d12a6bda1d03f6cc22005e5b898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Sun, 30 Mar 2025 22:32:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAM2=20Builder=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E8=8D=89=E7=A8=BF=E7=9A=84=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scheme/m2-scheme/Builder.module.css | 6 ++ .../scheme/m2-scheme/Builder.tsx | 80 +++++++++++++------ 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/src/page-components/scheme/m2-scheme/Builder.module.css b/src/page-components/scheme/m2-scheme/Builder.module.css index 9de5b8d..ca2ee72 100644 --- a/src/page-components/scheme/m2-scheme/Builder.module.css +++ b/src/page-components/scheme/m2-scheme/Builder.module.css @@ -23,6 +23,12 @@ align-items: center; gap: var(--spacing-s); } + .button_row { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--spacing-s); + } h5 { font-size: var(--font-size-m); line-height: 1.7em; diff --git a/src/page-components/scheme/m2-scheme/Builder.tsx b/src/page-components/scheme/m2-scheme/Builder.tsx index 38501d4..ad74937 100644 --- a/src/page-components/scheme/m2-scheme/Builder.tsx +++ b/src/page-components/scheme/m2-scheme/Builder.tsx @@ -2,8 +2,12 @@ import { includes, isEmpty, isNil, merge } from 'lodash-es'; import { useActionState, useCallback, useMemo, useState } from 'react'; import { useColorFunction } from '../../../ColorFunctionContext'; import { FloatColorPicker } from '../../../components/FloatColorPicker'; +import { NotificationType, useNotification } from '../../../components/Notifications'; import { ScrollArea } from '../../../components/ScrollArea'; -import { MaterialDesign2SchemeStorage } from '../../../material-2-scheme'; +import { + MaterialDesign2SchemeSource, + MaterialDesign2SchemeStorage, +} from '../../../material-2-scheme'; import { SchemeContent } from '../../../models'; import { useUpdateScheme } from '../../../stores/schemes'; import { mapToObject } from '../../../utls'; @@ -16,6 +20,7 @@ type M2SchemeBuilderProps = { }; export function M2SchemeBuilder({ scheme, onBuildComplete }: M2SchemeBuilderProps) { + const { showToast } = useNotification(); const { colorFn } = useColorFunction(); const updateScheme = useUpdateScheme(scheme.id); const originalColors = useMemo(() => { @@ -35,45 +40,67 @@ export function M2SchemeBuilder({ scheme, onBuildComplete }: M2SchemeBuilderProp .filter((c) => !includes(deleted, c)), [originalColors, newColors, deleted], ); + const colectSchemeSource = (formData: FormData): MaterialDesign2SchemeSource => { + const primaryColor = formData.get('primary') as string; + const secondaryColor = formData.get('secondary') as string; + const errorColor = formData.get('error') as string; + const customColors: Record = {}; + for (const key of colorKeys) { + const name = formData.get(`name_${key}`) as string; + const color = formData.get(`color_${key}`) as string; + if (isNil(name) || isEmpty(name) || isNil(color) || isEmpty(color)) continue; + customColors[name] = color; + } + return { + primary: isNil(primaryColor) || isEmpty(primaryColor) ? null : primaryColor, + secondary: isNil(secondaryColor) || isEmpty(secondaryColor) ? null : secondaryColor, + error: isNil(errorColor) || isEmpty(errorColor) ? null : errorColor, + custom_colors: customColors, + }; + }; + + const [, handleDraftAction] = useActionState, FormData>( + (_state, formData) => { + const errMsg = new Map(); + + const collectedSource = colectSchemeSource(formData); + updateScheme((prev) => { + prev.schemeStorage.source = collectedSource; + return prev; + }); + setNewColors([]); + + showToast(NotificationType.SUCCESS, 'Scheme draft saved!', 'tabler:device-floppy', 3000); + + return errMsg; + }, + new Map(), + ); const [errMsg, handleSubmitAction] = useActionState, FormData>( (_state, formData) => { const errMsg = new Map(); try { - const primaryColor = formData.get('primary') as string; - if (isNil(primaryColor) || isEmpty(primaryColor)) { + const collected = colectSchemeSource(formData); + if (isNil(collected.primary) || isEmpty(collected.primary)) { errMsg.set('primary', 'Primary color is required'); } - const secondaryColor = formData.get('secondary') as string; - if (isNil(secondaryColor) || isEmpty(secondaryColor)) { + if (isNil(collected.secondary) || isEmpty(collected.secondary)) { errMsg.set('secondary', 'Secondary color is required'); } - const errorColor = formData.get('error') as string; - if (isNil(errorColor) || isEmpty(errorColor)) { + if (isNil(collected.error) || isEmpty(collected.error)) { errMsg.set('error', 'Error color is required'); } if (!isEmpty(errMsg)) return errMsg; - const customColors: Record = {}; - for (const key of colorKeys) { - const name = formData.get(`name_${key}`) as string; - const color = formData.get(`color_${key}`) as string; - if (isNil(name) || isEmpty(name) || isNil(color) || isEmpty(color)) continue; - customColors[name] = color; - } const generatedScheme = colorFn?.generate_material_design_2_scheme( - primaryColor, - secondaryColor, - errorColor, - customColors, + collected.primary, + collected.secondary, + collected.error, + collected.custom_colors, ); updateScheme((prev) => { - prev.schemeStorage.source = { - primary: primaryColor, - secondary: secondaryColor, - error: errorColor, - custom_colors: customColors, - }; + prev.schemeStorage.source = collected; prev.schemeStorage.scheme = merge(generatedScheme[0], { light: { custom_colors: mapToObject(generatedScheme[0].light.custom_colors) }, dark: { custom_colors: mapToObject(generatedScheme[0].dark.custom_colors) }, @@ -168,10 +195,13 @@ export function M2SchemeBuilder({ scheme, onBuildComplete }: M2SchemeBuilderProp onDelete={(index) => setDeleted((prev) => [...prev, index])} /> ))} -
+
+