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
8c845e28
Commit
8c845e28
authored
Feb 02, 2026
by
Яков
Browse files
update iframe and video
parent
e1b05324
Changes
3
Show whitespace changes
Inline
Side-by-side
package.json
View file @
8c845e28
{
{
"name"
:
"react-ag-qeditor"
,
"name"
:
"react-ag-qeditor"
,
"version"
:
"1.1.2
4
"
,
"version"
:
"1.1.2
5
"
,
"description"
:
"WYSIWYG html editor"
,
"description"
:
"WYSIWYG html editor"
,
"author"
:
"atma"
,
"author"
:
"atma"
,
"license"
:
"
MIT
"
,
"license"
:
"
MIT
"
,
...
...
src/extensions/Iframe.js
View file @
8c845e28
...
@@ -18,8 +18,17 @@ const getStyleForAlign = (align) => {
...
@@ -18,8 +18,17 @@ const getStyleForAlign = (align) => {
return
style
return
style
}
}
const
getOuterAlignStyle
=
(
align
)
=>
{
return
{
width
:
'
100%
'
,
display
:
'
block
'
,
textAlign
:
align
===
'
center
'
?
'
center
'
:
align
===
'
right
'
?
'
right
'
:
'
left
'
,
}
}
const
ResizableIframeView
=
({
editor
,
node
,
updateAttributes
,
getPos
,
selected
})
=>
{
const
ResizableIframeView
=
({
editor
,
node
,
updateAttributes
,
getPos
,
selected
})
=>
{
const
wrapperRef
=
useRef
(
null
)
const
outerRef
=
useRef
(
null
)
const
innerRef
=
useRef
(
null
)
const
iframeRef
=
useRef
(
null
)
const
iframeRef
=
useRef
(
null
)
const
[
showAlignMenu
,
setShowAlignMenu
]
=
useState
(
false
)
const
[
showAlignMenu
,
setShowAlignMenu
]
=
useState
(
false
)
...
@@ -36,10 +45,9 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -36,10 +45,9 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
const
paddingRight
=
parseFloat
(
editorStyles
.
paddingRight
)
||
0
const
paddingRight
=
parseFloat
(
editorStyles
.
paddingRight
)
||
0
const
availableEditorWidth
=
fullEditorWidth
-
paddingLeft
-
paddingRight
const
availableEditorWidth
=
fullEditorWidth
-
paddingLeft
-
paddingRight
// важно: стартуем от parentElement, чтобы не схватить wrapperRef.current
// важно: стартуем от parentElement, чтобы не схватить innerRef.current
const
startEl
=
wrapperRef
.
current
?.
parentElement
||
editorContent
const
startEl
=
outerRef
.
current
?.
parentElement
||
editorContent
const
container
=
const
container
=
startEl
.
closest
(
'
li, blockquote, td, p, div
'
)
||
editorContent
startEl
.
closest
(
'
li, blockquote, td, p, div
'
)
||
editorContent
const
containerStyles
=
window
.
getComputedStyle
(
container
)
const
containerStyles
=
window
.
getComputedStyle
(
container
)
const
containerPaddingLeft
=
parseFloat
(
containerStyles
.
paddingLeft
)
||
0
const
containerPaddingLeft
=
parseFloat
(
containerStyles
.
paddingLeft
)
||
0
...
@@ -49,7 +57,6 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -49,7 +57,6 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
return
{
width
:
containerWidth
,
availableSpace
:
availableEditorWidth
}
return
{
width
:
containerWidth
,
availableSpace
:
availableEditorWidth
}
}
}
const
safeUpdateAttributes
=
(
newAttrs
)
=>
{
const
safeUpdateAttributes
=
(
newAttrs
)
=>
{
const
{
width
:
containerWidth
,
availableSpace
}
=
getEditorDimensions
()
const
{
width
:
containerWidth
,
availableSpace
}
=
getEditorDimensions
()
...
@@ -57,7 +64,8 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -57,7 +64,8 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
let
height
=
newAttrs
.
height
??
node
.
attrs
.
height
let
height
=
newAttrs
.
height
??
node
.
attrs
.
height
if
(
typeof
width
===
'
number
'
&&
typeof
height
===
'
number
'
)
{
if
(
typeof
width
===
'
number
'
&&
typeof
height
===
'
number
'
)
{
const
maxWidth
=
node
.
attrs
.
align
===
'
center
'
?
containerWidth
:
availableSpace
const
maxWidth
=
(
newAttrs
.
align
??
node
.
attrs
.
align
)
===
'
center
'
?
containerWidth
:
availableSpace
if
(
width
>
maxWidth
)
{
if
(
width
>
maxWidth
)
{
const
ratio
=
maxWidth
/
width
const
ratio
=
maxWidth
/
width
width
=
maxWidth
width
=
maxWidth
...
@@ -117,14 +125,14 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -117,14 +125,14 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
console
.
warn
(
'
getPos() failed:
'
,
err
)
console
.
warn
(
'
getPos() failed:
'
,
err
)
}
}
const
startWidth
=
node
.
attrs
.
width
||
i
frame
Ref
.
current
?.
clientWidth
||
560
const
startWidth
=
node
.
attrs
.
width
||
i
nner
Ref
.
current
?.
clientWidth
||
560
const
startHeight
=
node
.
attrs
.
height
||
i
frame
Ref
.
current
?.
clientHeight
||
315
const
startHeight
=
node
.
attrs
.
height
||
i
nner
Ref
.
current
?.
clientHeight
||
315
const
aspectRatio
=
startWidth
/
startHeight
const
aspectRatio
=
startWidth
/
startHeight
const
startX
=
e
.
clientX
const
startX
=
e
.
clientX
const
startY
=
e
.
clientY
const
startY
=
e
.
clientY
const
{
width
:
containerWidth
,
availableSpace
}
=
getEditorDimensions
()
const
{
width
:
containerWidth
,
availableSpace
}
=
getEditorDimensions
()
const
maxWidth
=
node
.
attrs
.
align
===
'
center
'
?
containerWidth
:
availableSpace
const
maxWidth
=
(
node
.
attrs
.
align
||
'
left
'
)
===
'
center
'
?
containerWidth
:
availableSpace
const
onMouseMove
=
(
ev
)
=>
{
const
onMouseMove
=
(
ev
)
=>
{
requestAnimationFrame
(()
=>
{
requestAnimationFrame
(()
=>
{
...
@@ -177,31 +185,24 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -177,31 +185,24 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
const
align
=
node
.
attrs
.
align
||
'
left
'
const
align
=
node
.
attrs
.
align
||
'
left
'
const
wrapperStyle
=
{
const
outerStyle
=
getOuterAlignStyle
(
align
)
const
innerStyle
=
{
position
:
'
relative
'
,
position
:
'
relative
'
,
display
:
'
inline-block
'
,
width
:
node
.
attrs
.
width
?
`
${
node
.
attrs
.
width
}
px`
:
undefined
,
width
:
node
.
attrs
.
width
?
`
${
node
.
attrs
.
width
}
px`
:
undefined
,
height
:
node
.
attrs
.
height
?
`
${
node
.
attrs
.
height
}
px`
:
undefined
,
height
:
node
.
attrs
.
height
?
`
${
node
.
attrs
.
height
}
px`
:
undefined
,
// align styles inside editor
display
:
align
===
'
center
'
?
'
block
'
:
'
inline-block
'
,
marginLeft
:
align
===
'
center
'
?
'
auto
'
:
undefined
,
marginRight
:
align
===
'
center
'
?
'
auto
'
:
undefined
,
float
:
align
===
'
left
'
?
'
left
'
:
align
===
'
right
'
?
'
right
'
:
'
none
'
,
// чтобы текст красиво обтекал
marginInlineEnd
:
align
===
'
left
'
?
'
1rem
'
:
undefined
,
marginInlineStart
:
align
===
'
right
'
?
'
1rem
'
:
undefined
,
}
}
return
(
return
(
<
NodeViewWrapper
<
NodeViewWrapper
ref
=
{
wrapp
erRef
}
ref
=
{
out
erRef
}
as
=
"
div
"
as
=
"
div
"
className
=
"
atma-iframe-wrapper
"
className
=
"
atma-iframe-wrapper
"
style
=
{
wrapp
erStyle
}
style
=
{
out
erStyle
}
data
-
align
=
{
node
.
attrs
.
align
||
'
left
'
}
data
-
align
=
{
align
}
>
>
<
div
ref
=
{
innerRef
}
style
=
{
innerStyle
}
>
<
iframe
<
iframe
ref
=
{
iframeRef
}
ref
=
{
iframeRef
}
src
=
{
node
.
attrs
.
src
}
src
=
{
node
.
attrs
.
src
}
...
@@ -272,21 +273,21 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -272,21 +273,21 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
display
:
'
flex
'
,
display
:
'
flex
'
,
}}
}}
>
>
{
ALIGN_OPTIONS
.
map
((
a
lign
)
=>
(
{
ALIGN_OPTIONS
.
map
((
a
)
=>
(
<
button
<
button
type
=
"
button
"
type
=
"
button
"
key
=
{
a
lign
}
key
=
{
a
}
onClick
=
{()
=>
handleAlign
(
a
lign
)}
onClick
=
{()
=>
handleAlign
(
a
)}
style
=
{{
style
=
{{
margin
:
'
0 2px
'
,
margin
:
'
0 2px
'
,
padding
:
'
10px 8px
'
,
padding
:
'
10px 8px
'
,
background
:
node
.
attrs
.
align
===
a
lign
?
'
#e6f7ff
'
:
'
transparent
'
,
background
:
align
===
a
?
'
#e6f7ff
'
:
'
transparent
'
,
border
:
'
1px solid #d9d9d9
'
,
border
:
'
1px solid #d9d9d9
'
,
borderRadius
:
2
,
borderRadius
:
2
,
cursor
:
'
pointer
'
,
cursor
:
'
pointer
'
,
}}
}}
>
>
{
align
}
{
a
}
<
/button
>
<
/button
>
))}
))}
<
/div
>
<
/div
>
...
@@ -316,6 +317,7 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
...
@@ -316,6 +317,7 @@ const ResizableIframeView = ({ editor, node, updateAttributes, getPos, selected
<
/button
>
<
/button
>
<
/Fragment
>
<
/Fragment
>
)}
)}
<
/div
>
<
/NodeViewWrapper
>
<
/NodeViewWrapper
>
)
)
}
}
...
...
src/extensions/Video.js
View file @
8c845e28
...
@@ -18,8 +18,17 @@ const getStyleForAlign = (align) => {
...
@@ -18,8 +18,17 @@ const getStyleForAlign = (align) => {
return
style
return
style
}
}
const
getOuterAlignStyle
=
(
align
)
=>
{
return
{
width
:
'
100%
'
,
display
:
'
block
'
,
textAlign
:
align
===
'
center
'
?
'
center
'
:
align
===
'
right
'
?
'
right
'
:
'
left
'
,
}
}
const
ResizableVideoView
=
({
editor
,
node
,
updateAttributes
,
getPos
,
selected
})
=>
{
const
ResizableVideoView
=
({
editor
,
node
,
updateAttributes
,
getPos
,
selected
})
=>
{
const
wrapperRef
=
useRef
(
null
)
const
outerRef
=
useRef
(
null
)
const
innerRef
=
useRef
(
null
)
const
videoRef
=
useRef
(
null
)
const
videoRef
=
useRef
(
null
)
const
[
showAlignMenu
,
setShowAlignMenu
]
=
useState
(
false
)
const
[
showAlignMenu
,
setShowAlignMenu
]
=
useState
(
false
)
...
@@ -36,7 +45,9 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
...
@@ -36,7 +45,9 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
const
paddingRight
=
parseFloat
(
editorStyles
.
paddingRight
)
||
0
const
paddingRight
=
parseFloat
(
editorStyles
.
paddingRight
)
||
0
const
availableEditorWidth
=
fullEditorWidth
-
paddingLeft
-
paddingRight
const
availableEditorWidth
=
fullEditorWidth
-
paddingLeft
-
paddingRight
const
container
=
wrapperRef
.
current
?.
closest
(
'
li, blockquote, td, p, div
'
)
||
editorContent
const
startEl
=
outerRef
.
current
?.
parentElement
||
editorContent
const
container
=
startEl
.
closest
(
'
li, blockquote, td, p, div
'
)
||
editorContent
const
containerStyles
=
window
.
getComputedStyle
(
container
)
const
containerStyles
=
window
.
getComputedStyle
(
container
)
const
containerPaddingLeft
=
parseFloat
(
containerStyles
.
paddingLeft
)
||
0
const
containerPaddingLeft
=
parseFloat
(
containerStyles
.
paddingLeft
)
||
0
const
containerPaddingRight
=
parseFloat
(
containerStyles
.
paddingRight
)
||
0
const
containerPaddingRight
=
parseFloat
(
containerStyles
.
paddingRight
)
||
0
...
@@ -52,7 +63,8 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
...
@@ -52,7 +63,8 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
let
height
=
newAttrs
.
height
??
node
.
attrs
.
height
let
height
=
newAttrs
.
height
??
node
.
attrs
.
height
if
(
typeof
width
===
'
number
'
&&
typeof
height
===
'
number
'
)
{
if
(
typeof
width
===
'
number
'
&&
typeof
height
===
'
number
'
)
{
const
maxWidth
=
node
.
attrs
.
align
===
'
center
'
?
containerWidth
:
availableSpace
const
maxWidth
=
(
newAttrs
.
align
??
node
.
attrs
.
align
)
===
'
center
'
?
containerWidth
:
availableSpace
if
(
width
>
maxWidth
)
{
if
(
width
>
maxWidth
)
{
const
ratio
=
maxWidth
/
width
const
ratio
=
maxWidth
/
width
width
=
maxWidth
width
=
maxWidth
...
@@ -112,14 +124,14 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
...
@@ -112,14 +124,14 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
console
.
warn
(
'
getPos() failed:
'
,
err
)
console
.
warn
(
'
getPos() failed:
'
,
err
)
}
}
const
startWidth
=
node
.
attrs
.
width
||
video
Ref
.
current
?.
clientWidth
||
640
const
startWidth
=
node
.
attrs
.
width
||
inner
Ref
.
current
?.
clientWidth
||
640
const
startHeight
=
node
.
attrs
.
height
||
video
Ref
.
current
?.
clientHeight
||
360
const
startHeight
=
node
.
attrs
.
height
||
inner
Ref
.
current
?.
clientHeight
||
360
const
aspectRatio
=
startWidth
/
startHeight
const
aspectRatio
=
startWidth
/
startHeight
const
startX
=
e
.
clientX
const
startX
=
e
.
clientX
const
startY
=
e
.
clientY
const
startY
=
e
.
clientY
const
{
width
:
containerWidth
,
availableSpace
}
=
getEditorDimensions
()
const
{
width
:
containerWidth
,
availableSpace
}
=
getEditorDimensions
()
const
maxWidth
=
node
.
attrs
.
align
===
'
center
'
?
containerWidth
:
availableSpace
const
maxWidth
=
(
node
.
attrs
.
align
||
'
left
'
)
===
'
center
'
?
containerWidth
:
availableSpace
const
onMouseMove
=
(
ev
)
=>
{
const
onMouseMove
=
(
ev
)
=>
{
requestAnimationFrame
(()
=>
{
requestAnimationFrame
(()
=>
{
...
@@ -170,21 +182,26 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
...
@@ -170,21 +182,26 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
}
}
}
}
const
wrapperStyle
=
{
const
align
=
node
.
attrs
.
align
||
'
left
'
const
outerStyle
=
getOuterAlignStyle
(
align
)
const
innerStyle
=
{
position
:
'
relative
'
,
position
:
'
relative
'
,
display
:
node
.
attrs
.
align
===
'
center
'
?
'
block
'
:
'
inline-block
'
,
display
:
'
inline-block
'
,
width
:
node
.
attrs
.
width
?
`
${
node
.
attrs
.
width
}
px`
:
undefined
,
width
:
node
.
attrs
.
width
?
`
${
node
.
attrs
.
width
}
px`
:
undefined
,
height
:
node
.
attrs
.
height
?
`
${
node
.
attrs
.
height
}
px`
:
undefined
,
height
:
node
.
attrs
.
height
?
`
${
node
.
attrs
.
height
}
px`
:
undefined
,
}
}
return
(
return
(
<
NodeViewWrapper
<
NodeViewWrapper
ref
=
{
wrapp
erRef
}
ref
=
{
out
erRef
}
as
=
"
div
"
as
=
"
div
"
className
=
"
atma-video-wrapper
"
className
=
"
atma-video-wrapper
"
style
=
{
wrapp
erStyle
}
style
=
{
out
erStyle
}
data
-
align
=
{
node
.
attrs
.
align
||
'
left
'
}
data
-
align
=
{
align
}
>
>
<
div
ref
=
{
innerRef
}
style
=
{
innerStyle
}
>
<
video
<
video
ref
=
{
videoRef
}
ref
=
{
videoRef
}
src
=
{
node
.
attrs
.
src
}
src
=
{
node
.
attrs
.
src
}
...
@@ -254,21 +271,21 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
...
@@ -254,21 +271,21 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
display
:
'
flex
'
,
display
:
'
flex
'
,
}}
}}
>
>
{
ALIGN_OPTIONS
.
map
((
a
lign
)
=>
(
{
ALIGN_OPTIONS
.
map
((
a
)
=>
(
<
button
<
button
type
=
"
button
"
type
=
"
button
"
key
=
{
a
lign
}
key
=
{
a
}
onClick
=
{()
=>
handleAlign
(
a
lign
)}
onClick
=
{()
=>
handleAlign
(
a
)}
style
=
{{
style
=
{{
margin
:
'
0 2px
'
,
margin
:
'
0 2px
'
,
padding
:
'
10px 8px
'
,
padding
:
'
10px 8px
'
,
background
:
node
.
attrs
.
align
===
a
lign
?
'
#e6f7ff
'
:
'
transparent
'
,
background
:
align
===
a
?
'
#e6f7ff
'
:
'
transparent
'
,
border
:
'
1px solid #d9d9d9
'
,
border
:
'
1px solid #d9d9d9
'
,
borderRadius
:
2
,
borderRadius
:
2
,
cursor
:
'
pointer
'
,
cursor
:
'
pointer
'
,
}}
}}
>
>
{
align
}
{
a
}
<
/button
>
<
/button
>
))}
))}
<
/div
>
<
/div
>
...
@@ -298,6 +315,7 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
...
@@ -298,6 +315,7 @@ const ResizableVideoView = ({ editor, node, updateAttributes, getPos, selected }
<
/button
>
<
/button
>
<
/Fragment
>
<
/Fragment
>
)}
)}
<
/div
>
<
/NodeViewWrapper
>
<
/NodeViewWrapper
>
)
)
}
}
...
...
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