update ckeditor
This commit is contained in:
parent
ce45ed8bdc
commit
58735a6343
|
|
@ -23,6 +23,7 @@ import {
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { Badge } from "../ui/badge";
|
import { Badge } from "../ui/badge";
|
||||||
import { map } from "zod";
|
import { map } from "zod";
|
||||||
|
import { formatTextToHtmlTag } from "@/utils/global";
|
||||||
|
|
||||||
type TabKey = "trending" | "comments" | "latest";
|
type TabKey = "trending" | "comments" | "latest";
|
||||||
|
|
||||||
|
|
@ -336,21 +337,14 @@ export default function DetailContent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeHtmlString(raw: string = "") {
|
function removeImgTags(htmlString?: { __html: string }) {
|
||||||
if (!raw) return "";
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString(String(htmlString?.__html), "text/html");
|
||||||
|
|
||||||
// 1️⃣ Hapus newline escape, backslash, dsb
|
const images = doc.querySelectorAll("img");
|
||||||
let decoded = raw
|
images.forEach((img) => img.remove());
|
||||||
.replace(/\\n/g, "\n")
|
|
||||||
.replace(/\\"/g, '"') // ubah \" jadi "
|
|
||||||
.replace(/\\'/g, "'") // ubah \' jadi '
|
|
||||||
.replace(/\\\\/g, "\\") // ubah \\ jadi \
|
|
||||||
.trim();
|
|
||||||
|
|
||||||
// 2️⃣ Decode entity HTML (misal ")
|
return { __html: doc.body.innerHTML };
|
||||||
const el = document.createElement("textarea");
|
|
||||||
el.innerHTML = decoded;
|
|
||||||
return el.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -529,11 +523,10 @@ export default function DetailContent() {
|
||||||
<div className="flex-1 overflow-y-auto">
|
<div className="flex-1 overflow-y-auto">
|
||||||
<div className="prose max-w-none text-justify">
|
<div className="prose max-w-none text-justify">
|
||||||
<div
|
<div
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={removeImgTags(
|
||||||
__html: decodeHtmlString(
|
formatTextToHtmlTag(articleDetail?.htmlDescription),
|
||||||
articleDetail?.htmlDescription || "",
|
)}
|
||||||
),
|
className="text-sm lg:text-xl lg:leading-8 text-justify space-y-4"
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// components/custom-editor.js
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
||||||
|
|
||||||
|
import "@/styles/custom-editor.css";
|
||||||
import Editor from "@/vendor/ckeditor5/build/ckeditor";
|
import Editor from "@/vendor/ckeditor5/build/ckeditor";
|
||||||
|
|
||||||
function CustomEditor(props) {
|
function CustomEditor(props) {
|
||||||
|
|
@ -47,7 +47,7 @@ function CustomEditor(props) {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0 !important;
|
||||||
}
|
}
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
margin: 1em 0 0.5em 0;
|
margin: 1em 0 0.5em 0;
|
||||||
|
|
@ -72,98 +72,6 @@ function CustomEditor(props) {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<style jsx>{`
|
|
||||||
.ckeditor-wrapper {
|
|
||||||
border-radius: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1),
|
|
||||||
0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ckeditor-wrapper :global(.ck.ck-editor__main) {
|
|
||||||
min-height: ${props.height || 400}px;
|
|
||||||
max-height: ${maxHeight}px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ckeditor-wrapper :global(.ck.ck-editor__editable) {
|
|
||||||
min-height: ${(props.height || 400) - 50}px;
|
|
||||||
max-height: ${maxHeight - 50}px;
|
|
||||||
overflow-y: auto !important;
|
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: #cbd5e1 #f1f5f9;
|
|
||||||
background: #fff !important;
|
|
||||||
color: #111 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark mode support */
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable) {
|
|
||||||
background: #111 !important;
|
|
||||||
color: #f9fafb !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h1),
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h2),
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h3),
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h4),
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h5),
|
|
||||||
:global(.dark) .ckeditor-wrapper :global(.ck.ck-editor__editable h6) {
|
|
||||||
color: #f9fafb !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark)
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable blockquote) {
|
|
||||||
background-color: #1f2937 !important;
|
|
||||||
border-left-color: #374151 !important;
|
|
||||||
color: #f3f4f6 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Custom scrollbar styling for webkit browsers */
|
|
||||||
.ckeditor-wrapper :global(.ck.ck-editor__editable::-webkit-scrollbar) {
|
|
||||||
width: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable::-webkit-scrollbar-track) {
|
|
||||||
background: #f1f5f9;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb) {
|
|
||||||
background: #cbd5e1;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb:hover) {
|
|
||||||
background: #94a3b8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark mode scrollbar */
|
|
||||||
:global(.dark)
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable::-webkit-scrollbar-track) {
|
|
||||||
background: #1f2937;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark)
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb) {
|
|
||||||
background: #4b5563;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.dark)
|
|
||||||
.ckeditor-wrapper
|
|
||||||
:global(.ck.ck-editor__editable::-webkit-scrollbar-thumb:hover) {
|
|
||||||
background: #6b7280;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure content doesn't overflow */
|
|
||||||
.ckeditor-wrapper :global(.ck.ck-editor__editable .ck-content) {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
`}</style>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@ function ViewEditor(props) {
|
||||||
.ckeditor-view-wrapper {
|
.ckeditor-view-wrapper {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1),
|
box-shadow:
|
||||||
|
0 1px 3px 0 rgba(0, 0, 0, 0.1),
|
||||||
0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ export default function ArticleTable() {
|
||||||
return cellValue;
|
return cellValue;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[article, page]
|
[article, page],
|
||||||
);
|
);
|
||||||
|
|
||||||
let typingTimer: NodeJS.Timeout;
|
let typingTimer: NodeJS.Timeout;
|
||||||
|
|
@ -445,8 +445,8 @@ export default function ArticleTable() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full overflow-x-hidden">
|
<div className="w-full overflow-x-hidden">
|
||||||
<div className="w-full mx-auto overflow-x-hidden">
|
<div className="w-full overflow-x-auto">
|
||||||
<Table className="w-full table-fixed border text-sm">
|
<Table className="min-w-[1000px] w-full table-auto border text-sm">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
{(username === "admin-mabes"
|
{(username === "admin-mabes"
|
||||||
|
|
@ -455,7 +455,18 @@ export default function ArticleTable() {
|
||||||
).map((column) => (
|
).map((column) => (
|
||||||
<TableHead
|
<TableHead
|
||||||
key={column.uid}
|
key={column.uid}
|
||||||
className="truncate bg-white dark:bg-black text-black dark:text-white border-b text-md"
|
className={`bg-white dark:bg-black text-black dark:text-white
|
||||||
|
text-sm font-semibold border-b px-3 py-3
|
||||||
|
${
|
||||||
|
column.uid === "no"
|
||||||
|
? "min-w-[60px] text-center"
|
||||||
|
: column.uid === "title"
|
||||||
|
? "min-w-[280px]"
|
||||||
|
: column.uid === "actions"
|
||||||
|
? "min-w-[100px] text-center"
|
||||||
|
: "min-w-[160px]"
|
||||||
|
}
|
||||||
|
`}
|
||||||
>
|
>
|
||||||
{column.name}
|
{column.name}
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
|
@ -472,7 +483,17 @@ export default function ArticleTable() {
|
||||||
).map((column) => (
|
).map((column) => (
|
||||||
<TableCell
|
<TableCell
|
||||||
key={column.uid}
|
key={column.uid}
|
||||||
className="truncate text-black dark:text-white max-w-[200px]"
|
className={`text-black dark:text-white text-sm px-3 py-3 align-top
|
||||||
|
${
|
||||||
|
column.uid === "no"
|
||||||
|
? "min-w-[60px] text-center font-medium"
|
||||||
|
: column.uid === "title"
|
||||||
|
? "min-w-[280px] whitespace-normal break-words leading-snug"
|
||||||
|
: column.uid === "actions"
|
||||||
|
? "min-w-[100px] text-center"
|
||||||
|
: "min-w-[160px] whitespace-normal break-words"
|
||||||
|
}
|
||||||
|
`}
|
||||||
>
|
>
|
||||||
{renderCell(item, column.uid)}
|
{renderCell(item, column.uid)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -44,7 +44,7 @@
|
||||||
"react-apexcharts": "^1.7.0",
|
"react-apexcharts": "^1.7.0",
|
||||||
"react-datepicker": "^8.4.0",
|
"react-datepicker": "^8.4.0",
|
||||||
"react-day-picker": "^9.7.0",
|
"react-day-picker": "^9.7.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.2.4",
|
||||||
"react-dropzone": "^14.3.8",
|
"react-dropzone": "^14.3.8",
|
||||||
"react-hook-form": "^7.59.0",
|
"react-hook-form": "^7.59.0",
|
||||||
"react-password-checklist": "^1.8.1",
|
"react-password-checklist": "^1.8.1",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/* ========== CKEditor Wrapper ========== */
|
||||||
|
.ckeditor-wrapper {
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow:
|
||||||
|
0 1px 3px 0 rgba(0, 0, 0, 0.1),
|
||||||
|
0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Main Editor Container ========== */
|
||||||
|
.ckeditor-wrapper .ck.ck-editor__main {
|
||||||
|
min-height: var(--editor-min-height, 400px);
|
||||||
|
max-height: var(--editor-max-height, 600px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Editable Content Area (ClassicEditor) ========== */
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline {
|
||||||
|
min-height: calc(var(--editor-min-height, 400px) - 50px);
|
||||||
|
max-height: calc(var(--editor-max-height, 600px) - 50px);
|
||||||
|
overflow-y: auto !important;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #cbd5e1 #f1f5f9;
|
||||||
|
background: #fff !important;
|
||||||
|
color: #111 !important;
|
||||||
|
font-family:
|
||||||
|
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
padding: 1rem;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Headings and Text Formatting ========== */
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h1,
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h2,
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h3,
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h4,
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h5,
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h6 {
|
||||||
|
margin: 1em 0 0.5em 0;
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline p {
|
||||||
|
margin: 0.5em 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline ul,
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline ol {
|
||||||
|
margin: 0.5em 0;
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline blockquote {
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
border-left: 4px solid #d1d5db;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Dark Mode Support ========== */
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline {
|
||||||
|
background: #111 !important;
|
||||||
|
color: #f9fafb !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h1,
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h2,
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h3,
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h4,
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h5,
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline h6 {
|
||||||
|
color: #f9fafb !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline blockquote {
|
||||||
|
background-color: #1f2937 !important;
|
||||||
|
border-left-color: #374151 !important;
|
||||||
|
color: #f3f4f6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========== Custom Scrollbars (Light & Dark) ========== */
|
||||||
|
.ckeditor-wrapper .ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ckeditor-wrapper
|
||||||
|
.ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-track {
|
||||||
|
background: #f1f5f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ckeditor-wrapper
|
||||||
|
.ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb {
|
||||||
|
background: #cbd5e1;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ckeditor-wrapper
|
||||||
|
.ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark
|
||||||
|
.ckeditor-wrapper
|
||||||
|
.ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-track {
|
||||||
|
background: #1f2937;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark
|
||||||
|
.ckeditor-wrapper
|
||||||
|
.ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb {
|
||||||
|
background: #4b5563;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark
|
||||||
|
.ckeditor-wrapper
|
||||||
|
.ck.ck-content.ck-editor__editable_inline::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #6b7280;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue