@underverse-ui/underverse 1.0.63 → 1.0.65
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/api-reference.json +1 -1
- package/dist/index.cjs +334 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -0
- package/dist/index.d.ts +64 -0
- package/dist/index.js +340 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/api-reference.json
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -890,7 +890,15 @@ var en_default = {
|
|
|
890
890
|
heading1: "Heading 1",
|
|
891
891
|
heading2: "Heading 2",
|
|
892
892
|
heading3: "Heading 3",
|
|
893
|
-
emoji: "Insert Emoji"
|
|
893
|
+
emoji: "Insert Emoji",
|
|
894
|
+
imageLayoutBlock: "Image Block",
|
|
895
|
+
imageLayoutLeft: "Wrap Text Right",
|
|
896
|
+
imageLayoutRight: "Wrap Text Left",
|
|
897
|
+
imageWidthSm: "Image Width Small",
|
|
898
|
+
imageWidthMd: "Image Width Medium",
|
|
899
|
+
imageWidthLg: "Image Width Large",
|
|
900
|
+
imageResetSize: "Reset Image Size",
|
|
901
|
+
imageDelete: "Delete Image"
|
|
894
902
|
},
|
|
895
903
|
slashCommand: {
|
|
896
904
|
basicBlocks: "Basic Blocks",
|
|
@@ -1114,7 +1122,15 @@ var vi_default = {
|
|
|
1114
1122
|
heading1: "Ti\xEAu \u0111\u1EC1 1",
|
|
1115
1123
|
heading2: "Ti\xEAu \u0111\u1EC1 2",
|
|
1116
1124
|
heading3: "Ti\xEAu \u0111\u1EC1 3",
|
|
1117
|
-
emoji: "Ch\xE8n Emoji"
|
|
1125
|
+
emoji: "Ch\xE8n Emoji",
|
|
1126
|
+
imageLayoutBlock: "\u1EA2nh D\u1EA1ng Kh\u1ED1i",
|
|
1127
|
+
imageLayoutLeft: "\u1EA2nh Tr\xE1i, Ch\u1EEF Ph\u1EA3i",
|
|
1128
|
+
imageLayoutRight: "\u1EA2nh Ph\u1EA3i, Ch\u1EEF Tr\xE1i",
|
|
1129
|
+
imageWidthSm: "\u1EA2nh Nh\u1ECF",
|
|
1130
|
+
imageWidthMd: "\u1EA2nh V\u1EEBa",
|
|
1131
|
+
imageWidthLg: "\u1EA2nh L\u1EDBn",
|
|
1132
|
+
imageResetSize: "\u0110\u1EB7t L\u1EA1i K\xEDch Th\u01B0\u1EDBc \u1EA2nh",
|
|
1133
|
+
imageDelete: "X\xF3a \u1EA2nh"
|
|
1118
1134
|
},
|
|
1119
1135
|
slashCommand: {
|
|
1120
1136
|
basicBlocks: "Kh\u1ED1i c\u01A1 b\u1EA3n",
|
|
@@ -1338,7 +1354,15 @@ var ko_default = {
|
|
|
1338
1354
|
heading1: "\uC81C\uBAA9 1",
|
|
1339
1355
|
heading2: "\uC81C\uBAA9 2",
|
|
1340
1356
|
heading3: "\uC81C\uBAA9 3",
|
|
1341
|
-
emoji: "\uC774\uBAA8\uC9C0 \uC0BD\uC785"
|
|
1357
|
+
emoji: "\uC774\uBAA8\uC9C0 \uC0BD\uC785",
|
|
1358
|
+
imageLayoutBlock: "\uC774\uBBF8\uC9C0 \uBE14\uB85D",
|
|
1359
|
+
imageLayoutLeft: "\uC67C\uCABD \uC774\uBBF8\uC9C0, \uC624\uB978\uCABD \uD14D\uC2A4\uD2B8",
|
|
1360
|
+
imageLayoutRight: "\uC624\uB978\uCABD \uC774\uBBF8\uC9C0, \uC67C\uCABD \uD14D\uC2A4\uD2B8",
|
|
1361
|
+
imageWidthSm: "\uC791\uC740 \uC774\uBBF8\uC9C0",
|
|
1362
|
+
imageWidthMd: "\uC911\uAC04 \uC774\uBBF8\uC9C0",
|
|
1363
|
+
imageWidthLg: "\uD070 \uC774\uBBF8\uC9C0",
|
|
1364
|
+
imageResetSize: "\uC774\uBBF8\uC9C0 \uD06C\uAE30 \uCD08\uAE30\uD654",
|
|
1365
|
+
imageDelete: "\uC774\uBBF8\uC9C0 \uC0AD\uC81C"
|
|
1342
1366
|
},
|
|
1343
1367
|
slashCommand: {
|
|
1344
1368
|
basicBlocks: "\uAE30\uBCF8 \uBE14\uB85D",
|
|
@@ -1561,7 +1585,15 @@ var ja_default = {
|
|
|
1561
1585
|
heading1: "\u898B\u51FA\u3057 1",
|
|
1562
1586
|
heading2: "\u898B\u51FA\u3057 2",
|
|
1563
1587
|
heading3: "\u898B\u51FA\u3057 3",
|
|
1564
|
-
emoji: "\u7D75\u6587\u5B57\u3092\u633F\u5165"
|
|
1588
|
+
emoji: "\u7D75\u6587\u5B57\u3092\u633F\u5165",
|
|
1589
|
+
imageLayoutBlock: "\u753B\u50CF\u30D6\u30ED\u30C3\u30AF",
|
|
1590
|
+
imageLayoutLeft: "\u753B\u50CF\u3092\u5DE6\u3001\u6587\u5B57\u3092\u53F3\u306B\u56DE\u308A\u8FBC\u307F",
|
|
1591
|
+
imageLayoutRight: "\u753B\u50CF\u3092\u53F3\u3001\u6587\u5B57\u3092\u5DE6\u306B\u56DE\u308A\u8FBC\u307F",
|
|
1592
|
+
imageWidthSm: "\u753B\u50CF \u5C0F",
|
|
1593
|
+
imageWidthMd: "\u753B\u50CF \u4E2D",
|
|
1594
|
+
imageWidthLg: "\u753B\u50CF \u5927",
|
|
1595
|
+
imageResetSize: "\u753B\u50CF\u30B5\u30A4\u30BA\u3092\u30EA\u30BB\u30C3\u30C8",
|
|
1596
|
+
imageDelete: "\u753B\u50CF\u3092\u524A\u9664"
|
|
1565
1597
|
},
|
|
1566
1598
|
slashCommand: {
|
|
1567
1599
|
basicBlocks: "\u57FA\u672C\u30D6\u30ED\u30C3\u30AF",
|
|
@@ -16384,12 +16416,12 @@ function Carousel({
|
|
|
16384
16416
|
mainScale: 1.12,
|
|
16385
16417
|
sideScale: 0.82,
|
|
16386
16418
|
farScale: 0.72,
|
|
16387
|
-
sideOpacity: 0.
|
|
16388
|
-
farOpacity: 0.
|
|
16419
|
+
sideOpacity: 0.84,
|
|
16420
|
+
farOpacity: 0.44,
|
|
16389
16421
|
sideOffset: 22,
|
|
16390
16422
|
rotate: 20,
|
|
16391
16423
|
depthStep: 120,
|
|
16392
|
-
blur:
|
|
16424
|
+
blur: 1.6
|
|
16393
16425
|
};
|
|
16394
16426
|
}
|
|
16395
16427
|
if (effectPreset === "gallery") {
|
|
@@ -16468,12 +16500,12 @@ function Carousel({
|
|
|
16468
16500
|
mainScale: 1.04,
|
|
16469
16501
|
sideScale: effectiveAnimation === "stack" ? 0.93 : 0.88,
|
|
16470
16502
|
farScale: effectiveAnimation === "stack" ? 0.86 : 0.76,
|
|
16471
|
-
sideOpacity: effectiveAnimation === "stack" ? 0.
|
|
16472
|
-
farOpacity: effectiveAnimation === "stack" ? 0.
|
|
16503
|
+
sideOpacity: effectiveAnimation === "stack" ? 0.8 : 0.86,
|
|
16504
|
+
farOpacity: effectiveAnimation === "stack" ? 0.5 : 0.48,
|
|
16473
16505
|
sideOffset: effectiveAnimation === "stack" ? 20 : 28,
|
|
16474
16506
|
rotate: 24,
|
|
16475
16507
|
depthStep: effectiveAnimation === "stack" ? 60 : 90,
|
|
16476
|
-
blur: 1.
|
|
16508
|
+
blur: 1.1,
|
|
16477
16509
|
stackOffset: 20,
|
|
16478
16510
|
stackLift: 12,
|
|
16479
16511
|
...presetEffectOptions,
|
|
@@ -16626,7 +16658,7 @@ function Carousel({
|
|
|
16626
16658
|
opacity: distance === 0 ? 1 : distance === 1 || distance === -1 ? mergedEffectOptions.sideOpacity : mergedEffectOptions.farOpacity,
|
|
16627
16659
|
transform: `translate3d(${xOffset2}px, ${yOffset}px, -${absDistance * mergedEffectOptions.depthStep}px) scale(${scale2})`,
|
|
16628
16660
|
filter: distance === 0 ? "blur(0px)" : `blur(${Math.min(absDistance, 2) * mergedEffectOptions.blur}px)`,
|
|
16629
|
-
pointerEvents:
|
|
16661
|
+
pointerEvents: "auto"
|
|
16630
16662
|
};
|
|
16631
16663
|
}
|
|
16632
16664
|
const xOffset = distance * mergedEffectOptions.sideOffset;
|
|
@@ -16636,7 +16668,7 @@ function Carousel({
|
|
|
16636
16668
|
opacity: distance === 0 ? 1 : distance === 1 || distance === -1 ? mergedEffectOptions.sideOpacity : mergedEffectOptions.farOpacity,
|
|
16637
16669
|
transform: `translate3d(${xOffset}%, 0, -${absDistance * mergedEffectOptions.depthStep}px) rotateY(${rotateY}deg) scale(${scale})`,
|
|
16638
16670
|
filter: distance === 0 ? "blur(0px)" : `blur(${Math.min(absDistance, 2) * mergedEffectOptions.blur}px)`,
|
|
16639
|
-
pointerEvents:
|
|
16671
|
+
pointerEvents: "auto"
|
|
16640
16672
|
};
|
|
16641
16673
|
},
|
|
16642
16674
|
[effectiveAnimation, getLoopDistance, mergedEffectOptions]
|
|
@@ -16688,10 +16720,12 @@ function Carousel({
|
|
|
16688
16720
|
effectiveAnimation === "fade" && (idx === currentIndex ? "opacity-100 z-10" : "opacity-0 pointer-events-none z-0"),
|
|
16689
16721
|
effectiveAnimation === "scale" && (idx === currentIndex ? "opacity-100 scale-100 z-10" : "opacity-0 scale-95 pointer-events-none z-0"),
|
|
16690
16722
|
isDeckAnimation && "w-full max-w-[78%] md:max-w-[72%] transition-[opacity,transform] duration-500 ease-out",
|
|
16723
|
+
isDeckAnimation && idx !== currentIndex && "cursor-pointer",
|
|
16691
16724
|
effectiveAnimation !== "slide" && "transition-[opacity,transform] duration-500 ease-in-out",
|
|
16692
16725
|
slideClassName
|
|
16693
16726
|
),
|
|
16694
16727
|
style: effectiveAnimation === "slide" ? { [isHorizontal ? "width" : "height"]: `${slideWidth}%` } : isDeckAnimation ? getDeckSlideStyles(idx) : void 0,
|
|
16728
|
+
onClick: isDeckAnimation && idx !== currentIndex ? () => scrollTo(idx) : void 0,
|
|
16695
16729
|
role: "group",
|
|
16696
16730
|
"aria-roledescription": "slide",
|
|
16697
16731
|
"aria-label": `${idx + 1} of ${totalSlides}`,
|
|
@@ -22535,6 +22569,8 @@ var import_react44 = require("@tiptap/react");
|
|
|
22535
22569
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
22536
22570
|
var MIN_IMAGE_SIZE_PX = 40;
|
|
22537
22571
|
var AXIS_LOCK_THRESHOLD_PX = 4;
|
|
22572
|
+
var IMAGE_LAYOUTS = /* @__PURE__ */ new Set(["block", "left", "right"]);
|
|
22573
|
+
var IMAGE_WIDTH_PRESETS = /* @__PURE__ */ new Set(["sm", "md", "lg"]);
|
|
22538
22574
|
function toNullableNumber(value) {
|
|
22539
22575
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
22540
22576
|
if (typeof value === "string") {
|
|
@@ -22546,6 +22582,33 @@ function toNullableNumber(value) {
|
|
|
22546
22582
|
function clamp8(value, min, max) {
|
|
22547
22583
|
return Math.min(max, Math.max(min, value));
|
|
22548
22584
|
}
|
|
22585
|
+
function parseImageLayout(value) {
|
|
22586
|
+
if (typeof value === "string" && IMAGE_LAYOUTS.has(value)) {
|
|
22587
|
+
return value;
|
|
22588
|
+
}
|
|
22589
|
+
return "block";
|
|
22590
|
+
}
|
|
22591
|
+
function parseImageWidthPreset(value) {
|
|
22592
|
+
if (typeof value === "string" && IMAGE_WIDTH_PRESETS.has(value)) {
|
|
22593
|
+
return value;
|
|
22594
|
+
}
|
|
22595
|
+
return null;
|
|
22596
|
+
}
|
|
22597
|
+
function getImageLayoutStyles(layout) {
|
|
22598
|
+
if (layout === "left") {
|
|
22599
|
+
return {
|
|
22600
|
+
"data-image-layout": "left",
|
|
22601
|
+
style: "float:left;display:block;margin:0.25rem 1rem 0.75rem 0;"
|
|
22602
|
+
};
|
|
22603
|
+
}
|
|
22604
|
+
if (layout === "right") {
|
|
22605
|
+
return {
|
|
22606
|
+
"data-image-layout": "right",
|
|
22607
|
+
style: "float:right;display:block;margin:0.25rem 0 0.75rem 1rem;"
|
|
22608
|
+
};
|
|
22609
|
+
}
|
|
22610
|
+
return {};
|
|
22611
|
+
}
|
|
22549
22612
|
function ResizableImageNodeView(props) {
|
|
22550
22613
|
const { node, selected, updateAttributes, editor, getPos } = props;
|
|
22551
22614
|
const wrapperRef = (0, import_react43.useRef)(null);
|
|
@@ -22555,6 +22618,8 @@ function ResizableImageNodeView(props) {
|
|
|
22555
22618
|
const widthAttr = toNullableNumber(node.attrs["width"]);
|
|
22556
22619
|
const heightAttr = toNullableNumber(node.attrs["height"]);
|
|
22557
22620
|
const textAlign = String(node.attrs["textAlign"] ?? "");
|
|
22621
|
+
const imageLayout = parseImageLayout(node.attrs["imageLayout"]);
|
|
22622
|
+
const preserveAspectByDefault = imageLayout === "left" || imageLayout === "right";
|
|
22558
22623
|
const dragStateRef = (0, import_react43.useRef)(null);
|
|
22559
22624
|
(0, import_react43.useEffect)(() => {
|
|
22560
22625
|
const img = imgRef.current;
|
|
@@ -22603,7 +22668,8 @@ function ResizableImageNodeView(props) {
|
|
|
22603
22668
|
const dy = event.clientY - drag.startY;
|
|
22604
22669
|
let nextW = drag.startW;
|
|
22605
22670
|
let nextH = drag.startH;
|
|
22606
|
-
|
|
22671
|
+
const shouldPreserveAspect = preserveAspectByDefault ? !event.ctrlKey : event.ctrlKey;
|
|
22672
|
+
if (shouldPreserveAspect) {
|
|
22607
22673
|
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
22608
22674
|
nextW = clamp8(drag.startW + dx, MIN_IMAGE_SIZE_PX, drag.maxW);
|
|
22609
22675
|
nextH = clamp8(nextW / drag.aspect, MIN_IMAGE_SIZE_PX, Number.POSITIVE_INFINITY);
|
|
@@ -22630,7 +22696,8 @@ function ResizableImageNodeView(props) {
|
|
|
22630
22696
|
if (!drag) return;
|
|
22631
22697
|
updateAttributes({
|
|
22632
22698
|
width: Math.round(drag.lastW),
|
|
22633
|
-
height: Math.round(drag.lastH)
|
|
22699
|
+
height: Math.round(drag.lastH),
|
|
22700
|
+
imageWidthPreset: null
|
|
22634
22701
|
});
|
|
22635
22702
|
};
|
|
22636
22703
|
const onResizePointerUp = (event) => {
|
|
@@ -22648,14 +22715,15 @@ function ResizableImageNodeView(props) {
|
|
|
22648
22715
|
finishResize();
|
|
22649
22716
|
};
|
|
22650
22717
|
const showHandle = selected || isHovered || isResizing;
|
|
22651
|
-
const wrapperAlignClass = textAlign === "center" ? "mx-auto" : textAlign === "right" ? "ml-auto" : textAlign === "justify" ? "mx-auto" : "";
|
|
22652
|
-
const
|
|
22718
|
+
const wrapperAlignClass = imageLayout === "block" ? textAlign === "center" ? "mx-auto" : textAlign === "right" ? "ml-auto" : textAlign === "justify" ? "mx-auto" : "" : "";
|
|
22719
|
+
const wrapperLayoutClass = imageLayout === "left" ? "float-left mr-4 mb-3 mt-1 clear-none max-w-[min(45%,20rem)]" : imageLayout === "right" ? "float-right ml-4 mb-3 mt-1 clear-none max-w-[min(45%,20rem)]" : "w-fit";
|
|
22653
22720
|
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
|
|
22654
22721
|
import_react44.NodeViewWrapper,
|
|
22655
22722
|
{
|
|
22656
22723
|
as: "div",
|
|
22657
22724
|
ref: wrapperRef,
|
|
22658
|
-
|
|
22725
|
+
"data-image-layout": imageLayout,
|
|
22726
|
+
className: ["relative block align-middle max-w-full my-4", wrapperLayoutClass, wrapperAlignClass].filter(Boolean).join(" "),
|
|
22659
22727
|
onMouseEnter: () => setIsHovered(true),
|
|
22660
22728
|
onMouseLeave: () => setIsHovered(false),
|
|
22661
22729
|
onClick: (e) => {
|
|
@@ -22725,6 +22793,25 @@ var ResizableImage = import_extension_image.default.extend({
|
|
|
22725
22793
|
return Number.isFinite(parsed) ? parsed : null;
|
|
22726
22794
|
},
|
|
22727
22795
|
renderHTML: (attrs) => typeof attrs.height === "number" ? { height: attrs.height } : {}
|
|
22796
|
+
},
|
|
22797
|
+
imageLayout: {
|
|
22798
|
+
default: "block",
|
|
22799
|
+
parseHTML: (element) => {
|
|
22800
|
+
const explicit = element.getAttribute("data-image-layout");
|
|
22801
|
+
if (explicit) return parseImageLayout(explicit);
|
|
22802
|
+
const floatValue = element.style.float;
|
|
22803
|
+
if (floatValue === "left" || floatValue === "right") return floatValue;
|
|
22804
|
+
return "block";
|
|
22805
|
+
},
|
|
22806
|
+
renderHTML: (attrs) => getImageLayoutStyles(parseImageLayout(attrs.imageLayout))
|
|
22807
|
+
},
|
|
22808
|
+
imageWidthPreset: {
|
|
22809
|
+
default: null,
|
|
22810
|
+
parseHTML: (element) => parseImageWidthPreset(element.getAttribute("data-image-size")),
|
|
22811
|
+
renderHTML: (attrs) => {
|
|
22812
|
+
const preset = parseImageWidthPreset(attrs.imageWidthPreset);
|
|
22813
|
+
return preset ? { "data-image-size": preset } : {};
|
|
22814
|
+
}
|
|
22728
22815
|
}
|
|
22729
22816
|
};
|
|
22730
22817
|
},
|
|
@@ -22953,6 +23040,96 @@ var EditorColorPalette = ({
|
|
|
22953
23040
|
)) })
|
|
22954
23041
|
] });
|
|
22955
23042
|
|
|
23043
|
+
// src/components/UEditor/image-commands.ts
|
|
23044
|
+
var import_state4 = require("@tiptap/pm/state");
|
|
23045
|
+
var IMAGE_WIDTHS_BY_LAYOUT = {
|
|
23046
|
+
block: {
|
|
23047
|
+
sm: 180,
|
|
23048
|
+
md: 280,
|
|
23049
|
+
lg: 380
|
|
23050
|
+
},
|
|
23051
|
+
wrap: {
|
|
23052
|
+
sm: 140,
|
|
23053
|
+
md: 200,
|
|
23054
|
+
lg: 260
|
|
23055
|
+
}
|
|
23056
|
+
};
|
|
23057
|
+
function isSelectedImage(editor) {
|
|
23058
|
+
const { selection } = editor.state;
|
|
23059
|
+
return selection instanceof import_state4.NodeSelection && selection.node.type.name === "image";
|
|
23060
|
+
}
|
|
23061
|
+
function applyImageLayout(editor, layout) {
|
|
23062
|
+
const { state, view } = editor;
|
|
23063
|
+
const { selection, schema } = state;
|
|
23064
|
+
if (!(selection instanceof import_state4.NodeSelection) || selection.node.type.name !== "image") {
|
|
23065
|
+
editor.chain().focus().updateAttributes("image", { imageLayout: layout }).run();
|
|
23066
|
+
return;
|
|
23067
|
+
}
|
|
23068
|
+
let transaction = state.tr.setNodeMarkup(selection.from, void 0, {
|
|
23069
|
+
...selection.node.attrs,
|
|
23070
|
+
imageLayout: layout
|
|
23071
|
+
});
|
|
23072
|
+
if (layout !== "block") {
|
|
23073
|
+
const nextPos = transaction.mapping.map(selection.to);
|
|
23074
|
+
const nextNode = transaction.doc.nodeAt(nextPos);
|
|
23075
|
+
if (!nextNode || nextNode.type.name !== "paragraph") {
|
|
23076
|
+
const paragraph = schema.nodes.paragraph?.create();
|
|
23077
|
+
if (paragraph) {
|
|
23078
|
+
transaction = transaction.insert(nextPos, paragraph);
|
|
23079
|
+
}
|
|
23080
|
+
}
|
|
23081
|
+
const resolvedPos = transaction.doc.resolve(Math.min(nextPos + 1, transaction.doc.content.size));
|
|
23082
|
+
transaction = transaction.setSelection(import_state4.TextSelection.near(resolvedPos));
|
|
23083
|
+
} else {
|
|
23084
|
+
const resolvedPos = transaction.doc.resolve(selection.from);
|
|
23085
|
+
transaction = transaction.setSelection(import_state4.NodeSelection.create(transaction.doc, resolvedPos.pos));
|
|
23086
|
+
}
|
|
23087
|
+
view.dispatch(transaction.scrollIntoView());
|
|
23088
|
+
view.focus();
|
|
23089
|
+
}
|
|
23090
|
+
function applyImageWidthPreset(editor, preset) {
|
|
23091
|
+
const attrs = editor.getAttributes("image");
|
|
23092
|
+
const mode = attrs.imageLayout === "left" || attrs.imageLayout === "right" ? "wrap" : "block";
|
|
23093
|
+
const width = IMAGE_WIDTHS_BY_LAYOUT[mode][preset];
|
|
23094
|
+
if (!isSelectedImage(editor)) {
|
|
23095
|
+
editor.chain().focus().updateAttributes("image", { width, imageWidthPreset: preset }).run();
|
|
23096
|
+
return;
|
|
23097
|
+
}
|
|
23098
|
+
const { state, view } = editor;
|
|
23099
|
+
const selection = state.selection;
|
|
23100
|
+
const transaction = state.tr.setNodeMarkup(selection.from, void 0, {
|
|
23101
|
+
...selection.node.attrs,
|
|
23102
|
+
width,
|
|
23103
|
+
imageWidthPreset: preset
|
|
23104
|
+
});
|
|
23105
|
+
view.dispatch(transaction.scrollIntoView());
|
|
23106
|
+
view.focus();
|
|
23107
|
+
}
|
|
23108
|
+
function resetImageSize(editor) {
|
|
23109
|
+
if (!isSelectedImage(editor)) {
|
|
23110
|
+
editor.chain().focus().updateAttributes("image", {
|
|
23111
|
+
width: null,
|
|
23112
|
+
height: null,
|
|
23113
|
+
imageWidthPreset: null
|
|
23114
|
+
}).run();
|
|
23115
|
+
return;
|
|
23116
|
+
}
|
|
23117
|
+
const { state, view } = editor;
|
|
23118
|
+
const selection = state.selection;
|
|
23119
|
+
const transaction = state.tr.setNodeMarkup(selection.from, void 0, {
|
|
23120
|
+
...selection.node.attrs,
|
|
23121
|
+
width: null,
|
|
23122
|
+
height: null,
|
|
23123
|
+
imageWidthPreset: null
|
|
23124
|
+
});
|
|
23125
|
+
view.dispatch(transaction.scrollIntoView());
|
|
23126
|
+
view.focus();
|
|
23127
|
+
}
|
|
23128
|
+
function deleteSelectedImage(editor) {
|
|
23129
|
+
if (!isSelectedImage(editor)) return;
|
|
23130
|
+
editor.chain().focus().deleteSelection().run();
|
|
23131
|
+
}
|
|
23132
|
+
|
|
22956
23133
|
// src/components/UEditor/inputs.tsx
|
|
22957
23134
|
var import_react46 = require("react");
|
|
22958
23135
|
var import_lucide_react42 = require("lucide-react");
|
|
@@ -23289,6 +23466,10 @@ var EditorToolbar = ({
|
|
|
23289
23466
|
const fileInputRef = (0, import_react48.useRef)(null);
|
|
23290
23467
|
const [isUploadingImage, setIsUploadingImage] = (0, import_react48.useState)(false);
|
|
23291
23468
|
const [imageUploadError, setImageUploadError] = (0, import_react48.useState)(null);
|
|
23469
|
+
const isImageSelected = editor.isActive("image");
|
|
23470
|
+
const imageAttrs = editor.getAttributes("image");
|
|
23471
|
+
const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
|
|
23472
|
+
const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
|
|
23292
23473
|
const insertImageFiles = async (files) => {
|
|
23293
23474
|
if (files.length === 0) return;
|
|
23294
23475
|
setIsUploadingImage(true);
|
|
@@ -23621,6 +23802,85 @@ var EditorToolbar = ({
|
|
|
23621
23802
|
void insertImageFiles(files);
|
|
23622
23803
|
}
|
|
23623
23804
|
}
|
|
23805
|
+
),
|
|
23806
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "my-1 border-t" }),
|
|
23807
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23808
|
+
DropdownMenuItem,
|
|
23809
|
+
{
|
|
23810
|
+
icon: import_lucide_react44.AlignCenter,
|
|
23811
|
+
label: t("toolbar.imageLayoutBlock"),
|
|
23812
|
+
onClick: () => applyImageLayout(editor, "block"),
|
|
23813
|
+
active: isImageSelected && imageLayout === "block",
|
|
23814
|
+
disabled: !isImageSelected
|
|
23815
|
+
}
|
|
23816
|
+
),
|
|
23817
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23818
|
+
DropdownMenuItem,
|
|
23819
|
+
{
|
|
23820
|
+
icon: import_lucide_react44.AlignLeft,
|
|
23821
|
+
label: t("toolbar.imageLayoutLeft"),
|
|
23822
|
+
onClick: () => applyImageLayout(editor, "left"),
|
|
23823
|
+
active: isImageSelected && imageLayout === "left",
|
|
23824
|
+
disabled: !isImageSelected
|
|
23825
|
+
}
|
|
23826
|
+
),
|
|
23827
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23828
|
+
DropdownMenuItem,
|
|
23829
|
+
{
|
|
23830
|
+
icon: import_lucide_react44.AlignRight,
|
|
23831
|
+
label: t("toolbar.imageLayoutRight"),
|
|
23832
|
+
onClick: () => applyImageLayout(editor, "right"),
|
|
23833
|
+
active: isImageSelected && imageLayout === "right",
|
|
23834
|
+
disabled: !isImageSelected
|
|
23835
|
+
}
|
|
23836
|
+
),
|
|
23837
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "my-1 border-t" }),
|
|
23838
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23839
|
+
DropdownMenuItem,
|
|
23840
|
+
{
|
|
23841
|
+
label: t("toolbar.imageWidthSm"),
|
|
23842
|
+
onClick: () => applyImageWidthPreset(editor, "sm"),
|
|
23843
|
+
active: isImageSelected && imageWidthPreset === "sm",
|
|
23844
|
+
disabled: !isImageSelected
|
|
23845
|
+
}
|
|
23846
|
+
),
|
|
23847
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23848
|
+
DropdownMenuItem,
|
|
23849
|
+
{
|
|
23850
|
+
label: t("toolbar.imageWidthMd"),
|
|
23851
|
+
onClick: () => applyImageWidthPreset(editor, "md"),
|
|
23852
|
+
active: isImageSelected && imageWidthPreset === "md",
|
|
23853
|
+
disabled: !isImageSelected
|
|
23854
|
+
}
|
|
23855
|
+
),
|
|
23856
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23857
|
+
DropdownMenuItem,
|
|
23858
|
+
{
|
|
23859
|
+
label: t("toolbar.imageWidthLg"),
|
|
23860
|
+
onClick: () => applyImageWidthPreset(editor, "lg"),
|
|
23861
|
+
active: isImageSelected && imageWidthPreset === "lg",
|
|
23862
|
+
disabled: !isImageSelected
|
|
23863
|
+
}
|
|
23864
|
+
),
|
|
23865
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "my-1 border-t" }),
|
|
23866
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23867
|
+
DropdownMenuItem,
|
|
23868
|
+
{
|
|
23869
|
+
icon: import_lucide_react44.RotateCcw,
|
|
23870
|
+
label: t("toolbar.imageResetSize"),
|
|
23871
|
+
onClick: () => resetImageSize(editor),
|
|
23872
|
+
disabled: !isImageSelected
|
|
23873
|
+
}
|
|
23874
|
+
),
|
|
23875
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)(
|
|
23876
|
+
DropdownMenuItem,
|
|
23877
|
+
{
|
|
23878
|
+
icon: import_lucide_react44.Trash2,
|
|
23879
|
+
label: t("toolbar.imageDelete"),
|
|
23880
|
+
onClick: () => deleteSelectedImage(editor),
|
|
23881
|
+
disabled: !isImageSelected,
|
|
23882
|
+
destructive: true
|
|
23883
|
+
}
|
|
23624
23884
|
)
|
|
23625
23885
|
] })
|
|
23626
23886
|
}
|
|
@@ -23933,6 +24193,10 @@ var BubbleMenuContent = ({
|
|
|
23933
24193
|
const { textColors, highlightColors } = useEditorColors();
|
|
23934
24194
|
const [showLinkInput, setShowLinkInput] = (0, import_react49.useState)(false);
|
|
23935
24195
|
const [showEditorColorPalette, setShowEditorColorPalette] = (0, import_react49.useState)(false);
|
|
24196
|
+
const isImageSelected = editor.isActive("image");
|
|
24197
|
+
const imageAttrs = editor.getAttributes("image");
|
|
24198
|
+
const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
|
|
24199
|
+
const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
|
|
23936
24200
|
(0, import_react49.useEffect)(() => {
|
|
23937
24201
|
onKeepOpenChange?.(showLinkInput);
|
|
23938
24202
|
}, [onKeepOpenChange, showLinkInput]);
|
|
@@ -24007,6 +24271,20 @@ var BubbleMenuContent = ({
|
|
|
24007
24271
|
) })
|
|
24008
24272
|
] });
|
|
24009
24273
|
}
|
|
24274
|
+
if (isImageSelected) {
|
|
24275
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex items-center gap-0.5 p-1", children: [
|
|
24276
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => applyImageLayout(editor, "block"), active: imageLayout === "block", title: t("toolbar.imageLayoutBlock"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.AlignCenter, { className: "w-4 h-4" }) }),
|
|
24277
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => applyImageLayout(editor, "left"), active: imageLayout === "left", title: t("toolbar.imageLayoutLeft"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.AlignLeft, { className: "w-4 h-4" }) }),
|
|
24278
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => applyImageLayout(editor, "right"), active: imageLayout === "right", title: t("toolbar.imageLayoutRight"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.AlignRight, { className: "w-4 h-4" }) }),
|
|
24279
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
|
|
24280
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "sm"), active: imageWidthPreset === "sm", title: t("toolbar.imageWidthSm"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-[10px] font-semibold", children: "S" }) }),
|
|
24281
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "md"), active: imageWidthPreset === "md", title: t("toolbar.imageWidthMd"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-[10px] font-semibold", children: "M" }) }),
|
|
24282
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => applyImageWidthPreset(editor, "lg"), active: imageWidthPreset === "lg", title: t("toolbar.imageWidthLg"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "text-[10px] font-semibold", children: "L" }) }),
|
|
24283
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "w-px h-6 bg-border/50 mx-1" }),
|
|
24284
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => resetImageSize(editor), title: t("toolbar.imageResetSize"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.RotateCcw, { className: "w-4 h-4" }) }),
|
|
24285
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => deleteSelectedImage(editor), title: t("toolbar.imageDelete"), className: "text-destructive hover:text-destructive", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.Trash2, { className: "w-4 h-4" }) })
|
|
24286
|
+
] });
|
|
24287
|
+
}
|
|
24010
24288
|
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "flex items-center gap-0.5 p-1", children: [
|
|
24011
24289
|
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.Bold, { className: "w-4 h-4" }) }),
|
|
24012
24290
|
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(import_lucide_react45.Italic, { className: "w-4 h-4" }) }),
|
|
@@ -24059,19 +24337,28 @@ var BubbleMenuContent = ({
|
|
|
24059
24337
|
] });
|
|
24060
24338
|
};
|
|
24061
24339
|
var CustomBubbleMenu = ({ editor }) => {
|
|
24340
|
+
const SHOW_DELAY_MS = 180;
|
|
24062
24341
|
const [isVisible, setIsVisible] = (0, import_react49.useState)(false);
|
|
24063
24342
|
const [position, setPosition] = (0, import_react49.useState)({ top: 0, left: 0 });
|
|
24064
24343
|
const menuRef = (0, import_react49.useRef)(null);
|
|
24065
24344
|
const keepOpenRef = (0, import_react49.useRef)(false);
|
|
24345
|
+
const showTimeoutRef = (0, import_react49.useRef)(null);
|
|
24066
24346
|
const setKeepOpen = (0, import_react49.useCallback)((next) => {
|
|
24067
24347
|
keepOpenRef.current = next;
|
|
24068
24348
|
if (next) setIsVisible(true);
|
|
24069
24349
|
}, []);
|
|
24070
24350
|
(0, import_react49.useEffect)(() => {
|
|
24351
|
+
const clearShowTimeout = () => {
|
|
24352
|
+
if (showTimeoutRef.current) {
|
|
24353
|
+
clearTimeout(showTimeoutRef.current);
|
|
24354
|
+
showTimeoutRef.current = null;
|
|
24355
|
+
}
|
|
24356
|
+
};
|
|
24071
24357
|
const updatePosition = () => {
|
|
24072
24358
|
const { state, view } = editor;
|
|
24073
24359
|
const { from, to, empty } = state.selection;
|
|
24074
24360
|
if (!keepOpenRef.current && (empty || !view.hasFocus())) {
|
|
24361
|
+
clearShowTimeout();
|
|
24075
24362
|
setIsVisible(false);
|
|
24076
24363
|
return;
|
|
24077
24364
|
}
|
|
@@ -24080,15 +24367,28 @@ var CustomBubbleMenu = ({ editor }) => {
|
|
|
24080
24367
|
const left = (start.left + end.left) / 2;
|
|
24081
24368
|
const top = start.top - 10;
|
|
24082
24369
|
setPosition({ top, left });
|
|
24083
|
-
|
|
24370
|
+
if (keepOpenRef.current) {
|
|
24371
|
+
clearShowTimeout();
|
|
24372
|
+
setIsVisible(true);
|
|
24373
|
+
return;
|
|
24374
|
+
}
|
|
24375
|
+
clearShowTimeout();
|
|
24376
|
+
showTimeoutRef.current = setTimeout(() => {
|
|
24377
|
+
setIsVisible(true);
|
|
24378
|
+
showTimeoutRef.current = null;
|
|
24379
|
+
}, SHOW_DELAY_MS);
|
|
24084
24380
|
};
|
|
24085
24381
|
const handleBlur = () => {
|
|
24086
|
-
if (!keepOpenRef.current)
|
|
24382
|
+
if (!keepOpenRef.current) {
|
|
24383
|
+
clearShowTimeout();
|
|
24384
|
+
setIsVisible(false);
|
|
24385
|
+
}
|
|
24087
24386
|
};
|
|
24088
24387
|
editor.on("selectionUpdate", updatePosition);
|
|
24089
24388
|
editor.on("focus", updatePosition);
|
|
24090
24389
|
editor.on("blur", handleBlur);
|
|
24091
24390
|
return () => {
|
|
24391
|
+
clearShowTimeout();
|
|
24092
24392
|
editor.off("selectionUpdate", updatePosition);
|
|
24093
24393
|
editor.off("focus", updatePosition);
|
|
24094
24394
|
editor.off("blur", handleBlur);
|
|
@@ -24572,7 +24872,21 @@ var UEditor = import_react50.default.forwardRef(({
|
|
|
24572
24872
|
"[&_blockquote]:rounded-r-lg",
|
|
24573
24873
|
"[&_blockquote]:italic",
|
|
24574
24874
|
"[&_blockquote]:text-muted-foreground",
|
|
24575
|
-
"[&_blockquote_p]:my-0"
|
|
24875
|
+
"[&_blockquote_p]:my-0",
|
|
24876
|
+
"[&_[data-image-layout='left']+p]:mt-1",
|
|
24877
|
+
"[&_[data-image-layout='left']+p]:min-h-[5rem]",
|
|
24878
|
+
"[&_[data-image-layout='right']+p]:mt-1",
|
|
24879
|
+
"[&_[data-image-layout='right']+p]:min-h-[5rem]",
|
|
24880
|
+
"max-md:[&_[data-image-layout='left']]:float-none",
|
|
24881
|
+
"max-md:[&_[data-image-layout='left']]:mr-0",
|
|
24882
|
+
"max-md:[&_[data-image-layout='left']]:ml-0",
|
|
24883
|
+
"max-md:[&_[data-image-layout='left']]:max-w-full",
|
|
24884
|
+
"max-md:[&_[data-image-layout='right']]:float-none",
|
|
24885
|
+
"max-md:[&_[data-image-layout='right']]:mr-0",
|
|
24886
|
+
"max-md:[&_[data-image-layout='right']]:ml-0",
|
|
24887
|
+
"max-md:[&_[data-image-layout='right']]:max-w-full",
|
|
24888
|
+
"max-md:[&_[data-image-layout='left']+p]:min-h-0",
|
|
24889
|
+
"max-md:[&_[data-image-layout='right']+p]:min-h-0"
|
|
24576
24890
|
)
|
|
24577
24891
|
}
|
|
24578
24892
|
},
|