@trafica/editor 1.0.21 → 1.0.23
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.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +815 -523
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +815 -523
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { forwardRef, useRef, useEffect, useCallback, useMemo, useImperativeHandle, useState, useLayoutEffect, useSyncExternalStore } from 'react';
|
|
2
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
2
|
import { createPortal } from 'react-dom';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
5
5
|
// src/editor/core/DocumentModel.ts
|
|
6
6
|
function isTextNode(node) {
|
|
@@ -3319,13 +3319,15 @@ var OPTIONS = [
|
|
|
3319
3319
|
function AlignmentDropdown({ engine, activeAlignment }) {
|
|
3320
3320
|
var _a;
|
|
3321
3321
|
const [open, setOpen] = useState(false);
|
|
3322
|
-
const
|
|
3322
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
3323
|
+
const buttonRef = useRef(null);
|
|
3324
|
+
const popupRef = useRef(null);
|
|
3323
3325
|
useEffect(() => {
|
|
3324
3326
|
if (!open) return;
|
|
3325
3327
|
const handler = (e) => {
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3328
|
+
var _a2, _b;
|
|
3329
|
+
const target = e.target;
|
|
3330
|
+
if (!((_a2 = popupRef.current) == null ? void 0 : _a2.contains(target)) && !((_b = buttonRef.current) == null ? void 0 : _b.contains(target))) setOpen(false);
|
|
3329
3331
|
};
|
|
3330
3332
|
document.addEventListener("mousedown", handler);
|
|
3331
3333
|
return () => document.removeEventListener("mousedown", handler);
|
|
@@ -3339,22 +3341,31 @@ function AlignmentDropdown({ engine, activeAlignment }) {
|
|
|
3339
3341
|
return () => document.removeEventListener("keydown", handler);
|
|
3340
3342
|
}, [open]);
|
|
3341
3343
|
const activeOption = (_a = OPTIONS.find((o) => o.value === activeAlignment)) != null ? _a : OPTIONS[0];
|
|
3342
|
-
return /* @__PURE__ */ jsxs(
|
|
3344
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3343
3345
|
/* @__PURE__ */ jsxs(
|
|
3344
3346
|
"button",
|
|
3345
3347
|
{
|
|
3348
|
+
ref: buttonRef,
|
|
3346
3349
|
type: "button",
|
|
3347
3350
|
title: `Text alignment (${activeOption.label})`,
|
|
3348
3351
|
"aria-haspopup": "listbox",
|
|
3349
3352
|
"aria-expanded": open,
|
|
3350
3353
|
onMouseDown: (e) => {
|
|
3351
3354
|
e.preventDefault();
|
|
3352
|
-
|
|
3355
|
+
if (open) {
|
|
3356
|
+
setOpen(false);
|
|
3357
|
+
return;
|
|
3358
|
+
}
|
|
3359
|
+
if (buttonRef.current) {
|
|
3360
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
3361
|
+
setPopupPos({ top: rect.bottom + 4, left: rect.left });
|
|
3362
|
+
}
|
|
3363
|
+
setOpen(true);
|
|
3353
3364
|
},
|
|
3354
3365
|
className: [
|
|
3355
3366
|
"flex items-center gap-0.5 px-1.5 h-8 rounded text-sm font-medium transition-colors",
|
|
3356
3367
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500",
|
|
3357
|
-
open ? "bg-gray-100
|
|
3368
|
+
open ? "bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3358
3369
|
].join(" "),
|
|
3359
3370
|
children: [
|
|
3360
3371
|
activeOption.icon,
|
|
@@ -3362,40 +3373,45 @@ function AlignmentDropdown({ engine, activeAlignment }) {
|
|
|
3362
3373
|
]
|
|
3363
3374
|
}
|
|
3364
3375
|
),
|
|
3365
|
-
open &&
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3376
|
+
open && createPortal(
|
|
3377
|
+
/* @__PURE__ */ jsx(
|
|
3378
|
+
"div",
|
|
3379
|
+
{
|
|
3380
|
+
ref: popupRef,
|
|
3381
|
+
role: "listbox",
|
|
3382
|
+
"aria-label": "Text alignment",
|
|
3383
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, minWidth: 168 },
|
|
3384
|
+
className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1",
|
|
3385
|
+
children: OPTIONS.map((option) => {
|
|
3386
|
+
const isActive = activeAlignment === option.value;
|
|
3387
|
+
return /* @__PURE__ */ jsxs(
|
|
3388
|
+
"button",
|
|
3389
|
+
{
|
|
3390
|
+
type: "button",
|
|
3391
|
+
role: "option",
|
|
3392
|
+
"aria-selected": isActive,
|
|
3393
|
+
title: `${option.label} (${option.shortcut})`,
|
|
3394
|
+
onMouseDown: (e) => {
|
|
3395
|
+
e.preventDefault();
|
|
3396
|
+
setAlignment(option.value)(engine);
|
|
3397
|
+
setOpen(false);
|
|
3398
|
+
},
|
|
3399
|
+
className: [
|
|
3400
|
+
"w-full flex items-center gap-3 px-3 py-1.5 text-sm transition-colors",
|
|
3401
|
+
isActive ? "bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3402
|
+
].join(" "),
|
|
3403
|
+
children: [
|
|
3404
|
+
/* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: option.icon }),
|
|
3405
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: option.label }),
|
|
3406
|
+
isActive && /* @__PURE__ */ jsx(CheckIcon, {})
|
|
3407
|
+
]
|
|
3384
3408
|
},
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: option.label }),
|
|
3392
|
-
isActive && /* @__PURE__ */ jsx(CheckIcon, {})
|
|
3393
|
-
]
|
|
3394
|
-
},
|
|
3395
|
-
option.value
|
|
3396
|
-
);
|
|
3397
|
-
})
|
|
3398
|
-
}
|
|
3409
|
+
option.value
|
|
3410
|
+
);
|
|
3411
|
+
})
|
|
3412
|
+
}
|
|
3413
|
+
),
|
|
3414
|
+
document.body
|
|
3399
3415
|
)
|
|
3400
3416
|
] });
|
|
3401
3417
|
}
|
|
@@ -3440,11 +3456,15 @@ function CheckIcon() {
|
|
|
3440
3456
|
var SIZES = ["8", "10", "12", "14", "16", "18", "24", "32", "48"];
|
|
3441
3457
|
function FontSizeDropdown({ engine, activeFontSize }) {
|
|
3442
3458
|
const [open, setOpen] = useState(false);
|
|
3443
|
-
const
|
|
3459
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
3460
|
+
const buttonRef = useRef(null);
|
|
3461
|
+
const popupRef = useRef(null);
|
|
3444
3462
|
useEffect(() => {
|
|
3445
3463
|
if (!open) return;
|
|
3446
3464
|
const handler = (e) => {
|
|
3447
|
-
|
|
3465
|
+
var _a, _b;
|
|
3466
|
+
const target = e.target;
|
|
3467
|
+
if (!((_a = popupRef.current) == null ? void 0 : _a.contains(target)) && !((_b = buttonRef.current) == null ? void 0 : _b.contains(target))) {
|
|
3448
3468
|
setOpen(false);
|
|
3449
3469
|
}
|
|
3450
3470
|
};
|
|
@@ -3459,24 +3479,36 @@ function FontSizeDropdown({ engine, activeFontSize }) {
|
|
|
3459
3479
|
document.addEventListener("keydown", handler);
|
|
3460
3480
|
return () => document.removeEventListener("keydown", handler);
|
|
3461
3481
|
}, [open]);
|
|
3482
|
+
function openDropdown() {
|
|
3483
|
+
if (buttonRef.current) {
|
|
3484
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
3485
|
+
setPopupPos({ top: rect.bottom + 4, left: rect.left });
|
|
3486
|
+
}
|
|
3487
|
+
setOpen(true);
|
|
3488
|
+
}
|
|
3462
3489
|
const activeNum = activeFontSize ? activeFontSize.replace("px", "") : null;
|
|
3463
3490
|
const label = activeNum != null ? activeNum : "Size";
|
|
3464
|
-
return /* @__PURE__ */ jsxs(
|
|
3491
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3465
3492
|
/* @__PURE__ */ jsxs(
|
|
3466
3493
|
"button",
|
|
3467
3494
|
{
|
|
3495
|
+
ref: buttonRef,
|
|
3468
3496
|
type: "button",
|
|
3469
3497
|
title: "Font size",
|
|
3470
3498
|
"aria-haspopup": "listbox",
|
|
3471
3499
|
"aria-expanded": open,
|
|
3472
3500
|
onMouseDown: (e) => {
|
|
3473
3501
|
e.preventDefault();
|
|
3474
|
-
|
|
3502
|
+
if (open) {
|
|
3503
|
+
setOpen(false);
|
|
3504
|
+
} else {
|
|
3505
|
+
openDropdown();
|
|
3506
|
+
}
|
|
3475
3507
|
},
|
|
3476
3508
|
className: [
|
|
3477
3509
|
"flex items-center gap-0.5 px-1.5 h-8 rounded text-sm font-medium transition-colors min-w-[52px]",
|
|
3478
3510
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500",
|
|
3479
|
-
open ? "bg-gray-100
|
|
3511
|
+
open ? "bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3480
3512
|
].join(" "),
|
|
3481
3513
|
children: [
|
|
3482
3514
|
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: label }),
|
|
@@ -3484,61 +3516,66 @@ function FontSizeDropdown({ engine, activeFontSize }) {
|
|
|
3484
3516
|
]
|
|
3485
3517
|
}
|
|
3486
3518
|
),
|
|
3487
|
-
open &&
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
role: "option",
|
|
3499
|
-
"aria-selected": activeFontSize === null,
|
|
3500
|
-
onMouseDown: (e) => {
|
|
3501
|
-
e.preventDefault();
|
|
3502
|
-
setFontSize(null)(engine);
|
|
3503
|
-
setOpen(false);
|
|
3504
|
-
},
|
|
3505
|
-
className: [
|
|
3506
|
-
"w-full flex items-center justify-between px-3 py-1.5 text-sm transition-colors",
|
|
3507
|
-
activeFontSize === null ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-100 "
|
|
3508
|
-
].join(" "),
|
|
3509
|
-
children: [
|
|
3510
|
-
/* @__PURE__ */ jsx("span", { children: "Default" }),
|
|
3511
|
-
activeFontSize === null && /* @__PURE__ */ jsx(CheckIcon2, {})
|
|
3512
|
-
]
|
|
3513
|
-
}
|
|
3514
|
-
),
|
|
3515
|
-
SIZES.map((size) => {
|
|
3516
|
-
const isActive = activeNum === size;
|
|
3517
|
-
return /* @__PURE__ */ jsxs(
|
|
3519
|
+
open && createPortal(
|
|
3520
|
+
/* @__PURE__ */ jsxs(
|
|
3521
|
+
"div",
|
|
3522
|
+
{
|
|
3523
|
+
ref: popupRef,
|
|
3524
|
+
role: "listbox",
|
|
3525
|
+
"aria-label": "Font size",
|
|
3526
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, minWidth: 88, maxHeight: 256, overflowY: "auto" },
|
|
3527
|
+
className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1",
|
|
3528
|
+
children: [
|
|
3529
|
+
/* @__PURE__ */ jsxs(
|
|
3518
3530
|
"button",
|
|
3519
3531
|
{
|
|
3520
3532
|
type: "button",
|
|
3521
3533
|
role: "option",
|
|
3522
|
-
"aria-selected":
|
|
3534
|
+
"aria-selected": activeFontSize === null,
|
|
3523
3535
|
onMouseDown: (e) => {
|
|
3524
3536
|
e.preventDefault();
|
|
3525
|
-
setFontSize(
|
|
3537
|
+
setFontSize(null)(engine);
|
|
3526
3538
|
setOpen(false);
|
|
3527
3539
|
},
|
|
3528
3540
|
className: [
|
|
3529
|
-
"w-full flex items-center justify-between px-3 py-1.5 transition-colors",
|
|
3530
|
-
|
|
3541
|
+
"w-full flex items-center justify-between px-3 py-1.5 text-sm transition-colors",
|
|
3542
|
+
activeFontSize === null ? "bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3531
3543
|
].join(" "),
|
|
3532
3544
|
children: [
|
|
3533
|
-
/* @__PURE__ */ jsx("span", {
|
|
3534
|
-
|
|
3545
|
+
/* @__PURE__ */ jsx("span", { children: "Default" }),
|
|
3546
|
+
activeFontSize === null && /* @__PURE__ */ jsx(CheckIcon2, {})
|
|
3535
3547
|
]
|
|
3536
|
-
}
|
|
3537
|
-
|
|
3538
|
-
)
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3548
|
+
}
|
|
3549
|
+
),
|
|
3550
|
+
SIZES.map((size) => {
|
|
3551
|
+
const isActive = activeNum === size;
|
|
3552
|
+
return /* @__PURE__ */ jsxs(
|
|
3553
|
+
"button",
|
|
3554
|
+
{
|
|
3555
|
+
type: "button",
|
|
3556
|
+
role: "option",
|
|
3557
|
+
"aria-selected": isActive,
|
|
3558
|
+
onMouseDown: (e) => {
|
|
3559
|
+
e.preventDefault();
|
|
3560
|
+
setFontSize(`${size}px`)(engine);
|
|
3561
|
+
setOpen(false);
|
|
3562
|
+
},
|
|
3563
|
+
className: [
|
|
3564
|
+
"w-full flex items-center justify-between px-3 py-1.5 transition-colors",
|
|
3565
|
+
isActive ? "bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3566
|
+
].join(" "),
|
|
3567
|
+
children: [
|
|
3568
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: `${size}px`, lineHeight: 1.3 }, children: size }),
|
|
3569
|
+
isActive && /* @__PURE__ */ jsx(CheckIcon2, {})
|
|
3570
|
+
]
|
|
3571
|
+
},
|
|
3572
|
+
size
|
|
3573
|
+
);
|
|
3574
|
+
})
|
|
3575
|
+
]
|
|
3576
|
+
}
|
|
3577
|
+
),
|
|
3578
|
+
document.body
|
|
3542
3579
|
)
|
|
3543
3580
|
] });
|
|
3544
3581
|
}
|
|
@@ -3564,12 +3601,16 @@ function FontFamilyDropdown({ engine, activeFontFamily }) {
|
|
|
3564
3601
|
const [open, setOpen] = useState(false);
|
|
3565
3602
|
const [showCustomInput, setShowCustomInput] = useState(false);
|
|
3566
3603
|
const [customValue, setCustomValue] = useState("");
|
|
3567
|
-
const
|
|
3604
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
3605
|
+
const buttonRef = useRef(null);
|
|
3606
|
+
const popupRef = useRef(null);
|
|
3568
3607
|
const customInputRef = useRef(null);
|
|
3569
3608
|
useEffect(() => {
|
|
3570
3609
|
if (!open) return;
|
|
3571
3610
|
const handler = (e) => {
|
|
3572
|
-
|
|
3611
|
+
var _a2, _b;
|
|
3612
|
+
const target = e.target;
|
|
3613
|
+
if (!((_a2 = popupRef.current) == null ? void 0 : _a2.contains(target)) && !((_b = buttonRef.current) == null ? void 0 : _b.contains(target))) {
|
|
3573
3614
|
closeDropdown();
|
|
3574
3615
|
}
|
|
3575
3616
|
};
|
|
@@ -3588,6 +3629,17 @@ function FontFamilyDropdown({ engine, activeFontFamily }) {
|
|
|
3588
3629
|
var _a2;
|
|
3589
3630
|
if (showCustomInput) (_a2 = customInputRef.current) == null ? void 0 : _a2.focus();
|
|
3590
3631
|
}, [showCustomInput]);
|
|
3632
|
+
function openDropdown() {
|
|
3633
|
+
if (buttonRef.current) {
|
|
3634
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
3635
|
+
const popupWidth = 200;
|
|
3636
|
+
const left = Math.min(rect.left, window.innerWidth - popupWidth - 8);
|
|
3637
|
+
setPopupPos({ top: rect.bottom + 4, left: Math.max(8, left) });
|
|
3638
|
+
}
|
|
3639
|
+
setShowCustomInput(false);
|
|
3640
|
+
setCustomValue("");
|
|
3641
|
+
setOpen(true);
|
|
3642
|
+
}
|
|
3591
3643
|
function closeDropdown() {
|
|
3592
3644
|
setOpen(false);
|
|
3593
3645
|
setShowCustomInput(false);
|
|
@@ -3599,10 +3651,11 @@ function FontFamilyDropdown({ engine, activeFontFamily }) {
|
|
|
3599
3651
|
}
|
|
3600
3652
|
const activeOption = activeFontFamily ? (_a = FONTS.find((f) => f.value === activeFontFamily)) != null ? _a : null : null;
|
|
3601
3653
|
const triggerLabel = activeOption ? activeOption.label : activeFontFamily ? activeFontFamily.split(",")[0].replace(/['"]/g, "").trim().slice(0, 10) : "Font";
|
|
3602
|
-
return /* @__PURE__ */ jsxs(
|
|
3654
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3603
3655
|
/* @__PURE__ */ jsxs(
|
|
3604
3656
|
"button",
|
|
3605
3657
|
{
|
|
3658
|
+
ref: buttonRef,
|
|
3606
3659
|
type: "button",
|
|
3607
3660
|
title: "Font family",
|
|
3608
3661
|
"aria-haspopup": "listbox",
|
|
@@ -3611,16 +3664,14 @@ function FontFamilyDropdown({ engine, activeFontFamily }) {
|
|
|
3611
3664
|
e.preventDefault();
|
|
3612
3665
|
if (open) {
|
|
3613
3666
|
closeDropdown();
|
|
3614
|
-
|
|
3667
|
+
} else {
|
|
3668
|
+
openDropdown();
|
|
3615
3669
|
}
|
|
3616
|
-
setShowCustomInput(false);
|
|
3617
|
-
setCustomValue("");
|
|
3618
|
-
setOpen(true);
|
|
3619
3670
|
},
|
|
3620
3671
|
className: [
|
|
3621
3672
|
"flex items-center gap-0.5 px-1.5 h-8 rounded text-sm font-medium transition-colors min-w-[60px] max-w-[120px]",
|
|
3622
3673
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500",
|
|
3623
|
-
open ? "bg-gray-100
|
|
3674
|
+
open ? "bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3624
3675
|
].join(" "),
|
|
3625
3676
|
children: [
|
|
3626
3677
|
/* @__PURE__ */ jsx(FontIcon, {}),
|
|
@@ -3629,60 +3680,65 @@ function FontFamilyDropdown({ engine, activeFontFamily }) {
|
|
|
3629
3680
|
]
|
|
3630
3681
|
}
|
|
3631
3682
|
),
|
|
3632
|
-
open &&
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
role: "option",
|
|
3644
|
-
"aria-selected": activeFontFamily === null,
|
|
3645
|
-
onMouseDown: (e) => {
|
|
3646
|
-
e.preventDefault();
|
|
3647
|
-
applyFont(null);
|
|
3648
|
-
},
|
|
3649
|
-
className: [
|
|
3650
|
-
"w-full flex items-center justify-between px-3 py-1.5 text-sm transition-colors",
|
|
3651
|
-
activeFontFamily === null ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-100 "
|
|
3652
|
-
].join(" "),
|
|
3653
|
-
children: [
|
|
3654
|
-
/* @__PURE__ */ jsx("span", { children: "Default" }),
|
|
3655
|
-
activeFontFamily === null && /* @__PURE__ */ jsx(CheckIcon3, {})
|
|
3656
|
-
]
|
|
3657
|
-
}
|
|
3658
|
-
),
|
|
3659
|
-
/* @__PURE__ */ jsx("div", { className: "my-1 border-t border-gray-100 " }),
|
|
3660
|
-
FONTS.map((font) => {
|
|
3661
|
-
const isActive = activeFontFamily === font.value;
|
|
3662
|
-
return /* @__PURE__ */ jsxs(
|
|
3683
|
+
open && createPortal(
|
|
3684
|
+
/* @__PURE__ */ jsxs(
|
|
3685
|
+
"div",
|
|
3686
|
+
{
|
|
3687
|
+
ref: popupRef,
|
|
3688
|
+
role: "listbox",
|
|
3689
|
+
"aria-label": "Font family",
|
|
3690
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, minWidth: 200 },
|
|
3691
|
+
className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1",
|
|
3692
|
+
children: [
|
|
3693
|
+
/* @__PURE__ */ jsxs(
|
|
3663
3694
|
"button",
|
|
3664
3695
|
{
|
|
3665
3696
|
type: "button",
|
|
3666
3697
|
role: "option",
|
|
3667
|
-
"aria-selected":
|
|
3698
|
+
"aria-selected": activeFontFamily === null,
|
|
3668
3699
|
onMouseDown: (e) => {
|
|
3669
3700
|
e.preventDefault();
|
|
3670
|
-
applyFont(
|
|
3701
|
+
applyFont(null);
|
|
3671
3702
|
},
|
|
3672
3703
|
className: [
|
|
3673
3704
|
"w-full flex items-center justify-between px-3 py-1.5 text-sm transition-colors",
|
|
3674
|
-
|
|
3705
|
+
activeFontFamily === null ? "bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3675
3706
|
].join(" "),
|
|
3676
3707
|
children: [
|
|
3677
|
-
/* @__PURE__ */ jsx("span", {
|
|
3678
|
-
|
|
3708
|
+
/* @__PURE__ */ jsx("span", { children: "Default" }),
|
|
3709
|
+
activeFontFamily === null && /* @__PURE__ */ jsx(CheckIcon3, {})
|
|
3679
3710
|
]
|
|
3680
|
-
}
|
|
3681
|
-
|
|
3682
|
-
)
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3711
|
+
}
|
|
3712
|
+
),
|
|
3713
|
+
/* @__PURE__ */ jsx("div", { className: "my-1 border-t border-gray-100 dark:border-gray-700" }),
|
|
3714
|
+
FONTS.map((font) => {
|
|
3715
|
+
const isActive = activeFontFamily === font.value;
|
|
3716
|
+
return /* @__PURE__ */ jsxs(
|
|
3717
|
+
"button",
|
|
3718
|
+
{
|
|
3719
|
+
type: "button",
|
|
3720
|
+
role: "option",
|
|
3721
|
+
"aria-selected": isActive,
|
|
3722
|
+
onMouseDown: (e) => {
|
|
3723
|
+
e.preventDefault();
|
|
3724
|
+
applyFont(font.value);
|
|
3725
|
+
},
|
|
3726
|
+
className: [
|
|
3727
|
+
"w-full flex items-center justify-between px-3 py-1.5 text-sm transition-colors",
|
|
3728
|
+
isActive ? "bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3729
|
+
].join(" "),
|
|
3730
|
+
children: [
|
|
3731
|
+
/* @__PURE__ */ jsx("span", { style: { fontFamily: font.value }, children: font.label }),
|
|
3732
|
+
isActive && /* @__PURE__ */ jsx(CheckIcon3, {})
|
|
3733
|
+
]
|
|
3734
|
+
},
|
|
3735
|
+
font.value
|
|
3736
|
+
);
|
|
3737
|
+
})
|
|
3738
|
+
]
|
|
3739
|
+
}
|
|
3740
|
+
),
|
|
3741
|
+
document.body
|
|
3686
3742
|
)
|
|
3687
3743
|
] });
|
|
3688
3744
|
}
|
|
@@ -3728,11 +3784,15 @@ function BackgroundColorDropdown({
|
|
|
3728
3784
|
const [lastColor, setLastColor] = useState(PRESET_COLORS[6].value);
|
|
3729
3785
|
const [hexInput, setHexInput] = useState("");
|
|
3730
3786
|
const [hexError, setHexError] = useState(false);
|
|
3731
|
-
const
|
|
3787
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
3788
|
+
const chevronRef = useRef(null);
|
|
3789
|
+
const popupRef = useRef(null);
|
|
3732
3790
|
useEffect(() => {
|
|
3733
3791
|
if (!open) return;
|
|
3734
3792
|
const handler = (e) => {
|
|
3735
|
-
|
|
3793
|
+
var _a, _b;
|
|
3794
|
+
const target = e.target;
|
|
3795
|
+
if (!((_a = popupRef.current) == null ? void 0 : _a.contains(target)) && !((_b = chevronRef.current) == null ? void 0 : _b.contains(target)))
|
|
3736
3796
|
setOpen(false);
|
|
3737
3797
|
};
|
|
3738
3798
|
document.addEventListener("mousedown", handler);
|
|
@@ -3775,7 +3835,7 @@ function BackgroundColorDropdown({
|
|
|
3775
3835
|
(c) => !PRESET_COLORS.some((p) => normalizeHex(p.value) === normalizeHex(c))
|
|
3776
3836
|
);
|
|
3777
3837
|
const normActive = activeColor ? normalizeHex(activeColor) : null;
|
|
3778
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3838
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
3779
3839
|
/* @__PURE__ */ jsxs(
|
|
3780
3840
|
"button",
|
|
3781
3841
|
{
|
|
@@ -3785,7 +3845,7 @@ function BackgroundColorDropdown({
|
|
|
3785
3845
|
e.preventDefault();
|
|
3786
3846
|
handleQuickApply();
|
|
3787
3847
|
},
|
|
3788
|
-
className: "flex flex-col items-center justify-center gap-0.5 w-8 h-8 rounded-l\n text-gray-700 \n hover:bg-gray-100 \n focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500\n transition-colors",
|
|
3848
|
+
className: "flex flex-col items-center justify-center gap-0.5 w-8 h-8 rounded-l\n text-gray-700 dark:text-gray-300\n hover:bg-gray-100 dark:hover:bg-gray-700\n focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500\n transition-colors",
|
|
3789
3849
|
children: [
|
|
3790
3850
|
/* @__PURE__ */ jsx(BgColorIcon, {}),
|
|
3791
3851
|
/* @__PURE__ */ jsx(ColorBar, { color: normActive != null ? normActive : lastColor })
|
|
@@ -3795,140 +3855,150 @@ function BackgroundColorDropdown({
|
|
|
3795
3855
|
/* @__PURE__ */ jsx(
|
|
3796
3856
|
"button",
|
|
3797
3857
|
{
|
|
3858
|
+
ref: chevronRef,
|
|
3798
3859
|
type: "button",
|
|
3799
3860
|
title: "More background colors",
|
|
3800
3861
|
"aria-haspopup": "listbox",
|
|
3801
3862
|
"aria-expanded": open,
|
|
3802
3863
|
onMouseDown: (e) => {
|
|
3803
3864
|
e.preventDefault();
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3865
|
+
if (open) {
|
|
3866
|
+
setOpen(false);
|
|
3867
|
+
return;
|
|
3868
|
+
}
|
|
3869
|
+
if (chevronRef.current) {
|
|
3870
|
+
const rect = chevronRef.current.getBoundingClientRect();
|
|
3871
|
+
setPopupPos({ top: rect.bottom + 4, left: rect.left - 190 });
|
|
3872
|
+
}
|
|
3873
|
+
setHexInput("");
|
|
3874
|
+
setHexError(false);
|
|
3875
|
+
setOpen(true);
|
|
3811
3876
|
},
|
|
3812
3877
|
className: [
|
|
3813
|
-
"flex items-center justify-center w-4 h-8 rounded-r border-l border-gray-200 ",
|
|
3878
|
+
"flex items-center justify-center w-4 h-8 rounded-r border-l border-gray-200 dark:border-gray-600",
|
|
3814
3879
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500",
|
|
3815
3880
|
"transition-colors",
|
|
3816
|
-
open ? "bg-gray-100
|
|
3881
|
+
open ? "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200" : "text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
3817
3882
|
].join(" "),
|
|
3818
3883
|
children: /* @__PURE__ */ jsx(ChevronDownIcon4, {})
|
|
3819
3884
|
}
|
|
3820
3885
|
),
|
|
3821
|
-
open &&
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
type: "button",
|
|
3832
|
-
onMouseDown: (e) => {
|
|
3833
|
-
e.preventDefault();
|
|
3834
|
-
applyColor(null);
|
|
3835
|
-
},
|
|
3836
|
-
className: "flex items-center gap-2 w-full px-2 py-1.5 mb-2.5 text-xs font-medium\n text-gray-600 \n rounded hover:bg-gray-100 \n transition-colors",
|
|
3837
|
-
children: [
|
|
3838
|
-
/* @__PURE__ */ jsx(RemoveColorIcon, {}),
|
|
3839
|
-
"Remove background"
|
|
3840
|
-
]
|
|
3841
|
-
}
|
|
3842
|
-
),
|
|
3843
|
-
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 mb-2.5" }),
|
|
3844
|
-
extraDocColors.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3845
|
-
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-1.5 px-0.5", children: "Document colors" }),
|
|
3846
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1 mb-2.5", children: extraDocColors.slice(0, 10).map((c) => /* @__PURE__ */ jsx(
|
|
3847
|
-
Swatch,
|
|
3848
|
-
{
|
|
3849
|
-
color: { label: c, value: c },
|
|
3850
|
-
isActive: normActive === normalizeHex(c),
|
|
3851
|
-
onSelect: applyColor
|
|
3852
|
-
},
|
|
3853
|
-
c
|
|
3854
|
-
)) }),
|
|
3855
|
-
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 mb-2.5" })
|
|
3856
|
-
] }),
|
|
3857
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1 mb-3", children: PRESET_COLORS.map((c) => /* @__PURE__ */ jsx(
|
|
3858
|
-
Swatch,
|
|
3859
|
-
{
|
|
3860
|
-
color: c,
|
|
3861
|
-
isActive: normActive === normalizeHex(c.value),
|
|
3862
|
-
onSelect: applyColor
|
|
3863
|
-
},
|
|
3864
|
-
c.value
|
|
3865
|
-
)) }),
|
|
3866
|
-
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 mb-2.5" }),
|
|
3867
|
-
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-1.5 px-0.5", children: "Custom color" }),
|
|
3868
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3869
|
-
/* @__PURE__ */ jsx(
|
|
3870
|
-
"div",
|
|
3871
|
-
{
|
|
3872
|
-
className: "shrink-0 w-7 h-7 rounded border border-gray-300 ",
|
|
3873
|
-
style: { backgroundColor: hexInputToPreview(hexInput) }
|
|
3874
|
-
}
|
|
3875
|
-
),
|
|
3886
|
+
open && createPortal(
|
|
3887
|
+
/* @__PURE__ */ jsxs(
|
|
3888
|
+
"div",
|
|
3889
|
+
{
|
|
3890
|
+
ref: popupRef,
|
|
3891
|
+
role: "dialog",
|
|
3892
|
+
"aria-label": "Background color",
|
|
3893
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, width: 208 },
|
|
3894
|
+
className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-xl p-3",
|
|
3895
|
+
children: [
|
|
3876
3896
|
/* @__PURE__ */ jsxs(
|
|
3877
|
-
"div",
|
|
3878
|
-
{
|
|
3879
|
-
className: "flex flex-1 items-center border rounded overflow-hidden\n border-gray-300 \n focus-within:ring-2 focus-within:ring-blue-500",
|
|
3880
|
-
children: [
|
|
3881
|
-
/* @__PURE__ */ jsx("span", { className: "pl-2 text-xs text-gray-400 select-none", children: "#" }),
|
|
3882
|
-
/* @__PURE__ */ jsx(
|
|
3883
|
-
"input",
|
|
3884
|
-
{
|
|
3885
|
-
type: "text",
|
|
3886
|
-
maxLength: 6,
|
|
3887
|
-
value: hexInput,
|
|
3888
|
-
onChange: (e) => {
|
|
3889
|
-
setHexInput(e.target.value.replace(/[^0-9a-fA-F]/g, ""));
|
|
3890
|
-
setHexError(false);
|
|
3891
|
-
},
|
|
3892
|
-
onKeyDown: (e) => {
|
|
3893
|
-
if (e.key === "Enter") {
|
|
3894
|
-
e.preventDefault();
|
|
3895
|
-
commitHexInput();
|
|
3896
|
-
}
|
|
3897
|
-
if (e.key === "Escape") setOpen(false);
|
|
3898
|
-
},
|
|
3899
|
-
placeholder: "e.g. ffff00",
|
|
3900
|
-
className: [
|
|
3901
|
-
"flex-1 px-1 py-1.5 text-xs bg-transparent outline-none font-mono",
|
|
3902
|
-
"text-gray-900 ",
|
|
3903
|
-
hexError ? "text-red-500" : ""
|
|
3904
|
-
].join(" "),
|
|
3905
|
-
"aria-label": "Hex colour value"
|
|
3906
|
-
}
|
|
3907
|
-
)
|
|
3908
|
-
]
|
|
3909
|
-
}
|
|
3910
|
-
),
|
|
3911
|
-
/* @__PURE__ */ jsx(
|
|
3912
3897
|
"button",
|
|
3913
3898
|
{
|
|
3914
3899
|
type: "button",
|
|
3915
3900
|
onMouseDown: (e) => {
|
|
3916
3901
|
e.preventDefault();
|
|
3917
|
-
|
|
3902
|
+
applyColor(null);
|
|
3918
3903
|
},
|
|
3919
|
-
className: "
|
|
3920
|
-
children:
|
|
3904
|
+
className: "flex items-center gap-2 w-full px-2 py-1.5 mb-2.5 text-xs font-medium\n text-gray-600 dark:text-gray-300\n rounded hover:bg-gray-100 dark:hover:bg-gray-700\n transition-colors",
|
|
3905
|
+
children: [
|
|
3906
|
+
/* @__PURE__ */ jsx(RemoveColorIcon, {}),
|
|
3907
|
+
"Remove background"
|
|
3908
|
+
]
|
|
3921
3909
|
}
|
|
3922
|
-
)
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
}
|
|
3930
|
-
|
|
3931
|
-
|
|
3910
|
+
),
|
|
3911
|
+
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 dark:bg-gray-700 mb-2.5" }),
|
|
3912
|
+
extraDocColors.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3913
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 dark:text-gray-500 mb-1.5 px-0.5", children: "Document colors" }),
|
|
3914
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1 mb-2.5", children: extraDocColors.slice(0, 10).map((c) => /* @__PURE__ */ jsx(
|
|
3915
|
+
Swatch,
|
|
3916
|
+
{
|
|
3917
|
+
color: { label: c, value: c },
|
|
3918
|
+
isActive: normActive === normalizeHex(c),
|
|
3919
|
+
onSelect: applyColor
|
|
3920
|
+
},
|
|
3921
|
+
c
|
|
3922
|
+
)) }),
|
|
3923
|
+
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 dark:bg-gray-700 mb-2.5" })
|
|
3924
|
+
] }),
|
|
3925
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1 mb-3", children: PRESET_COLORS.map((c) => /* @__PURE__ */ jsx(
|
|
3926
|
+
Swatch,
|
|
3927
|
+
{
|
|
3928
|
+
color: c,
|
|
3929
|
+
isActive: normActive === normalizeHex(c.value),
|
|
3930
|
+
onSelect: applyColor
|
|
3931
|
+
},
|
|
3932
|
+
c.value
|
|
3933
|
+
)) }),
|
|
3934
|
+
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 dark:bg-gray-700 mb-2.5" }),
|
|
3935
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 dark:text-gray-500 mb-1.5 px-0.5", children: "Custom color" }),
|
|
3936
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3937
|
+
/* @__PURE__ */ jsx(
|
|
3938
|
+
"div",
|
|
3939
|
+
{
|
|
3940
|
+
className: "shrink-0 w-7 h-7 rounded border border-gray-300 dark:border-gray-600",
|
|
3941
|
+
style: { backgroundColor: hexInputToPreview(hexInput) }
|
|
3942
|
+
}
|
|
3943
|
+
),
|
|
3944
|
+
/* @__PURE__ */ jsxs(
|
|
3945
|
+
"div",
|
|
3946
|
+
{
|
|
3947
|
+
className: "flex flex-1 items-center border rounded overflow-hidden\n border-gray-300 dark:border-gray-600\n focus-within:ring-2 focus-within:ring-blue-500",
|
|
3948
|
+
children: [
|
|
3949
|
+
/* @__PURE__ */ jsx("span", { className: "pl-2 text-xs text-gray-400 select-none", children: "#" }),
|
|
3950
|
+
/* @__PURE__ */ jsx(
|
|
3951
|
+
"input",
|
|
3952
|
+
{
|
|
3953
|
+
type: "text",
|
|
3954
|
+
maxLength: 6,
|
|
3955
|
+
value: hexInput,
|
|
3956
|
+
onChange: (e) => {
|
|
3957
|
+
setHexInput(e.target.value.replace(/[^0-9a-fA-F]/g, ""));
|
|
3958
|
+
setHexError(false);
|
|
3959
|
+
},
|
|
3960
|
+
onKeyDown: (e) => {
|
|
3961
|
+
if (e.key === "Enter") {
|
|
3962
|
+
e.preventDefault();
|
|
3963
|
+
commitHexInput();
|
|
3964
|
+
}
|
|
3965
|
+
if (e.key === "Escape") setOpen(false);
|
|
3966
|
+
},
|
|
3967
|
+
placeholder: "e.g. ffff00",
|
|
3968
|
+
className: [
|
|
3969
|
+
"flex-1 px-1 py-1.5 text-xs bg-transparent outline-none font-mono",
|
|
3970
|
+
"text-gray-900 dark:text-gray-100",
|
|
3971
|
+
hexError ? "text-red-500" : ""
|
|
3972
|
+
].join(" "),
|
|
3973
|
+
"aria-label": "Hex colour value"
|
|
3974
|
+
}
|
|
3975
|
+
)
|
|
3976
|
+
]
|
|
3977
|
+
}
|
|
3978
|
+
),
|
|
3979
|
+
/* @__PURE__ */ jsx(
|
|
3980
|
+
"button",
|
|
3981
|
+
{
|
|
3982
|
+
type: "button",
|
|
3983
|
+
onMouseDown: (e) => {
|
|
3984
|
+
e.preventDefault();
|
|
3985
|
+
commitHexInput();
|
|
3986
|
+
},
|
|
3987
|
+
className: "shrink-0 px-2 py-1.5 text-xs bg-blue-600 text-white rounded\n hover:bg-blue-700 transition-colors",
|
|
3988
|
+
children: "\u2713"
|
|
3989
|
+
}
|
|
3990
|
+
)
|
|
3991
|
+
] }),
|
|
3992
|
+
hexError && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-red-500 mt-1 px-0.5", children: "Invalid hex colour" })
|
|
3993
|
+
]
|
|
3994
|
+
}
|
|
3995
|
+
),
|
|
3996
|
+
document.body
|
|
3997
|
+
)
|
|
3998
|
+
] });
|
|
3999
|
+
}
|
|
4000
|
+
function Swatch({
|
|
4001
|
+
color,
|
|
3932
4002
|
isActive,
|
|
3933
4003
|
onSelect
|
|
3934
4004
|
}) {
|
|
@@ -3948,7 +4018,7 @@ function Swatch({
|
|
|
3948
4018
|
"hover:scale-110 focus:outline-none",
|
|
3949
4019
|
"focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-blue-500",
|
|
3950
4020
|
isActive ? "ring-2 ring-offset-1 ring-blue-500 scale-105" : "",
|
|
3951
|
-
color.hasBorder ? "border border-gray-300 " : ""
|
|
4021
|
+
color.hasBorder ? "border border-gray-300 dark:border-gray-500" : ""
|
|
3952
4022
|
].join(" "),
|
|
3953
4023
|
style: { backgroundColor: color.value },
|
|
3954
4024
|
children: isActive && /* @__PURE__ */ jsx(CheckIcon4, { light: isLight(color.value) })
|
|
@@ -4071,11 +4141,15 @@ function TextColorDropdown({
|
|
|
4071
4141
|
const [lastColor, setLastColor] = useState(PRESET_COLORS2[0].value);
|
|
4072
4142
|
const [hexInput, setHexInput] = useState("");
|
|
4073
4143
|
const [hexError, setHexError] = useState(false);
|
|
4074
|
-
const
|
|
4144
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
4145
|
+
const chevronRef = useRef(null);
|
|
4146
|
+
const popupRef = useRef(null);
|
|
4075
4147
|
useEffect(() => {
|
|
4076
4148
|
if (!open) return;
|
|
4077
4149
|
const handler = (e) => {
|
|
4078
|
-
|
|
4150
|
+
var _a, _b;
|
|
4151
|
+
const target = e.target;
|
|
4152
|
+
if (!((_a = popupRef.current) == null ? void 0 : _a.contains(target)) && !((_b = chevronRef.current) == null ? void 0 : _b.contains(target)))
|
|
4079
4153
|
setOpen(false);
|
|
4080
4154
|
};
|
|
4081
4155
|
document.addEventListener("mousedown", handler);
|
|
@@ -4115,7 +4189,7 @@ function TextColorDropdown({
|
|
|
4115
4189
|
(c) => !PRESET_COLORS2.some((p) => normalizeHex2(p.value) === normalizeHex2(c))
|
|
4116
4190
|
);
|
|
4117
4191
|
const normActive = activeColor ? normalizeHex2(activeColor) : null;
|
|
4118
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
4192
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
4119
4193
|
/* @__PURE__ */ jsxs(
|
|
4120
4194
|
"button",
|
|
4121
4195
|
{
|
|
@@ -4125,7 +4199,7 @@ function TextColorDropdown({
|
|
|
4125
4199
|
e.preventDefault();
|
|
4126
4200
|
handleQuickApply();
|
|
4127
4201
|
},
|
|
4128
|
-
className: "flex flex-col items-center justify-center gap-0.5 w-8 h-8 rounded-l\n text-gray-700 \n hover:bg-gray-100 \n focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500\n transition-colors",
|
|
4202
|
+
className: "flex flex-col items-center justify-center gap-0.5 w-8 h-8 rounded-l\n text-gray-700 dark:text-gray-300\n hover:bg-gray-100 dark:hover:bg-gray-700\n focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500\n transition-colors",
|
|
4129
4203
|
children: [
|
|
4130
4204
|
/* @__PURE__ */ jsx(TextColorIcon, {}),
|
|
4131
4205
|
/* @__PURE__ */ jsx(
|
|
@@ -4141,129 +4215,139 @@ function TextColorDropdown({
|
|
|
4141
4215
|
/* @__PURE__ */ jsx(
|
|
4142
4216
|
"button",
|
|
4143
4217
|
{
|
|
4218
|
+
ref: chevronRef,
|
|
4144
4219
|
type: "button",
|
|
4145
4220
|
title: "More text colors",
|
|
4146
4221
|
"aria-haspopup": "listbox",
|
|
4147
4222
|
"aria-expanded": open,
|
|
4148
4223
|
onMouseDown: (e) => {
|
|
4149
4224
|
e.preventDefault();
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4225
|
+
if (open) {
|
|
4226
|
+
setOpen(false);
|
|
4227
|
+
return;
|
|
4228
|
+
}
|
|
4229
|
+
if (chevronRef.current) {
|
|
4230
|
+
const rect = chevronRef.current.getBoundingClientRect();
|
|
4231
|
+
setPopupPos({ top: rect.bottom + 4, left: rect.left - 190 });
|
|
4232
|
+
}
|
|
4233
|
+
setHexInput("");
|
|
4234
|
+
setHexError(false);
|
|
4235
|
+
setOpen(true);
|
|
4157
4236
|
},
|
|
4158
4237
|
className: [
|
|
4159
|
-
"flex items-center justify-center w-4 h-8 rounded-r border-l border-gray-200 ",
|
|
4238
|
+
"flex items-center justify-center w-4 h-8 rounded-r border-l border-gray-200 dark:border-gray-600",
|
|
4160
4239
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-blue-500",
|
|
4161
4240
|
"transition-colors",
|
|
4162
|
-
open ? "bg-gray-100
|
|
4241
|
+
open ? "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200" : "text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
4163
4242
|
].join(" "),
|
|
4164
4243
|
children: /* @__PURE__ */ jsx(ChevronDownIcon5, {})
|
|
4165
4244
|
}
|
|
4166
4245
|
),
|
|
4167
|
-
open &&
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
"
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
4246
|
+
open && createPortal(
|
|
4247
|
+
/* @__PURE__ */ jsxs(
|
|
4248
|
+
"div",
|
|
4249
|
+
{
|
|
4250
|
+
ref: popupRef,
|
|
4251
|
+
role: "dialog",
|
|
4252
|
+
"aria-label": "Text color",
|
|
4253
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, width: 208 },
|
|
4254
|
+
className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-xl p-3",
|
|
4255
|
+
children: [
|
|
4256
|
+
/* @__PURE__ */ jsxs(
|
|
4257
|
+
"button",
|
|
4258
|
+
{
|
|
4259
|
+
type: "button",
|
|
4260
|
+
onMouseDown: (e) => {
|
|
4261
|
+
e.preventDefault();
|
|
4262
|
+
applyColor(null);
|
|
4263
|
+
},
|
|
4264
|
+
className: "flex items-center gap-2 w-full px-2 py-1.5 mb-2.5 text-xs font-medium\n text-gray-600 dark:text-gray-300\n rounded hover:bg-gray-100 dark:hover:bg-gray-700\n transition-colors",
|
|
4265
|
+
children: [
|
|
4266
|
+
/* @__PURE__ */ jsx(RemoveColorIcon2, {}),
|
|
4267
|
+
"Remove color"
|
|
4268
|
+
]
|
|
4269
|
+
}
|
|
4270
|
+
),
|
|
4271
|
+
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 dark:bg-gray-700 mb-2.5" }),
|
|
4272
|
+
extraDocColors.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4273
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 dark:text-gray-500 mb-1.5 px-0.5", children: "Document colors" }),
|
|
4274
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1 mb-2.5", children: extraDocColors.slice(0, 10).map((c) => /* @__PURE__ */ jsx(
|
|
4275
|
+
Swatch2,
|
|
4276
|
+
{
|
|
4277
|
+
color: { label: c, value: c },
|
|
4278
|
+
isActive: normActive === normalizeHex2(c),
|
|
4279
|
+
onSelect: applyColor
|
|
4280
|
+
},
|
|
4281
|
+
c
|
|
4282
|
+
)) }),
|
|
4283
|
+
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 dark:bg-gray-700 mb-2.5" })
|
|
4284
|
+
] }),
|
|
4285
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-5 gap-1 mb-3", children: PRESET_COLORS2.map((c) => /* @__PURE__ */ jsx(
|
|
4193
4286
|
Swatch2,
|
|
4194
4287
|
{
|
|
4195
|
-
color:
|
|
4196
|
-
isActive: normActive === normalizeHex2(c),
|
|
4288
|
+
color: c,
|
|
4289
|
+
isActive: normActive === normalizeHex2(c.value),
|
|
4197
4290
|
onSelect: applyColor
|
|
4198
4291
|
},
|
|
4199
|
-
c
|
|
4292
|
+
c.value
|
|
4200
4293
|
)) }),
|
|
4201
|
-
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
Swatch2,
|
|
4205
|
-
{
|
|
4206
|
-
color: c,
|
|
4207
|
-
isActive: normActive === normalizeHex2(c.value),
|
|
4208
|
-
onSelect: applyColor
|
|
4209
|
-
},
|
|
4210
|
-
c.value
|
|
4211
|
-
)) }),
|
|
4212
|
-
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 mb-2.5" }),
|
|
4213
|
-
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 mb-1.5 px-0.5", children: "Custom color" }),
|
|
4214
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
4215
|
-
/* @__PURE__ */ jsx(
|
|
4216
|
-
"div",
|
|
4217
|
-
{
|
|
4218
|
-
className: "shrink-0 w-7 h-7 rounded border border-gray-300 ",
|
|
4219
|
-
style: { backgroundColor: hexInputToPreview2(hexInput) }
|
|
4220
|
-
}
|
|
4221
|
-
),
|
|
4222
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center border rounded overflow-hidden\n border-gray-300 \n focus-within:ring-2 focus-within:ring-blue-500", children: [
|
|
4223
|
-
/* @__PURE__ */ jsx("span", { className: "pl-2 text-xs text-gray-400 select-none", children: "#" }),
|
|
4294
|
+
/* @__PURE__ */ jsx("div", { className: "h-px bg-gray-100 dark:bg-gray-700 mb-2.5" }),
|
|
4295
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-gray-400 dark:text-gray-500 mb-1.5 px-0.5", children: "Custom color" }),
|
|
4296
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
4224
4297
|
/* @__PURE__ */ jsx(
|
|
4225
|
-
"
|
|
4298
|
+
"div",
|
|
4226
4299
|
{
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4300
|
+
className: "shrink-0 w-7 h-7 rounded border border-gray-300 dark:border-gray-600",
|
|
4301
|
+
style: { backgroundColor: hexInputToPreview2(hexInput) }
|
|
4302
|
+
}
|
|
4303
|
+
),
|
|
4304
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center border rounded overflow-hidden\n border-gray-300 dark:border-gray-600\n focus-within:ring-2 focus-within:ring-blue-500", children: [
|
|
4305
|
+
/* @__PURE__ */ jsx("span", { className: "pl-2 text-xs text-gray-400 select-none", children: "#" }),
|
|
4306
|
+
/* @__PURE__ */ jsx(
|
|
4307
|
+
"input",
|
|
4308
|
+
{
|
|
4309
|
+
type: "text",
|
|
4310
|
+
maxLength: 6,
|
|
4311
|
+
value: hexInput,
|
|
4312
|
+
onChange: (e) => {
|
|
4313
|
+
setHexInput(e.target.value.replace(/[^0-9a-fA-F]/g, ""));
|
|
4314
|
+
setHexError(false);
|
|
4315
|
+
},
|
|
4316
|
+
onKeyDown: (e) => {
|
|
4317
|
+
if (e.key === "Enter") {
|
|
4318
|
+
e.preventDefault();
|
|
4319
|
+
commitHexInput();
|
|
4320
|
+
}
|
|
4321
|
+
if (e.key === "Escape") setOpen(false);
|
|
4322
|
+
},
|
|
4323
|
+
placeholder: "e.g. 000000",
|
|
4324
|
+
className: [
|
|
4325
|
+
"flex-1 px-1 py-1.5 text-xs bg-transparent outline-none font-mono",
|
|
4326
|
+
"text-gray-900 dark:text-gray-100",
|
|
4327
|
+
hexError ? "text-red-500" : ""
|
|
4328
|
+
].join(" "),
|
|
4329
|
+
"aria-label": "Hex colour value"
|
|
4330
|
+
}
|
|
4331
|
+
)
|
|
4332
|
+
] }),
|
|
4333
|
+
/* @__PURE__ */ jsx(
|
|
4334
|
+
"button",
|
|
4335
|
+
{
|
|
4336
|
+
type: "button",
|
|
4337
|
+
onMouseDown: (e) => {
|
|
4338
|
+
e.preventDefault();
|
|
4339
|
+
commitHexInput();
|
|
4240
4340
|
},
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
"flex-1 px-1 py-1.5 text-xs bg-transparent outline-none font-mono",
|
|
4244
|
-
"text-gray-900 ",
|
|
4245
|
-
hexError ? "text-red-500" : ""
|
|
4246
|
-
].join(" "),
|
|
4247
|
-
"aria-label": "Hex colour value"
|
|
4341
|
+
className: "shrink-0 px-2 py-1.5 text-xs bg-blue-600 text-white rounded\n hover:bg-blue-700 transition-colors",
|
|
4342
|
+
children: "\u2713"
|
|
4248
4343
|
}
|
|
4249
4344
|
)
|
|
4250
4345
|
] }),
|
|
4251
|
-
/* @__PURE__ */ jsx(
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
e.preventDefault();
|
|
4257
|
-
commitHexInput();
|
|
4258
|
-
},
|
|
4259
|
-
className: "shrink-0 px-2 py-1.5 text-xs bg-blue-600 text-white rounded\n hover:bg-blue-700 transition-colors",
|
|
4260
|
-
children: "\u2713"
|
|
4261
|
-
}
|
|
4262
|
-
)
|
|
4263
|
-
] }),
|
|
4264
|
-
hexError && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-red-500 mt-1 px-0.5", children: "Invalid hex colour" })
|
|
4265
|
-
]
|
|
4266
|
-
}
|
|
4346
|
+
hexError && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-red-500 mt-1 px-0.5", children: "Invalid hex colour" })
|
|
4347
|
+
]
|
|
4348
|
+
}
|
|
4349
|
+
),
|
|
4350
|
+
document.body
|
|
4267
4351
|
)
|
|
4268
4352
|
] });
|
|
4269
4353
|
}
|
|
@@ -4288,7 +4372,7 @@ function Swatch2({
|
|
|
4288
4372
|
"hover:scale-110 focus:outline-none",
|
|
4289
4373
|
"focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-blue-500",
|
|
4290
4374
|
isActive ? "ring-2 ring-offset-1 ring-blue-500 scale-105" : "",
|
|
4291
|
-
color.hasBorder ? "border border-gray-300 " : ""
|
|
4375
|
+
color.hasBorder ? "border border-gray-300 dark:border-gray-500" : ""
|
|
4292
4376
|
].join(" "),
|
|
4293
4377
|
style: { backgroundColor: color.value },
|
|
4294
4378
|
children: isActive && /* @__PURE__ */ jsx(CheckIcon5, { light: isLight2(color.value) })
|
|
@@ -5820,7 +5904,9 @@ function CodeBlockButton({ engine }) {
|
|
|
5820
5904
|
const activeBlock = getActiveBlockType(state.doc, state.selection);
|
|
5821
5905
|
const isActive = activeBlock === "code_block";
|
|
5822
5906
|
const [open, setOpen] = useState(false);
|
|
5823
|
-
const
|
|
5907
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
5908
|
+
const chevronRef = useRef(null);
|
|
5909
|
+
const popupRef = useRef(null);
|
|
5824
5910
|
const currentLang = (() => {
|
|
5825
5911
|
var _a2;
|
|
5826
5912
|
if (!isActive || !state.selection) return "plaintext";
|
|
@@ -5833,9 +5919,9 @@ function CodeBlockButton({ engine }) {
|
|
|
5833
5919
|
useEffect(() => {
|
|
5834
5920
|
if (!open) return;
|
|
5835
5921
|
const handler = (e) => {
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5922
|
+
var _a2, _b;
|
|
5923
|
+
const target = e.target;
|
|
5924
|
+
if (!((_a2 = popupRef.current) == null ? void 0 : _a2.contains(target)) && !((_b = chevronRef.current) == null ? void 0 : _b.contains(target))) closeDropdown();
|
|
5839
5925
|
};
|
|
5840
5926
|
document.addEventListener("mousedown", handler);
|
|
5841
5927
|
return () => document.removeEventListener("mousedown", handler);
|
|
@@ -5862,7 +5948,7 @@ function CodeBlockButton({ engine }) {
|
|
|
5862
5948
|
setOpen(false);
|
|
5863
5949
|
};
|
|
5864
5950
|
const activeLang = LANGUAGES.find((l) => l.value === currentLang);
|
|
5865
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
5951
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
5866
5952
|
/* @__PURE__ */ jsx(
|
|
5867
5953
|
"button",
|
|
5868
5954
|
{
|
|
@@ -5874,7 +5960,7 @@ function CodeBlockButton({ engine }) {
|
|
|
5874
5960
|
},
|
|
5875
5961
|
className: [
|
|
5876
5962
|
"flex items-center justify-center w-8 h-8 rounded-l text-sm transition-colors",
|
|
5877
|
-
isActive ? "bg-blue-100
|
|
5963
|
+
isActive ? "bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
5878
5964
|
].join(" "),
|
|
5879
5965
|
children: /* @__PURE__ */ jsx(CodeBlockIcon, {})
|
|
5880
5966
|
}
|
|
@@ -5882,55 +5968,69 @@ function CodeBlockButton({ engine }) {
|
|
|
5882
5968
|
/* @__PURE__ */ jsx(
|
|
5883
5969
|
"button",
|
|
5884
5970
|
{
|
|
5971
|
+
ref: chevronRef,
|
|
5885
5972
|
type: "button",
|
|
5886
5973
|
title: isActive ? `Language: ${(_a = activeLang == null ? void 0 : activeLang.label) != null ? _a : "Plain text"}` : "Select language",
|
|
5887
5974
|
"aria-haspopup": "listbox",
|
|
5888
5975
|
"aria-expanded": open,
|
|
5889
5976
|
onMouseDown: (e) => {
|
|
5890
5977
|
e.preventDefault();
|
|
5891
|
-
|
|
5978
|
+
if (open) {
|
|
5979
|
+
closeDropdown();
|
|
5980
|
+
return;
|
|
5981
|
+
}
|
|
5982
|
+
if (chevronRef.current) {
|
|
5983
|
+
const rect = chevronRef.current.getBoundingClientRect();
|
|
5984
|
+
setPopupPos({ top: rect.bottom + 4, left: rect.left - 160 });
|
|
5985
|
+
}
|
|
5986
|
+
setOpen(true);
|
|
5892
5987
|
},
|
|
5893
5988
|
className: [
|
|
5894
|
-
"flex items-center justify-center w-4 h-8 rounded-r border-l border-gray-200
|
|
5895
|
-
open ? "bg-gray-100
|
|
5989
|
+
"flex items-center justify-center w-4 h-8 rounded-r border-l border-gray-200 dark:border-gray-600 transition-colors",
|
|
5990
|
+
open ? "bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200" : "text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
5896
5991
|
].join(" "),
|
|
5897
5992
|
children: /* @__PURE__ */ jsx(ChevronIcon, {})
|
|
5898
5993
|
}
|
|
5899
5994
|
),
|
|
5900
|
-
open &&
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
|
|
5910
|
-
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5995
|
+
open && createPortal(
|
|
5996
|
+
/* @__PURE__ */ jsxs(
|
|
5997
|
+
"div",
|
|
5998
|
+
{
|
|
5999
|
+
ref: popupRef,
|
|
6000
|
+
role: "listbox",
|
|
6001
|
+
"aria-label": "Code block language",
|
|
6002
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, width: 176, maxHeight: 288, overflowY: "auto" },
|
|
6003
|
+
className: "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-xl py-1",
|
|
6004
|
+
children: [
|
|
6005
|
+
/* @__PURE__ */ jsx("p", { className: "px-3 py-1.5 text-[10px] font-semibold uppercase tracking-widest text-gray-400 dark:text-gray-500", children: "Language" }),
|
|
6006
|
+
LANGUAGES.map((lang) => {
|
|
6007
|
+
const isSelected = isActive && currentLang === lang.value;
|
|
6008
|
+
return /* @__PURE__ */ jsxs(
|
|
6009
|
+
"button",
|
|
6010
|
+
{
|
|
6011
|
+
type: "button",
|
|
6012
|
+
role: "option",
|
|
6013
|
+
"aria-selected": isSelected,
|
|
6014
|
+
onMouseDown: (e) => {
|
|
6015
|
+
e.preventDefault();
|
|
6016
|
+
handleSelectLanguage(lang.value);
|
|
6017
|
+
},
|
|
6018
|
+
className: [
|
|
6019
|
+
"w-full text-left px-3 py-1.5 text-sm flex items-center gap-2 transition-colors",
|
|
6020
|
+
isSelected ? "bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 font-medium" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
6021
|
+
].join(" "),
|
|
6022
|
+
children: [
|
|
6023
|
+
isSelected && /* @__PURE__ */ jsx("svg", { className: "w-3 h-3 shrink-0", viewBox: "0 0 12 12", fill: "currentColor", children: /* @__PURE__ */ jsx("polyline", { points: "1 6 4.5 9.5 11 2.5", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
6024
|
+
/* @__PURE__ */ jsx("span", { className: isSelected ? "" : "ml-5", children: lang.label })
|
|
6025
|
+
]
|
|
5919
6026
|
},
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
]
|
|
5928
|
-
},
|
|
5929
|
-
lang.value
|
|
5930
|
-
);
|
|
5931
|
-
})
|
|
5932
|
-
]
|
|
5933
|
-
}
|
|
6027
|
+
lang.value
|
|
6028
|
+
);
|
|
6029
|
+
})
|
|
6030
|
+
]
|
|
6031
|
+
}
|
|
6032
|
+
),
|
|
6033
|
+
document.body
|
|
5934
6034
|
)
|
|
5935
6035
|
] });
|
|
5936
6036
|
}
|
|
@@ -6260,12 +6360,16 @@ function HeadingDropdown({
|
|
|
6260
6360
|
}) {
|
|
6261
6361
|
var _a;
|
|
6262
6362
|
const [open, setOpen] = useState(false);
|
|
6263
|
-
const
|
|
6363
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
6364
|
+
const buttonRef = useRef(null);
|
|
6365
|
+
const popupRef = useRef(null);
|
|
6264
6366
|
const run = (command) => command(engine);
|
|
6265
6367
|
useEffect(() => {
|
|
6266
6368
|
if (!open) return;
|
|
6267
6369
|
const handler = (e) => {
|
|
6268
|
-
|
|
6370
|
+
var _a2, _b;
|
|
6371
|
+
const target = e.target;
|
|
6372
|
+
if (!((_a2 = popupRef.current) == null ? void 0 : _a2.contains(target)) && !((_b = buttonRef.current) == null ? void 0 : _b.contains(target)))
|
|
6269
6373
|
setOpen(false);
|
|
6270
6374
|
};
|
|
6271
6375
|
document.addEventListener("mousedown", handler);
|
|
@@ -6283,14 +6387,23 @@ function HeadingDropdown({
|
|
|
6283
6387
|
code_block: "Code"
|
|
6284
6388
|
};
|
|
6285
6389
|
const label = (_a = BLOCK_LABELS[activeBlock]) != null ? _a : "Paragraph";
|
|
6286
|
-
return /* @__PURE__ */ jsxs(
|
|
6390
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6287
6391
|
/* @__PURE__ */ jsxs(
|
|
6288
6392
|
"button",
|
|
6289
6393
|
{
|
|
6394
|
+
ref: buttonRef,
|
|
6290
6395
|
type: "button",
|
|
6291
6396
|
onMouseDown: (e) => {
|
|
6292
6397
|
e.preventDefault();
|
|
6293
|
-
|
|
6398
|
+
if (open) {
|
|
6399
|
+
setOpen(false);
|
|
6400
|
+
return;
|
|
6401
|
+
}
|
|
6402
|
+
if (buttonRef.current) {
|
|
6403
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
6404
|
+
setPopupPos({ top: rect.bottom + 2, left: rect.left });
|
|
6405
|
+
}
|
|
6406
|
+
setOpen(true);
|
|
6294
6407
|
},
|
|
6295
6408
|
className: "flex items-center gap-1 px-2 h-8 rounded text-sm font-medium text-gray-700 hover:bg-gray-100 cursor-pointer",
|
|
6296
6409
|
children: [
|
|
@@ -6299,7 +6412,7 @@ function HeadingDropdown({
|
|
|
6299
6412
|
]
|
|
6300
6413
|
}
|
|
6301
6414
|
),
|
|
6302
|
-
open && /* @__PURE__ */ jsx("div", {
|
|
6415
|
+
open && createPortal(/* @__PURE__ */ jsx("div", { ref: popupRef, style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, width: 160 }, className: "bg-white border border-gray-200 rounded shadow-lg", children: [
|
|
6303
6416
|
{
|
|
6304
6417
|
label: "Paragraph",
|
|
6305
6418
|
cmd: setParagraph,
|
|
@@ -6351,7 +6464,7 @@ function HeadingDropdown({
|
|
|
6351
6464
|
children: label2
|
|
6352
6465
|
},
|
|
6353
6466
|
label2
|
|
6354
|
-
)) })
|
|
6467
|
+
)) }), document.body)
|
|
6355
6468
|
] });
|
|
6356
6469
|
}
|
|
6357
6470
|
function LinkButton({
|
|
@@ -6366,10 +6479,16 @@ function LinkButton({
|
|
|
6366
6479
|
const [editMode, setEditMode] = useState(false);
|
|
6367
6480
|
const [url, setUrl] = useState("");
|
|
6368
6481
|
const [displayText, setDisplayText] = useState("");
|
|
6482
|
+
const [popupPos, setPopupPos] = useState({ top: 0, left: 0 });
|
|
6369
6483
|
const containerRef = useRef(null);
|
|
6484
|
+
const popupRef = useRef(null);
|
|
6370
6485
|
const urlInputRef = useRef(null);
|
|
6371
6486
|
const textInputRef = useRef(null);
|
|
6372
6487
|
const openPopup = () => {
|
|
6488
|
+
if (containerRef.current) {
|
|
6489
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
6490
|
+
setPopupPos({ top: rect.bottom + 4, left: rect.left });
|
|
6491
|
+
}
|
|
6373
6492
|
if (isActive) {
|
|
6374
6493
|
setUrl(activeHref != null ? activeHref : "");
|
|
6375
6494
|
setDisplayText("");
|
|
@@ -6401,7 +6520,9 @@ function LinkButton({
|
|
|
6401
6520
|
useEffect(() => {
|
|
6402
6521
|
if (!open) return;
|
|
6403
6522
|
const handler = (e) => {
|
|
6404
|
-
|
|
6523
|
+
var _a, _b;
|
|
6524
|
+
const target = e.target;
|
|
6525
|
+
if (!((_a = popupRef.current) == null ? void 0 : _a.contains(target)) && !((_b = containerRef.current) == null ? void 0 : _b.contains(target))) {
|
|
6405
6526
|
closePopup();
|
|
6406
6527
|
}
|
|
6407
6528
|
};
|
|
@@ -6441,7 +6562,7 @@ function LinkButton({
|
|
|
6441
6562
|
setEditMode(true);
|
|
6442
6563
|
};
|
|
6443
6564
|
const showTextInput = !hasTextSelected && !isActive;
|
|
6444
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef,
|
|
6565
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, children: [
|
|
6445
6566
|
/* @__PURE__ */ jsx(
|
|
6446
6567
|
ToolbarButton,
|
|
6447
6568
|
{
|
|
@@ -6452,115 +6573,43 @@ function LinkButton({
|
|
|
6452
6573
|
icon: /* @__PURE__ */ jsx(LinkIcon, {})
|
|
6453
6574
|
}
|
|
6454
6575
|
),
|
|
6455
|
-
open &&
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
href: activeHref != null ? activeHref : "#",
|
|
6468
|
-
target: "_blank",
|
|
6469
|
-
rel: "noopener noreferrer",
|
|
6470
|
-
className: "flex-1 text-sm text-blue-600 hover:underline truncate",
|
|
6471
|
-
title: activeHref != null ? activeHref : "",
|
|
6472
|
-
children: activeHref
|
|
6473
|
-
}
|
|
6474
|
-
),
|
|
6475
|
-
/* @__PURE__ */ jsx(
|
|
6476
|
-
"button",
|
|
6477
|
-
{
|
|
6478
|
-
type: "button",
|
|
6479
|
-
onMouseDown: (e) => {
|
|
6480
|
-
e.preventDefault();
|
|
6481
|
-
handleStartEdit();
|
|
6482
|
-
},
|
|
6483
|
-
className: "shrink-0 text-xs text-gray-500 hover:text-gray-700 px-2 py-1 rounded hover:bg-gray-100 ",
|
|
6484
|
-
"aria-label": "Edit link",
|
|
6485
|
-
children: "Edit"
|
|
6486
|
-
}
|
|
6487
|
-
),
|
|
6488
|
-
/* @__PURE__ */ jsx(
|
|
6489
|
-
"button",
|
|
6490
|
-
{
|
|
6491
|
-
type: "button",
|
|
6492
|
-
onMouseDown: (e) => {
|
|
6493
|
-
e.preventDefault();
|
|
6494
|
-
handleRemove();
|
|
6495
|
-
},
|
|
6496
|
-
className: "shrink-0 text-xs text-red-500 hover:text-red-700 px-2 py-1 rounded hover:bg-red-50 ",
|
|
6497
|
-
"aria-label": "Remove link",
|
|
6498
|
-
children: "Remove"
|
|
6499
|
-
}
|
|
6500
|
-
)
|
|
6501
|
-
] })
|
|
6502
|
-
] }) : (
|
|
6503
|
-
/* ── Edit / Insert mode ── */
|
|
6504
|
-
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6505
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-gray-400 mb-3 uppercase tracking-wide", children: isActive ? "Edit link" : "Insert link" }),
|
|
6506
|
-
showTextInput && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
|
|
6507
|
-
/* @__PURE__ */ jsx("label", { className: "block text-xs text-gray-600 mb-1", children: "Display text" }),
|
|
6508
|
-
/* @__PURE__ */ jsx(
|
|
6509
|
-
"input",
|
|
6510
|
-
{
|
|
6511
|
-
ref: textInputRef,
|
|
6512
|
-
type: "text",
|
|
6513
|
-
value: displayText,
|
|
6514
|
-
onChange: (e) => setDisplayText(e.target.value),
|
|
6515
|
-
onKeyDown: (e) => {
|
|
6516
|
-
var _a;
|
|
6517
|
-
if (e.key === "Enter") {
|
|
6518
|
-
e.preventDefault();
|
|
6519
|
-
(_a = urlInputRef.current) == null ? void 0 : _a.focus();
|
|
6520
|
-
}
|
|
6521
|
-
if (e.key === "Escape") closePopup();
|
|
6522
|
-
},
|
|
6523
|
-
placeholder: "Link text",
|
|
6524
|
-
className: "w-full border border-gray-300 rounded px-2 py-1.5 text-sm bg-white text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
6525
|
-
}
|
|
6526
|
-
)
|
|
6527
|
-
] }),
|
|
6528
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
6529
|
-
/* @__PURE__ */ jsx("label", { className: "block text-xs text-gray-600 mb-1", children: "URL" }),
|
|
6576
|
+
open && createPortal(
|
|
6577
|
+
/* @__PURE__ */ jsx(
|
|
6578
|
+
"div",
|
|
6579
|
+
{
|
|
6580
|
+
ref: popupRef,
|
|
6581
|
+
role: "dialog",
|
|
6582
|
+
"aria-label": "Link editor",
|
|
6583
|
+
style: { position: "fixed", top: popupPos.top, left: popupPos.left, zIndex: 9999, width: 320 },
|
|
6584
|
+
className: "bg-white border border-gray-200 rounded-lg shadow-xl p-3",
|
|
6585
|
+
children: isActive && !editMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6586
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-gray-400 mb-2 uppercase tracking-wide", children: "Link" }),
|
|
6587
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
6530
6588
|
/* @__PURE__ */ jsx(
|
|
6531
|
-
"
|
|
6589
|
+
"a",
|
|
6532
6590
|
{
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
e.preventDefault();
|
|
6540
|
-
handleApply();
|
|
6541
|
-
}
|
|
6542
|
-
if (e.key === "Escape") closePopup();
|
|
6543
|
-
},
|
|
6544
|
-
placeholder: "https://example.com",
|
|
6545
|
-
className: "w-full border border-gray-300 rounded px-2 py-1.5 text-sm bg-white text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
6591
|
+
href: activeHref != null ? activeHref : "#",
|
|
6592
|
+
target: "_blank",
|
|
6593
|
+
rel: "noopener noreferrer",
|
|
6594
|
+
className: "flex-1 text-sm text-blue-600 hover:underline truncate",
|
|
6595
|
+
title: activeHref != null ? activeHref : "",
|
|
6596
|
+
children: activeHref
|
|
6546
6597
|
}
|
|
6547
|
-
)
|
|
6548
|
-
] }),
|
|
6549
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6598
|
+
),
|
|
6550
6599
|
/* @__PURE__ */ jsx(
|
|
6551
6600
|
"button",
|
|
6552
6601
|
{
|
|
6553
6602
|
type: "button",
|
|
6554
6603
|
onMouseDown: (e) => {
|
|
6555
6604
|
e.preventDefault();
|
|
6556
|
-
|
|
6605
|
+
handleStartEdit();
|
|
6557
6606
|
},
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
children:
|
|
6607
|
+
className: "shrink-0 text-xs text-gray-500 hover:text-gray-700 px-2 py-1 rounded hover:bg-gray-100 ",
|
|
6608
|
+
"aria-label": "Edit link",
|
|
6609
|
+
children: "Edit"
|
|
6561
6610
|
}
|
|
6562
6611
|
),
|
|
6563
|
-
|
|
6612
|
+
/* @__PURE__ */ jsx(
|
|
6564
6613
|
"button",
|
|
6565
6614
|
{
|
|
6566
6615
|
type: "button",
|
|
@@ -6568,27 +6617,104 @@ function LinkButton({
|
|
|
6568
6617
|
e.preventDefault();
|
|
6569
6618
|
handleRemove();
|
|
6570
6619
|
},
|
|
6571
|
-
className: "
|
|
6620
|
+
className: "shrink-0 text-xs text-red-500 hover:text-red-700 px-2 py-1 rounded hover:bg-red-50 ",
|
|
6621
|
+
"aria-label": "Remove link",
|
|
6572
6622
|
children: "Remove"
|
|
6573
6623
|
}
|
|
6574
|
-
),
|
|
6575
|
-
/* @__PURE__ */ jsx(
|
|
6576
|
-
"button",
|
|
6577
|
-
{
|
|
6578
|
-
type: "button",
|
|
6579
|
-
onMouseDown: (e) => {
|
|
6580
|
-
e.preventDefault();
|
|
6581
|
-
closePopup();
|
|
6582
|
-
},
|
|
6583
|
-
className: "px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 ",
|
|
6584
|
-
"aria-label": "Cancel",
|
|
6585
|
-
children: "\u2715"
|
|
6586
|
-
}
|
|
6587
6624
|
)
|
|
6588
6625
|
] })
|
|
6589
|
-
] })
|
|
6590
|
-
|
|
6591
|
-
|
|
6626
|
+
] }) : (
|
|
6627
|
+
/* ── Edit / Insert mode ── */
|
|
6628
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6629
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium text-gray-400 mb-3 uppercase tracking-wide", children: isActive ? "Edit link" : "Insert link" }),
|
|
6630
|
+
showTextInput && /* @__PURE__ */ jsxs("div", { className: "mb-2", children: [
|
|
6631
|
+
/* @__PURE__ */ jsx("label", { className: "block text-xs text-gray-600 mb-1", children: "Display text" }),
|
|
6632
|
+
/* @__PURE__ */ jsx(
|
|
6633
|
+
"input",
|
|
6634
|
+
{
|
|
6635
|
+
ref: textInputRef,
|
|
6636
|
+
type: "text",
|
|
6637
|
+
value: displayText,
|
|
6638
|
+
onChange: (e) => setDisplayText(e.target.value),
|
|
6639
|
+
onKeyDown: (e) => {
|
|
6640
|
+
var _a;
|
|
6641
|
+
if (e.key === "Enter") {
|
|
6642
|
+
e.preventDefault();
|
|
6643
|
+
(_a = urlInputRef.current) == null ? void 0 : _a.focus();
|
|
6644
|
+
}
|
|
6645
|
+
if (e.key === "Escape") closePopup();
|
|
6646
|
+
},
|
|
6647
|
+
placeholder: "Link text",
|
|
6648
|
+
className: "w-full border border-gray-300 rounded px-2 py-1.5 text-sm bg-white text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
6649
|
+
}
|
|
6650
|
+
)
|
|
6651
|
+
] }),
|
|
6652
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3", children: [
|
|
6653
|
+
/* @__PURE__ */ jsx("label", { className: "block text-xs text-gray-600 mb-1", children: "URL" }),
|
|
6654
|
+
/* @__PURE__ */ jsx(
|
|
6655
|
+
"input",
|
|
6656
|
+
{
|
|
6657
|
+
ref: urlInputRef,
|
|
6658
|
+
type: "url",
|
|
6659
|
+
value: url,
|
|
6660
|
+
onChange: (e) => setUrl(e.target.value),
|
|
6661
|
+
onKeyDown: (e) => {
|
|
6662
|
+
if (e.key === "Enter") {
|
|
6663
|
+
e.preventDefault();
|
|
6664
|
+
handleApply();
|
|
6665
|
+
}
|
|
6666
|
+
if (e.key === "Escape") closePopup();
|
|
6667
|
+
},
|
|
6668
|
+
placeholder: "https://example.com",
|
|
6669
|
+
className: "w-full border border-gray-300 rounded px-2 py-1.5 text-sm bg-white text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
6670
|
+
}
|
|
6671
|
+
)
|
|
6672
|
+
] }),
|
|
6673
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
6674
|
+
/* @__PURE__ */ jsx(
|
|
6675
|
+
"button",
|
|
6676
|
+
{
|
|
6677
|
+
type: "button",
|
|
6678
|
+
onMouseDown: (e) => {
|
|
6679
|
+
e.preventDefault();
|
|
6680
|
+
handleApply();
|
|
6681
|
+
},
|
|
6682
|
+
disabled: !url.trim() || showTextInput && !displayText.trim() && !hasTextSelected && !isActive,
|
|
6683
|
+
className: "flex-1 px-3 py-1.5 bg-blue-600 text-white text-sm rounded hover:bg-blue-700 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
6684
|
+
children: isActive ? "Update" : "Insert"
|
|
6685
|
+
}
|
|
6686
|
+
),
|
|
6687
|
+
isActive && /* @__PURE__ */ jsx(
|
|
6688
|
+
"button",
|
|
6689
|
+
{
|
|
6690
|
+
type: "button",
|
|
6691
|
+
onMouseDown: (e) => {
|
|
6692
|
+
e.preventDefault();
|
|
6693
|
+
handleRemove();
|
|
6694
|
+
},
|
|
6695
|
+
className: "px-3 py-1.5 text-sm text-red-600 border border-red-200 rounded hover:bg-red-50 ",
|
|
6696
|
+
children: "Remove"
|
|
6697
|
+
}
|
|
6698
|
+
),
|
|
6699
|
+
/* @__PURE__ */ jsx(
|
|
6700
|
+
"button",
|
|
6701
|
+
{
|
|
6702
|
+
type: "button",
|
|
6703
|
+
onMouseDown: (e) => {
|
|
6704
|
+
e.preventDefault();
|
|
6705
|
+
closePopup();
|
|
6706
|
+
},
|
|
6707
|
+
className: "px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 ",
|
|
6708
|
+
"aria-label": "Cancel",
|
|
6709
|
+
children: "\u2715"
|
|
6710
|
+
}
|
|
6711
|
+
)
|
|
6712
|
+
] })
|
|
6713
|
+
] })
|
|
6714
|
+
)
|
|
6715
|
+
}
|
|
6716
|
+
),
|
|
6717
|
+
document.body
|
|
6592
6718
|
)
|
|
6593
6719
|
] });
|
|
6594
6720
|
}
|
|
@@ -8627,6 +8753,53 @@ function prettyPrintHTML(html) {
|
|
|
8627
8753
|
}
|
|
8628
8754
|
|
|
8629
8755
|
// src/editor/table/TablePlugin.ts
|
|
8756
|
+
function getCellDOMElement(cellPathJson) {
|
|
8757
|
+
return document.querySelector(`[data-block-path='${cellPathJson}']`);
|
|
8758
|
+
}
|
|
8759
|
+
function isCaretAtContainerStart(container) {
|
|
8760
|
+
const sel = window.getSelection();
|
|
8761
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;
|
|
8762
|
+
const range = sel.getRangeAt(0);
|
|
8763
|
+
if (range.startOffset !== 0) return false;
|
|
8764
|
+
let node = range.startContainer;
|
|
8765
|
+
while (node && node !== container) {
|
|
8766
|
+
if (node.previousSibling) return false;
|
|
8767
|
+
node = node.parentNode;
|
|
8768
|
+
}
|
|
8769
|
+
return node === container;
|
|
8770
|
+
}
|
|
8771
|
+
function isCaretAtContainerEnd(container) {
|
|
8772
|
+
var _a, _b;
|
|
8773
|
+
const sel = window.getSelection();
|
|
8774
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;
|
|
8775
|
+
const range = sel.getRangeAt(0);
|
|
8776
|
+
const endNode = range.endContainer;
|
|
8777
|
+
const endOffset = range.endOffset;
|
|
8778
|
+
const len = endNode.nodeType === Node.TEXT_NODE ? (_b = (_a = endNode.textContent) == null ? void 0 : _a.length) != null ? _b : 0 : endNode.childNodes.length;
|
|
8779
|
+
if (endOffset !== len) return false;
|
|
8780
|
+
let node = endNode;
|
|
8781
|
+
while (node && node !== container) {
|
|
8782
|
+
if (node.nextSibling) return false;
|
|
8783
|
+
node = node.parentNode;
|
|
8784
|
+
}
|
|
8785
|
+
return node === container;
|
|
8786
|
+
}
|
|
8787
|
+
function isCaretOnEdgeLine(container, direction) {
|
|
8788
|
+
const sel = window.getSelection();
|
|
8789
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return false;
|
|
8790
|
+
const caretRange = sel.getRangeAt(0).cloneRange();
|
|
8791
|
+
caretRange.collapse(true);
|
|
8792
|
+
const caretRects = caretRange.getClientRects();
|
|
8793
|
+
if (!caretRects.length) return true;
|
|
8794
|
+
const caretRect = caretRects[0];
|
|
8795
|
+
const containerRect = container.getBoundingClientRect();
|
|
8796
|
+
const lineHeight = parseFloat(getComputedStyle(container).lineHeight) || 20;
|
|
8797
|
+
if (direction === "up") {
|
|
8798
|
+
return caretRect.top < containerRect.top + lineHeight;
|
|
8799
|
+
} else {
|
|
8800
|
+
return caretRect.bottom > containerRect.bottom - lineHeight;
|
|
8801
|
+
}
|
|
8802
|
+
}
|
|
8630
8803
|
var TablePlugin = {
|
|
8631
8804
|
name: "table",
|
|
8632
8805
|
keyBindings: {
|
|
@@ -8677,6 +8850,125 @@ var TablePlugin = {
|
|
|
8677
8850
|
engine.dispatch(tr);
|
|
8678
8851
|
return true;
|
|
8679
8852
|
},
|
|
8853
|
+
"ArrowRight": (engine) => {
|
|
8854
|
+
var _a;
|
|
8855
|
+
const state = engine.getState();
|
|
8856
|
+
const sel = state.selection;
|
|
8857
|
+
if (!sel) return false;
|
|
8858
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8859
|
+
if (!cellPos) return false;
|
|
8860
|
+
const { tablePath, row, col } = cellPos;
|
|
8861
|
+
const cellPath = [...tablePath, row, col];
|
|
8862
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8863
|
+
if (!cellEl || !isCaretAtContainerEnd(cellEl)) return false;
|
|
8864
|
+
const table = getNodeAtPath(state.doc, tablePath);
|
|
8865
|
+
const { rows, cols } = getTableDimensions(table);
|
|
8866
|
+
let nextRow = row;
|
|
8867
|
+
let nextCol = col + 1;
|
|
8868
|
+
while (nextRow < rows) {
|
|
8869
|
+
if (nextCol >= cols) {
|
|
8870
|
+
nextCol = 0;
|
|
8871
|
+
nextRow++;
|
|
8872
|
+
continue;
|
|
8873
|
+
}
|
|
8874
|
+
const c = getNodeAtPath(state.doc, [...tablePath, nextRow, nextCol]);
|
|
8875
|
+
if (!((_a = c == null ? void 0 : c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8876
|
+
nextCol++;
|
|
8877
|
+
}
|
|
8878
|
+
if (nextRow >= rows) return true;
|
|
8879
|
+
const pos = getCellFirstPosition(state.doc, tablePath, nextRow, nextCol);
|
|
8880
|
+
if (!pos) return false;
|
|
8881
|
+
const tr = createTransaction();
|
|
8882
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8883
|
+
engine.dispatch(tr);
|
|
8884
|
+
return true;
|
|
8885
|
+
},
|
|
8886
|
+
"ArrowLeft": (engine) => {
|
|
8887
|
+
var _a;
|
|
8888
|
+
const state = engine.getState();
|
|
8889
|
+
const sel = state.selection;
|
|
8890
|
+
if (!sel) return false;
|
|
8891
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8892
|
+
if (!cellPos) return false;
|
|
8893
|
+
const { tablePath, row, col } = cellPos;
|
|
8894
|
+
const cellPath = [...tablePath, row, col];
|
|
8895
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8896
|
+
if (!cellEl || !isCaretAtContainerStart(cellEl)) return false;
|
|
8897
|
+
const table = getNodeAtPath(state.doc, tablePath);
|
|
8898
|
+
const { cols } = getTableDimensions(table);
|
|
8899
|
+
let prevRow = row;
|
|
8900
|
+
let prevCol = col - 1;
|
|
8901
|
+
while (prevRow >= 0) {
|
|
8902
|
+
if (prevCol < 0) {
|
|
8903
|
+
prevCol = cols - 1;
|
|
8904
|
+
prevRow--;
|
|
8905
|
+
continue;
|
|
8906
|
+
}
|
|
8907
|
+
const c = getNodeAtPath(state.doc, [...tablePath, prevRow, prevCol]);
|
|
8908
|
+
if (!((_a = c == null ? void 0 : c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8909
|
+
prevCol--;
|
|
8910
|
+
}
|
|
8911
|
+
if (prevRow < 0) return true;
|
|
8912
|
+
const pos = getCellLastPosition(state.doc, tablePath, prevRow, prevCol);
|
|
8913
|
+
if (!pos) return false;
|
|
8914
|
+
const tr = createTransaction();
|
|
8915
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8916
|
+
engine.dispatch(tr);
|
|
8917
|
+
return true;
|
|
8918
|
+
},
|
|
8919
|
+
"ArrowDown": (engine) => {
|
|
8920
|
+
var _a;
|
|
8921
|
+
const state = engine.getState();
|
|
8922
|
+
const sel = state.selection;
|
|
8923
|
+
if (!sel) return false;
|
|
8924
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8925
|
+
if (!cellPos) return false;
|
|
8926
|
+
const { tablePath, row, col } = cellPos;
|
|
8927
|
+
const cellPath = [...tablePath, row, col];
|
|
8928
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8929
|
+
if (!cellEl || !isCaretOnEdgeLine(cellEl, "down")) return false;
|
|
8930
|
+
const table = getNodeAtPath(state.doc, tablePath);
|
|
8931
|
+
const { rows, cols } = getTableDimensions(table);
|
|
8932
|
+
let nextRow = row + 1;
|
|
8933
|
+
while (nextRow < rows) {
|
|
8934
|
+
const c = getNodeAtPath(state.doc, [...tablePath, nextRow, col]);
|
|
8935
|
+
if (c && !((_a = c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8936
|
+
nextRow++;
|
|
8937
|
+
}
|
|
8938
|
+
if (nextRow >= rows) return false;
|
|
8939
|
+
const pos = getCellFirstPosition(state.doc, tablePath, nextRow, col < cols ? col : 0);
|
|
8940
|
+
if (!pos) return false;
|
|
8941
|
+
const tr = createTransaction();
|
|
8942
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8943
|
+
engine.dispatch(tr);
|
|
8944
|
+
return true;
|
|
8945
|
+
},
|
|
8946
|
+
"ArrowUp": (engine) => {
|
|
8947
|
+
var _a;
|
|
8948
|
+
const state = engine.getState();
|
|
8949
|
+
const sel = state.selection;
|
|
8950
|
+
if (!sel) return false;
|
|
8951
|
+
const cellPos = findCellPosition(state.doc, sel.anchor.path);
|
|
8952
|
+
if (!cellPos) return false;
|
|
8953
|
+
const { tablePath, row, col } = cellPos;
|
|
8954
|
+
const cellPath = [...tablePath, row, col];
|
|
8955
|
+
const cellEl = getCellDOMElement(JSON.stringify(cellPath));
|
|
8956
|
+
if (!cellEl || !isCaretOnEdgeLine(cellEl, "up")) return false;
|
|
8957
|
+
let prevRow = row - 1;
|
|
8958
|
+
while (prevRow >= 0) {
|
|
8959
|
+
const c = getNodeAtPath(state.doc, [...tablePath, prevRow, col]);
|
|
8960
|
+
if (c && !((_a = c.attrs) == null ? void 0 : _a.covered)) break;
|
|
8961
|
+
prevRow--;
|
|
8962
|
+
}
|
|
8963
|
+
if (prevRow < 0) return false;
|
|
8964
|
+
const { cols } = getTableDimensions(getNodeAtPath(state.doc, tablePath));
|
|
8965
|
+
const pos = getCellLastPosition(state.doc, tablePath, prevRow, col < cols ? col : 0);
|
|
8966
|
+
if (!pos) return false;
|
|
8967
|
+
const tr = createTransaction();
|
|
8968
|
+
tr.steps.push(tr_setSelection(makeCollapsedSelection(pos)));
|
|
8969
|
+
engine.dispatch(tr);
|
|
8970
|
+
return true;
|
|
8971
|
+
},
|
|
8680
8972
|
"Shift+Tab": (engine) => {
|
|
8681
8973
|
var _a;
|
|
8682
8974
|
const state = engine.getState();
|