Files
dpage-editor/src/pages/editor/components/sidebar/settings/EntranceAnimationSettings.tsx
T
2026-05-16 04:50:17 -07:00

99 lines
3.2 KiB
TypeScript

import Select from "@/components/Select";
import Input from "@/components/Input";
import type { EditorObject } from "../../../store/editorStore";
import { useEditorStore } from "../../../store/editorStore";
import { ENTRANCE_ANIMATION_SELECT_ITEMS } from "../constants/entranceAnimationOptions";
import {
DEFAULT_ENTRANCE_DURATION_MS,
DEFAULT_ENTRANCE_DELAY_MS,
MAX_ENTRANCE_DELAY_MS,
} from "@/shared/entranceAnimation";
type Props = {
selectedObject: EditorObject;
onUpdate: (id: string, updates: Partial<EditorObject>) => void;
};
/** اعضای گروه (نه خود باکس group) برای تنظیم انیمیشن ورود */
function getAnimationTargets(
selectedObject: EditorObject,
objects: EditorObject[],
): EditorObject[] {
if (selectedObject.type === "group") {
return objects.filter(
(o) => o.groupId === selectedObject.id && o.type !== "group",
);
}
return [selectedObject];
}
const EntranceAnimationSettings = ({ selectedObject, onUpdate }: Props) => {
const objects = useEditorStore((s) => s.objects);
const targets = getAnimationTargets(selectedObject, objects);
const primary = targets[0] ?? selectedObject;
const anim = primary.entranceAnimation ?? "none";
const duration = primary.entranceDurationMs ?? DEFAULT_ENTRANCE_DURATION_MS;
const delayMs = primary.entranceDelayMs ?? DEFAULT_ENTRANCE_DELAY_MS;
const applyToTargets = (updates: Partial<EditorObject>) => {
const ids =
targets.length > 0 ? targets.map((t) => t.id) : [selectedObject.id];
ids.forEach((id) => onUpdate(id, updates));
};
return (
<div className="pt-4 flex flex-col gap-4 border-t border-border">
<Select
label="انیمیشن هنگام نمایش"
items={ENTRANCE_ANIMATION_SELECT_ITEMS}
value={anim}
onChange={(e) => {
const v = e.target.value as EditorObject["entranceAnimation"];
applyToTargets({
entranceAnimation: v === "none" ? undefined : v,
...(v === "none" || !v
? { entranceDurationMs: undefined, entranceDelayMs: undefined }
: {}),
});
}}
/>
{anim !== "none" && (
<>
<Input
label="مدت انیمیشن (میلی‌ثانیه)"
type="number"
min={100}
max={4000}
value={duration}
onChange={(e) => {
const n = parseInt(e.target.value, 10);
if (Number.isNaN(n)) return;
applyToTargets({
entranceDurationMs: Math.min(4000, Math.max(100, n)),
});
}}
/>
<Input
label="تأخیر قبل از شروع (میلی‌ثانیه)"
type="number"
min={0}
max={MAX_ENTRANCE_DELAY_MS}
value={delayMs}
onChange={(e) => {
const n = parseInt(e.target.value, 10);
if (Number.isNaN(n)) return;
const clamped = Math.min(MAX_ENTRANCE_DELAY_MS, Math.max(0, n));
applyToTargets({
entranceDelayMs: clamped === 0 ? undefined : clamped,
});
}}
/>
</>
)}
</div>
);
};
export default EntranceAnimationSettings;