fix(BlockEditor): constrain select-all to current block and resize slash menu
- intercept Ctrl/Cmd+A to select only the current block's content, preventing cross-block merge bug - increase slash menu width from 280 to 375 and max-height from 320 to 360 - enlarge icon container, increase gap and padding, and upsize text in slash menu items
This commit is contained in:
@@ -120,6 +120,21 @@ const Block = forwardRef(function Block(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctrl/Cmd+A : limite la sélection au bloc courant. La sélection native
|
||||||
|
// s'étend sur plusieurs contentEditable et leur suppression fusionne le
|
||||||
|
// texte en un seul bloc — bug. On force la sélection à rester ici.
|
||||||
|
if ((e.ctrlKey || e.metaKey) && (e.key === 'a' || e.key === 'A')) {
|
||||||
|
if (el) {
|
||||||
|
e.preventDefault();
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(el);
|
||||||
|
const sel = window.getSelection();
|
||||||
|
sel?.removeAllRanges();
|
||||||
|
sel?.addRange(range);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.key === 'Enter' && !e.shiftKey) {
|
if (e.key === 'Enter' && !e.shiftKey) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const el = editableRef.current;
|
const el = editableRef.current;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
const MENU_WIDTH = 280;
|
const MENU_WIDTH = 375;
|
||||||
const MENU_MAX_HEIGHT = 320;
|
const MENU_MAX_HEIGHT = 360;
|
||||||
const VIEWPORT_MARGIN = 8;
|
const VIEWPORT_MARGIN = 8;
|
||||||
|
|
||||||
const SHORTCUT_HINT = {
|
const SHORTCUT_HINT = {
|
||||||
@@ -135,16 +135,16 @@ export default function SlashMenu({
|
|||||||
data-slash-index={i}
|
data-slash-index={i}
|
||||||
onMouseEnter={() => onHoverIndex?.(i)}
|
onMouseEnter={() => onHoverIndex?.(i)}
|
||||||
onClick={() => onSelect?.(def.type)}
|
onClick={() => onSelect?.(def.type)}
|
||||||
className={`w-full flex items-center gap-2.5 px-2 py-1 text-left transition-colors ${active ? 'bg-neutral-100 dark:bg-neutral-800' : ''}`}
|
className={`w-full flex items-center gap-3 px-2 py-1.5 text-left transition-colors ${active ? 'bg-neutral-100 dark:bg-neutral-800' : ''}`}
|
||||||
>
|
>
|
||||||
<span className="w-6 h-6 flex items-center justify-center rounded-[5px] border border-neutral-200 dark:border-neutral-700 text-[11px] font-medium text-neutral-700 dark:text-neutral-300 flex-shrink-0">
|
<span className="w-8 h-8 flex items-center justify-center rounded-md border border-neutral-200 dark:border-neutral-700 text-xs font-medium text-neutral-700 dark:text-neutral-300 flex-shrink-0">
|
||||||
{def.icon}
|
{def.icon}
|
||||||
</span>
|
</span>
|
||||||
<span className="flex-1 min-w-0 truncate text-[13px] text-neutral-900 dark:text-white">
|
<span className="flex-1 min-w-0 truncate text-sm text-neutral-900 dark:text-white">
|
||||||
{def.label}
|
{def.label}
|
||||||
</span>
|
</span>
|
||||||
{hint && (
|
{hint && (
|
||||||
<span className="text-[11px] font-mono text-neutral-400 dark:text-neutral-500 flex-shrink-0">
|
<span className="text-xs font-mono text-neutral-400 dark:text-neutral-500 flex-shrink-0">
|
||||||
{hint}
|
{hint}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user