@@ -0,0 +1,116 @@
|
|||||||
|
---
|
||||||
|
name: dpage-editor
|
||||||
|
description: Guides development in the dpage-editor React/Konva catalogue editor and HTML flip-book viewer. Use when editing editor tools, viewer rendering, Zustand store, catalogue autosave, entrance animations, masks, or any code under src/pages/editor or src/pages/viewer.
|
||||||
|
---
|
||||||
|
|
||||||
|
# dpage-editor
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- React 19 + TypeScript + Vite
|
||||||
|
- Canvas editor: **Konva** / **react-konva**
|
||||||
|
- Viewer: **react-pageflip** (HTML/CSS, not Konva)
|
||||||
|
- State: **Zustand** (`editorStore`)
|
||||||
|
- Data: **TanStack Query** + axios services
|
||||||
|
- Styling: **Tailwind CSS 4**, `clx()` from `@/helpers/utils`
|
||||||
|
- i18n: react-i18next (Persian UI)
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
| Area | Path | Role |
|
||||||
|
|------|------|------|
|
||||||
|
| Editor page | `src/pages/editor/Editor.tsx` | Loads catalogue, autosave, Konva lifecycle |
|
||||||
|
| Editor store | `src/pages/editor/store/editorStore.ts` | Pages, objects, undo, selection |
|
||||||
|
| Object types | `src/pages/editor/store/editorStore.types.ts` | `EditorObject`, `ToolType`, animations |
|
||||||
|
| Canvas | `src/pages/editor/components/canvas/` | Layers, drawing, transform, snap |
|
||||||
|
| Tools (Konva) | `src/pages/editor/components/tools/` | One component per shape/media type |
|
||||||
|
| Sidebar | `src/pages/editor/components/sidebar/` | ToolsBar, settings, instructions |
|
||||||
|
| Viewer | `src/pages/viewer/` | Flip-book, entrance animations, magnifier |
|
||||||
|
| Book render | `src/pages/viewer/components/BookPage.tsx` | HTML mirror of `EditorObject` |
|
||||||
|
| Catalogue API | `src/pages/catalogue/hooks/useCatalogueData.ts` | Load/save `content` JSON |
|
||||||
|
|
||||||
|
**Source of truth:** `EditorObject[]` per page, serialized into catalogue `content`. Editor and viewer must stay in sync.
|
||||||
|
|
||||||
|
## Critical conventions
|
||||||
|
|
||||||
|
### Konva text rendering
|
||||||
|
|
||||||
|
In `Editor.tsx`, `Konva.legacyTextRendering = true` is required. Konva 10's new text baseline breaks transformer bounds for Persian/Latin text. Do not remove without fixing text measurement.
|
||||||
|
|
||||||
|
### Store sync
|
||||||
|
|
||||||
|
`objects` and `pages[currentPageId].objects` must stay synced. Use existing helpers (`withSyncedCurrentPageObjects`, store actions) — never update one without the other.
|
||||||
|
|
||||||
|
### IDs and cloning
|
||||||
|
|
||||||
|
- Use `createScopedId` / helpers in `editorStore.helpers.ts` for new IDs.
|
||||||
|
- Undo history uses `structuredClone` on object lists; new fields on `EditorObject` must be JSON-serializable.
|
||||||
|
|
||||||
|
### Path alias
|
||||||
|
|
||||||
|
Use `@/` imports (e.g. `@/pages/editor/store/editorStore`).
|
||||||
|
|
||||||
|
## Adding or changing a tool type
|
||||||
|
|
||||||
|
Checklist — touch all relevant layers:
|
||||||
|
|
||||||
|
1. **`ToolType`** in `editorStore.types.ts` — add union member + fields on `EditorObject` if needed.
|
||||||
|
2. **Konva shape** — `src/pages/editor/components/tools/<Name>Shape.tsx`, export from `tools/index.ts`.
|
||||||
|
3. **`ObjectRenderer.tsx`** — `switch (obj.type)` case + props wiring.
|
||||||
|
4. **Sidebar** — `ToolsBar.tsx`, `ToolInstructions.tsx`, optional `instructions/` + `settings/`.
|
||||||
|
5. **Creation defaults** — store action or drawing handler that sets initial `x`, `y`, `width`, `height`.
|
||||||
|
6. **Viewer** — `BookPage.tsx` `renderObject` branch; reuse utils from `src/pages/editor/utils/` (gradient, fontFamily, textStyle, customShape).
|
||||||
|
7. **Entrance animation** (if applicable) — `entranceAnimations.css`, `entranceAnimationStyle.ts`, `useBookEntranceController.ts`.
|
||||||
|
|
||||||
|
Default tool prop pattern:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type ShapeProps = {
|
||||||
|
obj: EditorObject;
|
||||||
|
isSelected: boolean;
|
||||||
|
transformerRef: React.RefObject<Konva.Transformer | null>;
|
||||||
|
onSelect: (id: string, node: Konva.Node, e?: Konva.KonvaEventObject<MouseEvent>) => void;
|
||||||
|
onUpdate: (id: string, updates: Partial<EditorObject>) => void;
|
||||||
|
draggable: boolean;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Editor vs viewer
|
||||||
|
|
||||||
|
| Concern | Editor | Viewer |
|
||||||
|
|---------|--------|--------|
|
||||||
|
| Rendering | Konva nodes | HTML/CSS (`BookPage`) |
|
||||||
|
| Interaction | Select, transform, draw | Flip pages, links, autoplay |
|
||||||
|
| Scale | Stage zoom | `VIEWER_SCALE` + viewport hooks |
|
||||||
|
| Media | Full controls in sidebar | `staticMedia` option for thumbnails |
|
||||||
|
| RTL | Stage coordinates | `RTL_COVER_PAD_PAGE_ID` for odd page counts |
|
||||||
|
|
||||||
|
Viewer-specific logic belongs in `src/pages/viewer/hooks/` and `utils/`, not in editor components.
|
||||||
|
|
||||||
|
## Autosave (Editor.tsx)
|
||||||
|
|
||||||
|
- `useUpdateCatalog` debounces saves.
|
||||||
|
- On catalogue `id` change: `cancelPendingUpdate`, `resetEditor`, reload once per id (`loadedCatalogIdRef`).
|
||||||
|
- Skip first autosave after load (`skipNextAutosaveRef`).
|
||||||
|
|
||||||
|
## Code style for this repo
|
||||||
|
|
||||||
|
- Prefer extending existing components over new abstractions.
|
||||||
|
- Keep comments for non-obvious Konva/RTL/safari workarounds (see `BookViewer.tsx`, `Editor.tsx`).
|
||||||
|
- Match Persian UI strings in surrounding files.
|
||||||
|
- Minimize diff scope; do not refactor unrelated editor/viewer code.
|
||||||
|
- Run `npm run build` after substantive changes (strict TypeScript).
|
||||||
|
|
||||||
|
## Common pitfalls
|
||||||
|
|
||||||
|
- Adding an `EditorObject` field but forgetting viewer render → object invisible in preview.
|
||||||
|
- Transform commits: use `transformCommit.ts` patterns so scale/rotation persist correctly.
|
||||||
|
- Mask/group: check `groupId`, `maskId`, `isMask` in both editor layers and `maskStyle.ts`.
|
||||||
|
- Page background: editor `documentSettings` ↔ viewer `resolvePageBackground`.
|
||||||
|
- Fullscreen/viewer chrome: `isViewerPath` hides app header/sidebar in `MainRouter.tsx`.
|
||||||
|
|
||||||
|
## Key routes
|
||||||
|
|
||||||
|
- Editor: `/editor/:id`
|
||||||
|
- Viewer: `/viewer/:id` or `/viewer/:businessSlug/:slug`
|
||||||
|
- Catalogue list: see `src/config/Paths.ts`
|
||||||
Reference in New Issue
Block a user