fix ccolor one page

This commit is contained in:
hamid zarghami
2026-05-06 14:53:55 +03:30
parent b1068eec26
commit 8717afbced
7 changed files with 77 additions and 30 deletions
+8 -6
View File
@@ -32,6 +32,8 @@ const EditorCanvas = ({ catalogSize }: EditorCanvasProps) => {
tool,
objects,
guides,
pages,
currentPageId,
selectedObjectId,
selectedObjectIds,
selectedCellId,
@@ -40,17 +42,17 @@ const EditorCanvas = ({ catalogSize }: EditorCanvasProps) => {
setLayerRef,
setGuides,
zoom,
documentSettings,
} = useEditorStore();
const currentPage = pages.find((page) => page.id === currentPageId);
const bgColor =
documentSettings.backgroundType === 'color'
? documentSettings.backgroundColor
currentPage?.backgroundType === 'color'
? currentPage.backgroundColor
: '#ffffff';
const [bgImage] = useImage(
documentSettings.backgroundType === 'image'
? documentSettings.backgroundImageUrl
currentPage?.backgroundType === 'image'
? (currentPage.backgroundImageUrl || '')
: '',
);
const stageSize = useStageSize(catalogSize);
@@ -394,7 +396,7 @@ const EditorCanvas = ({ catalogSize }: EditorCanvasProps) => {
fill={bgColor}
listening={false}
/>
{documentSettings.backgroundType === 'image' && bgImage && (
{currentPage?.backgroundType === 'image' && bgImage && (
<KonvaImage
image={bgImage}
x={0}
+19 -11
View File
@@ -27,11 +27,21 @@ const BACKGROUND_TYPE_OPTIONS: { value: BackgroundType; label: string }[] = [
]
const SettingsPanel = () => {
const { documentSettings, updateDocumentSettings } = useEditorStore()
const {
documentSettings,
pages,
currentPageId,
updateDocumentSettings,
updateCurrentPageBackground,
} = useEditorStore()
const colorInputRef = useRef<HTMLInputElement>(null)
const { mutateAsync: uploadFile, isPending: imageLoading } = useSingleUpload()
const currentPage = pages.find((page) => page.id === currentPageId)
const backgroundType = currentPage?.backgroundType ?? 'color'
const backgroundColor = currentPage?.backgroundColor ?? '#ffffff'
const backgroundImageUrl = currentPage?.backgroundImageUrl ?? ''
const [uploadedPreviews, setUploadedPreviews] = useState<string[]>(
documentSettings.backgroundImageUrl ? [documentSettings.backgroundImageUrl] : []
backgroundImageUrl ? [backgroundImageUrl] : []
)
const {
@@ -39,15 +49,13 @@ const SettingsPanel = () => {
autoPlay,
pageFlipSound,
leftToRightFlip,
backgroundType,
backgroundColor,
} = documentSettings
useEffect(() => {
setUploadedPreviews(
documentSettings.backgroundImageUrl ? [documentSettings.backgroundImageUrl] : []
backgroundImageUrl ? [backgroundImageUrl] : []
)
}, [documentSettings.backgroundImageUrl])
}, [backgroundImageUrl])
const handleImageFiles = async (files: File[]) => {
if (files.length === 0) return
@@ -59,7 +67,7 @@ const SettingsPanel = () => {
const imageUrl = result?.data?.url
if (!imageUrl) return
updateDocumentSettings({ backgroundImageUrl: imageUrl })
updateCurrentPageBackground({ backgroundImageUrl: imageUrl })
setUploadedPreviews([imageUrl])
} catch {
// TODO: show error toast
@@ -69,7 +77,7 @@ const SettingsPanel = () => {
const handlePreviewChange = (previews: string[]) => {
setUploadedPreviews(previews)
if (previews.length === 0) {
updateDocumentSettings({ backgroundImageUrl: '' })
updateCurrentPageBackground({ backgroundImageUrl: '' })
}
}
@@ -137,7 +145,7 @@ const SettingsPanel = () => {
<label key={opt.value} className="flex items-center gap-1.5 cursor-pointer select-none">
<span className="text-xs text-gray-600">{opt.label}</span>
<div
onClick={() => updateDocumentSettings({ backgroundType: opt.value })}
onClick={() => updateCurrentPageBackground({ backgroundType: opt.value })}
className={clx(
'w-4 h-4 rounded-full border-2 flex items-center justify-center transition-colors cursor-pointer',
backgroundType === opt.value
@@ -161,7 +169,7 @@ const SettingsPanel = () => {
{PRESET_COLORS.map((color) => (
<button
key={color}
onClick={() => updateDocumentSettings({ backgroundColor: color })}
onClick={() => updateCurrentPageBackground({ backgroundColor: color })}
className={clx(
'w-9 h-9 rounded-xl border-2 transition-all',
backgroundColor === color
@@ -184,7 +192,7 @@ const SettingsPanel = () => {
ref={colorInputRef}
type="color"
value={backgroundColor}
onChange={(e) => updateDocumentSettings({ backgroundColor: e.target.value })}
onChange={(e) => updateCurrentPageBackground({ backgroundColor: e.target.value })}
className="absolute inset-0 opacity-0 w-full h-full cursor-pointer"
/>
</button>
@@ -78,7 +78,6 @@ export const useDrawingHandlers = () => {
opacity: defaults.opacity,
letterSpacing: defaults.letterSpacing,
wordSpacing: defaults.wordSpacing,
width: 150,
height: defaults.fontSize || 24,
};
useEditorStore.getState().commitObjectHistoryBeforeChange();
+16 -12
View File
@@ -84,21 +84,25 @@ const TextShape = ({
textNode._setTextData();
const { width: rw, height: rh } = textNode.getClientRect({
// اندازه‌گیری طبیعی متن (بدون width تحمیلی) تا باکس واقعاً دور متن فیت شود.
const measureNode = textNode.clone({
width: undefined,
x: 0,
y: 0,
});
measureNode._setTextData();
const { width: rw, height: rh } = measureNode.getClientRect({
skipTransform: true,
});
const measuredWidth = Math.ceil(rw);
const h = Math.ceil(rh);
const nextWidth = obj.width && obj.width > 0 ? obj.width : measuredWidth;
measureNode.destroy();
// For text alignment to be visible, keep an existing text box width
// and only auto-calc width when the object has no width yet.
if (
nextWidth > 0 &&
h > 0 &&
(nextWidth !== obj.width || h !== obj.height)
) {
onUpdate(obj.id, { width: nextWidth, height: h });
const nextWidth = Math.max(1, Math.ceil(rw));
const nextHeight = Math.max(1, Math.ceil(rh));
const widthChanged = Math.abs((obj.width || 0) - nextWidth) > 1;
const heightChanged = Math.abs((obj.height || 0) - nextHeight) > 1;
if (widthChanged || heightChanged) {
onUpdate(obj.id, { width: nextWidth, height: nextHeight });
}
textNode.getLayer()?.batchDraw();
};
@@ -53,6 +53,9 @@ export const createInitialPage = (name: string): Page => ({
name,
objects: [],
guides: [],
backgroundType: "color",
backgroundColor: "#ffffff",
backgroundImageUrl: "",
});
export const reorderByIds = (
+28
View File
@@ -44,6 +44,11 @@ export type {
BackgroundType,
} from "./editorStore.types";
type PageBackgroundSettings = Pick<
Page,
"backgroundType" | "backgroundColor" | "backgroundImageUrl"
>;
type EditorStoreType = {
tool: ToolType;
setTool: (tool: ToolType) => void;
@@ -134,6 +139,7 @@ type EditorStoreType = {
sendObjectBackward: (id: string) => void;
documentSettings: DocumentSettings;
updateDocumentSettings: (updates: Partial<DocumentSettings>) => void;
updateCurrentPageBackground: (updates: Partial<PageBackgroundSettings>) => void;
};
export const useEditorStore = create<EditorStoreType>((set, get) => {
@@ -191,6 +197,18 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
set((state) => ({
documentSettings: { ...state.documentSettings, ...updates },
})),
updateCurrentPageBackground: (updates) =>
set((state) => {
if (!state.currentPageId) return {};
const currentPage = state.pages.find((p) => p.id === state.currentPageId);
if (!currentPage) return {};
const nextPage = { ...currentPage, ...updates };
return {
pages: state.pages.map((p) =>
p.id === state.currentPageId ? nextPage : p,
),
};
}),
tool: "select",
setTool: (tool) =>
set((state) => ({
@@ -816,6 +834,9 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
name: `${pageToDuplicate.name} (کپی)`,
objects: duplicatedObjects,
guides: [...pageToDuplicate.guides],
backgroundType: pageToDuplicate.backgroundType,
backgroundColor: pageToDuplicate.backgroundColor,
backgroundImageUrl: pageToDuplicate.backgroundImageUrl,
};
set((state) => ({
@@ -978,11 +999,18 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
},
loadPages: (pages, documentSettings) => {
if (pages.length === 0) return;
const fallbackSettings = documentSettings ?? {};
const normalizedPages = pages.map((page) => ({
...page,
id: isInvalidPageId(page.id) ? createScopedId("page") : page.id,
guides: page.guides || [],
objects: ensureMissingGroupObjects(page.objects || []),
backgroundType:
page.backgroundType ?? fallbackSettings.backgroundType ?? "color",
backgroundColor:
page.backgroundColor ?? fallbackSettings.backgroundColor ?? "#ffffff",
backgroundImageUrl:
page.backgroundImageUrl ?? fallbackSettings.backgroundImageUrl ?? "",
}));
const firstPage = normalizedPages[0];
const currentSettings = get().documentSettings;
@@ -80,6 +80,9 @@ export type Page = {
name: string;
objects: EditorObject[];
guides: PageGuide[];
backgroundType: BackgroundType;
backgroundColor: string;
backgroundImageUrl: string;
};
export type DisplayStyle = 'single' | 'double';