@pubwave/editor 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +146 -24
- package/dist/index.js +146 -24
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4854,6 +4854,89 @@ function calculateVerticalPositionFromRect(triggerRect, dropdownHeight, margin =
|
|
|
4854
4854
|
margin
|
|
4855
4855
|
);
|
|
4856
4856
|
}
|
|
4857
|
+
function calculateHorizontalPosition(triggerLeft, triggerRight, dropdownWidth, preferredAlign = "left", margin = 8) {
|
|
4858
|
+
const viewportWidth = window.innerWidth;
|
|
4859
|
+
const triggerCenter = (triggerLeft + triggerRight) / 2;
|
|
4860
|
+
const spaceLeft = triggerLeft;
|
|
4861
|
+
const spaceRight = viewportWidth - triggerRight;
|
|
4862
|
+
const requiredSpaceForLeft = dropdownWidth + margin;
|
|
4863
|
+
const requiredSpaceForRight = dropdownWidth + margin;
|
|
4864
|
+
const requiredSpaceForCenter = dropdownWidth / 2 + margin;
|
|
4865
|
+
let align = preferredAlign;
|
|
4866
|
+
let left2;
|
|
4867
|
+
if (preferredAlign === "left") {
|
|
4868
|
+
left2 = triggerLeft;
|
|
4869
|
+
if (left2 < margin || left2 + dropdownWidth > viewportWidth - margin) {
|
|
4870
|
+
if (spaceRight >= requiredSpaceForRight && triggerRight + dropdownWidth <= viewportWidth - margin) {
|
|
4871
|
+
align = "right";
|
|
4872
|
+
left2 = triggerRight - dropdownWidth;
|
|
4873
|
+
} else if (spaceLeft >= requiredSpaceForCenter && triggerCenter - dropdownWidth / 2 >= margin) {
|
|
4874
|
+
align = "center";
|
|
4875
|
+
left2 = triggerCenter - dropdownWidth / 2;
|
|
4876
|
+
} else {
|
|
4877
|
+
if (spaceRight >= spaceLeft) {
|
|
4878
|
+
align = "right";
|
|
4879
|
+
left2 = triggerRight - dropdownWidth;
|
|
4880
|
+
} else {
|
|
4881
|
+
align = "left";
|
|
4882
|
+
left2 = triggerLeft;
|
|
4883
|
+
}
|
|
4884
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4885
|
+
}
|
|
4886
|
+
}
|
|
4887
|
+
} else if (preferredAlign === "center") {
|
|
4888
|
+
left2 = triggerCenter - dropdownWidth / 2;
|
|
4889
|
+
if (left2 < margin || left2 + dropdownWidth > viewportWidth - margin) {
|
|
4890
|
+
if (spaceRight >= requiredSpaceForRight && triggerRight + dropdownWidth <= viewportWidth - margin) {
|
|
4891
|
+
align = "right";
|
|
4892
|
+
left2 = triggerRight - dropdownWidth;
|
|
4893
|
+
} else if (spaceLeft >= requiredSpaceForLeft && triggerLeft + dropdownWidth <= viewportWidth - margin) {
|
|
4894
|
+
align = "left";
|
|
4895
|
+
left2 = triggerLeft;
|
|
4896
|
+
} else {
|
|
4897
|
+
if (spaceRight >= spaceLeft) {
|
|
4898
|
+
align = "right";
|
|
4899
|
+
left2 = triggerRight - dropdownWidth;
|
|
4900
|
+
} else {
|
|
4901
|
+
align = "left";
|
|
4902
|
+
left2 = triggerLeft;
|
|
4903
|
+
}
|
|
4904
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
} else {
|
|
4908
|
+
left2 = triggerRight - dropdownWidth;
|
|
4909
|
+
if (left2 < margin || left2 + dropdownWidth > viewportWidth - margin) {
|
|
4910
|
+
if (spaceLeft >= requiredSpaceForLeft && triggerLeft + dropdownWidth <= viewportWidth - margin) {
|
|
4911
|
+
align = "left";
|
|
4912
|
+
left2 = triggerLeft;
|
|
4913
|
+
} else if (spaceLeft >= requiredSpaceForCenter && triggerCenter - dropdownWidth / 2 >= margin) {
|
|
4914
|
+
align = "center";
|
|
4915
|
+
left2 = triggerCenter - dropdownWidth / 2;
|
|
4916
|
+
} else {
|
|
4917
|
+
if (spaceLeft >= spaceRight) {
|
|
4918
|
+
align = "left";
|
|
4919
|
+
left2 = triggerLeft;
|
|
4920
|
+
} else {
|
|
4921
|
+
align = "right";
|
|
4922
|
+
left2 = triggerRight - dropdownWidth;
|
|
4923
|
+
}
|
|
4924
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4925
|
+
}
|
|
4926
|
+
}
|
|
4927
|
+
}
|
|
4928
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4929
|
+
return { align, left: left2 };
|
|
4930
|
+
}
|
|
4931
|
+
function calculateHorizontalPositionFromRect(triggerRect, dropdownWidth, preferredAlign = "left", margin = 8) {
|
|
4932
|
+
return calculateHorizontalPosition(
|
|
4933
|
+
triggerRect.left,
|
|
4934
|
+
triggerRect.right,
|
|
4935
|
+
dropdownWidth,
|
|
4936
|
+
preferredAlign,
|
|
4937
|
+
margin
|
|
4938
|
+
);
|
|
4939
|
+
}
|
|
4857
4940
|
function PositionedDropdown({
|
|
4858
4941
|
isOpen,
|
|
4859
4942
|
buttonRef,
|
|
@@ -4866,7 +4949,8 @@ function PositionedDropdown({
|
|
|
4866
4949
|
onClick,
|
|
4867
4950
|
"data-testid": dataTestId
|
|
4868
4951
|
}) {
|
|
4869
|
-
const [
|
|
4952
|
+
const [verticalPosition, setVerticalPosition] = React.useState("top");
|
|
4953
|
+
const [horizontalPosition, setHorizontalPosition] = React.useState(null);
|
|
4870
4954
|
const dropdownRef = React.useRef(null);
|
|
4871
4955
|
React.useEffect(() => {
|
|
4872
4956
|
if (!isOpen || !buttonRef.current) return;
|
|
@@ -4874,15 +4958,37 @@ function PositionedDropdown({
|
|
|
4874
4958
|
if (!dropdownRef.current || !buttonRef.current) return;
|
|
4875
4959
|
const buttonRect = buttonRef.current.getBoundingClientRect();
|
|
4876
4960
|
const dropdownHeight = dropdownRef.current.offsetHeight || 300;
|
|
4877
|
-
const
|
|
4878
|
-
|
|
4961
|
+
const dropdownWidth = dropdownRef.current.offsetWidth || 240;
|
|
4962
|
+
const newVerticalPosition = calculateVerticalPositionFromRect(buttonRect, dropdownHeight, margin);
|
|
4963
|
+
setVerticalPosition(newVerticalPosition);
|
|
4964
|
+
let parentContainer = buttonRef.current.parentElement;
|
|
4965
|
+
while (parentContainer) {
|
|
4966
|
+
const style2 = window.getComputedStyle(parentContainer);
|
|
4967
|
+
if (style2.position === "relative" || style2.position === "absolute" || style2.position === "fixed") {
|
|
4968
|
+
break;
|
|
4969
|
+
}
|
|
4970
|
+
parentContainer = parentContainer.parentElement;
|
|
4971
|
+
}
|
|
4972
|
+
const horizontalPos = calculateHorizontalPositionFromRect(
|
|
4973
|
+
buttonRect,
|
|
4974
|
+
dropdownWidth,
|
|
4975
|
+
align,
|
|
4976
|
+
margin
|
|
4977
|
+
);
|
|
4978
|
+
if (parentContainer) {
|
|
4979
|
+
const parentRect = parentContainer.getBoundingClientRect();
|
|
4980
|
+
const relativeLeft = horizontalPos.left - parentRect.left;
|
|
4981
|
+
setHorizontalPosition({ align: horizontalPos.align, left: relativeLeft });
|
|
4982
|
+
} else {
|
|
4983
|
+
setHorizontalPosition(horizontalPos);
|
|
4984
|
+
}
|
|
4879
4985
|
};
|
|
4880
4986
|
checkPosition();
|
|
4881
4987
|
const rafId = requestAnimationFrame(() => {
|
|
4882
4988
|
checkPosition();
|
|
4883
4989
|
});
|
|
4884
4990
|
return () => cancelAnimationFrame(rafId);
|
|
4885
|
-
}, [isOpen, buttonRef, margin]);
|
|
4991
|
+
}, [isOpen, buttonRef, margin, align]);
|
|
4886
4992
|
React.useEffect(() => {
|
|
4887
4993
|
if (!isOpen || !onClickOutside2) return;
|
|
4888
4994
|
const handleClickOutside = (event) => {
|
|
@@ -4897,6 +5003,11 @@ function PositionedDropdown({
|
|
|
4897
5003
|
}, [isOpen, onClickOutside2, buttonRef]);
|
|
4898
5004
|
if (!isOpen) return null;
|
|
4899
5005
|
const getHorizontalStyle = () => {
|
|
5006
|
+
if (horizontalPosition) {
|
|
5007
|
+
return {
|
|
5008
|
+
left: `${horizontalPosition.left}px`
|
|
5009
|
+
};
|
|
5010
|
+
}
|
|
4900
5011
|
switch (align) {
|
|
4901
5012
|
case "center":
|
|
4902
5013
|
return {
|
|
@@ -4922,7 +5033,7 @@ function PositionedDropdown({
|
|
|
4922
5033
|
"data-testid": dataTestId,
|
|
4923
5034
|
style: {
|
|
4924
5035
|
position: "absolute",
|
|
4925
|
-
...
|
|
5036
|
+
...verticalPosition === "top" ? {
|
|
4926
5037
|
bottom: "100%",
|
|
4927
5038
|
marginBottom: `${margin}px`
|
|
4928
5039
|
} : {
|
|
@@ -5254,6 +5365,9 @@ function LinkButton({ editor, isOpen, onToggle, onClose, selectionState }) {
|
|
|
5254
5365
|
}
|
|
5255
5366
|
}, [isOpen, currentLinkHref, editor]);
|
|
5256
5367
|
React.useEffect(() => {
|
|
5368
|
+
if (isMobileDevice()) {
|
|
5369
|
+
return;
|
|
5370
|
+
}
|
|
5257
5371
|
if (!isOpen) {
|
|
5258
5372
|
tippyInstancesRef.current.forEach((instance) => instance.destroy());
|
|
5259
5373
|
tippyInstancesRef.current = [];
|
|
@@ -5601,6 +5715,9 @@ function ColorPicker({ editor, onClose, buttonRef }) {
|
|
|
5601
5715
|
}
|
|
5602
5716
|
};
|
|
5603
5717
|
React.useEffect(() => {
|
|
5718
|
+
if (isMobileDevice()) {
|
|
5719
|
+
return;
|
|
5720
|
+
}
|
|
5604
5721
|
if (!pickerRef.current) return;
|
|
5605
5722
|
tippyInstancesRef.current.forEach((instance) => instance.destroy());
|
|
5606
5723
|
tippyInstancesRef.current = [];
|
|
@@ -5992,8 +6109,6 @@ function calculatePosition(editor, toolbarEl) {
|
|
|
5992
6109
|
const toolbarRect = toolbarEl.getBoundingClientRect();
|
|
5993
6110
|
const toolbarWidth = toolbarRect.width;
|
|
5994
6111
|
const toolbarHeight = toolbarRect.height;
|
|
5995
|
-
const centerX = (selectionLeft + selectionRight) / 2;
|
|
5996
|
-
let left2 = centerX - toolbarWidth / 2;
|
|
5997
6112
|
const selectionBottom = Math.max(start2.bottom, end2.bottom);
|
|
5998
6113
|
const verticalPosition = calculateVerticalPosition(
|
|
5999
6114
|
selectionTop,
|
|
@@ -6007,20 +6122,21 @@ function calculatePosition(editor, toolbarEl) {
|
|
|
6007
6122
|
} else {
|
|
6008
6123
|
top2 = selectionBottom + TOOLBAR_OFFSET;
|
|
6009
6124
|
}
|
|
6125
|
+
const horizontalPos = calculateHorizontalPosition(
|
|
6126
|
+
selectionLeft,
|
|
6127
|
+
selectionRight,
|
|
6128
|
+
toolbarWidth,
|
|
6129
|
+
"center",
|
|
6130
|
+
// Default to center alignment
|
|
6131
|
+
TOOLBAR_OFFSET
|
|
6132
|
+
);
|
|
6133
|
+
const left2 = horizontalPos.left;
|
|
6010
6134
|
const viewportWidth = window.innerWidth;
|
|
6011
6135
|
const viewportHeight = window.innerHeight;
|
|
6012
|
-
const padding =
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
left2 = viewportWidth - toolbarWidth - padding;
|
|
6017
|
-
}
|
|
6018
|
-
if (top2 < padding) {
|
|
6019
|
-
top2 = padding;
|
|
6020
|
-
} else if (top2 + toolbarHeight > viewportHeight - padding) {
|
|
6021
|
-
top2 = viewportHeight - toolbarHeight - padding;
|
|
6022
|
-
}
|
|
6023
|
-
return { top: top2, left: left2, visible: true };
|
|
6136
|
+
const padding = TOOLBAR_OFFSET;
|
|
6137
|
+
const clampedLeft = Math.max(padding, Math.min(left2, viewportWidth - toolbarWidth - padding));
|
|
6138
|
+
const clampedTop = Math.max(padding, Math.min(top2, viewportHeight - toolbarHeight - padding));
|
|
6139
|
+
return { top: clampedTop, left: clampedLeft, visible: true };
|
|
6024
6140
|
}
|
|
6025
6141
|
function BubbleToolbar({
|
|
6026
6142
|
editor,
|
|
@@ -6181,6 +6297,9 @@ function BubbleToolbar({
|
|
|
6181
6297
|
}, [shouldShow, updatePosition]);
|
|
6182
6298
|
const locale = useLocale();
|
|
6183
6299
|
React.useEffect(() => {
|
|
6300
|
+
if (isMobileDevice()) {
|
|
6301
|
+
return;
|
|
6302
|
+
}
|
|
6184
6303
|
if (!shouldShow || !position.visible || !toolbarRef.current) {
|
|
6185
6304
|
tippyInstancesRef.current.forEach((instance) => instance.destroy());
|
|
6186
6305
|
tippyInstancesRef.current = [];
|
|
@@ -6265,6 +6384,7 @@ function BubbleToolbar({
|
|
|
6265
6384
|
}
|
|
6266
6385
|
);
|
|
6267
6386
|
}
|
|
6387
|
+
const MIN_WINDOW_WIDTH = 768;
|
|
6268
6388
|
function getClosestBlock(target, proseMirror, editor) {
|
|
6269
6389
|
if (!target || !(target instanceof Node)) return null;
|
|
6270
6390
|
try {
|
|
@@ -6310,14 +6430,16 @@ function BlockHandle({ editor }) {
|
|
|
6310
6430
|
const [isDragging, setIsDragging] = React.useState(false);
|
|
6311
6431
|
const [position, setPosition] = React.useState({ top: 0 });
|
|
6312
6432
|
const [isMobile, setIsMobile] = React.useState(false);
|
|
6433
|
+
const [isWindowTooSmall, setIsWindowTooSmall] = React.useState(false);
|
|
6313
6434
|
React.useEffect(() => {
|
|
6314
|
-
const
|
|
6435
|
+
const checkDeviceAndWindow = () => {
|
|
6315
6436
|
setIsMobile(isMobileDevice());
|
|
6437
|
+
setIsWindowTooSmall(window.innerWidth < MIN_WINDOW_WIDTH);
|
|
6316
6438
|
};
|
|
6317
|
-
|
|
6318
|
-
window.addEventListener("resize",
|
|
6439
|
+
checkDeviceAndWindow();
|
|
6440
|
+
window.addEventListener("resize", checkDeviceAndWindow);
|
|
6319
6441
|
return () => {
|
|
6320
|
-
window.removeEventListener("resize",
|
|
6442
|
+
window.removeEventListener("resize", checkDeviceAndWindow);
|
|
6321
6443
|
};
|
|
6322
6444
|
}, []);
|
|
6323
6445
|
const updatePosition = React.useCallback(() => {
|
|
@@ -6552,7 +6674,7 @@ function BlockHandle({ editor }) {
|
|
|
6552
6674
|
}
|
|
6553
6675
|
setVisible(false);
|
|
6554
6676
|
}, []);
|
|
6555
|
-
if (isMobile || !visible) return null;
|
|
6677
|
+
if (isMobile || isWindowTooSmall || !visible) return null;
|
|
6556
6678
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6557
6679
|
"div",
|
|
6558
6680
|
{
|
package/dist/index.js
CHANGED
|
@@ -4852,6 +4852,89 @@ function calculateVerticalPositionFromRect(triggerRect, dropdownHeight, margin =
|
|
|
4852
4852
|
margin
|
|
4853
4853
|
);
|
|
4854
4854
|
}
|
|
4855
|
+
function calculateHorizontalPosition(triggerLeft, triggerRight, dropdownWidth, preferredAlign = "left", margin = 8) {
|
|
4856
|
+
const viewportWidth = window.innerWidth;
|
|
4857
|
+
const triggerCenter = (triggerLeft + triggerRight) / 2;
|
|
4858
|
+
const spaceLeft = triggerLeft;
|
|
4859
|
+
const spaceRight = viewportWidth - triggerRight;
|
|
4860
|
+
const requiredSpaceForLeft = dropdownWidth + margin;
|
|
4861
|
+
const requiredSpaceForRight = dropdownWidth + margin;
|
|
4862
|
+
const requiredSpaceForCenter = dropdownWidth / 2 + margin;
|
|
4863
|
+
let align = preferredAlign;
|
|
4864
|
+
let left2;
|
|
4865
|
+
if (preferredAlign === "left") {
|
|
4866
|
+
left2 = triggerLeft;
|
|
4867
|
+
if (left2 < margin || left2 + dropdownWidth > viewportWidth - margin) {
|
|
4868
|
+
if (spaceRight >= requiredSpaceForRight && triggerRight + dropdownWidth <= viewportWidth - margin) {
|
|
4869
|
+
align = "right";
|
|
4870
|
+
left2 = triggerRight - dropdownWidth;
|
|
4871
|
+
} else if (spaceLeft >= requiredSpaceForCenter && triggerCenter - dropdownWidth / 2 >= margin) {
|
|
4872
|
+
align = "center";
|
|
4873
|
+
left2 = triggerCenter - dropdownWidth / 2;
|
|
4874
|
+
} else {
|
|
4875
|
+
if (spaceRight >= spaceLeft) {
|
|
4876
|
+
align = "right";
|
|
4877
|
+
left2 = triggerRight - dropdownWidth;
|
|
4878
|
+
} else {
|
|
4879
|
+
align = "left";
|
|
4880
|
+
left2 = triggerLeft;
|
|
4881
|
+
}
|
|
4882
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4883
|
+
}
|
|
4884
|
+
}
|
|
4885
|
+
} else if (preferredAlign === "center") {
|
|
4886
|
+
left2 = triggerCenter - dropdownWidth / 2;
|
|
4887
|
+
if (left2 < margin || left2 + dropdownWidth > viewportWidth - margin) {
|
|
4888
|
+
if (spaceRight >= requiredSpaceForRight && triggerRight + dropdownWidth <= viewportWidth - margin) {
|
|
4889
|
+
align = "right";
|
|
4890
|
+
left2 = triggerRight - dropdownWidth;
|
|
4891
|
+
} else if (spaceLeft >= requiredSpaceForLeft && triggerLeft + dropdownWidth <= viewportWidth - margin) {
|
|
4892
|
+
align = "left";
|
|
4893
|
+
left2 = triggerLeft;
|
|
4894
|
+
} else {
|
|
4895
|
+
if (spaceRight >= spaceLeft) {
|
|
4896
|
+
align = "right";
|
|
4897
|
+
left2 = triggerRight - dropdownWidth;
|
|
4898
|
+
} else {
|
|
4899
|
+
align = "left";
|
|
4900
|
+
left2 = triggerLeft;
|
|
4901
|
+
}
|
|
4902
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
} else {
|
|
4906
|
+
left2 = triggerRight - dropdownWidth;
|
|
4907
|
+
if (left2 < margin || left2 + dropdownWidth > viewportWidth - margin) {
|
|
4908
|
+
if (spaceLeft >= requiredSpaceForLeft && triggerLeft + dropdownWidth <= viewportWidth - margin) {
|
|
4909
|
+
align = "left";
|
|
4910
|
+
left2 = triggerLeft;
|
|
4911
|
+
} else if (spaceLeft >= requiredSpaceForCenter && triggerCenter - dropdownWidth / 2 >= margin) {
|
|
4912
|
+
align = "center";
|
|
4913
|
+
left2 = triggerCenter - dropdownWidth / 2;
|
|
4914
|
+
} else {
|
|
4915
|
+
if (spaceLeft >= spaceRight) {
|
|
4916
|
+
align = "left";
|
|
4917
|
+
left2 = triggerLeft;
|
|
4918
|
+
} else {
|
|
4919
|
+
align = "right";
|
|
4920
|
+
left2 = triggerRight - dropdownWidth;
|
|
4921
|
+
}
|
|
4922
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
}
|
|
4926
|
+
left2 = Math.max(margin, Math.min(left2, viewportWidth - dropdownWidth - margin));
|
|
4927
|
+
return { align, left: left2 };
|
|
4928
|
+
}
|
|
4929
|
+
function calculateHorizontalPositionFromRect(triggerRect, dropdownWidth, preferredAlign = "left", margin = 8) {
|
|
4930
|
+
return calculateHorizontalPosition(
|
|
4931
|
+
triggerRect.left,
|
|
4932
|
+
triggerRect.right,
|
|
4933
|
+
dropdownWidth,
|
|
4934
|
+
preferredAlign,
|
|
4935
|
+
margin
|
|
4936
|
+
);
|
|
4937
|
+
}
|
|
4855
4938
|
function PositionedDropdown({
|
|
4856
4939
|
isOpen,
|
|
4857
4940
|
buttonRef,
|
|
@@ -4864,7 +4947,8 @@ function PositionedDropdown({
|
|
|
4864
4947
|
onClick,
|
|
4865
4948
|
"data-testid": dataTestId
|
|
4866
4949
|
}) {
|
|
4867
|
-
const [
|
|
4950
|
+
const [verticalPosition, setVerticalPosition] = useState("top");
|
|
4951
|
+
const [horizontalPosition, setHorizontalPosition] = useState(null);
|
|
4868
4952
|
const dropdownRef = useRef(null);
|
|
4869
4953
|
useEffect(() => {
|
|
4870
4954
|
if (!isOpen || !buttonRef.current) return;
|
|
@@ -4872,15 +4956,37 @@ function PositionedDropdown({
|
|
|
4872
4956
|
if (!dropdownRef.current || !buttonRef.current) return;
|
|
4873
4957
|
const buttonRect = buttonRef.current.getBoundingClientRect();
|
|
4874
4958
|
const dropdownHeight = dropdownRef.current.offsetHeight || 300;
|
|
4875
|
-
const
|
|
4876
|
-
|
|
4959
|
+
const dropdownWidth = dropdownRef.current.offsetWidth || 240;
|
|
4960
|
+
const newVerticalPosition = calculateVerticalPositionFromRect(buttonRect, dropdownHeight, margin);
|
|
4961
|
+
setVerticalPosition(newVerticalPosition);
|
|
4962
|
+
let parentContainer = buttonRef.current.parentElement;
|
|
4963
|
+
while (parentContainer) {
|
|
4964
|
+
const style2 = window.getComputedStyle(parentContainer);
|
|
4965
|
+
if (style2.position === "relative" || style2.position === "absolute" || style2.position === "fixed") {
|
|
4966
|
+
break;
|
|
4967
|
+
}
|
|
4968
|
+
parentContainer = parentContainer.parentElement;
|
|
4969
|
+
}
|
|
4970
|
+
const horizontalPos = calculateHorizontalPositionFromRect(
|
|
4971
|
+
buttonRect,
|
|
4972
|
+
dropdownWidth,
|
|
4973
|
+
align,
|
|
4974
|
+
margin
|
|
4975
|
+
);
|
|
4976
|
+
if (parentContainer) {
|
|
4977
|
+
const parentRect = parentContainer.getBoundingClientRect();
|
|
4978
|
+
const relativeLeft = horizontalPos.left - parentRect.left;
|
|
4979
|
+
setHorizontalPosition({ align: horizontalPos.align, left: relativeLeft });
|
|
4980
|
+
} else {
|
|
4981
|
+
setHorizontalPosition(horizontalPos);
|
|
4982
|
+
}
|
|
4877
4983
|
};
|
|
4878
4984
|
checkPosition();
|
|
4879
4985
|
const rafId = requestAnimationFrame(() => {
|
|
4880
4986
|
checkPosition();
|
|
4881
4987
|
});
|
|
4882
4988
|
return () => cancelAnimationFrame(rafId);
|
|
4883
|
-
}, [isOpen, buttonRef, margin]);
|
|
4989
|
+
}, [isOpen, buttonRef, margin, align]);
|
|
4884
4990
|
useEffect(() => {
|
|
4885
4991
|
if (!isOpen || !onClickOutside2) return;
|
|
4886
4992
|
const handleClickOutside = (event) => {
|
|
@@ -4895,6 +5001,11 @@ function PositionedDropdown({
|
|
|
4895
5001
|
}, [isOpen, onClickOutside2, buttonRef]);
|
|
4896
5002
|
if (!isOpen) return null;
|
|
4897
5003
|
const getHorizontalStyle = () => {
|
|
5004
|
+
if (horizontalPosition) {
|
|
5005
|
+
return {
|
|
5006
|
+
left: `${horizontalPosition.left}px`
|
|
5007
|
+
};
|
|
5008
|
+
}
|
|
4898
5009
|
switch (align) {
|
|
4899
5010
|
case "center":
|
|
4900
5011
|
return {
|
|
@@ -4920,7 +5031,7 @@ function PositionedDropdown({
|
|
|
4920
5031
|
"data-testid": dataTestId,
|
|
4921
5032
|
style: {
|
|
4922
5033
|
position: "absolute",
|
|
4923
|
-
...
|
|
5034
|
+
...verticalPosition === "top" ? {
|
|
4924
5035
|
bottom: "100%",
|
|
4925
5036
|
marginBottom: `${margin}px`
|
|
4926
5037
|
} : {
|
|
@@ -5252,6 +5363,9 @@ function LinkButton({ editor, isOpen, onToggle, onClose, selectionState }) {
|
|
|
5252
5363
|
}
|
|
5253
5364
|
}, [isOpen, currentLinkHref, editor]);
|
|
5254
5365
|
useEffect(() => {
|
|
5366
|
+
if (isMobileDevice()) {
|
|
5367
|
+
return;
|
|
5368
|
+
}
|
|
5255
5369
|
if (!isOpen) {
|
|
5256
5370
|
tippyInstancesRef.current.forEach((instance) => instance.destroy());
|
|
5257
5371
|
tippyInstancesRef.current = [];
|
|
@@ -5599,6 +5713,9 @@ function ColorPicker({ editor, onClose, buttonRef }) {
|
|
|
5599
5713
|
}
|
|
5600
5714
|
};
|
|
5601
5715
|
useEffect(() => {
|
|
5716
|
+
if (isMobileDevice()) {
|
|
5717
|
+
return;
|
|
5718
|
+
}
|
|
5602
5719
|
if (!pickerRef.current) return;
|
|
5603
5720
|
tippyInstancesRef.current.forEach((instance) => instance.destroy());
|
|
5604
5721
|
tippyInstancesRef.current = [];
|
|
@@ -5990,8 +6107,6 @@ function calculatePosition(editor, toolbarEl) {
|
|
|
5990
6107
|
const toolbarRect = toolbarEl.getBoundingClientRect();
|
|
5991
6108
|
const toolbarWidth = toolbarRect.width;
|
|
5992
6109
|
const toolbarHeight = toolbarRect.height;
|
|
5993
|
-
const centerX = (selectionLeft + selectionRight) / 2;
|
|
5994
|
-
let left2 = centerX - toolbarWidth / 2;
|
|
5995
6110
|
const selectionBottom = Math.max(start2.bottom, end2.bottom);
|
|
5996
6111
|
const verticalPosition = calculateVerticalPosition(
|
|
5997
6112
|
selectionTop,
|
|
@@ -6005,20 +6120,21 @@ function calculatePosition(editor, toolbarEl) {
|
|
|
6005
6120
|
} else {
|
|
6006
6121
|
top2 = selectionBottom + TOOLBAR_OFFSET;
|
|
6007
6122
|
}
|
|
6123
|
+
const horizontalPos = calculateHorizontalPosition(
|
|
6124
|
+
selectionLeft,
|
|
6125
|
+
selectionRight,
|
|
6126
|
+
toolbarWidth,
|
|
6127
|
+
"center",
|
|
6128
|
+
// Default to center alignment
|
|
6129
|
+
TOOLBAR_OFFSET
|
|
6130
|
+
);
|
|
6131
|
+
const left2 = horizontalPos.left;
|
|
6008
6132
|
const viewportWidth = window.innerWidth;
|
|
6009
6133
|
const viewportHeight = window.innerHeight;
|
|
6010
|
-
const padding =
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
left2 = viewportWidth - toolbarWidth - padding;
|
|
6015
|
-
}
|
|
6016
|
-
if (top2 < padding) {
|
|
6017
|
-
top2 = padding;
|
|
6018
|
-
} else if (top2 + toolbarHeight > viewportHeight - padding) {
|
|
6019
|
-
top2 = viewportHeight - toolbarHeight - padding;
|
|
6020
|
-
}
|
|
6021
|
-
return { top: top2, left: left2, visible: true };
|
|
6134
|
+
const padding = TOOLBAR_OFFSET;
|
|
6135
|
+
const clampedLeft = Math.max(padding, Math.min(left2, viewportWidth - toolbarWidth - padding));
|
|
6136
|
+
const clampedTop = Math.max(padding, Math.min(top2, viewportHeight - toolbarHeight - padding));
|
|
6137
|
+
return { top: clampedTop, left: clampedLeft, visible: true };
|
|
6022
6138
|
}
|
|
6023
6139
|
function BubbleToolbar({
|
|
6024
6140
|
editor,
|
|
@@ -6179,6 +6295,9 @@ function BubbleToolbar({
|
|
|
6179
6295
|
}, [shouldShow, updatePosition]);
|
|
6180
6296
|
const locale = useLocale();
|
|
6181
6297
|
useEffect(() => {
|
|
6298
|
+
if (isMobileDevice()) {
|
|
6299
|
+
return;
|
|
6300
|
+
}
|
|
6182
6301
|
if (!shouldShow || !position.visible || !toolbarRef.current) {
|
|
6183
6302
|
tippyInstancesRef.current.forEach((instance) => instance.destroy());
|
|
6184
6303
|
tippyInstancesRef.current = [];
|
|
@@ -6263,6 +6382,7 @@ function BubbleToolbar({
|
|
|
6263
6382
|
}
|
|
6264
6383
|
);
|
|
6265
6384
|
}
|
|
6385
|
+
const MIN_WINDOW_WIDTH = 768;
|
|
6266
6386
|
function getClosestBlock(target, proseMirror, editor) {
|
|
6267
6387
|
if (!target || !(target instanceof Node)) return null;
|
|
6268
6388
|
try {
|
|
@@ -6308,14 +6428,16 @@ function BlockHandle({ editor }) {
|
|
|
6308
6428
|
const [isDragging, setIsDragging] = useState(false);
|
|
6309
6429
|
const [position, setPosition] = useState({ top: 0 });
|
|
6310
6430
|
const [isMobile, setIsMobile] = useState(false);
|
|
6431
|
+
const [isWindowTooSmall, setIsWindowTooSmall] = useState(false);
|
|
6311
6432
|
useEffect(() => {
|
|
6312
|
-
const
|
|
6433
|
+
const checkDeviceAndWindow = () => {
|
|
6313
6434
|
setIsMobile(isMobileDevice());
|
|
6435
|
+
setIsWindowTooSmall(window.innerWidth < MIN_WINDOW_WIDTH);
|
|
6314
6436
|
};
|
|
6315
|
-
|
|
6316
|
-
window.addEventListener("resize",
|
|
6437
|
+
checkDeviceAndWindow();
|
|
6438
|
+
window.addEventListener("resize", checkDeviceAndWindow);
|
|
6317
6439
|
return () => {
|
|
6318
|
-
window.removeEventListener("resize",
|
|
6440
|
+
window.removeEventListener("resize", checkDeviceAndWindow);
|
|
6319
6441
|
};
|
|
6320
6442
|
}, []);
|
|
6321
6443
|
const updatePosition = useCallback(() => {
|
|
@@ -6550,7 +6672,7 @@ function BlockHandle({ editor }) {
|
|
|
6550
6672
|
}
|
|
6551
6673
|
setVisible(false);
|
|
6552
6674
|
}, []);
|
|
6553
|
-
if (isMobile || !visible) return null;
|
|
6675
|
+
if (isMobile || isWindowTooSmall || !visible) return null;
|
|
6554
6676
|
return /* @__PURE__ */ jsxs(
|
|
6555
6677
|
"div",
|
|
6556
6678
|
{
|