@inshapardaz/likhari-react 0.1.18 → 0.1.19
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/EditorRoot.d.ts.map +1 -1
- package/dist/EditorRoot.js +3 -1
- package/dist/blocks/PoetryNode.d.ts +70 -0
- package/dist/blocks/PoetryNode.d.ts.map +1 -0
- package/dist/blocks/PoetryNode.js +198 -0
- package/dist/blocks/PoetryResizer.d.ts +11 -0
- package/dist/blocks/PoetryResizer.d.ts.map +1 -0
- package/dist/blocks/PoetryResizer.js +94 -0
- package/dist/blocks/poetryActions.d.ts +117 -0
- package/dist/blocks/poetryActions.d.ts.map +1 -0
- package/dist/blocks/poetryActions.js +481 -0
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +80 -8
- package/dist/i18n/strings.d.ts +21 -1
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +60 -3
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +2 -0
- package/dist/plugins/PoetryPlugin.d.ts +19 -0
- package/dist/plugins/PoetryPlugin.d.ts.map +1 -0
- package/dist/plugins/PoetryPlugin.js +54 -0
- package/dist/theme/editor.css +163 -0
- package/dist/theme/editorTheme.d.ts.map +1 -1
- package/dist/theme/editorTheme.js +1 -0
- package/package.json +1 -1
|
@@ -14,6 +14,9 @@ import { $createImageNode } from '../image/ImageNode.js';
|
|
|
14
14
|
import { INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
15
15
|
import { INSERT_LAYOUT_COMMAND } from '../blocks/LayoutNode.js';
|
|
16
16
|
import { INSERT_FOOTNOTE_COMMAND } from '../blocks/FootnoteNode.js';
|
|
17
|
+
import { $isPoetryBlockNode, POETRY_GUTTERS, POETRY_SPACINGS, POETRY_STAGGERS, } from '../blocks/PoetryNode.js';
|
|
18
|
+
import { $adjustPoetryGutter, $getCoupletCenteredFromSelection, $setCoupletCentered, $adjustPoetryStagger, $adjustPoetrySpacing, $deletePoetryBlock, $deletePoetryCouplet, $getPoetryBlockFromSelection, $insertCoupletRelativeToSelection, $setPoetryLayout, } from '../blocks/poetryActions.js';
|
|
19
|
+
import { INSERT_POETRY_COUPLET_COMMAND } from '../plugins/PoetryPlugin.js';
|
|
17
20
|
import { TableDialog } from './TableDialog.js';
|
|
18
21
|
import { LayoutDialog } from './LayoutDialog.js';
|
|
19
22
|
import { $getTableCellNodeFromLexicalNode, $isTableSelection, INSERT_TABLE_COMMAND } from '@lexical/table';
|
|
@@ -26,7 +29,7 @@ import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fo
|
|
|
26
29
|
import { setStyleProperty } from '../utils/style.js';
|
|
27
30
|
import { useStrings } from '../i18n/useStrings.js';
|
|
28
31
|
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
29
|
-
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconArrowMergeBoth, IconArrowsSplit2, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconColumns, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconTable, IconTableMinus, IconTableOptions, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
32
|
+
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconBold, IconClearFormatting, IconDeviceFloppy, IconDots, IconHistory, IconExternalLink, IconFeather, IconH1, IconH2, IconH3, IconH4, IconH5, IconH6, IconIndentDecrease, IconIndentIncrease, IconItalic, IconLetterCase, IconLetterCaseLower, IconLetterCaseUpper, IconLink, IconLinkOff, IconList, IconListCheck, IconListNumbers, IconPageBreak, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconArrowMergeBoth, IconArrowsSplit2, IconColumnInsertLeft, IconColumnInsertRight, IconColumnRemove, IconColumns, IconColumns1, IconColumns2, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconArrowsMaximize, IconArrowsMinimize, IconArrowsShuffle, IconTable, IconTableMinus, IconTrash, IconTableOptions, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
30
33
|
/** Sentinel for "no inline style": Lexical returns the default it is given when
|
|
31
34
|
* the selection has none, so this tells "unstyled" (show the canvas default)
|
|
32
35
|
* apart from "styled with a value the dropdown doesn't list" (show nothing). */
|
|
@@ -45,6 +48,10 @@ const INITIAL_STATE = {
|
|
|
45
48
|
tableColumns: 1,
|
|
46
49
|
canMergeCells: false,
|
|
47
50
|
canUnmergeCell: false,
|
|
51
|
+
inPoetry: false,
|
|
52
|
+
poetryLayout: 'single',
|
|
53
|
+
poetryScale: { spacing: 'normal', gutter: 'normal', stagger: 'normal' },
|
|
54
|
+
poetryCentered: false,
|
|
48
55
|
canUndo: false,
|
|
49
56
|
canRedo: false,
|
|
50
57
|
};
|
|
@@ -156,6 +163,25 @@ function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canU
|
|
|
156
163
|
};
|
|
157
164
|
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconRowInsertTop, manyRows ? t.insertRowsBefore : t.insertRowBefore, () => $insertTableRows(false)), item(IconRowInsertBottom, manyRows ? t.insertRowsAfter : t.insertRowAfter, () => $insertTableRows(true)), item(rtl ? IconColumnInsertRight : IconColumnInsertLeft, manyColumns ? t.insertColumnsBefore : t.insertColumnBefore, () => $insertTableColumns(false)), item(rtl ? IconColumnInsertLeft : IconColumnInsertRight, manyColumns ? t.insertColumnsAfter : t.insertColumnAfter, () => $insertTableColumns(true)), (canMergeCells || canUnmergeCell) && _jsx(Menu.Divider, {}), canMergeCells && item(IconArrowMergeBoth, t.mergeCells, $mergeTableCells), canUnmergeCell && item(IconArrowsSplit2, t.unmergeCell, $unmergeTableCell), _jsx(Menu.Divider, {}), item(IconRowRemove, manyRows ? t.deleteRows : t.deleteRow, $deleteTableRows), item(IconColumnRemove, manyColumns ? t.deleteColumns : t.deleteColumn, $deleteTableColumns), item(IconTableMinus, t.deleteTable, $deleteTable, 'red')] }));
|
|
158
165
|
}
|
|
166
|
+
/** Whether a one-notch step from `value` stays on the scale — a step that
|
|
167
|
+
* would fall off either end is disabled rather than silently clamped. */
|
|
168
|
+
function canStep(scale, value, step) {
|
|
169
|
+
const next = scale.indexOf(value) + step;
|
|
170
|
+
return next >= 0 && next < scale.length;
|
|
171
|
+
}
|
|
172
|
+
function PoetryMenuItems({ strings, layout, scale, centered, onAction, }) {
|
|
173
|
+
const t = strings.poetryMenu;
|
|
174
|
+
const item = (icon, label, action, active = false, color) => {
|
|
175
|
+
const Icon = icon;
|
|
176
|
+
return (_jsx(Menu.Item, { color: color, disabled: active, leftSection: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onAction(action), children: label }));
|
|
177
|
+
};
|
|
178
|
+
const setLayout = (next) => () => {
|
|
179
|
+
const node = $getPoetryBlockFromSelection();
|
|
180
|
+
if (node)
|
|
181
|
+
$setPoetryLayout(node, next);
|
|
182
|
+
};
|
|
183
|
+
return (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: t.menuLabel }), item(IconColumns1, t.singleColumn, setLayout('single'), layout === 'single'), item(IconColumns2, t.twoColumn, setLayout('two-column'), layout === 'two-column'), item(IconArrowsShuffle, t.staggered, setLayout('staggered'), layout === 'staggered'), _jsx(Menu.Divider, {}), _jsx(Menu.Divider, {}), item(IconRowInsertTop, t.insertCoupletBefore, () => $insertCoupletRelativeToSelection('before')), item(IconRowInsertBottom, t.insertCoupletAfter, () => $insertCoupletRelativeToSelection('after')), item(IconArrowsMinimize, t.tighterSpacing, () => $adjustPoetrySpacing(-1), !canStep(POETRY_SPACINGS, scale.spacing, -1)), item(IconArrowsMaximize, t.looserSpacing, () => $adjustPoetrySpacing(1), !canStep(POETRY_SPACINGS, scale.spacing, 1)), layout === 'staggered' && (_jsxs(_Fragment, { children: [item(IconArrowsMinimize, t.narrowerCouplets, () => $adjustPoetryStagger(-1), !canStep(POETRY_STAGGERS, scale.stagger, -1)), item(IconArrowsMaximize, t.widerCouplets, () => $adjustPoetryStagger(1), !canStep(POETRY_STAGGERS, scale.stagger, 1))] })), layout === 'two-column' && (_jsxs(_Fragment, { children: [item(IconAlignCenter, centered ? t.uncenterCouplet : t.centerCouplet, () => $setCoupletCentered(!centered)), item(IconColumns2, t.narrowerGutter, () => $adjustPoetryGutter(-1), !canStep(POETRY_GUTTERS, scale.gutter, -1)), item(IconColumns2, t.widerGutter, () => $adjustPoetryGutter(1), !canStep(POETRY_GUTTERS, scale.gutter, 1))] })), item(IconTrash, t.deleteCouplet, $deletePoetryCouplet, false, 'red'), item(IconTrash, t.deletePoetry, $deletePoetryBlock, false, 'red')] }));
|
|
184
|
+
}
|
|
159
185
|
export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en', drafts }) {
|
|
160
186
|
const [editor] = useLexicalComposerContext();
|
|
161
187
|
const [state, setState] = useState(INITIAL_STATE);
|
|
@@ -180,7 +206,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
180
206
|
if ($isTableSelection(selection)) {
|
|
181
207
|
const { rows, columns } = $getTableSelectionSize();
|
|
182
208
|
const canMergeCells = $canMergeSelectedCells();
|
|
183
|
-
setState((s) => ({ ...s, inTable: true, tableRows: rows, tableColumns: columns, canMergeCells, canUnmergeCell: false }));
|
|
209
|
+
setState((s) => ({ ...s, inTable: true, tableRows: rows, tableColumns: columns, canMergeCells, canUnmergeCell: false, inPoetry: false }));
|
|
184
210
|
return;
|
|
185
211
|
}
|
|
186
212
|
if (!$isRangeSelection(selection))
|
|
@@ -189,6 +215,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
189
215
|
const inTable = $getTableCellNodeFromLexicalNode(anchorNode) !== null;
|
|
190
216
|
const tableSize = inTable ? $getTableSelectionSize() : { rows: 1, columns: 1 };
|
|
191
217
|
const canUnmergeCell = inTable && $canUnmergeSelectedCell();
|
|
218
|
+
const poetryBlock = $getPoetryBlockFromSelection();
|
|
192
219
|
const element = anchorNode.getKey() === 'root' ? anchorNode : (anchorNode.getTopLevelElement() ?? anchorNode);
|
|
193
220
|
const listParent = $findMatchingParent(anchorNode, $isListNode);
|
|
194
221
|
const listType = listParent && $isListNode(listParent) ? listParent.getListType() : null;
|
|
@@ -214,6 +241,11 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
214
241
|
// Lexical's read/update context has already closed, so any $-prefixed
|
|
215
242
|
// node method (getFormatType() included) must not be deferred into it.
|
|
216
243
|
const elementFormat = ($isElementNode(element) ? element.getFormatType() : 'start') || 'start';
|
|
244
|
+
const poetryLayout = poetryBlock?.getLayout();
|
|
245
|
+
const poetryCentered = $getCoupletCenteredFromSelection();
|
|
246
|
+
const poetryScale = poetryBlock
|
|
247
|
+
? { spacing: poetryBlock.getSpacing(), gutter: poetryBlock.getGutter(), stagger: poetryBlock.getStagger() }
|
|
248
|
+
: null;
|
|
217
249
|
setState((s) => ({
|
|
218
250
|
...s,
|
|
219
251
|
blockType,
|
|
@@ -229,6 +261,10 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
229
261
|
tableColumns: tableSize.columns,
|
|
230
262
|
canMergeCells: false,
|
|
231
263
|
canUnmergeCell,
|
|
264
|
+
inPoetry: poetryBlock !== null,
|
|
265
|
+
poetryLayout: poetryLayout ?? s.poetryLayout,
|
|
266
|
+
poetryScale: poetryScale ?? s.poetryScale,
|
|
267
|
+
poetryCentered: poetryCentered ?? false,
|
|
232
268
|
}));
|
|
233
269
|
});
|
|
234
270
|
}, [editor]);
|
|
@@ -457,9 +493,9 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
457
493
|
root?.addEventListener('contextmenu', onContextMenu);
|
|
458
494
|
});
|
|
459
495
|
}, [editor, config.links]);
|
|
460
|
-
// Table actions. The menu takes focus, so the
|
|
461
|
-
// opens and restored before an action runs.
|
|
462
|
-
const
|
|
496
|
+
// Table/poetry contextual-menu actions. The menu takes focus, so the
|
|
497
|
+
// selection is snapshotted when it opens and restored before an action runs.
|
|
498
|
+
const runMenuAction = (action) => () => {
|
|
463
499
|
restoreSelection();
|
|
464
500
|
editor.update(action);
|
|
465
501
|
editor.focus();
|
|
@@ -501,6 +537,38 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
501
537
|
root?.addEventListener('contextmenu', onContextMenu);
|
|
502
538
|
});
|
|
503
539
|
}, [editor, config.tables]);
|
|
540
|
+
// Right-clicking a poetry couplet opens the same options menu at the pointer.
|
|
541
|
+
const [poetryContext, setPoetryContext] = useState(null);
|
|
542
|
+
useEffect(() => {
|
|
543
|
+
if (!config.poetry.enabled)
|
|
544
|
+
return;
|
|
545
|
+
const onContextMenu = (event) => {
|
|
546
|
+
if (event.defaultPrevented)
|
|
547
|
+
return; // a link inside the couplet already took it
|
|
548
|
+
const coupletElement = event.target?.closest?.('.likhari-poetry');
|
|
549
|
+
if (!coupletElement)
|
|
550
|
+
return;
|
|
551
|
+
let handled = false;
|
|
552
|
+
editor.update(() => {
|
|
553
|
+
const node = $getNearestNodeFromDOMNode(coupletElement);
|
|
554
|
+
const couplet = node ? $findMatchingParent(node, $isPoetryBlockNode) : null;
|
|
555
|
+
if (!couplet)
|
|
556
|
+
return;
|
|
557
|
+
handled = true;
|
|
558
|
+
if (!$getPoetryBlockFromSelection())
|
|
559
|
+
couplet.selectStart();
|
|
560
|
+
}, { discrete: true });
|
|
561
|
+
if (!handled)
|
|
562
|
+
return;
|
|
563
|
+
event.preventDefault();
|
|
564
|
+
snapshotSelectionRef.current();
|
|
565
|
+
setPoetryContext({ x: event.clientX, y: event.clientY });
|
|
566
|
+
};
|
|
567
|
+
return editor.registerRootListener((root, previous) => {
|
|
568
|
+
previous?.removeEventListener('contextmenu', onContextMenu);
|
|
569
|
+
root?.addEventListener('contextmenu', onContextMenu);
|
|
570
|
+
});
|
|
571
|
+
}, [editor, config.poetry.enabled]);
|
|
504
572
|
// Ctrl/Cmd+K opens the link dialog.
|
|
505
573
|
useEffect(() => {
|
|
506
574
|
if (!config.links)
|
|
@@ -740,8 +808,9 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
740
808
|
restoreSelection();
|
|
741
809
|
openLinkDialog();
|
|
742
810
|
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
|
|
743
|
-
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.blocks.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_COMMAND, undefined) })), config.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.columns && _jsx(ToolbarButton, { icon: IconColumns, title: strings.toolbar.insertColumns, onClick: openLayoutDialog }), config.footnotes && (_jsx(ToolbarButton, { icon: IconNumber1Small, title: strings.toolbar.insertFootnote, onClick: () => editor.dispatchCommand(INSERT_FOOTNOTE_COMMAND, undefined) })), config.blocks.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.poetry.enabled && _jsx(
|
|
744
|
-
config.tables && state.inTable && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.tableOptions, title: strings.toolbar.tableOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconTableOptions, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction:
|
|
811
|
+
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.blocks.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_COMMAND, undefined) })), config.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.columns && _jsx(ToolbarButton, { icon: IconColumns, title: strings.toolbar.insertColumns, onClick: openLayoutDialog }), config.footnotes && (_jsx(ToolbarButton, { icon: IconNumber1Small, title: strings.toolbar.insertFootnote, onClick: () => editor.dispatchCommand(INSERT_FOOTNOTE_COMMAND, undefined) })), config.blocks.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.poetry.enabled && locale !== 'en' && (_jsx(ToolbarButton, { icon: IconFeather, title: strings.toolbar.insertPoetryCouplet, onClick: () => editor.dispatchCommand(INSERT_POETRY_COUPLET_COMMAND, { layout: config.poetry.defaultLayout }) }))] }, "stubInsert")),
|
|
812
|
+
config.tables && state.inTable && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.tableOptions, title: strings.toolbar.tableOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconTableOptions, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] }) }, "tableActions")),
|
|
813
|
+
config.poetry.enabled && state.inPoetry && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.poetryOptions, title: strings.toolbar.poetryOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }) })] }) }, "poetryActions")),
|
|
745
814
|
showLanguageGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [config.language.autocorrect && _jsx(StubButton, { icon: IconWand, title: strings.toolbar.autocorrect, comingSoon: strings.toolbar.comingSoon }), config.language.textCleanup && _jsx(StubButton, { icon: IconSparkles, title: strings.toolbar.textCleanup, comingSoon: strings.toolbar.comingSoon }), config.language.spellCheck && _jsx(StubButton, { icon: IconAbc, title: strings.toolbar.spellChecker, comingSoon: strings.toolbar.comingSoon })] }, "language")),
|
|
746
815
|
];
|
|
747
816
|
return (_jsxs("div", { className: "likhari-toolbar", role: "toolbar", "aria-label": strings.toolbar.ariaLabel, ref: toolbarContainerRef, children: [fixedGroups, movableGroups
|
|
@@ -757,7 +826,10 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
757
826
|
}, onRemove: removeLink, strings: strings }) })] })), config.tables && (_jsxs(Menu, { opened: tableContext !== null, onChange: (opened) => {
|
|
758
827
|
if (!opened)
|
|
759
828
|
setTableContext(null);
|
|
760
|
-
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: tableContext?.x ?? -9999, top: tableContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: tableContext?.rows ?? 1, columns: tableContext?.columns ?? 1, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction:
|
|
829
|
+
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: tableContext?.x ?? -9999, top: tableContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: tableContext?.rows ?? 1, columns: tableContext?.columns ?? 1, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] })), config.poetry.enabled && (_jsxs(Menu, { opened: poetryContext !== null, onChange: (opened) => {
|
|
830
|
+
if (!opened)
|
|
831
|
+
setPoetryContext(null);
|
|
832
|
+
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: poetryContext?.x ?? -9999, top: poetryContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }) })] })), _jsxs("div", { "aria-hidden": "true", ref: toolbarMeasureRef, style: {
|
|
761
833
|
position: 'absolute',
|
|
762
834
|
visibility: 'hidden',
|
|
763
835
|
pointerEvents: 'none',
|
package/dist/i18n/strings.d.ts
CHANGED
|
@@ -42,14 +42,16 @@ export interface Strings {
|
|
|
42
42
|
linkOptions: string;
|
|
43
43
|
/** Toolbar button (shown while the caret is in a table) that opens the table actions menu. */
|
|
44
44
|
tableOptions: string;
|
|
45
|
+
/** Toolbar button (shown while the caret is in a couplet) that opens the poetry layout/alignment menu. */
|
|
46
|
+
poetryOptions: string;
|
|
45
47
|
insertLink: string;
|
|
46
48
|
insertImage: string;
|
|
47
49
|
insertPageBreak: string;
|
|
48
50
|
insertTable: string;
|
|
49
51
|
insertColumns: string;
|
|
50
52
|
insertFootnote: string;
|
|
53
|
+
insertPoetryCouplet: string;
|
|
51
54
|
insertHorizontalRule: string;
|
|
52
|
-
poetryBlocks: string;
|
|
53
55
|
comingSoon: (label: string) => string;
|
|
54
56
|
autocorrect: string;
|
|
55
57
|
textCleanup: string;
|
|
@@ -136,6 +138,24 @@ export interface Strings {
|
|
|
136
138
|
mergeCells: string;
|
|
137
139
|
unmergeCell: string;
|
|
138
140
|
};
|
|
141
|
+
poetryMenu: {
|
|
142
|
+
menuLabel: string;
|
|
143
|
+
singleColumn: string;
|
|
144
|
+
twoColumn: string;
|
|
145
|
+
staggered: string;
|
|
146
|
+
narrowerCouplets: string;
|
|
147
|
+
widerCouplets: string;
|
|
148
|
+
insertCoupletBefore: string;
|
|
149
|
+
insertCoupletAfter: string;
|
|
150
|
+
centerCouplet: string;
|
|
151
|
+
uncenterCouplet: string;
|
|
152
|
+
tighterSpacing: string;
|
|
153
|
+
looserSpacing: string;
|
|
154
|
+
narrowerGutter: string;
|
|
155
|
+
widerGutter: string;
|
|
156
|
+
deleteCouplet: string;
|
|
157
|
+
deletePoetry: string;
|
|
158
|
+
};
|
|
139
159
|
link: {
|
|
140
160
|
menuLabel: string;
|
|
141
161
|
noUrl: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;+DAC+D;AAC/D,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,cAAc,CAAC;AAElD,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE;QACN,mGAAmG;QACnG,WAAW,EAAE,MAAM,CAAC;QACpB,gDAAgD;QAChD,YAAY,EAAE,MAAM,CAAC;QACrB,sEAAsE;QACtE,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,OAAO,EAAE;QACP,gEAAgE;QAChE,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,0CAA0C;QAC1C,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,QAAQ,EAAE,MAAM,CAAC;QACjB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,8FAA8F;QAC9F,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,
|
|
1
|
+
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n/strings.js
CHANGED
|
@@ -33,14 +33,15 @@ const en = {
|
|
|
33
33
|
alignment: 'Alignment',
|
|
34
34
|
linkOptions: 'Link options',
|
|
35
35
|
tableOptions: 'Table options',
|
|
36
|
+
poetryOptions: 'Poetry options',
|
|
36
37
|
insertLink: 'Insert link (Ctrl+K)',
|
|
37
38
|
insertImage: 'Insert image',
|
|
38
39
|
insertPageBreak: 'Insert page break',
|
|
39
40
|
insertTable: 'Insert table',
|
|
40
41
|
insertColumns: 'Insert columns',
|
|
41
42
|
insertFootnote: 'Insert footnote',
|
|
43
|
+
insertPoetryCouplet: 'Insert poetry couplet',
|
|
42
44
|
insertHorizontalRule: 'Insert horizontal rule',
|
|
43
|
-
poetryBlocks: 'Poetry blocks',
|
|
44
45
|
comingSoon: (label) => `${label} (coming soon)`,
|
|
45
46
|
autocorrect: 'Auto-correct',
|
|
46
47
|
textCleanup: 'Text cleanup',
|
|
@@ -120,6 +121,24 @@ const en = {
|
|
|
120
121
|
mergeCells: 'Merge cells',
|
|
121
122
|
unmergeCell: 'Unmerge cell',
|
|
122
123
|
},
|
|
124
|
+
poetryMenu: {
|
|
125
|
+
menuLabel: 'Poetry',
|
|
126
|
+
singleColumn: 'Single column',
|
|
127
|
+
twoColumn: 'Two column',
|
|
128
|
+
staggered: 'Alternating sides',
|
|
129
|
+
narrowerCouplets: 'Narrower couplets',
|
|
130
|
+
widerCouplets: 'Wider couplets',
|
|
131
|
+
insertCoupletBefore: 'Insert couplet above',
|
|
132
|
+
insertCoupletAfter: 'Insert couplet below',
|
|
133
|
+
centerCouplet: 'Center this couplet',
|
|
134
|
+
uncenterCouplet: 'Un-center this couplet',
|
|
135
|
+
tighterSpacing: 'Tighter couplet spacing',
|
|
136
|
+
looserSpacing: 'Looser couplet spacing',
|
|
137
|
+
narrowerGutter: 'Narrower gutter',
|
|
138
|
+
widerGutter: 'Wider gutter',
|
|
139
|
+
deleteCouplet: 'Delete couplet',
|
|
140
|
+
deletePoetry: 'Delete poetry',
|
|
141
|
+
},
|
|
123
142
|
link: {
|
|
124
143
|
menuLabel: 'Link',
|
|
125
144
|
noUrl: '(no URL)',
|
|
@@ -234,14 +253,15 @@ const ur = {
|
|
|
234
253
|
alignment: 'سیدھ',
|
|
235
254
|
linkOptions: 'لنک کے اختیارات',
|
|
236
255
|
tableOptions: 'جدول کے اختیارات',
|
|
256
|
+
poetryOptions: 'شاعری کے اختیارات',
|
|
237
257
|
insertLink: 'لنک شامل کریں (Ctrl+K)',
|
|
238
258
|
insertImage: 'تصویر شامل کریں',
|
|
239
259
|
insertPageBreak: 'صفحے کی تقسیم شامل کریں',
|
|
240
260
|
insertTable: 'جدول شامل کریں',
|
|
241
261
|
insertColumns: 'کالم شامل کریں',
|
|
242
262
|
insertFootnote: 'فٹ نوٹ شامل کریں',
|
|
263
|
+
insertPoetryCouplet: 'شعر شامل کریں',
|
|
243
264
|
insertHorizontalRule: 'افقی لکیر شامل کریں',
|
|
244
|
-
poetryBlocks: 'شاعری کے بلاکس',
|
|
245
265
|
comingSoon: (label) => `${label} (جلد آ رہا ہے)`,
|
|
246
266
|
autocorrect: 'خودکار تصحیح',
|
|
247
267
|
textCleanup: 'متن کی صفائی',
|
|
@@ -321,6 +341,24 @@ const ur = {
|
|
|
321
341
|
mergeCells: 'خانے ضم کریں',
|
|
322
342
|
unmergeCell: 'خانہ الگ کریں',
|
|
323
343
|
},
|
|
344
|
+
poetryMenu: {
|
|
345
|
+
menuLabel: 'شاعری',
|
|
346
|
+
singleColumn: 'ایک کالم',
|
|
347
|
+
twoColumn: 'دو کالم',
|
|
348
|
+
staggered: 'کالم متبادل',
|
|
349
|
+
narrowerCouplets: 'شعر کی چوڑائی کم',
|
|
350
|
+
widerCouplets: 'شعر کی چوڑائی زیادہ',
|
|
351
|
+
insertCoupletBefore: 'اوپر شعر شامل کریں',
|
|
352
|
+
insertCoupletAfter: 'نیچے شعر شامل کریں',
|
|
353
|
+
centerCouplet: 'یہ شعر وسط میں رکھیں',
|
|
354
|
+
uncenterCouplet: 'وسط میں رکھنا ختم کریں',
|
|
355
|
+
tighterSpacing: 'شعروں کے درمیان کم جگہ',
|
|
356
|
+
looserSpacing: 'شعروں کے درمیان زیادہ جگہ',
|
|
357
|
+
narrowerGutter: 'کالمز کے درمیان کم جگہ',
|
|
358
|
+
widerGutter: 'کالمز کے درمیان زیادہ جگہ',
|
|
359
|
+
deleteCouplet: 'شعر حذف کریں',
|
|
360
|
+
deletePoetry: 'پوری شاعری حذف کریں',
|
|
361
|
+
},
|
|
324
362
|
link: {
|
|
325
363
|
menuLabel: 'لنک',
|
|
326
364
|
noUrl: '(کوئی یو آر ایل نہیں)',
|
|
@@ -435,14 +473,15 @@ const paShahmukhi = {
|
|
|
435
473
|
alignment: 'سیدھ',
|
|
436
474
|
linkOptions: 'لنک دے اختیار',
|
|
437
475
|
tableOptions: 'ٹیبل دے اختیار',
|
|
476
|
+
poetryOptions: 'شاعری دے اختیار',
|
|
438
477
|
insertLink: 'لنک پاؤ (Ctrl+K)',
|
|
439
478
|
insertImage: 'تصویر پاؤ',
|
|
440
479
|
insertPageBreak: 'صفحے دی ونڈ پاؤ',
|
|
441
480
|
insertTable: 'ٹیبل پاؤ',
|
|
442
481
|
insertColumns: 'کالم پاؤ',
|
|
443
482
|
insertFootnote: 'فٹ نوٹ پاؤ',
|
|
483
|
+
insertPoetryCouplet: 'شعر پاؤ',
|
|
444
484
|
insertHorizontalRule: 'لیٹی لکیر پاؤ',
|
|
445
|
-
poetryBlocks: 'شاعری بلاک',
|
|
446
485
|
comingSoon: (label) => `${label} (چھیتی آ رہا اے)`,
|
|
447
486
|
autocorrect: 'خودکار درستی',
|
|
448
487
|
textCleanup: 'متن دی صفائی',
|
|
@@ -522,6 +561,24 @@ const paShahmukhi = {
|
|
|
522
561
|
mergeCells: 'خانے رلاؤ',
|
|
523
562
|
unmergeCell: 'خانہ الگ کرو',
|
|
524
563
|
},
|
|
564
|
+
poetryMenu: {
|
|
565
|
+
menuLabel: 'شاعری',
|
|
566
|
+
singleColumn: 'اک کالم',
|
|
567
|
+
twoColumn: 'دو کالم',
|
|
568
|
+
staggered: 'وارو وار پاسے',
|
|
569
|
+
narrowerCouplets: 'شعر دی چوڑائی گھٹ',
|
|
570
|
+
widerCouplets: 'شعر دی چوڑائی ودھ',
|
|
571
|
+
insertCoupletBefore: 'اُتے شعر شامل کرو',
|
|
572
|
+
insertCoupletAfter: 'ھیٹھ شعر شامل کرو',
|
|
573
|
+
centerCouplet: 'ایہ شعر وچکار رکھو',
|
|
574
|
+
uncenterCouplet: 'وچکار رکھنا بند کرو',
|
|
575
|
+
tighterSpacing: 'شعراں وچکار گھٹ جگہ',
|
|
576
|
+
looserSpacing: 'شعراں وچکار ودھ جگہ',
|
|
577
|
+
narrowerGutter: 'کالماں وچکار گھٹ جگہ',
|
|
578
|
+
widerGutter: 'کالماں وچکار ودھ جگہ',
|
|
579
|
+
deleteCouplet: 'شعر مٹاؤ',
|
|
580
|
+
deletePoetry: 'ساری شاعری مٹاؤ',
|
|
581
|
+
},
|
|
525
582
|
link: {
|
|
526
583
|
menuLabel: 'لنک',
|
|
527
584
|
noUrl: '(کوئی یو آر ایل نئیں)',
|
package/dist/nodes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAalD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAkB5C,CAAC"}
|
package/dist/nodes.js
CHANGED
|
@@ -8,6 +8,7 @@ import { PageBreakNode } from './blocks/PageBreakNode.js';
|
|
|
8
8
|
import { LayoutContainerNode, LayoutItemNode } from './blocks/LayoutNode.js';
|
|
9
9
|
import { FootnoteReferenceNode } from './blocks/FootnoteNode.js';
|
|
10
10
|
import { FootnoteItemNode, FootnoteListNode } from './blocks/FootnoteListNode.js';
|
|
11
|
+
import { PoetryBlockNode } from './blocks/PoetryNode.js';
|
|
11
12
|
/**
|
|
12
13
|
* Node types registered on the editor at construction time. Per
|
|
13
14
|
* editor-architecture-design.md §2, node registration cannot be conditional
|
|
@@ -34,4 +35,5 @@ export const EDITOR_NODES = [
|
|
|
34
35
|
FootnoteReferenceNode,
|
|
35
36
|
FootnoteListNode,
|
|
36
37
|
FootnoteItemNode,
|
|
38
|
+
PoetryBlockNode,
|
|
37
39
|
];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type LexicalCommand } from 'lexical';
|
|
2
|
+
import { type PoetryLayout } from '../blocks/PoetryNode.js';
|
|
3
|
+
export declare const INSERT_POETRY_COUPLET_COMMAND: LexicalCommand<{
|
|
4
|
+
layout: PoetryLayout;
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Registers INSERT_POETRY_COUPLET_COMMAND (mirrors LayoutPlugin/FootnotePlugin's
|
|
8
|
+
* shape); a node transform that removes a couplet left with no misra
|
|
9
|
+
* content (e.g. after undo/paste leaves it structurally empty) and keeps a
|
|
10
|
+
* trailing couplet always followed by an editable paragraph; a
|
|
11
|
+
* KEY_ENTER_COMMAND handler (above RichTextPlugin's own, which would
|
|
12
|
+
* otherwise trap Enter inside the couplet — see poetryActions.ts) that lets
|
|
13
|
+
* Enter at the end of the last misra add a paragraph after the block; and a
|
|
14
|
+
* KEY_BACKSPACE_COMMAND handler that removes an empty couplet entirely when
|
|
15
|
+
* Backspace is pressed at its very start (the explicit "Delete couplet"
|
|
16
|
+
* menu action in Toolbar.tsx covers removing a non-empty one).
|
|
17
|
+
*/
|
|
18
|
+
export declare function PoetryPlugin(): null;
|
|
19
|
+
//# sourceMappingURL=PoetryPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PoetryPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PoetryPlugin.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAU1E,eAAO,MAAM,6BAA6B,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAElF,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,SAsD3B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
3
|
+
import { COMMAND_PRIORITY_EDITOR, COMMAND_PRIORITY_HIGH, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_ENTER_COMMAND, createCommand, } from 'lexical';
|
|
4
|
+
import { mergeRegister } from '@lexical/utils';
|
|
5
|
+
import { LayoutContainerNode, LayoutItemNode } from '../blocks/LayoutNode.js';
|
|
6
|
+
import { PoetryBlockNode } from '../blocks/PoetryNode.js';
|
|
7
|
+
import { $deletePoetryForward, $deletePoetryOnBackspace, $ensureTrailingParagraph, $completeSingleCoupletBlock, $exitPoetryOnEnter, $insertPoetryCouplet, } from '../blocks/poetryActions.js';
|
|
8
|
+
export const INSERT_POETRY_COUPLET_COMMAND = createCommand('INSERT_POETRY_COUPLET_COMMAND');
|
|
9
|
+
/**
|
|
10
|
+
* Registers INSERT_POETRY_COUPLET_COMMAND (mirrors LayoutPlugin/FootnotePlugin's
|
|
11
|
+
* shape); a node transform that removes a couplet left with no misra
|
|
12
|
+
* content (e.g. after undo/paste leaves it structurally empty) and keeps a
|
|
13
|
+
* trailing couplet always followed by an editable paragraph; a
|
|
14
|
+
* KEY_ENTER_COMMAND handler (above RichTextPlugin's own, which would
|
|
15
|
+
* otherwise trap Enter inside the couplet — see poetryActions.ts) that lets
|
|
16
|
+
* Enter at the end of the last misra add a paragraph after the block; and a
|
|
17
|
+
* KEY_BACKSPACE_COMMAND handler that removes an empty couplet entirely when
|
|
18
|
+
* Backspace is pressed at its very start (the explicit "Delete couplet"
|
|
19
|
+
* menu action in Toolbar.tsx covers removing a non-empty one).
|
|
20
|
+
*/
|
|
21
|
+
export function PoetryPlugin() {
|
|
22
|
+
const [editor] = useLexicalComposerContext();
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!editor.hasNodes([PoetryBlockNode, LayoutContainerNode, LayoutItemNode])) {
|
|
25
|
+
throw new Error('PoetryPlugin: PoetryBlockNode (and the columns nodes it composes) not registered on the editor');
|
|
26
|
+
}
|
|
27
|
+
return mergeRegister(editor.registerCommand(INSERT_POETRY_COUPLET_COMMAND, ({ layout }) => $insertPoetryCouplet(layout), COMMAND_PRIORITY_EDITOR), editor.registerNodeTransform(PoetryBlockNode, (node) => {
|
|
28
|
+
if (node.getChildrenSize() === 0) {
|
|
29
|
+
node.remove();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
$completeSingleCoupletBlock(node);
|
|
33
|
+
$ensureTrailingParagraph(node);
|
|
34
|
+
}), editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
|
|
35
|
+
if (event?.shiftKey)
|
|
36
|
+
return false; // Shift+Enter stays a plain line break
|
|
37
|
+
const handled = $exitPoetryOnEnter();
|
|
38
|
+
if (handled)
|
|
39
|
+
event?.preventDefault();
|
|
40
|
+
return handled;
|
|
41
|
+
}, COMMAND_PRIORITY_HIGH), editor.registerCommand(KEY_BACKSPACE_COMMAND, (event) => {
|
|
42
|
+
const handled = $deletePoetryOnBackspace();
|
|
43
|
+
if (handled)
|
|
44
|
+
event?.preventDefault();
|
|
45
|
+
return handled;
|
|
46
|
+
}, COMMAND_PRIORITY_HIGH), editor.registerCommand(KEY_DELETE_COMMAND, (event) => {
|
|
47
|
+
const handled = $deletePoetryForward();
|
|
48
|
+
if (handled)
|
|
49
|
+
event?.preventDefault();
|
|
50
|
+
return handled;
|
|
51
|
+
}, COMMAND_PRIORITY_HIGH));
|
|
52
|
+
}, [editor]);
|
|
53
|
+
return null;
|
|
54
|
+
}
|