From 5f3d58f0f5b178c8a999027853206fc6edb3e920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Sun, 30 Mar 2025 22:01:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAM3D=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 --- .../m3-dynamic-scheme/Builder.module.css | 6 ++ .../scheme/m3-dynamic-scheme/Builder.tsx | 85 +++++++++++++------ 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/page-components/scheme/m3-dynamic-scheme/Builder.module.css b/src/page-components/scheme/m3-dynamic-scheme/Builder.module.css index bd149d9..ca9de1a 100644 --- a/src/page-components/scheme/m3-dynamic-scheme/Builder.module.css +++ b/src/page-components/scheme/m3-dynamic-scheme/Builder.module.css @@ -29,6 +29,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/m3-dynamic-scheme/Builder.tsx b/src/page-components/scheme/m3-dynamic-scheme/Builder.tsx index 6776b77..5ea4c39 100644 --- a/src/page-components/scheme/m3-dynamic-scheme/Builder.tsx +++ b/src/page-components/scheme/m3-dynamic-scheme/Builder.tsx @@ -2,10 +2,14 @@ import { includes, isEmpty, isEqual, isNil } 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 { Switch } from '../../../components/Switch'; import { VSegmentedControl } from '../../../components/VSegmentedControl'; -import { MaterialDesign3DynamicSchemeStorage } from '../../../material-3-scheme'; +import { + MaterialDesign3DynamicSchemeSource, + MaterialDesign3DynamicSchemeStorage, +} from '../../../material-3-scheme'; import { Option, SchemeContent } from '../../../models'; import { useUpdateScheme } from '../../../stores/schemes'; import { mapToObject } from '../../../utls'; @@ -18,6 +22,7 @@ type M3DynamicSchemeBuilderProps = { }; export function M3DynamicSchemeBuilder({ scheme, onBuildCompleted }: M3DynamicSchemeBuilderProps) { + const { showToast } = useNotification(); const { colorFn } = useColorFunction(); const updateScheme = useUpdateScheme(scheme.id); const originalColors = useMemo(() => { @@ -49,7 +54,47 @@ export function M3DynamicSchemeBuilder({ scheme, onBuildCompleted }: M3DynamicSc const [contrastLevel, setContrastLevel] = useState( () => scheme.schemeStorage.source?.contrastLevel ?? 1, ); + const collectSchemeSource = (formData: FormData): MaterialDesign3DynamicSchemeSource => { + const sourceColor = formData.get('source') as string; + const dynamicVariant = Number(formData.get('variant')); + const contrast = Number(formData.get('contrast_level')); + const harmonizeCustoms = isEqual(formData.get('harmonize_customs'), 'true'); + 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 { + source: isNil(sourceColor) || isEmpty(sourceColor) ? null : sourceColor, + error: isNil(errorColor) || isEmpty(errorColor) ? null : errorColor, + custom_colors: customColors, + variant: dynamicVariant, + contrastLevel: contrast, + harmonizeCustoms: harmonizeCustoms, + }; + }; + + const [, handleDraftAction] = useActionState, FormData>( + (_state, formData) => { + const errMsg = new Map(); + + const collectedSource = collectSchemeSource(formData); + + updateScheme((prev) => { + prev.schemeStorage.source = collectedSource; + return prev; + }); + + 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(); @@ -61,35 +106,18 @@ export function M3DynamicSchemeBuilder({ scheme, onBuildCompleted }: M3DynamicSc if (!isEmpty(errMsg)) return errMsg; try { - const dynamicVariant = Number(formData.get('variant')); - const contrast = Number(formData.get('contrast_level')); - const harmonizeCustoms = isEqual(formData.get('harmonize_customs'), 'true'); - 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; - } + const collectedSource = collectSchemeSource(formData); const generate_scheme = colorFn.generate_material_design_3_dynamic_scheme( - sourceColor, - isNil(errorColor) || isEmpty(errorColor) ? null : errorColor, - dynamicVariant, - contrastLevel, - harmonizeCustoms, - customColors, + collectedSource.source, + collectedSource.error, + collectedSource.variant, + collectedSource.contrastLevel, + collectedSource.harmonizeCustoms, + collectedSource.custom_colors, ); updateScheme((prev) => { - prev.schemeStorage.source = { - source: sourceColor, - error: errorColor, - custom_colors: customColors, - variant: dynamicVariant, - contrastLevel: contrast, - harmonizeCustoms: harmonizeCustoms, - }; + prev.schemeStorage.source = collectedSource; prev.schemeStorage.scheme = { white: generate_scheme[0].white, black: generate_scheme[0].black, @@ -204,10 +232,13 @@ export function M3DynamicSchemeBuilder({ scheme, onBuildCompleted }: M3DynamicSc onDelete={(index) => setDeleted((prev) => [...prev, index])} /> ))} -
+
+