Compare commits

..

74 Commits

Author SHA1 Message Date
hamid zarghami 677c62e6eb fix extra light weight
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-11 09:39:03 +03:30
hamid zarghami e0eb29488a position x and y in line 2026-07-11 09:31:40 +03:30
hamid zarghami ae3787241a object box smaller 2026-07-11 09:21:13 +03:30
hamid zarghami 9e105606a3 fix blur in viewer 2026-07-11 09:10:41 +03:30
hamid zarghami c6bb275d05 fix order in blur layers + fix aligment 2026-07-11 09:05:13 +03:30
hamid zarghami 4273e899ca cursor ignore
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 16:44:46 +03:30
hamid zarghami 0361e05acb blur
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 16:42:55 +03:30
hamid zarghami 33cce93064 bg opcity
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 15:50:21 +03:30
hamid zarghami a2a591420c color opacity
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 09:21:41 +03:30
hamid zarghami 3c764a1652 spinner to loading page compeletely
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-05 16:26:37 +03:30
hamid zarghami 954ad48486 ankle gredient 2026-07-05 16:18:57 +03:30
hamid zarghami 368cace143 border radius for all shape 2026-07-05 15:52:39 +03:30
hamid zarghami 46926c66e7 blue
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-04 14:51:24 +03:30
hamid zarghami a448ff10de rtl in mobile 2026-07-04 14:45:44 +03:30
hamid zarghami 80a92ea4c4 fix in mobile 2026-07-04 14:43:51 +03:30
hamid zarghami 63a774c4af fix repeat animation 2026-07-04 14:21:27 +03:30
hamid zarghami 1ed198ca69 add max width in text
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-02 12:23:58 +03:30
hamid zarghami d94bf77522 background video 2026-07-02 12:08:29 +03:30
hamid zarghami 5e314bb581 add skill
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 16:54:06 +03:30
hamid zarghami 0391513928 next and prev
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 16:30:23 +03:30
hamid zarghami 22d15f9a13 progressbar uploading
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 16:27:21 +03:30
hamid zarghami bbb797cc62 border z-index than paper 2026-07-01 16:21:43 +03:30
hamid zarghami 4af7181384 fix animation 2026-07-01 16:17:03 +03:30
hamid zarghami cda1b5b5bd fix viewer in even pages
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 15:11:47 +03:30
hamid zarghami 2b4fd31ea2 fix diffrent size in editor and viewer
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 11:53:30 +03:30
hamid zarghami 168af3bf95 pages video fix 2026-07-01 11:23:11 +03:30
hamid zarghami 0bef54c51c pages list in editor 2026-07-01 11:20:55 +03:30
hamid zarghami 85ba8e4261 magnifier
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 11:17:08 +03:30
hamid zarghami 39e18c3331 RTL Trick
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-22 16:44:00 +03:30
hamid zarghami ca02a621da paint
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-20 15:32:02 +03:30
hamid zarghami b13a46ec65 auto save fix
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-20 12:59:39 +03:30
hamid zarghami e93ab38b05 mask 2026-06-20 12:19:23 +03:30
hamid zarghami 052b737653 change design alignmentsetting 2026-06-20 11:35:37 +03:30
hamid zarghami b8de25e9d1 fix big size image
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-15 16:40:08 +03:30
hamid zarghami 8b194fd7cd change icon
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-15 14:15:57 +03:30
hamid zarghami b7ffb2b857 fonts
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-15 09:35:24 +03:30
hamid zarghami c6d1097a30 move custum shape to shapes 2026-06-14 12:30:24 +03:30
hamid zarghami 494a6a53fc move pages 2026-06-14 11:48:55 +03:30
hamid zarghami ebb2092ec1 fix bug custom shape 2026-06-13 16:46:37 +03:30
hamid zarghami 9447500725 fix custom shape in viewer 2026-06-13 16:31:24 +03:30
hamid zarghami 46f5389036 remove line and peykan from sidebar and added to shape 2026-06-13 16:26:52 +03:30
hamid zarghami f9113ef9c8 costum shape 2026-06-13 16:22:46 +03:30
hamid zarghami e6fc300fba audio name
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 15:43:30 +03:30
hamid zarghami 01f890e9ea fix remove delete and edit in business
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 15:26:44 +03:30
hamid zarghami f57761b726 linkn to my catalogue in header ser menu 2026-06-13 15:13:16 +03:30
hamid zarghami 0f0408d9f6 without preview text center
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 11:36:35 +03:30
hamid zarghami e987163bd9 change design buy catalogue 2026-06-13 11:06:35 +03:30
hamid zarghami d573e8dc8d private route go to login page + direct login in dev 2026-06-13 10:53:44 +03:30
hamid zarghami 0245e8d407 remove login button 2026-06-13 10:46:32 +03:30
hamid zarghami 3402ad39f6 fix link to out
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 10:37:35 +03:30
hamid zarghami 121852ab20 fix design links
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 10:34:09 +03:30
hamid zarghami 879bc0ae49 line height fix
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 10:31:53 +03:30
hamid zarghami 5174d0371d mask in viewer 2026-06-13 10:24:16 +03:30
hamid zarghami ef4ddeb3fa my catalogue 2026-06-13 10:17:59 +03:30
hamid zarghami 7f35f5b9dd space border to top
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 09:54:00 +03:30
hamid zarghami a1c182afde fix to navigate to another page
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 09:47:37 +03:30
hamid zarghami 89d9155184 fix build
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-07 16:00:37 +03:30
hamid zarghami 5002596bb9 fix bug slug
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-07 15:58:08 +03:30
hamid zarghami 9b00a22d11 original base url
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-07 14:54:53 +03:30
hamid zarghami 03fc293ee9 list of requests 2026-06-07 14:47:11 +03:30
hamid zarghami 2804cc4100 update request 2026-06-07 14:27:48 +03:30
hamid zarghami 17717eb195 clean code 2026-06-07 14:23:51 +03:30
hamid zarghami 0138261643 save request and link to invoice 2026-06-07 12:56:49 +03:30
hamid zarghami 6653e3db82 save request 2026-06-07 12:43:43 +03:30
hamid zarghami 032050bacc fix bug design datepcker 2026-06-07 12:37:41 +03:30
hamid zarghami c65e8cd303 formik and yup in request design 2026-06-07 12:30:05 +03:30
hamid zarghami d95a6e679e business slug 2026-06-07 12:04:15 +03:30
hamid zarghami 3c9bb6274f update link 2026-06-07 11:48:13 +03:30
hamid zarghami 8dd00d4cc7 user in header 2026-06-07 11:43:24 +03:30
hamid zarghami 3c833df63c business page 2026-06-07 10:40:15 +03:30
hamid zarghami 4daa03d0de catalogue service , hook 2026-06-07 10:38:31 +03:30
hamid zarghami 172cbea22c remove button add 2026-06-07 10:24:57 +03:30
hamid zarghami 8014fe7ad3 skeleton for catalogues 2026-06-07 10:24:29 +03:30
hamid zarghami d977c20744 get business catalog 2026-06-07 10:21:57 +03:30
253 changed files with 9446 additions and 5717 deletions
+116
View File
@@ -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`
+35
View File
@@ -0,0 +1,35 @@
# Dependencies
node_modules/
# Build outputs
dist/
dist-ssr/
build/
out/
# Caches
.cache/
.vite/
# Coverage
coverage/
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Environment / secrets
.env
.env.*
!.env.example
# Editor / IDE
.vscode/
!.vscode/extensions.json
.idea/
# OS files
.DS_Store
+9
View File
@@ -2,3 +2,12 @@ VITE_API_URL=https://dpage-api.danakcorp.com
# VITE_API_URL=http://192.168.99.131:4000
VITE_TOKEN_NAME=dpage-editor-t
VITE_REFRESH_TOKEN_NAME=dpage-editor-refresh-t
VITE_INVOICE_URL=https://console.danakcorp.com/receipts/
VITE_LOGIN_URL=https://console.danakcorp.com/auth/login
VITE_DESIGN_TIER_1_MAX=10
VITE_DESIGN_PRICE_TIER_1=700000
VITE_DESIGN_TIER_2_MAX=30
VITE_DESIGN_PRICE_TIER_2=500000
VITE_DESIGN_TIER_3_MAX=70
VITE_DESIGN_PRICE_TIER_3=400000
VITE_DESIGN_PRICE_TIER_4=350000
+16
View File
@@ -19,6 +19,14 @@ WORKDIR /build
ARG VITE_API_URL
ARG VITE_TOKEN_NAME
ARG VITE_REFRESH_TOKEN_NAME
ARG VITE_INVOICE_URL
ARG VITE_DESIGN_TIER_1_MAX
ARG VITE_DESIGN_PRICE_TIER_1
ARG VITE_DESIGN_TIER_2_MAX
ARG VITE_DESIGN_PRICE_TIER_2
ARG VITE_DESIGN_TIER_3_MAX
ARG VITE_DESIGN_PRICE_TIER_3
ARG VITE_DESIGN_PRICE_TIER_4
COPY package*.json ./
RUN npm ci --legacy-peer-deps
@@ -28,6 +36,14 @@ RUN set -e; \
[ -n "$VITE_API_URL" ] && env_args="$env_args VITE_API_URL=$VITE_API_URL"; \
[ -n "$VITE_TOKEN_NAME" ] && env_args="$env_args VITE_TOKEN_NAME=$VITE_TOKEN_NAME"; \
[ -n "$VITE_REFRESH_TOKEN_NAME" ] && env_args="$env_args VITE_REFRESH_TOKEN_NAME=$VITE_REFRESH_TOKEN_NAME"; \
[ -n "$VITE_INVOICE_URL" ] && env_args="$env_args VITE_INVOICE_URL=$VITE_INVOICE_URL"; \
[ -n "$VITE_DESIGN_TIER_1_MAX" ] && env_args="$env_args VITE_DESIGN_TIER_1_MAX=$VITE_DESIGN_TIER_1_MAX"; \
[ -n "$VITE_DESIGN_PRICE_TIER_1" ] && env_args="$env_args VITE_DESIGN_PRICE_TIER_1=$VITE_DESIGN_PRICE_TIER_1"; \
[ -n "$VITE_DESIGN_TIER_2_MAX" ] && env_args="$env_args VITE_DESIGN_TIER_2_MAX=$VITE_DESIGN_TIER_2_MAX"; \
[ -n "$VITE_DESIGN_PRICE_TIER_2" ] && env_args="$env_args VITE_DESIGN_PRICE_TIER_2=$VITE_DESIGN_PRICE_TIER_2"; \
[ -n "$VITE_DESIGN_TIER_3_MAX" ] && env_args="$env_args VITE_DESIGN_TIER_3_MAX=$VITE_DESIGN_TIER_3_MAX"; \
[ -n "$VITE_DESIGN_PRICE_TIER_3" ] && env_args="$env_args VITE_DESIGN_PRICE_TIER_3=$VITE_DESIGN_PRICE_TIER_3"; \
[ -n "$VITE_DESIGN_PRICE_TIER_4" ] && env_args="$env_args VITE_DESIGN_PRICE_TIER_4=$VITE_DESIGN_PRICE_TIER_4"; \
eval "env$env_args npm run build"
FROM nginx:stable-alpine AS production-stage
+498 -3402
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -10,13 +10,14 @@
"preview": "vite preview"
},
"dependencies": {
"@liara/cli": "^9.4.7",
"@headlessui/react": "^2.2.10",
"@radix-ui/react-switch": "^1.2.6",
"@tailwindcss/vite": "^4.1.17",
"@tanstack/react-query": "^5.90.21",
"axios": "^1.13.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"formik": "^2.4.9",
"html2canvas": "^1.4.1",
"i18next": "^25.6.2",
"iconsax-react": "^0.0.8",
@@ -24,6 +25,7 @@
"moment-jalaali": "^0.10.4",
"page-flip": "^2.0.7",
"react": "^19.2.0",
"react-colorful": "^5.7.0",
"react-dom": "^19.2.0",
"react-dropzone": "^14.3.8",
"react-i18next": "^16.3.0",
@@ -34,6 +36,7 @@
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.17",
"use-image": "^1.1.4",
"yup": "^1.7.1",
"zustand": "^5.0.8"
},
"devDependencies": {
+398
View File
@@ -0,0 +1,398 @@
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.join(__dirname, "../src/assets/fonts/irancell/fonts-editor");
const OUT_JSON = path.join(ROOT, "fonts.json");
const OUT_CSS = path.join(ROOT, "fonts.css");
const WEIGHT_LABELS = {
100: "Thin",
200: "Extra Light",
300: "Light",
400: "Regular",
500: "Medium",
600: "Semi Bold",
700: "Bold",
800: "Extra Bold",
900: "Black",
};
/** @type {Array<{ id: string; label: string; cssFamily: string; category: "persian" | "english"; faces: Array<{ weight: number; src: string; format?: string }> }>} */
const FONT_FAMILIES = [
{
id: "irancell",
label: "ایرانسل",
cssFamily: "editor-irancell",
category: "persian",
defaultWeight: "300",
faces: [
{ weight: 200, src: "../irancell-extralight.ttf" },
{ weight: 300, src: "../irancell-light.ttf" },
{ weight: 600, src: "../irancell-bold.ttf" },
{ weight: 700, src: "../irancell-bold.ttf" },
],
},
{
id: "peyda",
label: "پیدا",
cssFamily: "editor-peyda",
category: "persian",
faces: [
{ weight: 100, src: "Persian Font/peyda/woff2/PeydaWeb-Thin.woff2", format: "woff2" },
{ weight: 200, src: "Persian Font/peyda/woff2/peydaWeb-extralight.woff2", format: "woff2" },
{ weight: 300, src: "Persian Font/peyda/woff2/peydaWeb-light.woff2", format: "woff2" },
{ weight: 400, src: "Persian Font/peyda/woff2/PeydaWeb-Regular.woff2", format: "woff2" },
{ weight: 500, src: "Persian Font/peyda/woff2/PeydaWeb-Medium.woff2", format: "woff2" },
{ weight: 600, src: "Persian Font/peyda/woff2/PeydaWeb-SemiBold.woff2", format: "woff2" },
{ weight: 700, src: "Persian Font/peyda/woff2/PeydaWeb-Bold.woff2", format: "woff2" },
{ weight: 800, src: "Persian Font/peyda/woff2/PeydaWeb-ExtraBold.woff2", format: "woff2" },
{ weight: 900, src: "Persian Font/peyda/woff2/PeydaWeb-Black.woff2", format: "woff2" },
],
},
{
id: "iransans-fanum",
label: "ایران‌سنس (اعداد فارسی)",
cssFamily: "editor-iransans-fanum",
category: "persian",
faces: [
{ weight: 200, src: "Persian Font/IRANSansWeb(FaNum)_UltraLight.ttf" },
{ weight: 300, src: "Persian Font/IRANSansWeb(FaNum)_Light.ttf" },
{ weight: 400, src: "Persian Font/IRANSansWeb(FaNum).ttf" },
{ weight: 500, src: "Persian Font/IRANSansWeb(FaNum)_Medium.ttf" },
{ weight: 700, src: "Persian Font/IRANSansWeb(FaNum)_Bold.ttf" },
],
},
{
id: "sahel",
label: "ساحل",
cssFamily: "editor-sahel",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/Sahel-VF.ttf" }],
},
{
id: "yekan",
label: "یکان",
cssFamily: "editor-yekan",
category: "persian",
faces: [
{ weight: 400, src: "Persian Font/Yekan.ttf" },
{ weight: 700, src: "Persian Font/BYekan.ttf" },
],
},
{
id: "btehran",
label: "تهران",
cssFamily: "editor-btehran",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BTehran.ttf" }],
},
{
id: "byagut",
label: "یاقوت",
cssFamily: "editor-byagut",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BYagut.ttf" }],
},
{
id: "byas",
label: "یاس",
cssFamily: "editor-byas",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BYas.ttf" }],
},
{
id: "bzar",
label: "زر",
cssFamily: "editor-bzar",
category: "persian",
faces: [{ weight: 700, src: "Persian Font/BZarBd.ttf" }],
},
{
id: "bkoodak",
label: "کودک",
cssFamily: "editor-bkoodak",
category: "persian",
faces: [{ weight: 700, src: "Persian Font/BKoodakBold.ttf" }],
},
{
id: "bbaran",
label: "باران",
cssFamily: "editor-bbaran",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BBaran.ttf" }],
},
{
id: "broya",
label: "رویا",
cssFamily: "editor-broya",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BRoya.ttf" }],
},
{
id: "bmahsa",
label: "مهسا",
cssFamily: "editor-bmahsa",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BMahsa.ttf" }],
},
{
id: "bmorvarid",
label: "مروارید",
cssFamily: "editor-bmorvarid",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BMorvarid.ttf" }],
},
{
id: "bbc-nassim",
label: "نسیم",
cssFamily: "editor-bbc-nassim",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BBCNassim.ttf" }],
},
{
id: "far-titr",
label: "تیتر",
cssFamily: "editor-far-titr",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/Far_TitrDF.ttf" }],
},
{
id: "roboto",
label: "Roboto",
cssFamily: "editor-roboto",
category: "english",
faces: [
{ weight: 100, src: "English Font/Roboto-Thin-webfont.ttf" },
{ weight: 300, src: "English Font/Roboto-Light-webfont.ttf" },
{ weight: 400, src: "English Font/Roboto-Regular-webfont.ttf" },
{ weight: 500, src: "English Font/Roboto-Medium-webfont.ttf" },
{ weight: 700, src: "English Font/Roboto-Bold-webfont.ttf" },
{ weight: 900, src: "English Font/Roboto-Black-webfont.ttf" },
],
},
{
id: "roboto-condensed",
label: "Roboto Condensed",
cssFamily: "editor-roboto-condensed",
category: "english",
faces: [
{ weight: 400, src: "English Font/Roboto-Condensed-webfont.ttf" },
{ weight: 700, src: "English Font/Roboto-BoldCondensed-webfont.ttf" },
],
},
{
id: "vollkorn",
label: "Vollkorn",
cssFamily: "editor-vollkorn",
category: "english",
faces: [
{ weight: 400, src: "English Font/Vollkorn-Regular.ttf" },
{ weight: 500, src: "English Font/Vollkorn-Medium.ttf" },
{ weight: 600, src: "English Font/Vollkorn-Semibold.ttf" },
{ weight: 700, src: "English Font/Vollkorn-Bold.ttf" },
],
},
{
id: "caviar-dreams",
label: "Caviar Dreams",
cssFamily: "editor-caviar-dreams",
category: "english",
faces: [
{ weight: 400, src: "English Font/CaviarDreams.ttf" },
{ weight: 700, src: "English Font/CaviarDreams_Bold.ttf" },
],
},
{
id: "raleway",
label: "Raleway",
cssFamily: "editor-raleway",
category: "english",
faces: [
{ weight: 200, src: "English Font/raleway-extralight-webfont.ttf" },
{ weight: 400, src: "English Font/raleway-regular-webfont.ttf" },
{ weight: 500, src: "English Font/raleway-medium-webfont.ttf" },
{ weight: 600, src: "English Font/raleway-semibold-webfont.ttf" },
{ weight: 700, src: "English Font/raleway-bold-webfont.ttf" },
{ weight: 800, src: "English Font/raleway-extrabold-webfont.ttf" },
],
},
{
id: "proxima-nova",
label: "Proxima Nova",
cssFamily: "editor-proxima-nova",
category: "english",
faces: [
{ weight: 300, src: "English Font/proximanova-light-webfont.ttf" },
{ weight: 400, src: "English Font/proximanova-reg-webfont.ttf" },
{ weight: 600, src: "English Font/proximanova-semibold-webfont.ttf" },
{ weight: 700, src: "English Font/proximanova-bold-webfont.ttf" },
{ weight: 800, src: "English Font/proximanova-extrabold-webfont.ttf" },
{ weight: 900, src: "English Font/proximanova-black-webfont.ttf" },
],
},
{
id: "proxima-nova-condensed",
label: "Proxima Nova Condensed",
cssFamily: "editor-proxima-nova-condensed",
category: "english",
faces: [
{ weight: 300, src: "English Font/proximanovacond-light-webfont.ttf" },
{ weight: 600, src: "English Font/proximanovacond-semiboldit-webfont.ttf" },
],
},
{
id: "din-pro",
label: "DIN Pro",
cssFamily: "editor-din-pro",
category: "english",
faces: [
{ weight: 400, src: "English Font/dinpro-regular.ttf" },
{ weight: 500, src: "English Font/dinpro-medium.ttf" },
{ weight: 700, src: "English Font/dinpro-bold.ttf" },
{ weight: 900, src: "English Font/dinpro-black.ttf" },
],
},
{
id: "din-alternate",
label: "DIN Alternate",
cssFamily: "editor-din-alternate",
category: "english",
faces: [
{ weight: 300, src: "English Font/din-lightalternate.ttf" },
{ weight: 400, src: "English Font/din-regularalternate.ttf" },
{ weight: 500, src: "English Font/din-mediumalternate.ttf" },
{ weight: 700, src: "English Font/din-boldalternate.ttf" },
{ weight: 900, src: "English Font/din-blackalternate.ttf" },
],
},
{
id: "abril-fatface",
label: "Abril Fatface",
cssFamily: "editor-abril-fatface",
category: "english",
faces: [{ weight: 400, src: "English Font/AbrilFatface-Regular.otf", format: "opentype" }],
},
{
id: "anton",
label: "Anton",
cssFamily: "editor-anton",
category: "english",
faces: [{ weight: 400, src: "English Font/Anton.ttf" }],
},
{
id: "bebas-neue",
label: "Bebas Neue",
cssFamily: "editor-bebas-neue",
category: "english",
faces: [{ weight: 400, src: "English Font/Bebas Neue.ttf" }],
},
{
id: "kepler-std",
label: "Kepler Std",
cssFamily: "editor-kepler-std",
category: "english",
faces: [{ weight: 400, src: "English Font/kepler-std.ttf" }],
},
{
id: "playfair-display",
label: "Playfair Display",
cssFamily: "editor-playfair-display",
category: "english",
faces: [{ weight: 900, src: "English Font/playfairdisplay-black-webfont.ttf" }],
},
];
function encodeUrlSegment(segment) {
return segment
.split("/")
.map((part) => encodeURIComponent(part))
.join("/");
}
function buildCss(families) {
const blocks = families.flatMap((family) =>
family.faces.map((face) => {
const formatSuffix = face.format ? ` format("${face.format}")` : "";
const url = encodeUrlSegment(face.src);
return `@font-face {
font-family: "${family.cssFamily}";
font-style: normal;
font-weight: ${face.weight};
src: url("${url}")${formatSuffix};
}`;
}),
);
return `/* Auto-generated by scripts/generate-editor-fonts.mjs — do not edit manually */\n\n${blocks.join("\n\n")}\n`;
}
function buildJson(families) {
const fonts = families.map((family) => {
const srcToFace = new Map();
for (const face of family.faces) {
const existing = srcToFace.get(face.src);
if (!existing || face.weight > existing.weight) {
srcToFace.set(face.src, face);
}
}
const uniqueWeightFaces = [...srcToFace.values()].sort(
(a, b) => a.weight - b.weight,
);
const uniqueWeights = uniqueWeightFaces.map((f) => f.weight);
return {
id: family.id,
label: family.label,
cssFamily: family.cssFamily,
category: family.category,
defaultWeight: family.defaultWeight
? String(family.defaultWeight)
: uniqueWeights.includes(400)
? "400"
: String(uniqueWeights[0]),
weights: uniqueWeightFaces.map((face) => ({
value: String(face.weight),
label: WEIGHT_LABELS[face.weight] || String(face.weight),
})),
};
});
return {
version: 1,
fonts,
};
}
function verifySources(families) {
const missing = [];
for (const family of families) {
for (const face of family.faces) {
const resolved = face.src.startsWith("../")
? path.join(ROOT, face.src)
: path.join(ROOT, face.src);
if (!fs.existsSync(resolved)) {
missing.push(resolved);
}
}
}
if (missing.length) {
console.error("Missing font files:\n" + missing.map((m) => ` - ${m}`).join("\n"));
process.exit(1);
}
}
verifySources(FONT_FAMILIES);
const json = buildJson(FONT_FAMILIES);
const css = buildCss(FONT_FAMILIES);
fs.writeFileSync(OUT_JSON, JSON.stringify(json, null, 2) + "\n");
fs.writeFileSync(OUT_CSS, css);
console.log(`Wrote ${OUT_JSON}`);
console.log(`Wrote ${OUT_CSS}`);
console.log(`Fonts: ${json.fonts.length}`);
+1
View File
@@ -7,6 +7,7 @@ import { I18nextProvider } from "react-i18next";
import "react-multi-date-picker/styles/layouts/mobile.css";
import { BrowserRouter } from "react-router-dom";
import "./assets/fonts/irancell/style.css";
import "./assets/fonts/irancell/fonts-editor/fonts.css";
import ToastContainer from "./components/Toast";
import MainRouter from "./router/MainRouter";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More