diff --git a/backlog/features.json b/backlog/features.json index 7891a6d..0a4bc6a 100644 --- a/backlog/features.json +++ b/backlog/features.json @@ -3157,6 +3157,37 @@ "close": true }, "completed_at": "2026-08-19T14:56:06Z" + }, + { + "id": "F-062", + "type": "feature", + "title": "CMS page editor becomes WYSIWYG with Lexical", + "problem": "CMS body field is edited with a plain textarea which forces admins to write raw HTML by hand", + "goal": "Editing pages in the CMS is WYSIWYG using Lexical. Output stays as HTML so existing public render and DB schema do not change", + "scope_in": [ + "Add lexical and the @lexical scope to apps/admin; build a reusable LexicalEditor component with toolbar bold italic underline H2 H3 lists link undo redo; mount it inside the existing CMS form replacing the textarea; serialize to HTML on save" + ], + "scope_out": [ + "No backend schema change; no public render change; no new auth scope" + ], + "priority": "med", + "risk": "low", + "description": "Problem: CMS body field is edited with a plain textarea which forces admins to write raw HTML by hand. Goal: Editing pages in the CMS is WYSIWYG using Lexical. Output stays as HTML so existing public render and DB schema do not change. Scope IN: Add lexical and the @lexical scope to apps/admin; build a reusable LexicalEditor component with toolbar bold italic underline H2 H3 lists link undo redo; mount it inside the existing CMS form replacing the textarea; serialize to HTML on save. Scope OUT: No backend schema change; no public render change; no new auth scope. Type: feature. Priority: med. Risk: low.", + "acceptance": [ + "LexicalEditor renders in the CMS edit form with a working toolbar", + "Saved body is valid HTML and round-trips through the existing API", + "Existing pages still load with their current body unchanged", + "verify.sh is green" + ], + "status": "done", + "created_at": "2026-08-19", + "gates": { + "reviewer": true, + "security": true, + "qa": true, + "close": true + }, + "completed_at": "2026-08-19T15:02:14Z" } ] } diff --git a/project/apps/admin/package-lock.json b/project/apps/admin/package-lock.json index 792dfdf..be67c14 100644 --- a/project/apps/admin/package-lock.json +++ b/project/apps/admin/package-lock.json @@ -8,6 +8,15 @@ "name": "@mercadodevida/admin", "version": "0.1.0", "dependencies": { + "@lexical/history": "^0.49.0", + "@lexical/html": "^0.49.0", + "@lexical/link": "^0.49.0", + "@lexical/list": "^0.49.0", + "@lexical/markdown": "^0.49.0", + "@lexical/react": "^0.49.0", + "@lexical/rich-text": "^0.49.0", + "@lexical/utils": "^0.49.0", + "lexical": "^0.49.0", "next": "16.3.1", "react": "19.2.8", "react-dom": "19.2.8", @@ -454,6 +463,59 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.20", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.20.tgz", + "integrity": "sha512-CMqMy7OaXl9W0eq1Uy7L7i2Y/anPvHmFmESd2CEw0t5YvZhcVCeo4MBevAmswRllX7Y2dEidA4ozGPunLSTQpw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.9", + "@floating-ui/utils": "^0.2.12", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.8.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.2", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", @@ -1070,6 +1132,491 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lexical/a11y": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/a11y/-/a11y-0.49.0.tgz", + "integrity": "sha512-ypvO0SI9DCzEAjxkRLq+gNzRqfjg632RCkwu16Hk94PCBrEmcDhx5iUGg3SRJC7WnM2wXC/F/SB8yWDEfq7tEw==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/clipboard": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/clipboard/-/clipboard-0.49.0.tgz", + "integrity": "sha512-AVKj21xH1qU7JAFA/v0hCoafa+Yti1I7cHG+JQIgc/EqCtP8ePeJyIfTPNN/tXskoCdq++HewQoiSXRwwlocVg==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/html": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/list": "0.49.0", + "@lexical/selection": "0.49.0", + "@lexical/utils": "0.49.0", + "@types/trusted-types": "^2.0.7", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/code-core": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/code-core/-/code-core-0.49.0.tgz", + "integrity": "sha512-29sXI4ydcN/OyBJNlZXkGKtQXzfiIWet+YN20+wT97zkqityOvRilK6qzTRz9Cd0ungEPlJENqXQhsy6BJeXpg==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/html": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/devtools-core": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/devtools-core/-/devtools-core-0.49.0.tgz", + "integrity": "sha512-LgjNlvRiuO/QF36aG6kfR4ptEvSw587o2+YF6SOsaOB7iw2Z3pqpsKloWSEF4QXaLFI65Li8JjMdQj+BaFMIOA==", + "license": "MIT", + "dependencies": { + "@lexical/html": "0.49.0", + "@lexical/link": "0.49.0", + "@lexical/mark": "0.49.0", + "@lexical/table": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "react": ">=18.x", + "react-dom": ">=18.x", + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/dragon": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/dragon/-/dragon-0.49.0.tgz", + "integrity": "sha512-62/4DP5qyX/l4Yf5qRyyQrs9BV725eRU3OmLUW6g7T5xrcHXxAo7tia/NvqjqvXdpvQzyHjWgsy7dMitGITUsw==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/extension": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/extension/-/extension-0.49.0.tgz", + "integrity": "sha512-Wv0VsuqxorbxHCK4ms1PwAu6cXIGNLtflq66auF+zwxOtBprkSFV8VzzzdKLOYD2admP0VK6EqVCeGXFK1GggA==", + "license": "MIT", + "dependencies": { + "@lexical/internal": "0.49.0", + "@lexical/utils": "0.49.0", + "@preact/signals-core": "^1.14.1", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/hashtag": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/hashtag/-/hashtag-0.49.0.tgz", + "integrity": "sha512-aQTpNjrEO5apsaohWGl4ku22EgHpWUzZg5CIzvriS2A1vNmIfzLoCL+lDFpzAwk3DT1Kj1yvGHh5TvhYsb9D8w==", + "license": "MIT", + "dependencies": { + "@lexical/text": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/history": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/history/-/history-0.49.0.tgz", + "integrity": "sha512-uQdtEd34gIJklXNSdHS2Wko1zxx1xUMVXbiodcLO6a3GeFTE5bKnx6af1zGX78KpYhUQYnHWorKuUvtdZlJPaA==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/html": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/html/-/html-0.49.0.tgz", + "integrity": "sha512-NQqAydKzRjQl7Jx+bTTyC2iuz5uhuDaQX0SSPrdfgaFDCPjqQEejcBkCt1QXnu1CkbVHutZKVGVzljx40Y6y+Q==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/selection": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/internal": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/internal/-/internal-0.49.0.tgz", + "integrity": "sha512-s+XjPC7Qb39A/Xx9ahcz1s69CPix4ultaqyW+MDG0AXYW2quDr7m0USqReKIAiuoLIWtGN5HW8BwV2Y6t4qr6Q==", + "license": "MIT", + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/link": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.49.0.tgz", + "integrity": "sha512-CsZVu1OfnPOn6IKWVO5DbmKwIuicGtgWSzrZMdMB8w6yPoMgFyPWeVulhPE7LNz2FhaQCWv+lVVYVAiJrUzJsg==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/html": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/list": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.49.0.tgz", + "integrity": "sha512-zs6wYkxakDRcJO0KmwrPPHgeLLIxzjD+P2CRu+scJCHRuA5e2iSw2iFjH5n/LlWBrlnPMSjeQse4QqsRy9nnqA==", + "license": "MIT", + "dependencies": { + "@lexical/extension": "0.49.0", + "@lexical/html": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/mark": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/mark/-/mark-0.49.0.tgz", + "integrity": "sha512-JSYD8UYQQOMT6oDYh1KsLPK3KMGfQzU7E9fJkugKEO0/XebfsmiuNtkLCGDVIZOo8bNHlwb1YVvmswC2bjotMQ==", + "license": "MIT", + "dependencies": { + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/markdown": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/markdown/-/markdown-0.49.0.tgz", + "integrity": "sha512-n7x/3OLdi5R0ztICCn8udxRIWFZFVtmQS3a06Tjkyvm/j/dPlFQ/henKSOFjjX/IqVzQzSmiNaDhqKWxXM5npQ==", + "license": "MIT", + "dependencies": { + "@lexical/code-core": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/link": "0.49.0", + "@lexical/list": "0.49.0", + "@lexical/rich-text": "0.49.0", + "@lexical/selection": "0.49.0", + "@lexical/text": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/overflow": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/overflow/-/overflow-0.49.0.tgz", + "integrity": "sha512-h5Qjv2SkpI76kaukvKJzvWehG9hwB06GEmAnp6aJaioOzoDcBAeWpmYBebtBUwRm0PNLFe3YICFFLpZ5Tg5VoQ==", + "license": "MIT", + "dependencies": { + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/plain-text": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.49.0.tgz", + "integrity": "sha512-l7IuUj9n9CtFfz4Fz6zU6mmO+VkcnvyyebABx+lHevvTa7B6YI5PPVgABFfzdyPanyW/FGs7qpKBf59inAqbkg==", + "license": "MIT", + "dependencies": { + "@lexical/clipboard": "0.49.0", + "@lexical/dragon": "0.49.0", + "@lexical/extension": "0.49.0", + "@lexical/selection": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/react": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/react/-/react-0.49.0.tgz", + "integrity": "sha512-NqXF4i/IBFKVDDLDJYTwmBXE++MQuIrTQs7VTux6IPyDEpyfeFMn1rQTFb949S3f7rs33Rcu1uGtFbODQfS1Iw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.27.19", + "@lexical/a11y": "0.49.0", + "@lexical/devtools-core": "0.49.0", + "@lexical/dragon": "0.49.0", + "@lexical/extension": "0.49.0", + "@lexical/hashtag": "0.49.0", + "@lexical/history": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/link": "0.49.0", + "@lexical/list": "0.49.0", + "@lexical/mark": "0.49.0", + "@lexical/markdown": "0.49.0", + "@lexical/overflow": "0.49.0", + "@lexical/plain-text": "0.49.0", + "@lexical/rich-text": "0.49.0", + "@lexical/table": "0.49.0", + "@lexical/text": "0.49.0", + "@lexical/utils": "0.49.0", + "@lexical/yjs": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "react": ">=18.x", + "react-dom": ">=18.x", + "typescript": ">=5.2", + "yjs": ">=13.5.22" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "yjs": { + "optional": true + } + } + }, + "node_modules/@lexical/rich-text": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.49.0.tgz", + "integrity": "sha512-LM+d8ULmQvi2Av6UaW4NAIa/Bj9FOo9oh6+dglTzuoFPFQ3sogy5c38i2K9k0ul7aE+bFsXkSmHbu4LkrHIkBQ==", + "license": "MIT", + "dependencies": { + "@lexical/clipboard": "0.49.0", + "@lexical/dragon": "0.49.0", + "@lexical/extension": "0.49.0", + "@lexical/html": "0.49.0", + "@lexical/selection": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/selection": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/selection/-/selection-0.49.0.tgz", + "integrity": "sha512-08Vd1+VoC6YnztWOFWVsqF/Hxw5EP8qeL1c7t3+rVCV8revLzXxdQw+vbPX3tgM4fmjOBDUXk6Ws1+rTtsqjcQ==", + "license": "MIT", + "dependencies": { + "@lexical/internal": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/table": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/table/-/table-0.49.0.tgz", + "integrity": "sha512-PG+dxSTBPbUZUY2kBZm0pJuqCEOGom4RrGrc6Jlj/7o0F37k/gGRVprFSRKuf3CqO03QIP6qRovXGDuKb+Exuw==", + "license": "MIT", + "dependencies": { + "@lexical/clipboard": "0.49.0", + "@lexical/extension": "0.49.0", + "@lexical/html": "0.49.0", + "@lexical/internal": "0.49.0", + "@lexical/utils": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/text": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/text/-/text-0.49.0.tgz", + "integrity": "sha512-mowedvbvx0HDaW+ymVdYmWVhueqgauhhqIWaCtbJj33tPk8pOu1BB0pZuJQbOB+1bDnFiZhkJV8W/CvR2M9lEA==", + "license": "MIT", + "dependencies": { + "@lexical/internal": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/utils": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/utils/-/utils-0.49.0.tgz", + "integrity": "sha512-Jaa6DERBqxiFOFa49VPRV1WOb7mzRbMZ5U+v+RFagjzTmBhfxDmEkbQQ9nYTU3n3DPfdT8Hkyffextmw04etXg==", + "license": "MIT", + "dependencies": { + "@lexical/internal": "0.49.0", + "@lexical/selection": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lexical/yjs": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@lexical/yjs/-/yjs-0.49.0.tgz", + "integrity": "sha512-uqV3D0AOLqQ1f/Bo6ZtuDLoJYGlBm0RlucNYhNvfMAncEw0f/xHc1pTyXeWjdCI/iWgWR/MV6hgVi26TSPs+Vg==", + "license": "MIT", + "dependencies": { + "@lexical/internal": "0.49.0", + "@lexical/selection": "0.49.0", + "lexical": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2", + "yjs": ">=13.5.22" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", @@ -1317,6 +1864,16 @@ "node": ">=12.4.0" } }, + "node_modules/@preact/signals-core": { + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.4.tgz", + "integrity": "sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -1666,6 +2223,12 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.67.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", @@ -4568,6 +5131,17 @@ "dev": true, "license": "ISC" }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "license": "MIT", + "peer": true, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/iterator.prototype": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", @@ -4733,6 +5307,45 @@ "node": ">= 0.8.0" } }, + "node_modules/lexical": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/lexical/-/lexical-0.49.0.tgz", + "integrity": "sha512-9V1ZIzGpJEd8rIN+nN7veL4fW4fFWbS66Un4JNqSZB4D5t9euzN9+3+jEXy83FjNjNy0MiiUI3+DQaGCLYko0w==", + "license": "MIT", + "dependencies": { + "@lexical/internal": "0.49.0" + }, + "peerDependencies": { + "typescript": ">=5.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/lib0": { + "version": "0.2.117", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", + "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", + "license": "MIT", + "peer": true, + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -6255,6 +6868,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz", + "integrity": "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==", + "license": "MIT" + }, "node_modules/tailwindcss": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", @@ -6477,7 +7096,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -6738,6 +7357,24 @@ "dev": true, "license": "ISC" }, + "node_modules/yjs": { + "version": "13.6.32", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.32.tgz", + "integrity": "sha512-lfiJIIC4Xayt5ItynE407ehlE03pCjeOc4hkR4yxxvvNJ4kuiN25B0g+Qp8XagYz361LLL7DCzR5bvFJ81QKtQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/project/apps/admin/package.json b/project/apps/admin/package.json index 291a17a..ef2c57f 100644 --- a/project/apps/admin/package.json +++ b/project/apps/admin/package.json @@ -10,6 +10,15 @@ "typecheck": "tsc --noEmit" }, "dependencies": { + "@lexical/history": "^0.49.0", + "@lexical/html": "^0.49.0", + "@lexical/link": "^0.49.0", + "@lexical/list": "^0.49.0", + "@lexical/markdown": "^0.49.0", + "@lexical/react": "^0.49.0", + "@lexical/rich-text": "^0.49.0", + "@lexical/utils": "^0.49.0", + "lexical": "^0.49.0", "next": "16.3.1", "react": "19.2.8", "react-dom": "19.2.8", diff --git a/project/apps/admin/src/app/(dashboard)/cms/page.tsx b/project/apps/admin/src/app/(dashboard)/cms/page.tsx index 252ab0b..76e3626 100644 --- a/project/apps/admin/src/app/(dashboard)/cms/page.tsx +++ b/project/apps/admin/src/app/(dashboard)/cms/page.tsx @@ -1,6 +1,7 @@ 'use client'; import { useState, useEffect, useCallback } from 'react'; import { cmsApi } from '@/lib/api-client'; +import LexicalEditor from '@/features/cms/components/LexicalEditor'; interface Page { id: string; slug: string; title: string; body: string; status: string; createdAt: string; updatedAt: string; } @@ -92,7 +93,11 @@ export default function CmsPage() { ))}
-