Skip to content

Commit 06c5e62

Browse files
dnd
1 parent fdaef55 commit 06c5e62

File tree

8 files changed

+666
-20
lines changed

8 files changed

+666
-20
lines changed

src/components/modules/blockDragNDrop.ts

Lines changed: 560 additions & 0 deletions
Large diffs are not rendered by default.

src/components/modules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import Renderer from './renderer';
3737
import Saver from './saver';
3838
import Tools from './tools';
3939
import UI from './ui';
40+
import BlockDragNDrop from './blockDragNDrop';
4041

4142
export default {
4243
// API Modules
@@ -64,6 +65,7 @@ export default {
6465
InlineToolbar,
6566

6667
// Modules
68+
BlockDragNDrop,
6769
BlockEvents,
6870
BlockManager,
6971
BlockSelection,

src/components/modules/toolbar/index.ts

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { IconMenu, IconPlus } from '@codexteam/icons';
1111
import { BlockHovered } from '../../events/BlockHovered';
1212
import { beautifyShortcut } from '../../utils';
1313
import { getKeyboardKeyForCode } from '../../utils/keyboard';
14+
import Selection from '../../selection';
1415

1516
/**
1617
* @todo Tab on non-empty block should open Block Settings of the hoveredBlock (not where caret is set)
@@ -233,6 +234,13 @@ export default class Toolbar extends Module<ToolbarNodes> {
233234
this.enableModuleBindings();
234235
}, { timeout: 2000 });
235236
} else {
237+
const { BlockDragNDrop } = this.Editor;
238+
const dragHandle = this.nodes.settingsToggler;
239+
240+
if (dragHandle != null) {
241+
BlockDragNDrop.disableDragHandleModuleBindings(dragHandle);
242+
}
243+
236244
this.destroy();
237245
this.Editor.BlockSettings.destroy();
238246
this.disableModuleBindings();
@@ -469,18 +477,7 @@ export default class Toolbar extends Module<ToolbarNodes> {
469477

470478
$.append(this.nodes.actions, this.nodes.settingsToggler);
471479

472-
const blockTunesTooltip = $.make('div');
473-
const blockTunesTooltipEl = $.text(I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'Click to tune'));
474-
const slashRealKey = await getKeyboardKeyForCode('Slash', '/');
475-
476-
blockTunesTooltip.appendChild(blockTunesTooltipEl);
477-
blockTunesTooltip.appendChild($.make('div', this.CSS.plusButtonShortcut, {
478-
textContent: beautifyShortcut(`CMD + ${slashRealKey}`),
479-
}));
480-
481-
tooltip.onHover(this.nodes.settingsToggler, blockTunesTooltip, {
482-
hidingDelay: 400,
483-
});
480+
await this.makeSettingsTogglerTooltip();
484481

485482
/**
486483
* Appending Toolbar components to itself
@@ -494,6 +491,39 @@ export default class Toolbar extends Module<ToolbarNodes> {
494491
$.append(this.Editor.UI.nodes.wrapper, this.nodes.wrapper);
495492
}
496493

494+
/**
495+
* Creates and configures a tooltip for the settings toggler button in the toolbar.
496+
*
497+
* @returns {Promise<void>} A promise that resolves when the tooltip is successfully created.
498+
*/
499+
private async makeSettingsTogglerTooltip(): Promise<void> {
500+
const { BlockDragNDrop } = this.Editor;
501+
const tooltipTextParts: string[] = [
502+
I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'Click to tune'),
503+
];
504+
505+
if (BlockDragNDrop.isEnabled) {
506+
tooltipTextParts.push(
507+
I18n.ui(I18nInternalNS.ui.blockTunes.toggler, 'or drag to move')
508+
);
509+
}
510+
511+
const blockTunesTooltip = $.make('div');
512+
const blockTunesTooltipEl = $.text(tooltipTextParts.join(' '));
513+
const slashRealKey = await getKeyboardKeyForCode('Slash', '/');
514+
515+
blockTunesTooltip.appendChild(blockTunesTooltipEl);
516+
blockTunesTooltip.appendChild(
517+
$.make('div', this.CSS.plusButtonShortcut, {
518+
textContent: beautifyShortcut(`CMD + ${slashRealKey}`),
519+
})
520+
);
521+
522+
tooltip.onHover(this.nodes.settingsToggler, blockTunesTooltip, {
523+
hidingDelay: 400,
524+
});
525+
}
526+
497527
/**
498528
* Creates the Toolbox instance and return it's rendered element
499529
*/
@@ -598,6 +628,28 @@ export default class Toolbar extends Module<ToolbarNodes> {
598628
this.moveAndOpen(data.block);
599629
});
600630
}
631+
632+
const { BlockDragNDrop } = this.Editor;
633+
const dragHandle = this.nodes.settingsToggler;
634+
635+
if (dragHandle != null) {
636+
const { dragstart, dragend } = BlockDragNDrop.getDragHandleModuleBindings(dragHandle);
637+
638+
this.readOnlyMutableListeners.on(
639+
dragHandle,
640+
'dragstart',
641+
(event) => dragstart(event, () => this.hoveredBlock),
642+
true
643+
);
644+
this.readOnlyMutableListeners.on(
645+
dragHandle,
646+
'dragend',
647+
() => dragend(),
648+
true
649+
);
650+
651+
this.makeSettingsTogglerTooltip();
652+
}
601653
}
602654

603655
/**

src/components/utils.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,10 @@ export function isValidMimeType(type: string): boolean {
416416
* @param {boolean} immediate - call now
417417
* @returns {Function}
418418
*/
419-
export function debounce(func: (...args: unknown[]) => void, wait?: number, immediate?: boolean): () => void {
419+
export function debounce<T =(...args: unknown[]) => void>(func: T, wait?: number, immediate?: boolean): T {
420420
let timeout;
421421

422-
return (...args: unknown[]): void => {
422+
return ((...args: unknown[]): void => {
423423
// eslint-disable-next-line @typescript-eslint/no-this-alias
424424
const context = this;
425425

@@ -438,7 +438,7 @@ export function debounce(func: (...args: unknown[]) => void, wait?: number, imme
438438
if (callNow) {
439439
func.apply(context, args);
440440
}
441-
};
441+
}) as T;
442442
}
443443

444444
/**
@@ -451,7 +451,7 @@ export function debounce(func: (...args: unknown[]) => void, wait?: number, imme
451451
* but if you'd like to disable the execution on the leading edge, pass
452452
* `{leading: false}`. To disable execution on the trailing edge, ditto.
453453
*/
454-
export function throttle(func, wait, options: {leading?: boolean; trailing?: boolean} = undefined): () => void {
454+
export function throttle<T =(...args:unknown[]) => void>(func: T, wait: number, options: {leading?: boolean; trailing?: boolean} = undefined): T {
455455
let context, args, result;
456456
let timeout = null;
457457
let previous = 0;
@@ -470,7 +470,7 @@ export function throttle(func, wait, options: {leading?: boolean; trailing?: boo
470470
}
471471
};
472472

473-
return function (): unknown {
473+
return (function () {
474474
const now = Date.now();
475475

476476
if (!previous && options.leading === false) {
@@ -501,7 +501,7 @@ export function throttle(func, wait, options: {leading?: boolean; trailing?: boo
501501
}
502502

503503
return result;
504-
};
504+
}) as T;
505505
}
506506

507507
/**

src/styles/block.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,4 @@
8888
i {
8989
font-style: italic;
9090
}
91-
}
91+
}

src/styles/blockDragNDrop.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
.ce-drag-wrapper {
2+
&.ce-drag-image {
3+
position: absolute;
4+
pointer-events: none;
5+
z-index: 9999;
6+
opacity: 0.5;
7+
transition: none;
8+
user-select: none;
9+
width: fit-content;
10+
top: -10000px;
11+
left: -10000px;
12+
background: var(--selectionColor);
13+
}
14+
15+
&.ce-drop-holder {
16+
position: relative;
17+
18+
&::before {
19+
content: '';
20+
position: absolute;
21+
left: 0;
22+
bottom: 0;
23+
width: 100%;
24+
height: 5px;
25+
background-color: #388ae5;
26+
opacity: 0.5;
27+
z-index: 9999;
28+
}
29+
}
30+
}

src/styles/main.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
@import './popover.css';
1313
@import './popover-inline.css';
1414
@import './placeholders.css';
15-
15+
@import './blockDragNDrop.css';

src/types-internal/editor-modules.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import Saver from '../components/modules/saver';
3737
import Tools from '../components/modules/tools';
3838
import UI from '../components/modules/ui';
3939
import ToolsAPI from '../components/modules/api/tools';
40+
import BlockDragNDrop from '../components/modules/blockDragNDrop';
4041

4142
export interface EditorModules {
4243
// API Modules
@@ -64,6 +65,7 @@ export interface EditorModules {
6465
InlineToolbar: InlineToolbar,
6566

6667
// Modules
68+
BlockDragNDrop: BlockDragNDrop,
6769
BlockEvents: BlockEvents,
6870
BlockManager: BlockManager,
6971
BlockSelection: BlockSelection,

0 commit comments

Comments
 (0)