Commit 1f83ff59 authored by Яков's avatar Яков
Browse files

update

parent 98ec316b
......@@ -9,7 +9,7 @@ const App = () => {
// value={`<iframe src="https://cdn.atmaguru.online/2/atmacompany/8/b/8bTfGoWtAuv5waVabQRTtWaNOrve5uv8UBXFbGOH9cowQ1K56dYi7TFz6h5jUfzr.pdf" width="100%" /><iframe src="https://www.youtube.com/embed/YmZGP7YP8c4" frameborder="0" allowfullscreen="true"></iframe><video src="https://cdn.atmaguru.online/2/demo/V/k/VkrEXjkxnutXLgcJPt5CLXNgEj4RaL9Zk4SQhIMUjOeIRpu0dSKtQCIMl49pJM6N.webm" controls="true"></video><p>Так исторически сложилось, что взрослым людям стараются дать максимум материалов: часовые лекции, объемные массивы текста и должностных инструкций. Сотрудник изучает огромный объем информации. Пытается его запомнить, а потом в конце курса сдать большой аттестационный экзамен. Вы не учитывете при этом, что мозг взрослого человека перегружен, ему нужно выполнять обязанности по работе, думать о домашних делах, его постоянно отвлекают менеджеры и коллеги по работе… Единственный правильный способ — это давать информацию небольшими кусочками и после каждой порции проверять усвоена она или нет.</p><p></p><p>что-то новое о компании<br><a href="https://cdn.atmaguru.online/1/demo/T/G/TGvSAoLawONkteJ47yyNfmsC8zNe3ZRG4iO0ZfAjmvOIZkm20BWp8KdWCH5p1Rrx.gif" target="_blank" download="Редактор.gif" data-size="37 Мб">РСкачать книгу</a> <br></p>`}
// value={"<p style=\"text-align: left\"><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://telemost.yandex.ru/j/5911922929\">дшдлодлод</a></p><table data-bordered=\"true\" class=\"\" style=\"min-width: 75px\"><colgroup><col style=\"min-width: 25px\"><col style=\"min-width: 25px\"><col style=\"min-width: 25px\"></colgroup><tbody><tr><th colspan=\"1\" rowspan=\"1\"><p style=\"text-align: left\">sdfsdf</p></th><th colspan=\"1\" rowspan=\"1\"><p style=\"text-align: left\"></p></th><th colspan=\"1\" rowspan=\"1\"><p style=\"text-align: left\">sdfsdf</p></th></tr><tr><td colspan=\"1\" rowspan=\"1\"><p style=\"text-align: left\">sdfsdf</p></td><td colspan=\"1\" rowspan=\"1\"><p style=\"text-align: left\"></p></td><td colspan=\"1\" rowspan=\"1\"><p style=\"text-align: left\">sdfsdf</p></td></tr></tbody></table><p style=\"text-align: left\"></p>"}
// value={"<h2 style=\"text-align: center\">В данном разделе Вы сможете изучить профильные системы KRAUSS и их предназначения.</h2><h2 style=\"text-align: center\">Профильные системы с которыми мы работаем</h2><p style=\"text-align: left\"></p><p style=\"text-align: left\"><img src=\"https://cdn.atmaguru.online/1/galereya-okon/t/J/tJkxP0341Yu58FNTDNtan20IxGVVegvv4Ns8kQvn1SdiWbRBTKj009cPUNpYfD4S.png\" alt=\"fgdgdfdg&amp;#10;sdfsdf&amp;#10;SDfsdf&amp;#10;sdfsdf\" width=\"798\" height=\"449\" data-align=\"center\" style=\"display: block; margin-left: auto; margin-right: auto; width: 798px; height: 449px\" data-node-id=\"img-1752479121918-zsmot20zn\">​</p><p style=\"text-align: left\"><img src=\"https://cdn.atmaguru.online/1/galereya-okon/6/D/6DPwk96e0ja5vPaXFSDzz3SVmeJgWvMLeysYxxYXu5YgOjr57CxS21vzsMThgMgz.png\" alt=\"\" width=\"798\" height=\"431\" data-align=\"center\" style=\"display: block; margin-left: auto; margin-right: auto; width: 798px; height: 431px\" data-node-id=\"img-1752479121912-lk1uabgxv\">​</p><p style=\"text-align: left\"><span style=\"color: rgb(243, 76, 55)\"><strong>Примечание: профильные системы KRAUSS мы закупаем у компании \"Реалит\". Офис данной компании находится в г. Уфа.</strong></span></p><h2 style=\"text-align: left\"><a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://disk.yandex.ru/d/KvB3VMNFKu4ULg\">Ссылка для скачивания видео-курсов от компании \"Реалит\" https://disk.yandex.ru/d/KvB3VMNFKu4ULg</a></h2><h2 style=\"text-align: left\">Файл для скачивания: <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://cdn.atmaguru.online/1/galereya-okon/4/N/4N30p3UR8gb4jph1m1u8KijlQmDp6H9DgHKucRjvxOPUnMprnJyBaK2S1dGZPqaD.pdf\">Профильные системы</a></h2><p style=\"text-align: left\"></p>"}
value={"<p style=\"text-align: left\"></p><h2 style=\"text-align: center\">Скрипт \"Вх.телефонного звонка потенциального клиента\"</h2><h2 style=\"text-align: center\"></h2><interactive-image src=\"https://cdn.atmaguru.online/1/demo/y/V/yVH7VsNRAYz5w8ORxax0VfMgF8iYAkGmc6VUF6rGy1NX3URC2GaOil8EHDuAm6cM.png\" data-points=\"[{&quot;x&quot;:19.703389830508474,&quot;y&quot;:36.440677966101696,&quot;text&quot;:&quot;ываываыва&quot;},{&quot;x&quot;:76.0593220338983,&quot;y&quot;:80.72033898305084,&quot;text&quot;:&quot;ываываываыва&quot;}]\"></interactive-image><h2 style=\"text-align: center\"><br><img src=\"https://cdn.atmaguru.online/1/demo/N/8/N80blh8vFcvZ8vxF5gM92NW0asDy1HPB0eXt40tzHdtfWBKRR2IKW3P539sxoebj.png\" alt=\"Rutube_icon.svg.png\" title=\"Rutube_icon.svg.png\" width=\"518\" height=\"518\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 518px; height: 518px\" data-node-id=\"img-1752484531717-671thw3tt\">​​​​<br><img src=\"https://cdn.atmaguru.online/2/galereya-okon/s/I/sIt4vIbMQqB72fNnirRzc4SFge6ZYluV2RiVxz4lnr8eCe72U3uexQMR7ZM9CldA.jpg\" alt=\"\" width=\"1064\" height=\"822\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 822px\" data-node-id=\"img-1751607113981-zg693aosm\">​​​​<br><img src=\"https://cdn.atmaguru.online/2/galereya-okon/4/9/497lE0e2jzPAoyCnk0g1omLYKXOqJEG7ApkfaT5lBTRfuwioJIfsIVUy7fcbG9l6.jpg\" alt=\"\" width=\"1064\" height=\"822\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 822px\" data-node-id=\"img-1751607113986-utmlo6wda\">​​​​​​​<br>Файл для скачивания: <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://cdn.atmaguru.online/2/galereya-okon/Z/H/ZHeH2tnX0RZXy6ibijHNHpXySW01JIJElYzx1xoBQ9EZjKwHJZWFQ6tX8RyoS7TD.xls\">скрипт вх.звонка</a></h2><p style=\"text-align: left\"></p><p style=\"text-align: center\"></p><p style=\"text-align: left\"></p><p style=\"text-align: left\"></p><p style=\"text-align: center\"><img src=\"https://cdn.atmaguru.online/2/galereya-okon/L/7/L7IOgSXhT54y82ezhUIYjXYVxoqFjOBELKmQrp66UjwEybnX0QRwwDRttNHQ1OME.jpg\" alt=\"\" width=\"1064\" height=\"1505\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 1505px\" data-node-id=\"img-1751607113981-cxqc0fbac\">​​​​</p><p style=\"text-align: center\"><img src=\"https://cdn.atmaguru.online/2/galereya-okon/0/B/0Bw7BxdBMLHprU3mtib3TFuXlnyrbarQF82XvUM3jBGD4v3lGPQQCp19of82EMDx.jpg\" alt=\"\" width=\"1064\" height=\"1505\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 1505px\" data-node-id=\"img-1751607113976-kfrhg4ziw\">​​​​</p><p style=\"text-align: center\"><img src=\"https://cdn.atmaguru.online/2/galereya-okon/D/W/DW5FvXAFSm6A8gEx8qDBoYCyj0r5ep9yuI2qnUSvpNg2C2SzV3tff7ScIlvWjelB.jpg\" alt=\"\" width=\"1064\" height=\"1505\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 1505px\" data-node-id=\"img-1751607113980-zcr1g75pv\">​​​​</p><p style=\"text-align: left\"></p><p style=\"text-align: left\">Файл для скачивания: <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://cdn.atmaguru.online/2/galereya-okon/F/O/FOvmHQ85dMkyLCIVWc4LK7Gxc7tVXAEdhL6soGR3EP9Fgo4d3ObVeUbtN9U18pmw.docx\">Скрипт при отказе клиента записываться на замер</a></p>"}
value={"<p style=\"text-align: left\"></p><h2 style=\"text-align: center\">Скрипт \"Вх.телефонного звонка потенциального клиента\"</h2><h2 style=\"text-align: center\"></h2><interactive-image src=\"https://cdn.atmaguru.online/1/demo/y/V/yVH7VsNRAYz5w8ORxax0VfMgF8iYAkGmc6VUF6rGy1NX3URC2GaOil8EHDuAm6cM.png\" width=\"798\" height=\"798\" style=\"display: block; margin-left: auto; margin-right: auto; width: 798px; height: 798px\" data-align=\"center\" data-points=\"[{&quot;x&quot;:57.180851063829785,&quot;y&quot;:20.877659574468087,&quot;text&quot;:&quot;qweqweqweqweqw\\neqweqweqwe\\nqweqweqwe\\nqweqwe&quot;,&quot;title&quot;:&quot;qweqweqweqwe&quot;},{&quot;x&quot;:73.00531914893617,&quot;y&quot;:45.87765957446808,&quot;text&quot;:&quot;sdfsndfsdfgbsdkfg\\nsdfgjnsdfkgjsdfg\\nsdfgjndskfjgsdfg&quot;,&quot;title&quot;:&quot;sdfsdfsdf&quot;}]\"></interactive-image><p style=\"text-align: left\">​</p><p style=\"text-align: left\">​</p><h2 style=\"text-align: center\"><br><img src=\"https://cdn.atmaguru.online/1/demo/N/8/N80blh8vFcvZ8vxF5gM92NW0asDy1HPB0eXt40tzHdtfWBKRR2IKW3P539sxoebj.png\" alt=\"Rutube_icon.svg.png\" title=\"Rutube_icon.svg.png\" width=\"518\" height=\"518\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 518px; height: 518px\" data-node-id=\"img-1752484531717-671thw3tt\">​​​​​​<br><img src=\"https://cdn.atmaguru.online/2/galereya-okon/s/I/sIt4vIbMQqB72fNnirRzc4SFge6ZYluV2RiVxz4lnr8eCe72U3uexQMR7ZM9CldA.jpg\" alt=\"\" width=\"1064\" height=\"822\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 822px\" data-node-id=\"img-1751607113981-zg693aosm\">​​​​​​<br><img src=\"https://cdn.atmaguru.online/2/galereya-okon/4/9/497lE0e2jzPAoyCnk0g1omLYKXOqJEG7ApkfaT5lBTRfuwioJIfsIVUy7fcbG9l6.jpg\" alt=\"\" width=\"1064\" height=\"822\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 822px\" data-node-id=\"img-1751607113986-utmlo6wda\">​​​​​​​​​<br>Файл для скачивания: <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://cdn.atmaguru.online/2/galereya-okon/Z/H/ZHeH2tnX0RZXy6ibijHNHpXySW01JIJElYzx1xoBQ9EZjKwHJZWFQ6tX8RyoS7TD.xls\">скрипт вх.звонка</a></h2><p style=\"text-align: left\"></p><p style=\"text-align: center\"></p><p style=\"text-align: left\"></p><p style=\"text-align: left\"></p><p style=\"text-align: center\"><img src=\"https://cdn.atmaguru.online/2/galereya-okon/L/7/L7IOgSXhT54y82ezhUIYjXYVxoqFjOBELKmQrp66UjwEybnX0QRwwDRttNHQ1OME.jpg\" alt=\"\" width=\"1064\" height=\"1505\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 1505px\" data-node-id=\"img-1751607113981-cxqc0fbac\">​​​​​​</p><p style=\"text-align: center\"><img src=\"https://cdn.atmaguru.online/2/galereya-okon/0/B/0Bw7BxdBMLHprU3mtib3TFuXlnyrbarQF82XvUM3jBGD4v3lGPQQCp19of82EMDx.jpg\" alt=\"\" width=\"1064\" height=\"1505\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 1505px\" data-node-id=\"img-1751607113976-kfrhg4ziw\">​​​​</p><p style=\"text-align: center\"><img src=\"https://cdn.atmaguru.online/2/galereya-okon/D/W/DW5FvXAFSm6A8gEx8qDBoYCyj0r5ep9yuI2qnUSvpNg2C2SzV3tff7ScIlvWjelB.jpg\" alt=\"\" width=\"1064\" height=\"1505\" data-align=\"left\" style=\"float: left; margin-right: 1rem; width: 1064px; height: 1505px\" data-node-id=\"img-1751607113980-zcr1g75pv\">​​​​​​</p><p style=\"text-align: left\"></p><p style=\"text-align: left\">Файл для скачивания: <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://cdn.atmaguru.online/2/galereya-okon/F/O/FOvmHQ85dMkyLCIVWc4LK7Gxc7tVXAEdhL6soGR3EP9Fgo4d3ObVeUbtN9U18pmw.docx\">Скрипт при отказе клиента записываться на замер</a></p>"}
onChange={(value)=>{
console.log(value);
}}
......
{
"name": "react-ag-qeditor",
"version": "1.1.10",
"version": "1.1.11",
"description": "WYSIWYG html editor",
"author": "atma",
"license": "MIT",
......
......@@ -1147,6 +1147,7 @@ const QEditor = ({
src: file.path,
width: Math.round(realWidth),
height: Math.round(realHeight),
align: 'center',
points: []
},
})
......
......@@ -31,6 +31,48 @@ const Audio = Node.create({
];
},
addNodeView() {
return ({ editor, node }) => {
const container = document.createElement('div')
container.style.position = 'relative'
const audio = document.createElement('audio')
audio.src = node.attrs.src
audio.controls = true
const closeBtn = document.createElement('button')
closeBtn.textContent = '×'
closeBtn.className = 'audio-delete-btn'
closeBtn.style.cssText = `
position: absolute;
top: -6px;
right: -6px;
z-index: 10;
background: white;
border: 1px solid #ccc;
border-radius: 50%;
width: 20px;
height: 20px;
font-size: 12px;
line-height: 1;
cursor: pointer;
`
closeBtn.addEventListener('click', function () {
const pos = editor.view.posAtDOM(container, 0)
editor.view.dispatch(
editor.view.state.tr.delete(pos, pos + node.nodeSize)
)
})
container.appendChild(closeBtn)
container.appendChild(audio)
return {
dom: container,
}
}
},
addCommands() {
return {
addVoiceMessage: (options) => ({ chain }) => {
......
......@@ -7,7 +7,7 @@ const Iframe = Node.create({
draggable: true,
atom: true,
addAttributes() {
addAttributes () {
return {
src: {
default: null
......@@ -24,7 +24,7 @@ const Iframe = Node.create({
}
},
parseHTML() {
parseHTML () {
return [
{
tag: 'iframe'
......@@ -32,12 +32,12 @@ const Iframe = Node.create({
]
},
renderHTML({ HTMLAttributes }) {
renderHTML ({HTMLAttributes}) {
return ['iframe', mergeAttributes(HTMLAttributes)]
},
addNodeView() {
return ({ editor, node, ...a }) => {
addNodeView () {
return ({editor, node, ...a}) => {
const container = document.createElement('div')
const iframe = document.createElement('iframe')
......@@ -48,8 +48,12 @@ const Iframe = Node.create({
const closeBtn = document.createElement('button')
closeBtn.textContent = 'X'
closeBtn.classList.add('closeBtn')
closeBtn.addEventListener('click', function () {
container.remove()
const pos = editor.view.posAtDOM(container, 0)
editor.view.dispatch(
editor.view.state.tr.delete(pos, pos + node.nodeSize)
)
})
// if (editor.isEditable) {
......@@ -64,12 +68,12 @@ const Iframe = Node.create({
}
},
addCommands() {
addCommands () {
return {
setIframe:
(options) =>
({ tr, dispatch }) => {
const { selection } = tr
({tr, dispatch}) => {
const {selection} = tr
const node = this.type.create(options)
if (dispatch) {
......
......@@ -402,6 +402,58 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
}}
/>
<Button
size="default"
shape={'circle'}
type={node.attrs.alt?.length > 0 ? 'primary' : 'default'}
onClick={(e) => {
e.stopPropagation();
setTempAlt(node.attrs.alt || '');
setAltModalVisible(true);
}}
style={{
position: 'absolute',
top: 4,
right: '30px',
zIndex: 15,
}}
>
<FontSizeOutlined />
</Button>
{selected && (
<Button
type="text"
danger
size="small"
onClick={(e) => {
e.stopPropagation()
const pos = getPos?.()
if (typeof pos === 'number') {
editor.view.dispatch(
editor.view.state.tr.delete(pos, pos + node.nodeSize)
)
}
}}
style={{
position: 'absolute',
top: 4,
right: 4,
zIndex: 30,
backgroundColor: 'white',
border: '1px solid #d9d9d9',
borderRadius: '50%',
width: 20,
height: 20,
fontSize: 12,
lineHeight: 1,
padding: '0px 0px 2px 0px',
cursor: 'pointer'
}}
>
×
</Button>
)}
{(selected || isResizing) && (
<Fragment>
{['nw', 'ne', 'sw', 'se'].map(dir => (
......@@ -479,25 +531,6 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
>
Align
</button>
<Button
size="default"
shape={'circle'}
type={node.attrs.alt?.length > 0 ? 'primary' : 'default'}
onClick={(e) => {
e.stopPropagation();
setTempAlt(node.attrs.alt || '');
setAltModalVisible(true);
}}
style={{
position: 'absolute',
top: 4,
right: 4,
zIndex: 15,
}}
>
<FontSizeOutlined />
</Button>
</Fragment>
)}
<Modal
......
This diff is collapsed.
import { Node } from '@tiptap/core'
import { ReactNodeViewRenderer, NodeViewWrapper, NodeViewContent } from '@tiptap/react'
import React, { useEffect, useRef, useState } from 'react'
import { TextSelection } from 'prosemirror-state'
// React компонент NodeView
export const ToggleBlockComponent = ({ node, updateAttributes }) => {
export const ToggleBlockComponent = ({node, updateAttributes, getPos, editor}) => {
const open = node.attrs.open
const title = node.attrs.title
......@@ -11,7 +12,7 @@ export const ToggleBlockComponent = ({ node, updateAttributes }) => {
const [inputWidth, setInputWidth] = useState('100px')
const toggle = () => {
updateAttributes({ open: !open })
updateAttributes({open: ! open})
}
useEffect(() => {
......@@ -23,6 +24,40 @@ export const ToggleBlockComponent = ({ node, updateAttributes }) => {
return (
<NodeViewWrapper className="toggle-block" data-open={open}>
<button
type="button"
onClick={(e) => {
e.stopPropagation()
try {
const pos = getPos?.()
if (typeof pos === 'number') {
editor.view.dispatch(
editor.view.state.tr.delete(pos, pos + node.nodeSize)
)
}
} catch (err) {
console.warn('Ошибка удаления toggleBlock:', err)
}
}}
style={{
position: 'absolute',
top: 4,
right: 4,
zIndex: 10,
background: 'white',
border: '1px solid #ccc',
borderRadius: '50%',
width: 20,
height: 20,
fontSize: 12,
lineHeight: 1,
cursor: 'pointer',
padding: 0,
}}
>
×
</button>
<div className="toggle-block-inner">
<div className="toggle-header-wrapper">
<span
......@@ -40,17 +75,56 @@ export const ToggleBlockComponent = ({ node, updateAttributes }) => {
onChange={(e) => updateAttributes({ title: e.target.value })}
placeholder="Заголовок..."
style={{ width: inputWidth }}
onFocus={(e) => {
if (title.trim() === 'Заголовок') {
// выделить весь текст
setTimeout(() => e.target.select(), 0)
}
}}
/>
</div>
</div>
<div
className="toggle-body"
data-collapsed={!open}
style={{
maxHeight: open ? '1000px' : '0',
}}
>
<div className="toggle-body-wrapper">
<NodeViewContent className="toggle-content" />
<div
className="toggle-body-wrapper"
onClick={(e) => {
e.stopPropagation()
try {
const pos = getPos?.()
if (typeof pos !== 'number') return
const doc = editor.state.doc
const toggleNode = doc.nodeAt(pos)
if (!toggleNode || toggleNode.childCount === 0) return
const firstBlock = toggleNode.child(0)
if (
firstBlock.type.name === 'paragraph' &&
firstBlock.textContent.trim() === 'Введите подробности...'
) {
const from = pos + 2 // +1 = paragraph, +1 = start of text inside it
const to = from + firstBlock.textContent.length
const tr = editor.state.tr.setSelection(
TextSelection.create(doc, from, to)
)
editor.view.dispatch(tr)
editor.view.focus()
}
} catch (err) {
console.warn('Ошибка выделения toggleBlock:', err)
}
}}
>
<NodeViewContent className="toggle-content"/>
</div>
</div>
</NodeViewWrapper>
......@@ -63,14 +137,14 @@ const ToggleBlock = Node.create({
group: 'block',
content: 'block+',
addAttributes() {
addAttributes () {
return {
title: { default: 'Заголовок' },
open: { default: false },
title: {default: 'Заголовок'},
open: {default: false},
}
},
parseHTML() {
parseHTML () {
return [{
tag: 'div.toggle-block',
getAttrs: (element) => {
......@@ -83,12 +157,12 @@ const ToggleBlock = Node.create({
titleEl.parentNode.removeChild(titleEl)
}
return { title }
return {title}
}
}]
},
renderHTML({ HTMLAttributes }) {
renderHTML ({HTMLAttributes}) {
return [
'div',
{
......@@ -96,15 +170,15 @@ const ToggleBlock = Node.create({
},
[
'div',
{ class: 'toggle-block-inner' },
['span', { class: 'toggle-button ' }],
['span', { class: 'toggle-header' }, HTMLAttributes.title || 'Заголовок'],
{class: 'toggle-block-inner'},
['span', {class: 'toggle-button '}],
['span', {class: 'toggle-header'}, HTMLAttributes.title || 'Заголовок'],
],
['div', { class: 'toggle-body' }, ['div', { class: 'toggle-content' }, 0]],
['div', {class: 'toggle-body'}, ['div', {class: 'toggle-content'}, 0]],
]
},
addNodeView() {
addNodeView () {
return ReactNodeViewRenderer(ToggleBlockComponent)
},
})
......
......@@ -49,8 +49,12 @@ const Video = Node.create({
closeBtn.textContent = 'X'
closeBtn.classList.add('closeBtn')
closeBtn.addEventListener('click', function () {
container.remove()
const pos = editor.view.posAtDOM(container, 0)
editor.view.dispatch(
editor.view.state.tr.delete(pos, pos + node.nodeSize)
)
})
container.append(closeBtn, video)
return {
......
......@@ -1102,14 +1102,14 @@ body{
display: flex;
justify-content: end;
border-radius: 50%;
border: none;
background-color: #2677e3;
color: #fff;
border: 1px solid rgb(217, 217, 217);
background-color: white;
color: #ff4d4f;
font-size: 0.5rem;
padding: 4px 6px;
top: 10px;
top: 4px;
cursor: pointer;
right: 8px;
right: 4px;
z-index: 9;
}
......@@ -1149,20 +1149,18 @@ body{
}
.toggle-body {
overflow: hidden;
transition: max-height 0.3s ease;
transition: max-height 0.5s ease, opacity 0.5s ease;
&[data-collapsed="true"] {
max-height: 0 !important;
opacity: 0;
}
}
.toggle-block[data-open="false"] .toggle-body {
max-height: 0;
padding: 0;
border: none;
}
.toggle-block[data-open="true"] .toggle-body {
max-height: 1000px;
border: 1px dashed #D9D9D9;
border-radius: 6px;
padding: 10px;
background: #FAFAFA;
}
.toggle-block {
margin-bottom: 12px;
}
......@@ -1205,12 +1203,21 @@ body{
background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzYxMDlfNDAzMjYpIj4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNi43NDc1NiA0LjIxMzMzQzYuODc3NDUgNC4wNjQzMSA3LjEyNDkxIDQuMDY0MzEgNy4yNTM0MiA0LjIxMzMzTDExLjc0MjcgOS40MTkzOEMxMS45MDk0IDkuNjEzNTIgMTEuNzU5MSA5Ljg5NzkgMTEuNDg5OCA5Ljg5NzlIMi41MTAyNkMyLjI0MDk5IDkuODk3OSAyLjA5MDcyIDkuNjEzNTIgMi4yNTczMyA5LjQxOTM4TDYuNzQ3NTYgNC4yMTMzM1oiIGZpbGw9ImJsYWNrIiBmaWxsLW9wYWNpdHk9IjAuODUiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF82MTA5XzQwMzI2Ij4KPHJlY3Qgd2lkdGg9IjE0IiBoZWlnaHQ9IjE0IiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);
background-repeat: no-repeat;
background-position: 4px 3px;
transform: rotate(0deg);
transform: rotate(180deg);
background-color: white;
cursor: pointer;
&.open {
transform: rotate(180deg) !important;
transform: rotate(0deg) !important;
}
}
.toggle-block {
position: relative;
}
.toggle-body-wrapper {
padding: 12px;
background: #f7f7f7;
border: 1px solid #d9d9d9;
border-radius: 4px;
transition: background 0.3s ease, border 0.3s ease;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment