base group

This commit is contained in:
hamid zarghami
2026-01-05 12:27:58 +03:30
parent e683b30fa1
commit 61d8e5a814
17 changed files with 607 additions and 231 deletions
+109 -8
View File
@@ -13,7 +13,8 @@ export type ToolType =
| "document"
| "video"
| "link"
| "grid";
| "grid"
| "group";
export type TableCell = {
id: string;
@@ -83,6 +84,10 @@ type EditorStoreType = {
duplicateObject: (id: string) => void;
selectedObjectId: string | null;
setSelectedObjectId: (id: string | null) => void;
selectedObjectIds: string[];
setSelectedObjectIds: (ids: string[]) => void;
addToSelection: (id: string) => void;
removeFromSelection: (id: string) => void;
selectedTableId: string | null;
setSelectedTableId: (id: string | null) => void;
selectedCellId: string | null;
@@ -301,7 +306,37 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
}));
},
selectedObjectId: null,
setSelectedObjectId: (id) => set({ selectedObjectId: id }),
setSelectedObjectId: (id) => {
set({
selectedObjectId: id,
selectedObjectIds: id ? [id] : []
});
},
selectedObjectIds: [],
setSelectedObjectIds: (ids) => {
set({
selectedObjectIds: ids,
selectedObjectId: ids.length > 0 ? ids[0] : null
});
},
addToSelection: (id) => {
const state = get();
if (!state.selectedObjectIds.includes(id)) {
const newIds = [...state.selectedObjectIds, id];
set({
selectedObjectIds: newIds,
selectedObjectId: newIds[0]
});
}
},
removeFromSelection: (id) => {
const state = get();
const newIds = state.selectedObjectIds.filter(selectedId => selectedId !== id);
set({
selectedObjectIds: newIds,
selectedObjectId: newIds.length > 0 ? newIds[0] : null
});
},
selectedTableId: null,
setSelectedTableId: (id) => set({ selectedTableId: id }),
selectedCellId: null,
@@ -650,6 +685,57 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
if (objectIds.length < 2) return;
const groupId = `group-${crypto.randomUUID()}`;
const objectsToGroup = state.objects.filter((obj) => objectIds.includes(obj.id));
if (objectsToGroup.length === 0) return;
// محاسبه bounds گروه با در نظر گرفتن rotation
let minX = Infinity;
let minY = Infinity;
let maxX = -Infinity;
let maxY = -Infinity;
objectsToGroup.forEach((obj) => {
const cx = (obj.x || 0) + (obj.width || 0) / 2;
const cy = (obj.y || 0) + (obj.height || 0) / 2;
const w = obj.width || 0;
const h = obj.height || 0;
const rot = ((obj.rotation || 0) * Math.PI) / 180;
// محاسبه چهار گوشه rectangle با rotation
const corners = [
{ x: -w / 2, y: -h / 2 },
{ x: w / 2, y: -h / 2 },
{ x: w / 2, y: h / 2 },
{ x: -w / 2, y: h / 2 },
];
corners.forEach((corner) => {
const rotatedX = corner.x * Math.cos(rot) - corner.y * Math.sin(rot);
const rotatedY = corner.x * Math.sin(rot) + corner.y * Math.cos(rot);
const finalX = cx + rotatedX;
const finalY = cy + rotatedY;
minX = Math.min(minX, finalX);
minY = Math.min(minY, finalY);
maxX = Math.max(maxX, finalX);
maxY = Math.max(maxY, finalY);
});
});
const groupWidth = maxX - minX;
const groupHeight = maxY - minY;
// ایجاد group object
const groupObject: EditorObject = {
id: groupId,
type: "group",
x: minX,
y: minY,
width: groupWidth,
height: groupHeight,
};
// اضافه کردن groupId به objectهای داخل گروه
const updateObjects = (objects: EditorObject[]) =>
objects.map((obj) =>
objectIds.includes(obj.id) ? { ...obj, groupId } : obj
@@ -657,25 +743,32 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
if (state.currentPageId) {
set((state) => ({
objects: updateObjects(state.objects),
objects: [...updateObjects(state.objects), groupObject],
pages: state.pages.map((p) =>
p.id === state.currentPageId
? { ...p, objects: updateObjects(p.objects) }
? { ...p, objects: [...updateObjects(p.objects), groupObject] }
: p
),
selectedObjectId: groupId,
selectedObjectIds: [groupId],
}));
return;
}
set((state) => ({
objects: updateObjects(state.objects),
objects: [...updateObjects(state.objects), groupObject],
selectedObjectId: groupId,
selectedObjectIds: [groupId],
}));
},
ungroupObjects: (groupId) => {
const state = get();
// حذف groupId از objectهای داخل گروه و حذف group object
const updateObjects = (objects: EditorObject[]) =>
objects.map((obj) =>
obj.groupId === groupId ? { ...obj, groupId: undefined } : obj
);
objects
.map((obj) =>
obj.groupId === groupId ? { ...obj, groupId: undefined } : obj
)
.filter((obj) => obj.id !== groupId); // حذف group object
if (state.currentPageId) {
set((state) => ({
@@ -685,12 +778,20 @@ export const useEditorStore = create<EditorStoreType>((set, get) => {
? { ...p, objects: updateObjects(p.objects) }
: p
),
selectedObjectId: null,
selectedObjectIds: [],
}));
return;
}
set((state) => ({
objects: updateObjects(state.objects),
selectedObjectId: null,
selectedObjectIds: [],
}));
},
getGroupObjects: (groupId) => {
const state = get();
return state.objects.filter((obj) => obj.groupId === groupId);
},
};
});