@inshapardaz/likhari-react 0.1.9-dev.99 → 0.1.9
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 +1 -3
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +5 -111
- package/dist/i18n/strings.d.ts +0 -30
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +0 -78
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +0 -6
- package/dist/theme/editor.css +0 -76
- package/dist/theme/editorTheme.d.ts.map +1 -1
- package/dist/theme/editorTheme.js +0 -6
- package/package.json +1 -2
- package/dist/blocks/PageBreakNode.d.ts +0 -30
- package/dist/blocks/PageBreakNode.d.ts.map +0 -1
- package/dist/blocks/PageBreakNode.js +0 -112
- package/dist/components/TableDialog.d.ts +0 -17
- package/dist/components/TableDialog.d.ts.map +0 -1
- package/dist/components/TableDialog.js +0 -33
- package/dist/plugins/PageBreakPlugin.d.ts +0 -3
- package/dist/plugins/PageBreakPlugin.d.ts.map +0 -1
- package/dist/plugins/PageBreakPlugin.js +0 -19
- package/dist/table/tableActions.d.ts +0 -21
- package/dist/table/tableActions.d.ts.map +0 -1
- package/dist/table/tableActions.js +0 -71
package/dist/EditorRoot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"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"}
|
package/dist/EditorRoot.js
CHANGED
|
@@ -7,7 +7,6 @@ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
|
|
|
7
7
|
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
|
|
8
8
|
import { CheckListPlugin } from '@lexical/react/LexicalCheckListPlugin';
|
|
9
9
|
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
|
10
|
-
import { TablePlugin } from '@lexical/react/LexicalTablePlugin';
|
|
11
10
|
import { HorizontalRulePlugin } from '@lexical/react/LexicalHorizontalRulePlugin';
|
|
12
11
|
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
|
|
13
12
|
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
|
|
@@ -19,7 +18,6 @@ import { EditorThemeProvider } from './theme/EditorThemeProvider.js';
|
|
|
19
18
|
import { Toolbar } from './components/Toolbar.js';
|
|
20
19
|
import { injectUrduWebFontsCss } from './fonts/index.js';
|
|
21
20
|
import { LinkPastePlugin } from './plugins/LinkPastePlugin.js';
|
|
22
|
-
import { PageBreakPlugin } from './plugins/PageBreakPlugin.js';
|
|
23
21
|
import { DraftRestore } from './components/DraftRestore.js';
|
|
24
22
|
import { LeaveDialog } from './components/LeaveDialog.js';
|
|
25
23
|
import { clearDraft, createDraftId, hasDraftContent, pruneDrafts, writeDraft, } from './persistence/draftStorage.js';
|
|
@@ -268,7 +266,7 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, initialCo
|
|
|
268
266
|
const portalTargetSelector = `#${CSS.escape(portalTargetId)}`;
|
|
269
267
|
return (_jsx(EditorThemeProvider, { theme: theme, colorScheme: colorScheme, accentColor: accentColor, scopeElementId: portalTargetId, children: _jsxs("div", { className: "likhari-root", dir: dir, ref: rootElementRef, "data-document-id": documentId, style: { height: typeof height === 'number' ? `${height}px` : height }, children: [_jsx("div", { id: portalTargetId, className: "likhari-portal-target" }), _jsx(PortalTargetContext.Provider, { value: portalTargetSelector, children: _jsxs(UiStringsContext.Provider, { value: strings, children: [_jsx(ImageOptionsContext.Provider, { value: imageOptions, children: _jsxs(LexicalComposer, { initialConfig: initialConfig, children: [_jsx(Toolbar, { config: config, onSave: handleSave, isDirty: isDirty, showSave: showSave, fontOptions: fontOptions, direction: dir, locale: locale, drafts: autosave
|
|
270
268
|
? { currentId: draftId, maxBytes: autosaveMaxBytes, adoptOnRestore: !documentId, onRestored: handleDraftRestored }
|
|
271
|
-
: undefined }), documentId && (_jsx(DraftRestore, { draftId: documentId, mode: restoreDraft, initialJson: initialContentJsonRef.current, locale: locale, onRestored: handleDraftRestored })), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.
|
|
269
|
+
: undefined }), documentId && (_jsx(DraftRestore, { draftId: documentId, mode: restoreDraft, initialJson: initialContentJsonRef.current, locale: locale, onRestored: handleDraftRestored })), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, "aria-label": strings.editor.contentLabel }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.horizontalRule && _jsx(HorizontalRulePlugin, {}), _jsx(OnChangePlugin, { onChange: handleChange })] }) }), _jsx(LeaveDialog, { opened: leavePrompt !== null, canSave: Boolean(onSave), canSaveDraft: autosave || navigationGuard === 'save-draft', draftFailed: leavePrompt?.draftFailed ?? false, onSave: () => {
|
|
272
270
|
handleSave();
|
|
273
271
|
settleLeave(true);
|
|
274
272
|
}, onSaveDraft: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA4CA,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AAuUvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,EAAE,YAAY,+BA4xBxJ"}
|
|
@@ -11,10 +11,6 @@ import { $findMatchingParent, $insertNodeToNearestRoot } from '@lexical/utils';
|
|
|
11
11
|
import { INSERT_HORIZONTAL_RULE_COMMAND } from '@lexical/react/LexicalHorizontalRuleNode';
|
|
12
12
|
import { ImageDialog } from '../image/ImageDialog.js';
|
|
13
13
|
import { $createImageNode } from '../image/ImageNode.js';
|
|
14
|
-
import { INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
15
|
-
import { TableDialog } from './TableDialog.js';
|
|
16
|
-
import { $getTableCellNodeFromLexicalNode, $isTableSelection, INSERT_TABLE_COMMAND } from '@lexical/table';
|
|
17
|
-
import { $deleteTable, $deleteTableColumns, $deleteTableRows, $getTableSelectionSize, $insertTableColumns, $insertTableRows, } from '../table/tableActions.js';
|
|
18
14
|
import { $createLinkNode, $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';
|
|
19
15
|
import { LinkDialog } from './LinkDialog.js';
|
|
20
16
|
import { DraftsDialog } from './DraftsDialog.js';
|
|
@@ -23,7 +19,7 @@ import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX } from '../fo
|
|
|
23
19
|
import { setStyleProperty } from '../utils/style.js';
|
|
24
20
|
import { useStrings } from '../i18n/useStrings.js';
|
|
25
21
|
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
26
|
-
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,
|
|
22
|
+
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, IconPencil, IconPhoto, IconPilcrow, IconQuote, IconSeparatorHorizontal, IconSparkles, IconStrikethrough, IconSubscript, IconSuperscript, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
27
23
|
/** Sentinel for "no inline style": Lexical returns the default it is given when
|
|
28
24
|
* the selection has none, so this tells "unstyled" (show the canvas default)
|
|
29
25
|
* apart from "styled with a value the dropdown doesn't list" (show nothing). */
|
|
@@ -37,9 +33,6 @@ const INITIAL_STATE = {
|
|
|
37
33
|
fontSize: UNSET_STYLE,
|
|
38
34
|
isLink: false,
|
|
39
35
|
linkUrl: '',
|
|
40
|
-
inTable: false,
|
|
41
|
-
tableRows: 1,
|
|
42
|
-
tableColumns: 1,
|
|
43
36
|
canUndo: false,
|
|
44
37
|
canRedo: false,
|
|
45
38
|
};
|
|
@@ -128,21 +121,6 @@ function LinkMenuItems({ url, onEdit, onRemove, strings }) {
|
|
|
128
121
|
// Not a URL the editor would accept (e.g. loaded from a document): show it, don't make it clickable.
|
|
129
122
|
_jsx(Menu.Item, { disabled: true, title: url, className: "likhari-link-menu-url", children: url || strings.link.noUrl })), _jsx(Menu.Item, { leftSection: _jsx(IconPencil, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onEdit, children: strings.link.editLink }), _jsx(Menu.Item, { color: "red", leftSection: _jsx(IconLinkOff, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onRemove, children: strings.link.removeLink })] }));
|
|
130
123
|
}
|
|
131
|
-
/** The table actions menu's contents — shared by the toolbar button and the
|
|
132
|
-
* right-click menu. Each acts on the selected cell, or on every row/column a
|
|
133
|
-
* multi-cell selection covers. */
|
|
134
|
-
function TableMenuItems({ strings, direction, rows, columns, onAction, }) {
|
|
135
|
-
const t = strings.tableMenu;
|
|
136
|
-
// "Before" is the start side, which is on the right in an RTL table.
|
|
137
|
-
const rtl = direction === 'rtl';
|
|
138
|
-
const manyRows = rows > 1;
|
|
139
|
-
const manyColumns = columns > 1;
|
|
140
|
-
const item = (icon, label, action, color) => {
|
|
141
|
-
const Icon = icon;
|
|
142
|
-
return (_jsx(Menu.Item, { color: color, leftSection: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onAction(action), children: label }));
|
|
143
|
-
};
|
|
144
|
-
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)), _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')] }));
|
|
145
|
-
}
|
|
146
124
|
export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAULT_FONT_OPTIONS, direction = 'ltr', locale = 'en', drafts }) {
|
|
147
125
|
const [editor] = useLexicalComposerContext();
|
|
148
126
|
const [state, setState] = useState(INITIAL_STATE);
|
|
@@ -161,17 +139,9 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
161
139
|
const updateToolbar = useCallback(() => {
|
|
162
140
|
editor.getEditorState().read(() => {
|
|
163
141
|
const selection = $getSelection();
|
|
164
|
-
// A selection of several table cells isn't a range selection.
|
|
165
|
-
if ($isTableSelection(selection)) {
|
|
166
|
-
const { rows, columns } = $getTableSelectionSize();
|
|
167
|
-
setState((s) => ({ ...s, inTable: true, tableRows: rows, tableColumns: columns }));
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
142
|
if (!$isRangeSelection(selection))
|
|
171
143
|
return;
|
|
172
144
|
const anchorNode = selection.anchor.getNode();
|
|
173
|
-
const inTable = $getTableCellNodeFromLexicalNode(anchorNode) !== null;
|
|
174
|
-
const tableSize = inTable ? $getTableSelectionSize() : { rows: 1, columns: 1 };
|
|
175
145
|
const element = anchorNode.getKey() === 'root' ? anchorNode : (anchorNode.getTopLevelElement() ?? anchorNode);
|
|
176
146
|
const listParent = $findMatchingParent(anchorNode, $isListNode);
|
|
177
147
|
const listType = listParent && $isListNode(listParent) ? listParent.getListType() : null;
|
|
@@ -207,9 +177,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
207
177
|
fontSize,
|
|
208
178
|
isLink,
|
|
209
179
|
linkUrl,
|
|
210
|
-
inTable,
|
|
211
|
-
tableRows: tableSize.rows,
|
|
212
|
-
tableColumns: tableSize.columns,
|
|
213
180
|
}));
|
|
214
181
|
});
|
|
215
182
|
}, [editor]);
|
|
@@ -309,26 +276,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
309
276
|
});
|
|
310
277
|
closeImageDialog();
|
|
311
278
|
};
|
|
312
|
-
const [tableDialogOpen, setTableDialogOpen] = useState(false);
|
|
313
|
-
const openTableDialog = () => {
|
|
314
|
-
snapshotSelection();
|
|
315
|
-
setTableDialogOpen(true);
|
|
316
|
-
};
|
|
317
|
-
const closeTableDialog = () => {
|
|
318
|
-
setTableDialogOpen(false);
|
|
319
|
-
editor.focus();
|
|
320
|
-
};
|
|
321
|
-
const insertTable = ({ rows, columns, headerRow }) => {
|
|
322
|
-
const saved = menuSelectionRef.current;
|
|
323
|
-
if (saved)
|
|
324
|
-
editor.update(() => $setSelection(saved.clone()), { discrete: true });
|
|
325
|
-
editor.dispatchCommand(INSERT_TABLE_COMMAND, {
|
|
326
|
-
rows: String(rows),
|
|
327
|
-
columns: String(columns),
|
|
328
|
-
includeHeaders: { rows: headerRow, columns: false },
|
|
329
|
-
});
|
|
330
|
-
closeTableDialog();
|
|
331
|
-
};
|
|
332
279
|
/** Applies a font property per `config.font.scope`: to the selection, to
|
|
333
280
|
* every text node in the document, or (for 'both') to the selection when
|
|
334
281
|
* there is a range and to the whole document when there isn't. */
|
|
@@ -422,50 +369,6 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
422
369
|
root?.addEventListener('contextmenu', onContextMenu);
|
|
423
370
|
});
|
|
424
371
|
}, [editor, config.links]);
|
|
425
|
-
// Table actions. The menu takes focus, so the selection is snapshotted when it
|
|
426
|
-
// opens and restored before an action runs.
|
|
427
|
-
const runTableAction = (action) => () => {
|
|
428
|
-
restoreSelection();
|
|
429
|
-
editor.update(action);
|
|
430
|
-
editor.focus();
|
|
431
|
-
};
|
|
432
|
-
// Right-clicking a table cell opens the same actions at the pointer.
|
|
433
|
-
const [tableContext, setTableContext] = useState(null);
|
|
434
|
-
useEffect(() => {
|
|
435
|
-
if (!config.tables)
|
|
436
|
-
return;
|
|
437
|
-
const onContextMenu = (event) => {
|
|
438
|
-
if (event.defaultPrevented)
|
|
439
|
-
return; // a link inside the cell already took it
|
|
440
|
-
const cellElement = event.target?.closest?.('td, th');
|
|
441
|
-
if (!cellElement)
|
|
442
|
-
return;
|
|
443
|
-
let handled = false;
|
|
444
|
-
editor.update(() => {
|
|
445
|
-
const node = $getNearestNodeFromDOMNode(cellElement);
|
|
446
|
-
const cell = node ? $getTableCellNodeFromLexicalNode(node) : null;
|
|
447
|
-
if (!cell)
|
|
448
|
-
return;
|
|
449
|
-
handled = true;
|
|
450
|
-
const selection = $getSelection();
|
|
451
|
-
// Keep a multi-cell selection that includes this cell, so "insert
|
|
452
|
-
// rows" / "delete columns" act on everything selected.
|
|
453
|
-
const insideSelection = $isTableSelection(selection) && selection.getNodes().some((n) => n.getKey() === cell.getKey());
|
|
454
|
-
if (!insideSelection)
|
|
455
|
-
cell.selectEnd();
|
|
456
|
-
}, { discrete: true });
|
|
457
|
-
if (!handled)
|
|
458
|
-
return;
|
|
459
|
-
event.preventDefault();
|
|
460
|
-
snapshotSelectionRef.current();
|
|
461
|
-
const size = editor.getEditorState().read($getTableSelectionSize);
|
|
462
|
-
setTableContext({ x: event.clientX, y: event.clientY, rows: size.rows, columns: size.columns });
|
|
463
|
-
};
|
|
464
|
-
return editor.registerRootListener((root, previous) => {
|
|
465
|
-
previous?.removeEventListener('contextmenu', onContextMenu);
|
|
466
|
-
root?.addEventListener('contextmenu', onContextMenu);
|
|
467
|
-
});
|
|
468
|
-
}, [editor, config.tables]);
|
|
469
372
|
// Ctrl/Cmd+K opens the link dialog.
|
|
470
373
|
useEffect(() => {
|
|
471
374
|
if (!config.links)
|
|
@@ -526,12 +429,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
526
429
|
const showFormattingGroup = headingLevels.length > 0 || config.lists.bullet || config.lists.numbered || config.lists.check || config.blocks.quote;
|
|
527
430
|
const showInlineGroup = fmt.bold || fmt.italic || fmt.underline;
|
|
528
431
|
const showAlignGroup = config.alignment.start || config.alignment.center || config.alignment.justify || config.alignment.left || config.alignment.right;
|
|
529
|
-
const showStubInsertGroup = config.images.linked ||
|
|
530
|
-
config.images.embedded ||
|
|
531
|
-
config.tables ||
|
|
532
|
-
config.blocks.horizontalRule ||
|
|
533
|
-
config.blocks.pageBreak ||
|
|
534
|
-
config.poetry.enabled;
|
|
432
|
+
const showStubInsertGroup = config.images.linked || config.images.embedded || config.blocks.horizontalRule || config.poetry.enabled;
|
|
535
433
|
const showLanguageGroup = config.language.autocorrect || config.language.textCleanup || config.language.spellCheck;
|
|
536
434
|
// The "script & cleanup" and "indent/outdent" groups (UI spec §3.3) render
|
|
537
435
|
// as normal inline toolbar groups whenever there's room, and only move
|
|
@@ -701,8 +599,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
701
599
|
restoreSelection();
|
|
702
600
|
openLinkDialog();
|
|
703
601
|
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
|
|
704
|
-
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.
|
|
705
|
-
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, onAction: runTableAction }) })] }) }, "tableActions")),
|
|
602
|
+
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.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.poetry.enabled && _jsx(StubButton, { icon: IconFeather, title: strings.toolbar.poetryBlocks, comingSoon: strings.toolbar.comingSoon })] }, "stubInsert")),
|
|
706
603
|
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")),
|
|
707
604
|
];
|
|
708
605
|
return (_jsxs("div", { className: "likhari-toolbar", role: "toolbar", "aria-label": strings.toolbar.ariaLabel, ref: toolbarContainerRef, children: [fixedGroups, movableGroups
|
|
@@ -715,10 +612,7 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
715
612
|
}, 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: linkContext?.x ?? -9999, top: linkContext?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsx(Menu.Dropdown, { children: _jsx(LinkMenuItems, { url: linkContext?.url ?? '', onEdit: () => {
|
|
716
613
|
restoreSelection();
|
|
717
614
|
openLinkDialog();
|
|
718
|
-
}, onRemove: removeLink, strings: strings }) })] })),
|
|
719
|
-
if (!opened)
|
|
720
|
-
setTableContext(null);
|
|
721
|
-
}, 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, onAction: runTableAction }) })] })), _jsxs("div", { "aria-hidden": "true", ref: toolbarMeasureRef, style: {
|
|
615
|
+
}, onRemove: removeLink, strings: strings }) })] })), _jsxs("div", { "aria-hidden": "true", ref: toolbarMeasureRef, style: {
|
|
722
616
|
position: 'absolute',
|
|
723
617
|
visibility: 'hidden',
|
|
724
618
|
pointerEvents: 'none',
|
|
@@ -727,5 +621,5 @@ export function Toolbar({ config, onSave, isDirty, showSave, fontOptions = DEFAU
|
|
|
727
621
|
display: 'flex',
|
|
728
622
|
flexWrap: 'nowrap',
|
|
729
623
|
gap: 8,
|
|
730
|
-
}, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.
|
|
624
|
+
}, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.links && (_jsx(LinkDialog, { opened: linkDialogOpen, initialUrl: state.linkUrl, showTextField: linkNeedsText, onSubmit: applyLink, onRemove: state.isLink ? removeLink : undefined, onClose: closeLinkDialog })), drafts && _jsx(DraftsDialog, { opened: draftsOpen, locale: locale, onClose: () => setDraftsOpen(false), ...drafts })] }));
|
|
731
625
|
}
|
package/dist/i18n/strings.d.ts
CHANGED
|
@@ -13,8 +13,6 @@ export interface Strings {
|
|
|
13
13
|
placeholder: string;
|
|
14
14
|
/** aria-label on the contenteditable itself. */
|
|
15
15
|
contentLabel: string;
|
|
16
|
-
/** Label shown on a page-break marker's dashed line while editing. */
|
|
17
|
-
pageBreakLabel: string;
|
|
18
16
|
};
|
|
19
17
|
common: {
|
|
20
18
|
cancel: string;
|
|
@@ -40,12 +38,8 @@ export interface Strings {
|
|
|
40
38
|
noMatch: string;
|
|
41
39
|
alignment: string;
|
|
42
40
|
linkOptions: string;
|
|
43
|
-
/** Toolbar button (shown while the caret is in a table) that opens the table actions menu. */
|
|
44
|
-
tableOptions: string;
|
|
45
41
|
insertLink: string;
|
|
46
42
|
insertImage: string;
|
|
47
|
-
insertPageBreak: string;
|
|
48
|
-
insertTable: string;
|
|
49
43
|
insertHorizontalRule: string;
|
|
50
44
|
poetryBlocks: string;
|
|
51
45
|
comingSoon: (label: string) => string;
|
|
@@ -114,24 +108,6 @@ export interface Strings {
|
|
|
114
108
|
delete: string;
|
|
115
109
|
close: string;
|
|
116
110
|
};
|
|
117
|
-
/** The table actions menu (toolbar button and right-click on a cell). */
|
|
118
|
-
tableMenu: {
|
|
119
|
-
menuLabel: string;
|
|
120
|
-
insertRowBefore: string;
|
|
121
|
-
insertRowAfter: string;
|
|
122
|
-
insertColumnBefore: string;
|
|
123
|
-
insertColumnAfter: string;
|
|
124
|
-
deleteRow: string;
|
|
125
|
-
deleteColumn: string;
|
|
126
|
-
deleteTable: string;
|
|
127
|
-
/** Plural forms, used when the selection spans several rows or columns. */
|
|
128
|
-
insertRowsBefore: string;
|
|
129
|
-
insertRowsAfter: string;
|
|
130
|
-
insertColumnsBefore: string;
|
|
131
|
-
insertColumnsAfter: string;
|
|
132
|
-
deleteRows: string;
|
|
133
|
-
deleteColumns: string;
|
|
134
|
-
};
|
|
135
111
|
link: {
|
|
136
112
|
menuLabel: string;
|
|
137
113
|
noUrl: string;
|
|
@@ -148,12 +124,6 @@ export interface Strings {
|
|
|
148
124
|
invalidUrl: string;
|
|
149
125
|
apply: string;
|
|
150
126
|
};
|
|
151
|
-
tableDialog: {
|
|
152
|
-
title: string;
|
|
153
|
-
rows: string;
|
|
154
|
-
columns: string;
|
|
155
|
-
headerRow: string;
|
|
156
|
-
};
|
|
157
127
|
imageDialog: {
|
|
158
128
|
titleInsert: string;
|
|
159
129
|
titleEdit: 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;
|
|
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
|
@@ -8,7 +8,6 @@ const en = {
|
|
|
8
8
|
editor: {
|
|
9
9
|
placeholder: 'Start writing…',
|
|
10
10
|
contentLabel: 'Editor content',
|
|
11
|
-
pageBreakLabel: 'Page break',
|
|
12
11
|
},
|
|
13
12
|
common: {
|
|
14
13
|
cancel: 'Cancel',
|
|
@@ -32,11 +31,8 @@ const en = {
|
|
|
32
31
|
noMatch: 'No match',
|
|
33
32
|
alignment: 'Alignment',
|
|
34
33
|
linkOptions: 'Link options',
|
|
35
|
-
tableOptions: 'Table options',
|
|
36
34
|
insertLink: 'Insert link (Ctrl+K)',
|
|
37
35
|
insertImage: 'Insert image',
|
|
38
|
-
insertPageBreak: 'Insert page break',
|
|
39
|
-
insertTable: 'Insert table',
|
|
40
36
|
insertHorizontalRule: 'Insert horizontal rule',
|
|
41
37
|
poetryBlocks: 'Poetry blocks',
|
|
42
38
|
comingSoon: (label) => `${label} (coming soon)`,
|
|
@@ -100,22 +96,6 @@ const en = {
|
|
|
100
96
|
delete: 'Delete',
|
|
101
97
|
close: 'Close',
|
|
102
98
|
},
|
|
103
|
-
tableMenu: {
|
|
104
|
-
menuLabel: 'Table',
|
|
105
|
-
insertRowBefore: 'Insert row before',
|
|
106
|
-
insertRowAfter: 'Insert row after',
|
|
107
|
-
insertColumnBefore: 'Insert column before',
|
|
108
|
-
insertColumnAfter: 'Insert column after',
|
|
109
|
-
deleteRow: 'Delete row',
|
|
110
|
-
deleteColumn: 'Delete column',
|
|
111
|
-
deleteTable: 'Delete table',
|
|
112
|
-
insertRowsBefore: 'Insert rows before',
|
|
113
|
-
insertRowsAfter: 'Insert rows after',
|
|
114
|
-
insertColumnsBefore: 'Insert columns before',
|
|
115
|
-
insertColumnsAfter: 'Insert columns after',
|
|
116
|
-
deleteRows: 'Delete rows',
|
|
117
|
-
deleteColumns: 'Delete columns',
|
|
118
|
-
},
|
|
119
99
|
link: {
|
|
120
100
|
menuLabel: 'Link',
|
|
121
101
|
noUrl: '(no URL)',
|
|
@@ -132,12 +112,6 @@ const en = {
|
|
|
132
112
|
invalidUrl: 'Enter a valid http(s), mailto, tel or relative URL',
|
|
133
113
|
apply: 'Apply',
|
|
134
114
|
},
|
|
135
|
-
tableDialog: {
|
|
136
|
-
title: 'Insert table',
|
|
137
|
-
rows: 'Rows',
|
|
138
|
-
columns: 'Columns',
|
|
139
|
-
headerRow: 'Header row',
|
|
140
|
-
},
|
|
141
115
|
imageDialog: {
|
|
142
116
|
titleInsert: 'Insert image',
|
|
143
117
|
titleEdit: 'Edit image',
|
|
@@ -201,7 +175,6 @@ const ur = {
|
|
|
201
175
|
editor: {
|
|
202
176
|
placeholder: 'لکھنا شروع کریں…',
|
|
203
177
|
contentLabel: 'ایڈیٹر کا مواد',
|
|
204
|
-
pageBreakLabel: 'صفحے کی تقسیم',
|
|
205
178
|
},
|
|
206
179
|
common: {
|
|
207
180
|
cancel: 'منسوخ کریں',
|
|
@@ -225,11 +198,8 @@ const ur = {
|
|
|
225
198
|
noMatch: 'کوئی مماثلت نہیں',
|
|
226
199
|
alignment: 'سیدھ',
|
|
227
200
|
linkOptions: 'لنک کے اختیارات',
|
|
228
|
-
tableOptions: 'جدول کے اختیارات',
|
|
229
201
|
insertLink: 'لنک شامل کریں (Ctrl+K)',
|
|
230
202
|
insertImage: 'تصویر شامل کریں',
|
|
231
|
-
insertPageBreak: 'صفحے کی تقسیم شامل کریں',
|
|
232
|
-
insertTable: 'جدول شامل کریں',
|
|
233
203
|
insertHorizontalRule: 'افقی لکیر شامل کریں',
|
|
234
204
|
poetryBlocks: 'شاعری کے بلاکس',
|
|
235
205
|
comingSoon: (label) => `${label} (جلد آ رہا ہے)`,
|
|
@@ -293,22 +263,6 @@ const ur = {
|
|
|
293
263
|
delete: 'حذف کریں',
|
|
294
264
|
close: 'بند کریں',
|
|
295
265
|
},
|
|
296
|
-
tableMenu: {
|
|
297
|
-
menuLabel: 'جدول',
|
|
298
|
-
insertRowBefore: 'پہلے قطار شامل کریں',
|
|
299
|
-
insertRowAfter: 'بعد میں قطار شامل کریں',
|
|
300
|
-
insertColumnBefore: 'پہلے کالم شامل کریں',
|
|
301
|
-
insertColumnAfter: 'بعد میں کالم شامل کریں',
|
|
302
|
-
deleteRow: 'قطار حذف کریں',
|
|
303
|
-
deleteColumn: 'کالم حذف کریں',
|
|
304
|
-
deleteTable: 'جدول حذف کریں',
|
|
305
|
-
insertRowsBefore: 'پہلے قطاریں شامل کریں',
|
|
306
|
-
insertRowsAfter: 'بعد میں قطاریں شامل کریں',
|
|
307
|
-
insertColumnsBefore: 'پہلے کالمز شامل کریں',
|
|
308
|
-
insertColumnsAfter: 'بعد میں کالمز شامل کریں',
|
|
309
|
-
deleteRows: 'قطاریں حذف کریں',
|
|
310
|
-
deleteColumns: 'کالمز حذف کریں',
|
|
311
|
-
},
|
|
312
266
|
link: {
|
|
313
267
|
menuLabel: 'لنک',
|
|
314
268
|
noUrl: '(کوئی یو آر ایل نہیں)',
|
|
@@ -325,12 +279,6 @@ const ur = {
|
|
|
325
279
|
invalidUrl: 'براہِ کرم ایک درست http(s)، mailto، tel یا رشتہ دار یو آر ایل درج کریں',
|
|
326
280
|
apply: 'لاگو کریں',
|
|
327
281
|
},
|
|
328
|
-
tableDialog: {
|
|
329
|
-
title: 'جدول شامل کریں',
|
|
330
|
-
rows: 'قطاریں',
|
|
331
|
-
columns: 'کالم',
|
|
332
|
-
headerRow: 'سرِ فہرست قطار',
|
|
333
|
-
},
|
|
334
282
|
imageDialog: {
|
|
335
283
|
titleInsert: 'تصویر شامل کریں',
|
|
336
284
|
titleEdit: 'تصویر میں ترمیم کریں',
|
|
@@ -394,7 +342,6 @@ const paShahmukhi = {
|
|
|
394
342
|
editor: {
|
|
395
343
|
placeholder: 'لکھنا شروع کرو…',
|
|
396
344
|
contentLabel: 'ایڈیٹر دی سامگری',
|
|
397
|
-
pageBreakLabel: 'صفحے دی ونڈ',
|
|
398
345
|
},
|
|
399
346
|
common: {
|
|
400
347
|
cancel: 'رد کرو',
|
|
@@ -418,11 +365,8 @@ const paShahmukhi = {
|
|
|
418
365
|
noMatch: 'کوئی نئیں ملیا',
|
|
419
366
|
alignment: 'سیدھ',
|
|
420
367
|
linkOptions: 'لنک دے اختیار',
|
|
421
|
-
tableOptions: 'ٹیبل دے اختیار',
|
|
422
368
|
insertLink: 'لنک پاؤ (Ctrl+K)',
|
|
423
369
|
insertImage: 'تصویر پاؤ',
|
|
424
|
-
insertPageBreak: 'صفحے دی ونڈ پاؤ',
|
|
425
|
-
insertTable: 'ٹیبل پاؤ',
|
|
426
370
|
insertHorizontalRule: 'لیٹی لکیر پاؤ',
|
|
427
371
|
poetryBlocks: 'شاعری بلاک',
|
|
428
372
|
comingSoon: (label) => `${label} (چھیتی آ رہا اے)`,
|
|
@@ -486,22 +430,6 @@ const paShahmukhi = {
|
|
|
486
430
|
delete: 'مٹاؤ',
|
|
487
431
|
close: 'بند کرو',
|
|
488
432
|
},
|
|
489
|
-
tableMenu: {
|
|
490
|
-
menuLabel: 'ٹیبل',
|
|
491
|
-
insertRowBefore: 'پہلاں قطار پاؤ',
|
|
492
|
-
insertRowAfter: 'بعد وچ قطار پاؤ',
|
|
493
|
-
insertColumnBefore: 'پہلاں کالم پاؤ',
|
|
494
|
-
insertColumnAfter: 'بعد وچ کالم پاؤ',
|
|
495
|
-
deleteRow: 'قطار مٹاؤ',
|
|
496
|
-
deleteColumn: 'کالم مٹاؤ',
|
|
497
|
-
deleteTable: 'ٹیبل مٹاؤ',
|
|
498
|
-
insertRowsBefore: 'پہلاں قطاراں پاؤ',
|
|
499
|
-
insertRowsAfter: 'بعد وچ قطاراں پاؤ',
|
|
500
|
-
insertColumnsBefore: 'پہلاں کالماں پاؤ',
|
|
501
|
-
insertColumnsAfter: 'بعد وچ کالماں پاؤ',
|
|
502
|
-
deleteRows: 'قطاراں مٹاؤ',
|
|
503
|
-
deleteColumns: 'کالماں مٹاؤ',
|
|
504
|
-
},
|
|
505
433
|
link: {
|
|
506
434
|
menuLabel: 'لنک',
|
|
507
435
|
noUrl: '(کوئی یو آر ایل نئیں)',
|
|
@@ -518,12 +446,6 @@ const paShahmukhi = {
|
|
|
518
446
|
invalidUrl: 'کِرپا کر کے صحیح http(s)، mailto، tel یا نسبتی یو آر ایل پاؤ',
|
|
519
447
|
apply: 'لاگو کرو',
|
|
520
448
|
},
|
|
521
|
-
tableDialog: {
|
|
522
|
-
title: 'ٹیبل پاؤ',
|
|
523
|
-
rows: 'قطاراں',
|
|
524
|
-
columns: 'کالم',
|
|
525
|
-
headerRow: 'سرکڑی قطار',
|
|
526
|
-
},
|
|
527
449
|
imageDialog: {
|
|
528
450
|
titleInsert: 'تصویر پاؤ',
|
|
529
451
|
titleEdit: 'تصویر وچ تبدیلی کرو',
|
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;AAOlD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,EAQ5C,CAAC"}
|
package/dist/nodes.js
CHANGED
|
@@ -2,9 +2,7 @@ import { HeadingNode, QuoteNode } from '@lexical/rich-text';
|
|
|
2
2
|
import { ListItemNode, ListNode } from '@lexical/list';
|
|
3
3
|
import { LinkNode } from '@lexical/link';
|
|
4
4
|
import { HorizontalRuleNode } from '@lexical/react/LexicalHorizontalRuleNode';
|
|
5
|
-
import { TableCellNode, TableNode, TableRowNode } from '@lexical/table';
|
|
6
5
|
import { ImageNode } from './image/ImageNode.js';
|
|
7
|
-
import { PageBreakNode } from './blocks/PageBreakNode.js';
|
|
8
6
|
/**
|
|
9
7
|
* Node types registered on the editor at construction time. Per
|
|
10
8
|
* editor-architecture-design.md §2, node registration cannot be conditional
|
|
@@ -21,9 +19,5 @@ export const EDITOR_NODES = [
|
|
|
21
19
|
ListItemNode,
|
|
22
20
|
LinkNode,
|
|
23
21
|
HorizontalRuleNode,
|
|
24
|
-
TableNode,
|
|
25
|
-
TableRowNode,
|
|
26
|
-
TableCellNode,
|
|
27
22
|
ImageNode,
|
|
28
|
-
PageBreakNode,
|
|
29
23
|
];
|
package/dist/theme/editor.css
CHANGED
|
@@ -51,12 +51,6 @@
|
|
|
51
51
|
pointer-events: none;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/* pointer-events is inherited, so without this every menu, dropdown and dialog
|
|
55
|
-
portaled into the (pointer-transparent) anchor would be unclickable. */
|
|
56
|
-
.likhari-portal-target > * {
|
|
57
|
-
pointer-events: auto;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
54
|
.likhari-toolbar-group {
|
|
61
55
|
display: flex;
|
|
62
56
|
align-items: center;
|
|
@@ -259,76 +253,6 @@
|
|
|
259
253
|
margin: 1.5em 0;
|
|
260
254
|
}
|
|
261
255
|
|
|
262
|
-
/* Page break — a print/export concept with no visual meaning while editing
|
|
263
|
-
on screen, so it gets its own clearly-labeled dashed marker rather than
|
|
264
|
-
masquerading as a horizontal rule. The actual page-break behavior only
|
|
265
|
-
takes effect when printing (lexical-editor-spec.md §4.3/§4.6). */
|
|
266
|
-
.likhari-page-break {
|
|
267
|
-
display: flex;
|
|
268
|
-
align-items: center;
|
|
269
|
-
gap: 8px;
|
|
270
|
-
margin: 1.5em 0;
|
|
271
|
-
font-size: 12px;
|
|
272
|
-
cursor: default;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
.likhari-page-break-line {
|
|
276
|
-
flex: 1 1 auto;
|
|
277
|
-
border-top: 1px dashed var(--editor-line);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
.likhari-page-break-label {
|
|
281
|
-
color: var(--editor-ink-soft);
|
|
282
|
-
white-space: nowrap;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
.likhari-page-break-selected {
|
|
286
|
-
outline: 2px solid var(--editor-accent);
|
|
287
|
-
outline-offset: 2px;
|
|
288
|
-
border-radius: 4px;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
@media print {
|
|
292
|
-
.likhari-page-break {
|
|
293
|
-
page-break-after: always;
|
|
294
|
-
/* Hide the on-screen marker itself when actually printing — the
|
|
295
|
-
browser's own pagination (triggered by page-break-after) is what
|
|
296
|
-
matters there, not the editing-time label. */
|
|
297
|
-
visibility: hidden;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/* Tables — cell merge/split is deliberately out of scope for now (a flagged
|
|
302
|
-
open risk, lexical-editor-spec.md §12 item 3, needing its own scope
|
|
303
|
-
decision); TablePlugin is configured with hasCellMerge={false} to keep
|
|
304
|
-
every table a plain grid until that's resolved. */
|
|
305
|
-
.likhari-table {
|
|
306
|
-
border-collapse: collapse;
|
|
307
|
-
margin: 1em 0;
|
|
308
|
-
width: 100%;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
.likhari-table-row {
|
|
312
|
-
border-bottom: 1px solid var(--editor-line);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.likhari-table-cell {
|
|
316
|
-
border: 1px solid var(--editor-line);
|
|
317
|
-
padding: 6px 10px;
|
|
318
|
-
min-width: 72px;
|
|
319
|
-
vertical-align: top;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.likhari-table-cell-header {
|
|
323
|
-
background: var(--editor-paper-dim);
|
|
324
|
-
font-weight: 600;
|
|
325
|
-
text-align: start;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
.likhari-table-cell-selected {
|
|
329
|
-
background: var(--editor-accent-soft);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
256
|
/* Images — block-level figure; the caption is static text (edited in the
|
|
333
257
|
image's dialog), and a selected image gets a corner resize handle. */
|
|
334
258
|
.likhari-image-block {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../src/theme/editorTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,kBA8BzB,CAAC"}
|
|
@@ -33,10 +33,4 @@ export const editorTheme = {
|
|
|
33
33
|
},
|
|
34
34
|
hr: 'likhari-hr',
|
|
35
35
|
image: 'likhari-image-block',
|
|
36
|
-
pageBreak: 'likhari-page-break',
|
|
37
|
-
table: 'likhari-table',
|
|
38
|
-
tableRow: 'likhari-table-row',
|
|
39
|
-
tableCell: 'likhari-table-cell',
|
|
40
|
-
tableCellHeader: 'likhari-table-cell-header',
|
|
41
|
-
tableCellSelected: 'likhari-table-cell-selected',
|
|
42
36
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inshapardaz/likhari-react",
|
|
3
|
-
"version": "0.1.9
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "React implementation of the Likhari editor, built on @lexical/react.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
"@lexical/react": "^0.20.0",
|
|
39
39
|
"@lexical/rich-text": "^0.20.0",
|
|
40
40
|
"@lexical/selection": "^0.20.0",
|
|
41
|
-
"@lexical/table": "^0.20.0",
|
|
42
41
|
"@lexical/utils": "^0.20.0",
|
|
43
42
|
"@inshapardaz/likhari-converters": "^0.1.0",
|
|
44
43
|
"@inshapardaz/likhari-core": "^0.1.0",
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type ReactElement } from 'react';
|
|
2
|
-
import { DecoratorNode, type DOMConversionMap, type DOMExportOutput, type EditorConfig, type LexicalCommand, type LexicalNode, type SerializedLexicalNode } from 'lexical';
|
|
3
|
-
export declare const INSERT_PAGE_BREAK_COMMAND: LexicalCommand<void>;
|
|
4
|
-
export type SerializedPageBreakNode = SerializedLexicalNode;
|
|
5
|
-
/**
|
|
6
|
-
* A manual page break — a print/paginated-export concept with no native
|
|
7
|
-
* Lexical node (lexical-editor-spec.md §4.3/§4.6). Renders as a visible
|
|
8
|
-
* dashed marker while editing, and as `page-break-after: always` both live
|
|
9
|
-
* (a print stylesheet, editor.css) and in exported HTML (`exportDOM`).
|
|
10
|
-
*
|
|
11
|
-
* Mirrors @lexical/react's HorizontalRuleNode pattern: `createDOM` returns
|
|
12
|
-
* the actual visible element (the click target `PageBreakComponent` wires
|
|
13
|
-
* selection/delete against), rather than `decorate()` rendering visuals.
|
|
14
|
-
*/
|
|
15
|
-
export declare class PageBreakNode extends DecoratorNode<ReactElement> {
|
|
16
|
-
static getType(): string;
|
|
17
|
-
static clone(node: PageBreakNode): PageBreakNode;
|
|
18
|
-
static importJSON(): PageBreakNode;
|
|
19
|
-
exportJSON(): SerializedPageBreakNode;
|
|
20
|
-
static importDOM(): DOMConversionMap | null;
|
|
21
|
-
exportDOM(): DOMExportOutput;
|
|
22
|
-
createDOM(config: EditorConfig): HTMLElement;
|
|
23
|
-
getTextContent(): string;
|
|
24
|
-
isInline(): false;
|
|
25
|
-
updateDOM(): boolean;
|
|
26
|
-
decorate(): import("react").JSX.Element;
|
|
27
|
-
}
|
|
28
|
-
export declare function $createPageBreakNode(): PageBreakNode;
|
|
29
|
-
export declare function $isPageBreakNode(node: LexicalNode | null | undefined): node is PageBreakNode;
|
|
30
|
-
//# sourceMappingURL=PageBreakNode.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PageBreakNode.d.ts","sourceRoot":"","sources":["../../src/blocks/PageBreakNode.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAKlE,OAAO,EAOL,aAAa,EAGb,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAEhB,KAAK,qBAAqB,EAC3B,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,yBAAyB,EAAE,cAAc,CAAC,IAAI,CAA8C,CAAC;AAE1G,MAAM,MAAM,uBAAuB,GAAG,qBAAqB,CAAC;AA6D5D;;;;;;;;;GASG;AACH,qBAAa,aAAc,SAAQ,aAAa,CAAC,YAAY,CAAC;IAC5D,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa;IAIhD,MAAM,CAAC,UAAU,IAAI,aAAa;IAIlC,UAAU,IAAI,uBAAuB;IAIrC,MAAM,CAAC,SAAS,IAAI,gBAAgB,GAAG,IAAI;IAS3C,SAAS,IAAI,eAAe;IAO5B,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW;IAM5C,cAAc,IAAI,MAAM;IAIxB,QAAQ,IAAI,KAAK;IAIjB,SAAS,IAAI,OAAO;IAIpB,QAAQ;CAGT;AAED,wBAAgB,oBAAoB,IAAI,aAAa,CAEpD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,aAAa,CAE5F"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect } from 'react';
|
|
3
|
-
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
|
-
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
5
|
-
import { addClassNamesToElement, mergeRegister, removeClassNamesFromElement } from '@lexical/utils';
|
|
6
|
-
import { useUiStrings } from '../i18n/useStrings.js';
|
|
7
|
-
import { $applyNodeReplacement, $getSelection, $isNodeSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, createCommand, DecoratorNode, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, } from 'lexical';
|
|
8
|
-
export const INSERT_PAGE_BREAK_COMMAND = createCommand('INSERT_PAGE_BREAK_COMMAND');
|
|
9
|
-
const SELECTED_CLASS_NAME = 'likhari-page-break-selected';
|
|
10
|
-
function PageBreakComponent({ nodeKey }) {
|
|
11
|
-
const [editor] = useLexicalComposerContext();
|
|
12
|
-
const strings = useUiStrings();
|
|
13
|
-
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(nodeKey);
|
|
14
|
-
const onDelete = useCallback((event) => {
|
|
15
|
-
const selection = $getSelection();
|
|
16
|
-
if (isSelected && $isNodeSelection(selection)) {
|
|
17
|
-
event.preventDefault();
|
|
18
|
-
editor.update(() => {
|
|
19
|
-
selection.getNodes().forEach((node) => {
|
|
20
|
-
if ($isPageBreakNode(node))
|
|
21
|
-
node.remove();
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
return false;
|
|
26
|
-
}, [editor, isSelected]);
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
return mergeRegister(editor.registerCommand(CLICK_COMMAND, (event) => {
|
|
29
|
-
const element = editor.getElementByKey(nodeKey);
|
|
30
|
-
// The marker is made of child spans (the label and two lines), so a
|
|
31
|
-
// click almost never lands on the outer element itself.
|
|
32
|
-
if (!element || !element.contains(event.target))
|
|
33
|
-
return false;
|
|
34
|
-
if (!event.shiftKey)
|
|
35
|
-
clearSelection();
|
|
36
|
-
setSelected(!isSelected);
|
|
37
|
-
return true;
|
|
38
|
-
}, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_DELETE_COMMAND, onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_BACKSPACE_COMMAND, onDelete, COMMAND_PRIORITY_LOW));
|
|
39
|
-
}, [clearSelection, editor, isSelected, nodeKey, onDelete, setSelected]);
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
const element = editor.getElementByKey(nodeKey);
|
|
42
|
-
if (!element)
|
|
43
|
-
return;
|
|
44
|
-
if (isSelected)
|
|
45
|
-
addClassNamesToElement(element, SELECTED_CLASS_NAME);
|
|
46
|
-
else
|
|
47
|
-
removeClassNamesFromElement(element, SELECTED_CLASS_NAME);
|
|
48
|
-
}, [editor, isSelected, nodeKey]);
|
|
49
|
-
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "likhari-page-break-line", "aria-hidden": "true" }), _jsx("span", { className: "likhari-page-break-label", children: strings.editor.pageBreakLabel }), _jsx("span", { className: "likhari-page-break-line", "aria-hidden": "true" })] }));
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* A manual page break — a print/paginated-export concept with no native
|
|
53
|
-
* Lexical node (lexical-editor-spec.md §4.3/§4.6). Renders as a visible
|
|
54
|
-
* dashed marker while editing, and as `page-break-after: always` both live
|
|
55
|
-
* (a print stylesheet, editor.css) and in exported HTML (`exportDOM`).
|
|
56
|
-
*
|
|
57
|
-
* Mirrors @lexical/react's HorizontalRuleNode pattern: `createDOM` returns
|
|
58
|
-
* the actual visible element (the click target `PageBreakComponent` wires
|
|
59
|
-
* selection/delete against), rather than `decorate()` rendering visuals.
|
|
60
|
-
*/
|
|
61
|
-
export class PageBreakNode extends DecoratorNode {
|
|
62
|
-
static getType() {
|
|
63
|
-
return 'page-break';
|
|
64
|
-
}
|
|
65
|
-
static clone(node) {
|
|
66
|
-
return new PageBreakNode(node.__key);
|
|
67
|
-
}
|
|
68
|
-
static importJSON() {
|
|
69
|
-
return $createPageBreakNode();
|
|
70
|
-
}
|
|
71
|
-
exportJSON() {
|
|
72
|
-
return { type: 'page-break', version: 1 };
|
|
73
|
-
}
|
|
74
|
-
static importDOM() {
|
|
75
|
-
return {
|
|
76
|
-
div: (domNode) => {
|
|
77
|
-
if (!domNode.hasAttribute('data-likhari-page-break'))
|
|
78
|
-
return null;
|
|
79
|
-
return { conversion: () => ({ node: $createPageBreakNode() }), priority: 2 };
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
exportDOM() {
|
|
84
|
-
const element = document.createElement('div');
|
|
85
|
-
element.setAttribute('data-likhari-page-break', '');
|
|
86
|
-
element.style.pageBreakAfter = 'always';
|
|
87
|
-
return { element };
|
|
88
|
-
}
|
|
89
|
-
createDOM(config) {
|
|
90
|
-
const element = document.createElement('div');
|
|
91
|
-
addClassNamesToElement(element, config.theme.pageBreak ?? 'likhari-page-break');
|
|
92
|
-
return element;
|
|
93
|
-
}
|
|
94
|
-
getTextContent() {
|
|
95
|
-
return '\n';
|
|
96
|
-
}
|
|
97
|
-
isInline() {
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
updateDOM() {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
decorate() {
|
|
104
|
-
return _jsx(PageBreakComponent, { nodeKey: this.__key });
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
export function $createPageBreakNode() {
|
|
108
|
-
return $applyNodeReplacement(new PageBreakNode());
|
|
109
|
-
}
|
|
110
|
-
export function $isPageBreakNode(node) {
|
|
111
|
-
return node instanceof PageBreakNode;
|
|
112
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface TableDialogValue {
|
|
2
|
-
rows: number;
|
|
3
|
-
columns: number;
|
|
4
|
-
headerRow: boolean;
|
|
5
|
-
}
|
|
6
|
-
export interface TableDialogProps {
|
|
7
|
-
opened: boolean;
|
|
8
|
-
onSubmit: (value: TableDialogValue) => void;
|
|
9
|
-
onClose: () => void;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Insert-table dialog: rows x columns and an optional header row. Cell
|
|
13
|
-
* merge/split is intentionally not offered anywhere in this dialog or the
|
|
14
|
-
* table it creates — see the comment on `TablePlugin` in `EditorRoot.tsx`.
|
|
15
|
-
*/
|
|
16
|
-
export declare function TableDialog({ opened, onSubmit, onClose }: TableDialogProps): import("react").JSX.Element;
|
|
17
|
-
//# sourceMappingURL=TableDialog.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TableDialog.d.ts","sourceRoot":"","sources":["../../src/components/TableDialog.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAOD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,gBAAgB,+BAiD1E"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
3
|
-
import { Button, Checkbox, Group, Modal, NumberInput } from '@mantine/core';
|
|
4
|
-
import { useUiStrings } from '../i18n/useStrings.js';
|
|
5
|
-
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
6
|
-
const MIN_DIMENSION = 1;
|
|
7
|
-
const MAX_DIMENSION = 20;
|
|
8
|
-
const DEFAULT_ROWS = 3;
|
|
9
|
-
const DEFAULT_COLUMNS = 3;
|
|
10
|
-
/**
|
|
11
|
-
* Insert-table dialog: rows x columns and an optional header row. Cell
|
|
12
|
-
* merge/split is intentionally not offered anywhere in this dialog or the
|
|
13
|
-
* table it creates — see the comment on `TablePlugin` in `EditorRoot.tsx`.
|
|
14
|
-
*/
|
|
15
|
-
export function TableDialog({ opened, onSubmit, onClose }) {
|
|
16
|
-
const strings = useUiStrings();
|
|
17
|
-
const portalTarget = usePortalTarget();
|
|
18
|
-
const [rows, setRows] = useState(DEFAULT_ROWS);
|
|
19
|
-
const [columns, setColumns] = useState(DEFAULT_COLUMNS);
|
|
20
|
-
const [headerRow, setHeaderRow] = useState(true);
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (!opened)
|
|
23
|
-
return;
|
|
24
|
-
setRows(DEFAULT_ROWS);
|
|
25
|
-
setColumns(DEFAULT_COLUMNS);
|
|
26
|
-
setHeaderRow(true);
|
|
27
|
-
}, [opened]);
|
|
28
|
-
const handleSubmit = (e) => {
|
|
29
|
-
e.preventDefault();
|
|
30
|
-
onSubmit({ rows, columns, headerRow });
|
|
31
|
-
};
|
|
32
|
-
return (_jsx(Modal, { opened: opened, onClose: onClose, title: strings.tableDialog.title, centered: true, size: "sm", portalProps: { target: portalTarget }, children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(Group, { grow: true, align: "flex-end", children: [_jsx(NumberInput, { label: strings.tableDialog.rows, min: MIN_DIMENSION, max: MAX_DIMENSION, value: rows, onChange: (v) => setRows(typeof v === 'number' ? v : DEFAULT_ROWS), "data-autofocus": true }), _jsx(NumberInput, { label: strings.tableDialog.columns, min: MIN_DIMENSION, max: MAX_DIMENSION, value: columns, onChange: (v) => setColumns(typeof v === 'number' ? v : DEFAULT_COLUMNS) })] }), _jsx(Checkbox, { mt: "sm", label: strings.tableDialog.headerRow, checked: headerRow, onChange: (e) => setHeaderRow(e.currentTarget.checked) }), _jsxs(Group, { justify: "flex-end", gap: "xs", mt: "md", children: [_jsx(Button, { variant: "default", onClick: onClose, children: strings.common.cancel }), _jsx(Button, { type: "submit", children: strings.common.insert })] })] }) }));
|
|
33
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PageBreakPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/PageBreakPlugin.tsx"],"names":[],"mappings":"AAMA,+FAA+F;AAC/F,wBAAgB,eAAe,SAiB9B"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
3
|
-
import { $getSelection, $isRangeSelection, COMMAND_PRIORITY_EDITOR } from 'lexical';
|
|
4
|
-
import { $insertNodeToNearestRoot } from '@lexical/utils';
|
|
5
|
-
import { $createPageBreakNode, INSERT_PAGE_BREAK_COMMAND } from '../blocks/PageBreakNode.js';
|
|
6
|
-
/** Registers INSERT_PAGE_BREAK_COMMAND — mirrors @lexical/react's own HorizontalRulePlugin. */
|
|
7
|
-
export function PageBreakPlugin() {
|
|
8
|
-
const [editor] = useLexicalComposerContext();
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
return editor.registerCommand(INSERT_PAGE_BREAK_COMMAND, () => {
|
|
11
|
-
const selection = $getSelection();
|
|
12
|
-
if (!$isRangeSelection(selection))
|
|
13
|
-
return false;
|
|
14
|
-
$insertNodeToNearestRoot($createPageBreakNode());
|
|
15
|
-
return true;
|
|
16
|
-
}, COMMAND_PRIORITY_EDITOR);
|
|
17
|
-
}, [editor]);
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/** How many rows and columns the selection spans (1 × 1 for a caret in a cell, 0 × 0 outside a table). */
|
|
2
|
-
export declare function $getTableSelectionSize(): {
|
|
3
|
-
rows: number;
|
|
4
|
-
columns: number;
|
|
5
|
-
};
|
|
6
|
-
/**
|
|
7
|
-
* Inserts as many rows as the selection spans, before its first row or after
|
|
8
|
-
* its last. Lexical's own insert works from the selection's focus cell and adds
|
|
9
|
-
* one row, so with several rows selected it would land mid-selection.
|
|
10
|
-
*/
|
|
11
|
-
export declare function $insertTableRows(insertAfter: boolean): void;
|
|
12
|
-
/** Like $insertTableRows, for columns. "Before" is the column index below the
|
|
13
|
-
* first selected one (the right-hand side in a right-to-left table). */
|
|
14
|
-
export declare function $insertTableColumns(insertAfter: boolean): void;
|
|
15
|
-
/** Deletes every row the selection touches (Lexical handles a multi-cell selection). */
|
|
16
|
-
export declare function $deleteTableRows(): void;
|
|
17
|
-
/** Deletes every column the selection touches. */
|
|
18
|
-
export declare function $deleteTableColumns(): void;
|
|
19
|
-
/** Removes the whole table the selection is in. */
|
|
20
|
-
export declare function $deleteTable(): void;
|
|
21
|
-
//# sourceMappingURL=tableActions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tableActions.d.ts","sourceRoot":"","sources":["../../src/table/tableActions.ts"],"names":[],"mappings":"AA2BA,0GAA0G;AAC1G,wBAAgB,sBAAsB,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAS1E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAS3D;AAED;wEACwE;AACxE,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAQ9D;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED,kDAAkD;AAClD,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,mDAAmD;AACnD,wBAAgB,YAAY,IAAI,IAAI,CAInC"}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { $deleteTableColumn__EXPERIMENTAL, $deleteTableRow__EXPERIMENTAL, $getTableCellNodeFromLexicalNode, $getTableColumnIndexFromTableCellNode, $getTableNodeFromLexicalNodeOrThrow, $getTableRowIndexFromTableCellNode, $insertTableColumn__EXPERIMENTAL, $insertTableRow__EXPERIMENTAL, $isTableCellNode, $isTableSelection, } from '@lexical/table';
|
|
2
|
-
import { $getSelection, $isRangeSelection } from 'lexical';
|
|
3
|
-
/** Table cells the selection covers: the caret's own cell, or every cell of a
|
|
4
|
-
* multi-cell selection. Empty when the selection isn't in a table. */
|
|
5
|
-
function $selectedCells() {
|
|
6
|
-
const selection = $getSelection();
|
|
7
|
-
if ($isTableSelection(selection))
|
|
8
|
-
return selection.getNodes().filter($isTableCellNode);
|
|
9
|
-
if ($isRangeSelection(selection)) {
|
|
10
|
-
const cell = $getTableCellNodeFromLexicalNode(selection.anchor.getNode());
|
|
11
|
-
return cell ? [cell] : [];
|
|
12
|
-
}
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
/** How many rows and columns the selection spans (1 × 1 for a caret in a cell, 0 × 0 outside a table). */
|
|
16
|
-
export function $getTableSelectionSize() {
|
|
17
|
-
const cells = $selectedCells();
|
|
18
|
-
if (cells.length === 0)
|
|
19
|
-
return { rows: 0, columns: 0 };
|
|
20
|
-
const rows = cells.map($getTableRowIndexFromTableCellNode);
|
|
21
|
-
const columns = cells.map($getTableColumnIndexFromTableCellNode);
|
|
22
|
-
return {
|
|
23
|
-
rows: Math.max(...rows) - Math.min(...rows) + 1,
|
|
24
|
-
columns: Math.max(...columns) - Math.min(...columns) + 1,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Inserts as many rows as the selection spans, before its first row or after
|
|
29
|
-
* its last. Lexical's own insert works from the selection's focus cell and adds
|
|
30
|
-
* one row, so with several rows selected it would land mid-selection.
|
|
31
|
-
*/
|
|
32
|
-
export function $insertTableRows(insertAfter) {
|
|
33
|
-
const cells = $selectedCells();
|
|
34
|
-
if (cells.length === 0)
|
|
35
|
-
return;
|
|
36
|
-
const rows = cells.map($getTableRowIndexFromTableCellNode);
|
|
37
|
-
const first = Math.min(...rows);
|
|
38
|
-
const last = Math.max(...rows);
|
|
39
|
-
// Park the caret in a cell on the edge row; every insert then lands right next to it.
|
|
40
|
-
cells[rows.indexOf(insertAfter ? last : first)].selectEnd();
|
|
41
|
-
for (let i = 0; i <= last - first; i++)
|
|
42
|
-
$insertTableRow__EXPERIMENTAL(insertAfter);
|
|
43
|
-
}
|
|
44
|
-
/** Like $insertTableRows, for columns. "Before" is the column index below the
|
|
45
|
-
* first selected one (the right-hand side in a right-to-left table). */
|
|
46
|
-
export function $insertTableColumns(insertAfter) {
|
|
47
|
-
const cells = $selectedCells();
|
|
48
|
-
if (cells.length === 0)
|
|
49
|
-
return;
|
|
50
|
-
const columns = cells.map($getTableColumnIndexFromTableCellNode);
|
|
51
|
-
const first = Math.min(...columns);
|
|
52
|
-
const last = Math.max(...columns);
|
|
53
|
-
cells[columns.indexOf(insertAfter ? last : first)].selectEnd();
|
|
54
|
-
for (let i = 0; i <= last - first; i++)
|
|
55
|
-
$insertTableColumn__EXPERIMENTAL(insertAfter);
|
|
56
|
-
}
|
|
57
|
-
/** Deletes every row the selection touches (Lexical handles a multi-cell selection). */
|
|
58
|
-
export function $deleteTableRows() {
|
|
59
|
-
$deleteTableRow__EXPERIMENTAL();
|
|
60
|
-
}
|
|
61
|
-
/** Deletes every column the selection touches. */
|
|
62
|
-
export function $deleteTableColumns() {
|
|
63
|
-
$deleteTableColumn__EXPERIMENTAL();
|
|
64
|
-
}
|
|
65
|
-
/** Removes the whole table the selection is in. */
|
|
66
|
-
export function $deleteTable() {
|
|
67
|
-
const selection = $getSelection();
|
|
68
|
-
const anchor = $isRangeSelection(selection) || $isTableSelection(selection) ? selection.anchor.getNode() : null;
|
|
69
|
-
if (anchor)
|
|
70
|
-
$getTableNodeFromLexicalNodeOrThrow(anchor).remove();
|
|
71
|
-
}
|