Skip to content

Commit

Permalink
feat(note, tabs): added leave block logic for second enter (#248)
Browse files Browse the repository at this point in the history
* feat(note, tabs): added leave block logic for second enter
* fix(cut): updated leave block logic for second enter
* fix(tabs): updated leave block logic for second enter

---------

Co-authored-by: Yuriy Demidov <[email protected]>
  • Loading branch information
makhnatkin and d3m1d0v authored May 31, 2024
1 parent e12abda commit ed8ba66
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/extensions/yfm/YfmCut/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const liftEmptyBlockFromCut: Command = (state, dispatch) => {
if (
$cursor.depth > 2 && // yfm_cut -> yfm_cut_content -> <textblock>, depth must be at least 3
isSameNodeType($cursor.node(-1), cutContentType(schema)) &&
isSameNodeType($cursor.node(-2), cutType(schema))
isSameNodeType($cursor.node(-2), cutType(schema)) &&
$cursor.node(-1).childCount > 1
) {
// current texblock is last child of yfm_cut_content
if ($cursor.after() === $cursor.end(-1)) {
Expand Down
27 changes: 26 additions & 1 deletion src/extensions/yfm/YfmNote/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {isSameNodeType} from '../../../utils/schema';
import {isTextSelection} from '../../../utils/selection';
import {pType} from '../../base';

import {noteTitleType, noteType} from './utils';
import {noteContentType, noteTitleType, noteType} from './utils';

export const exitFromNoteTitle: Command = (state, dispatch) => {
const {selection, schema} = state;
Expand All @@ -31,6 +31,31 @@ export const exitFromNoteTitle: Command = (state, dispatch) => {
return true;
};

export const liftEmptyBlockFromNote: Command = (state, dispatch) => {
const {selection, schema} = state;
if (!isTextSelection(selection)) return false;

const {$cursor} = selection;
// cursor should be inside an empty textblock
if (!$cursor || $cursor.parent.content.size) return false;

if (
$cursor.depth > 2 && // depth must be at least 3
isSameNodeType($cursor.node(-1), noteContentType(schema)) &&
isSameNodeType($cursor.node(-2), noteType(schema)) &&
$cursor.node(-1).childCount > 1
) {
// current texblock is last child
if ($cursor.after() === $cursor.end(-1)) {
if (dispatch) {
dispatch(state.tr.lift($cursor.blockRange()!, $cursor.depth - 3).scrollIntoView());
}
return true;
}
}
return false;
};

function getNoteContent(noteNode: Node): Fragment {
const noteChildren: Node[] = [];
noteNode.forEach((node) => noteChildren.push(node));
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/yfm/YfmNote/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {withLogAction} from '../../../utils/keymap';

import {YfmNoteSpecs, YfmNoteSpecsOptions} from './YfmNoteSpecs';
import {createYfmNote, toYfmNote} from './actions/toYfmNote';
import {backToNoteTitle, exitFromNoteTitle, removeNote} from './commands';
import {backToNoteTitle, exitFromNoteTitle, liftEmptyBlockFromNote, removeNote} from './commands';
import {yfmNoteTooltipPlugin} from './plugins/YfmNoteTooltipPlugin';
import {noteType} from './utils';

Expand All @@ -25,7 +25,7 @@ export const YfmNote: ExtensionAuto<YfmNoteOptions> = (builder, opts) => {

builder
.addKeymap(() => ({
Enter: exitFromNoteTitle,
Enter: chainCommands(exitFromNoteTitle, liftEmptyBlockFromNote),
Backspace: chainCommands(backToNoteTitle, removeNote),
}))
.addAction(noteAction, () => toYfmNote)
Expand Down
3 changes: 2 additions & 1 deletion src/extensions/yfm/YfmTabs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {createYfmTabs} from './actions';
import {
dragAutoSwitch,
joinBackwardToOpenTab,
liftEmptyBlockFromTabPanel,
removeTabWhenCursorAtTheStartOfTab,
tabEnter,
tabPanelArrowDown,
Expand All @@ -27,7 +28,7 @@ export const YfmTabs: ExtensionAuto = (builder) => {
() => ({
Backspace: chainCommands(removeTabWhenCursorAtTheStartOfTab, joinBackwardToOpenTab),
ArrowDown: tabPanelArrowDown,
Enter: tabEnter,
Enter: chainCommands(tabEnter, liftEmptyBlockFromTabPanel),
'Shift-Enter': tabEnter,
}),
builder.Priority.High,
Expand Down
35 changes: 35 additions & 0 deletions src/extensions/yfm/YfmTabs/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from '../../';
import {throttle} from '../../../lodash';
import {findChildIndex} from '../../../table-utils/helpers';
import {isSameNodeType} from '../../../utils';
import {get$Cursor, isTextSelection} from '../../../utils/selection';

import {TabAttrs, TabPanelAttrs} from './YfmTabsSpecs/const';
Expand Down Expand Up @@ -218,6 +219,40 @@ export const tabEnter: Command = (state) => {
return $cursor?.node($cursor.depth).type === tabType(state.schema);
};

export const liftEmptyBlockFromTabPanel: Command = (state, dispatch) => {
const {selection, schema} = state;
if (!isTextSelection(selection)) return false;

const {$cursor} = selection;

// cursor should be inside an empty textblock
if (!$cursor || $cursor.parent.content.size) return false;

if (
$cursor.depth > 2 && // depth must be at least 3
isSameNodeType($cursor.node(-1), tabPanelType(schema)) &&
isSameNodeType($cursor.node(-2), tabsType(schema))
) {
// current texblock is last child
if ($cursor.after() === $cursor.end(-1)) {
if (dispatch) {
const copeidNode = $cursor.parent.copy();
const tabsAfter = $cursor.after(-2);

const {tr} = state;

tr.insert(tabsAfter, copeidNode)
.delete($cursor.before(), $cursor.after())
.setSelection(TextSelection.create(tr.doc, tr.mapping.map(tabsAfter)));

dispatch(tr.scrollIntoView());
}
return true;
}
}
return false;
};

const makeTabsInactive = (tabNodes: NodeWithPos[], tabPanels: NodeWithPos[], tr: Transaction) => {
// Find all active tabs and make them inactive
const activeTabs = tabNodes.filter(
Expand Down

0 comments on commit ed8ba66

Please sign in to comment.