Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
lib
react-ag-qeditor
Commits
5499f2c8
Commit
5499f2c8
authored
Oct 02, 2023
by
Nikita
Browse files
added remove iframe button
parent
6ce5f728
Changes
6
Show whitespace changes
Inline
Side-by-side
src/QEditor.jsx
View file @
5499f2c8
...
...
@@ -31,6 +31,9 @@ import ReactStopwatch from 'react-stopwatch';
import
Audio
from
"
./extensions/Audio
"
;
import
{
isMobile
}
from
'
react-device-detect
'
;
import
IframeModal
from
"
./modals/IframeModal
"
;
import
IframeCustomModal
from
"
./modals/IframeCustomModal
"
;
import
RemoveIframeModal
from
"
./modals/RemoveIframeModal
"
;
const
initialBubbleItems
=
[
'
bold
'
,
'
italic
'
,
'
underline
'
,
'
strike
'
,
'
|
'
,
'
colorText
'
,
'
highlight
'
];
...
...
@@ -55,6 +58,7 @@ const QEditor = ({
const
[
oldFocusFromTo
,
setOldFocusFromTo
]
=
useState
(
null
);
const
[
isUploading
,
setIsUploading
]
=
useState
(
false
);
const
[
recordType
,
setRecordType
]
=
useState
({
video
:
true
})
const
[
currentRemoveIframe
,
setCurrentRemoveIframe
]
=
useState
(
null
);
const
getRgb
=
(
hex
)
=>
{
var
result
=
/^#
?([
a-f
\d]{2})([
a-f
\d]{2})([
a-f
\d]{2})
$/i
.
exec
(
hex
);
...
...
@@ -495,29 +499,18 @@ const QEditor = ({
const
getInnerModal
=
()
=>
{
switch
(
innerModalType
)
{
case
'
remove_iframe
'
:
return
<
RemoveIframeModal
/>
case
'
iframe
'
:
return
(
<
Fragment
>
<
input
type
=
"text"
value
=
{
embedContent
}
placeholder
=
{
'
https://
'
}
onInput
=
{
(
e
)
=>
setEmbedContent
(
e
.
target
.
value
)
}
/>
<
ul
className
=
{
'
atma-editor-soc-video
'
}
>
<
li
className
=
{
'
youtube
'
}
/>
<
li
className
=
{
'
vimeo
'
}
/>
{
/* <li className={'vk'}/> */
}
<
li
className
=
{
'
ok
'
}
/>
<
li
className
=
{
'
rutube
'
}
/>
</
ul
>
</
Fragment
>
)
return
<
IframeModal
embedContent
=
{
embedContent
}
setEmbedContent
=
{
setEmbedContent
}
/>
case
'
iframe_custom
'
:
return
(
<
Fragment
>
<
textarea
style
=
{
{
width
:
'
100%
'
,
height
:
'
100%
'
}
}
rows
=
{
18
}
value
=
{
embedContent
}
placeholder
=
{
'
<iframe></iframe>
'
}
onInput
=
{
(
e
)
=>
setEmbedContent
(
e
.
target
.
value
)
}
return
<
IframeCustomModal
embedContent
=
{
embedContent
}
setEmbedContent
=
{
setEmbedContent
}
/>
</
Fragment
>
)
case
'
iframe_pptx
'
:
return
(
<
Fragment
>
{
getUploader
({
accept
:
'
application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.slideshow, application/vnd.openxmlformats-officedocument.presentationml.presentation
'
,
afterParams
:
[
'
no_convert=1
'
]})
}
</
Fragment
>
...
...
@@ -536,7 +529,6 @@ const QEditor = ({
)
case
'
voicemessage
'
:
return
(
<>
<
Fragment
>
{
isMobile
&&
...
...
@@ -577,7 +569,6 @@ const QEditor = ({
</
div
>
}
</
Fragment
>
</>
)
case
'
screencust
'
:
return
(
...
...
@@ -794,86 +785,35 @@ const QEditor = ({
return
null
}
return
(
<
div
className
=
"atma-editor-wrap"
style
=
{
style
}
>
<
div
className
=
"atma-editor"
>
<
ToolBar
editor
=
{
editor
}
{
...{
toolsOptions
}
}
{
...{
toolsLib
}
}
/>
<
BubbleMenu
typpyOptions
=
{
{
followCursor
:
true
,}
}
editor
=
{
editor
}
shouldShow
=
{
({...
o
})
=>
{
let
items
=
[];
if
(
o
.
from
!==
o
.
to
&&
editor
.
isActive
(
'
paragraph
'
)
&&
editor
.
isActive
(
'
image
'
)
===
false
&&
document
.
querySelectorAll
(
'
.selectedCell
'
).
length
===
0
)
{
items
=
initialBubbleItems
;
}
if
(
editor
.
isActive
(
'
image
'
)
===
true
)
{
items
=
[
'
alignLeft
'
,
'
alignCenter
'
,
'
alignRight
'
];
}
setFocusFromTo
([
o
.
from
,
o
.
to
].
join
(
'
:
'
));
if
(
items
.
length
>
0
)
{
setBubbleItems
(
items
);
return
true
;
}
}
}
tippyOptions
=
{
{
duration
:
100
}
}
>
<
div
className
=
{
"
atma-editor-bubble
"
}
onClick
=
{
e
=>
e
.
stopPropagation
()
}
>
const
buttons
=
innerModalType
===
'
remove_iframe
'
?
[
{
colorsSelected
!==
null
?
colors
[
colorsSelected
].
map
((
itemColor
,
i
)
=>
{
return
(<
div
key
=
{
'
colors
'
+
colorsSelected
+
i
}
className
=
{
'
qcolors
'
+
(
itemColor
===
'
none
'
?
'
unset
'
:
''
)
}
style
=
{
{
background
:
itemColor
}
}
onClick
=
{
()
=>
{
if
(
itemColor
===
'
none
'
)
{
colorsSelected
===
'
color
'
?
editor
.
chain
().
focus
().
unsetHighlight
().
unsetColor
().
run
()
:
editor
.
chain
().
focus
().
unsetColor
().
unsetHighlight
().
run
();
}
else
{
colorsSelected
===
'
color
'
?
editor
.
chain
().
focus
().
unsetHighlight
().
setColor
(
itemColor
).
run
()
:
editor
.
chain
().
focus
().
unsetColor
().
toggleHighlight
({
color
:
itemColor
}).
run
();
}
setColorsSelected
(
null
);
}
}
/>)
})
:
bubbleItems
.
map
((
type
,
i
)
=>
{
if
(
type
===
'
|
'
)
{
return
(<
div
key
=
{
'
bubbleSeparator
'
+
i
}
className
=
{
'
qseparator
'
}
/>)
}
else
{
return
(
<
div
key
=
{
'
bubbleItems
'
+
i
}
className
=
{
'
qicon q
'
+
type
+
(
editor
.
isActive
(
type
)
?
'
active
'
:
''
)
}
title
=
{
toolsLib
[
type
]
?
toolsLib
[
type
].
title
:
''
}
onClick
=
{
toolsLib
[
type
].
onClick
}
/>
)
}
})
title
:
'
Отмена
'
,
className
:
'
atma-editor-cancel
'
,
onClick
:
()
=>
{
stopRecording
();
unMuteAudio
();
clearBlobUrl
();
setUploaderUid
(
`uid
${
new
Date
()}
`
);
setUploadedPaths
([]);
setModalIsOpen
(
false
);
}
</
div
>
</
BubbleMenu
>
<
EditorContent
editor
=
{
editor
}
className
=
{
'
atma-editor-content
'
}
/>
</
div
>
<
EditorModal
isOpen
=
{
modalIsOpen
}
title
=
{
modalTitle
}
>
},
{
getInnerModal
()
title
:
'
Удалить
'
,
className
:
'
atma-editor-complete
'
,
onClick
:
()
=>
{
currentRemoveIframe
?.
remove
();
stopRecording
();
unMuteAudio
();
clearBlobUrl
();
setUploaderUid
(
`uid
${
new
Date
()}
`
);
setUploadedPaths
([]);
setModalIsOpen
(
false
);
}
{
buildActionsModal
(
[
},
]
:
[
{
title
:
'
Отмена
'
,
className
:
'
atma-editor-cancel
'
,
...
...
@@ -979,7 +919,7 @@ const QEditor = ({
_url
=
`https://www.youtube.com/embed/
${
urlId
}
`
;
break
}
editor
.
chain
().
focus
().
setIframe
({
src
:
_url
}).
run
();
editor
.
chain
().
focus
().
setIframe
({
src
:
_url
,
setModalIsOpen
,
setInnerModalType
,
setModalTitle
,
setCurrentRemoveIframe
}).
run
();
break
case
'
iframe_custom
'
:
...
...
@@ -1018,7 +958,88 @@ const QEditor = ({
},
disabled
:
isDisabledAction
()
}
])
];
return
(
<
div
className
=
"atma-editor-wrap"
style
=
{
style
}
>
<
div
className
=
"atma-editor"
>
<
ToolBar
editor
=
{
editor
}
{
...{
toolsOptions
}
}
{
...{
toolsLib
}
}
/>
<
BubbleMenu
typpyOptions
=
{
{
followCursor
:
true
,}
}
editor
=
{
editor
}
shouldShow
=
{
({...
o
})
=>
{
let
items
=
[];
if
(
o
.
from
!==
o
.
to
&&
editor
.
isActive
(
'
paragraph
'
)
&&
editor
.
isActive
(
'
image
'
)
===
false
&&
document
.
querySelectorAll
(
'
.selectedCell
'
).
length
===
0
)
{
items
=
initialBubbleItems
;
}
if
(
editor
.
isActive
(
'
image
'
)
===
true
)
{
items
=
[
'
alignLeft
'
,
'
alignCenter
'
,
'
alignRight
'
];
}
setFocusFromTo
([
o
.
from
,
o
.
to
].
join
(
'
:
'
));
if
(
items
.
length
>
0
)
{
setBubbleItems
(
items
);
return
true
;
}
}
}
tippyOptions
=
{
{
duration
:
100
}
}
>
<
div
className
=
{
"
atma-editor-bubble
"
}
onClick
=
{
e
=>
e
.
stopPropagation
()
}
>
{
colorsSelected
!==
null
?
colors
[
colorsSelected
].
map
((
itemColor
,
i
)
=>
{
return
(<
div
key
=
{
'
colors
'
+
colorsSelected
+
i
}
className
=
{
'
qcolors
'
+
(
itemColor
===
'
none
'
?
'
unset
'
:
''
)
}
style
=
{
{
background
:
itemColor
}
}
onClick
=
{
()
=>
{
if
(
itemColor
===
'
none
'
)
{
colorsSelected
===
'
color
'
?
editor
.
chain
().
focus
().
unsetHighlight
().
unsetColor
().
run
()
:
editor
.
chain
().
focus
().
unsetColor
().
unsetHighlight
().
run
();
}
else
{
colorsSelected
===
'
color
'
?
editor
.
chain
().
focus
().
unsetHighlight
().
setColor
(
itemColor
).
run
()
:
editor
.
chain
().
focus
().
unsetColor
().
toggleHighlight
({
color
:
itemColor
}).
run
();
}
setColorsSelected
(
null
);
}
}
/>)
})
:
bubbleItems
.
map
((
type
,
i
)
=>
{
if
(
type
===
'
|
'
)
{
return
(<
div
key
=
{
'
bubbleSeparator
'
+
i
}
className
=
{
'
qseparator
'
}
/>)
}
else
{
return
(
<
div
key
=
{
'
bubbleItems
'
+
i
}
className
=
{
'
qicon q
'
+
type
+
(
editor
.
isActive
(
type
)
?
'
active
'
:
''
)
}
title
=
{
toolsLib
[
type
]
?
toolsLib
[
type
].
title
:
''
}
onClick
=
{
toolsLib
[
type
].
onClick
}
/>
)
}
})
}
</
div
>
</
BubbleMenu
>
<
EditorContent
editor
=
{
editor
}
className
=
{
'
atma-editor-content
'
}
/>
</
div
>
<
EditorModal
isOpen
=
{
modalIsOpen
}
title
=
{
modalTitle
}
>
{
getInnerModal
()
}
{
buildActionsModal
(
buttons
)
}
</
EditorModal
>
</
div
>
...
...
src/extensions/Iframe.js
View file @
5499f2c8
...
...
@@ -21,6 +21,18 @@ const Iframe = Node.create({
console
.
log
(
this
)
},
},
"
setInnerModalType
"
:
{
default
:
null
},
"
setModalIsOpen
"
:
{
default
:
null
},
"
setModalTitle
"
:
{
default
:
null
},
"
setCurrentRemoveIframe
"
:
{
default
:
null
}
}
},
...
...
@@ -38,21 +50,35 @@ const Iframe = Node.create({
addNodeView
()
{
return
({
editor
,
node
,
...
a
})
=>
{
const
container
=
document
.
createElement
(
'
div
'
);
// div.className = 'aspect-w-16 aspect-h-9' + (editor.isEditable ? ' cursor-pointer' : '');
const
iframe
=
document
.
createElement
(
'
iframe
'
);
if
(
editor
.
isEditable
)
{
iframe
.
className
=
'
pointer-events-none
'
;
}
iframe
.
src
=
node
.
attrs
.
src
;
iframe
.
frameBorder
=
node
.
attrs
.
frameborder
;
iframe
.
allowfullscreen
=
node
.
attrs
.
allowfullscreen
;
iframe
.
style
=
'
width:1280px;height:auto;aspect-ratio: 16 / 9;
'
;
// div.append(video);
iframe
.
classList
.
add
(
'
customIframe
'
);
const
closeBtn
=
document
.
createElement
(
'
button
'
);
closeBtn
.
textContent
=
'
X
'
;
closeBtn
.
classList
.
add
(
'
closeBtn
'
);
closeBtn
.
addEventListener
(
'
click
'
,
function
()
{
try
{
node
.
attrs
.
setModalTitle
(
'
Вы уверены, что хотите удалить?
'
);
node
.
attrs
.
setInnerModalType
(
'
remove_iframe
'
);
node
.
attrs
.
setModalIsOpen
(
true
);
node
.
attrs
.
setCurrentRemoveIframe
(
container
);
}
catch
{
container
.
remove
();
}
});
// if (editor.isEditable) {
// container.classList.add('pointer-events-none');
// }
container
.
append
(
closeBtn
,
iframe
);
return
{
dom
:
iframe
,
dom
:
container
,
}
}
},
...
...
@@ -62,7 +88,7 @@ const Iframe = Node.create({
setIframe
:
(
options
)
=>
({
tr
,
dispatch
})
=>
{
const
{
selection
}
=
tr
const
node
=
this
.
type
.
create
(
options
)
//
if
(
dispatch
)
{
tr
.
replaceRangeWith
(
selection
.
from
,
selection
.
to
,
node
)
}
...
...
src/index.scss
View file @
5499f2c8
...
...
@@ -1022,4 +1022,25 @@ body{
.qseparator{
width: 16px;
}
.closeBtn {
position: relative;
display: flex;
justify-content: end;
border-radius: 50%;
border: none;
background-color: #2677e3;
color: #fff;
font-size: 0.5rem;
padding: 4px 6px;
top: 10px;
cursor: pointer;
right: 8px;
}
.customIframe {
width:1280px;
height:auto;
aspect-ratio: 16 / 9;
}
}
src/modals/IframeCustomModal.js
0 → 100644
View file @
5499f2c8
import
React
,
{
Fragment
}
from
"
react
"
;
export
default
function
IframeCustomModal
({
embedContent
,
setEmbedContent
})
{
return
(
<
Fragment
>
<
textarea
style
=
{{
width
:
'
100%
'
,
height
:
'
100%
'
}}
rows
=
{
18
}
value
=
{
embedContent
}
placeholder
=
{
'
<iframe></iframe>
'
}
onInput
=
{(
e
)
=>
setEmbedContent
(
e
.
target
.
value
)}
/
>
<
/Fragment
>
)
}
src/modals/IframeModal.js
0 → 100644
View file @
5499f2c8
import
React
,
{
Fragment
}
from
"
react
"
;
export
default
function
IframeModal
({
embedContent
,
setEmbedContent
})
{
return
(
<
Fragment
>
<
input
type
=
"
text
"
value
=
{
embedContent
}
placeholder
=
{
'
https://
'
}
onInput
=
{(
e
)
=>
setEmbedContent
(
e
.
target
.
value
)
}
/
>
<
ul
className
=
{
'
atma-editor-soc-video
'
}
>
<
li
className
=
{
'
youtube
'
}
/
>
<
li
className
=
{
'
vimeo
'
}
/
>
{
/* <li className={'vk'}/> */
}
<
li
className
=
{
'
ok
'
}
/
>
<
li
className
=
{
'
rutube
'
}
/
>
<
/ul
>
<
/Fragment
>
)
}
src/modals/RemoveIframeModal.js
0 → 100644
View file @
5499f2c8
import
React
,
{
Fragment
}
from
"
react
"
;
export
default
function
RemoveIframeModal
(){
return
(
<
Fragment
>
<
/Fragment
>
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment