@inshapardaz/likhari-react 0.1.48-dev.354 → 0.1.48-dev.356
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA2CA,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAA2B,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAmDtF,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAkF,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAI1I,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -36,7 +36,7 @@ import { CANVAS_FONT_DEFAULTS, DEFAULT_FONT_OPTIONS, FONT_SIZES_PX, ZOOM_LEVELS_
|
|
|
36
36
|
import { setStyleProperty } from '../utils/style.js';
|
|
37
37
|
import { useStrings } from '../i18n/useStrings.js';
|
|
38
38
|
import { usePortalTarget } from '../PortalTargetContext.js';
|
|
39
|
-
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconArrowsJoin, IconBold, IconClearFormatting, IconDeviceFloppy, IconChevronDown, IconChevronUp, IconDots, IconHelpCircle, 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, IconClipboard, IconCopy, IconCut, IconSearch, IconSelectAll, IconColumns1, IconColumns2, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconArrowsMaximize, IconArrowsMinimize, IconArrowsShuffle, IconTable, IconTableMinus, IconTrash, IconTableOptions, IconMinus, IconPlus, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
39
|
+
import { IconAbc, IconAlignCenter, IconAlignJustified, IconAlignLeft, IconAlignRight, IconArrowBackUp, IconArrowForwardUp, IconArrowsJoin, IconBold, IconClearFormatting, IconDeviceFloppy, IconBook, IconChevronDown, IconChevronUp, IconDots, IconHelpCircle, 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, IconClipboard, IconCopy, IconCut, IconSearch, IconSelectAll, IconColumns1, IconColumns2, IconNumber1Small, IconRowInsertBottom, IconRowInsertTop, IconRowRemove, IconArrowsMaximize, IconArrowsMinimize, IconArrowsShuffle, IconTable, IconTableMinus, IconTrash, IconTableOptions, IconMinus, IconPlus, IconTextSize, IconTypography, IconUnderline, IconWand, } from '@tabler/icons-react';
|
|
40
40
|
/** Sentinel for "no inline style": Lexical returns the default it is given when
|
|
41
41
|
* the selection has none, so this tells "unstyled" (show the canvas default)
|
|
42
42
|
* apart from "styled with a value the dropdown doesn't list" (show nothing). */
|
|
@@ -70,6 +70,12 @@ const CONTEXT_MENU_WIDTH = 220;
|
|
|
70
70
|
const CONTEXT_MENU_VIEWPORT_PADDING = 8;
|
|
71
71
|
/** `likhari-context-menu` (editor.css) shrinks the icons to match the smaller text. */
|
|
72
72
|
const CONTEXT_MENU_CLASS_NAMES = { dropdown: 'likhari-context-menu' };
|
|
73
|
+
/** The submenus: opened to the side, flipped or shifted to stay in the window, and positioned against the window (`fixed`) so
|
|
74
|
+
* the menu's own scrolling does not clip them. */
|
|
75
|
+
const CONTEXT_SUBMENU_PROPS = {
|
|
76
|
+
floatingStrategy: 'fixed',
|
|
77
|
+
middlewares: { flip: true, shift: { crossAxis: true, padding: CONTEXT_MENU_VIEWPORT_PADDING }, size: { padding: CONTEXT_MENU_VIEWPORT_PADDING } },
|
|
78
|
+
};
|
|
73
79
|
const CONTEXT_MENU_STYLES = {
|
|
74
80
|
dropdown: { overflowY: 'auto', padding: 4 },
|
|
75
81
|
item: { fontSize: 'var(--mantine-font-size-xs)', padding: '4px 8px', minHeight: 0 },
|
|
@@ -190,8 +196,8 @@ function CommandItem({ mode, icon: Icon, label, onClick, disabled, color, }) {
|
|
|
190
196
|
}
|
|
191
197
|
return (_jsx(Menu.Item, { color: color, disabled: disabled, leftSection: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onClick, children: label }));
|
|
192
198
|
}
|
|
193
|
-
/** A group heading in a menu; the ribbon's tab already
|
|
194
|
-
const ItemLabel = ({ mode, children }) => (mode === '
|
|
199
|
+
/** A group heading in a menu; the ribbon's tab and a submenu's parent item already name the group, so they show nothing. */
|
|
200
|
+
const ItemLabel = ({ mode, children }) => (mode === 'menu' ? _jsx(Menu.Label, { children: children }) : null);
|
|
195
201
|
const ItemDivider = ({ mode }) => (mode === 'ribbon' ? _jsx(MantineToolbar.Divider, {}) : _jsx(Menu.Divider, {}));
|
|
196
202
|
function LinkMenuItems({ url, onEdit, onRemove, strings, mode = 'menu' }) {
|
|
197
203
|
// Only offer the link as clickable if it's a URL the editor would have accepted.
|
|
@@ -666,6 +672,14 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
666
672
|
}
|
|
667
673
|
}
|
|
668
674
|
}
|
|
675
|
+
// A misspelled word's menu is its spelling fixes and the clipboard, nothing else: no synonyms to look up either.
|
|
676
|
+
if (menu.spelling) {
|
|
677
|
+
menu.thesaurus = undefined;
|
|
678
|
+
menu.link = undefined;
|
|
679
|
+
menu.table = undefined;
|
|
680
|
+
menu.poetry = undefined;
|
|
681
|
+
menu.text = undefined;
|
|
682
|
+
}
|
|
669
683
|
setContextMenu(menu);
|
|
670
684
|
if (word && menu.thesaurus) {
|
|
671
685
|
// Synonyms can take a while (the first WordNet lookup downloads the database), so the menu
|
|
@@ -1003,7 +1017,13 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
1003
1017
|
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: CONTEXT_MENU_WIDTH,
|
|
1004
1018
|
// Stays inside the visible area: flips above the click or shifts sideways when it fits that
|
|
1005
1019
|
// way, and otherwise is cut to the room there is and scrolls (a long menu in a short window).
|
|
1006
|
-
middlewares: { flip: true, shift: true, size: { padding: CONTEXT_MENU_VIEWPORT_PADDING } },
|
|
1020
|
+
middlewares: { flip: true, shift: true, size: { padding: CONTEXT_MENU_VIEWPORT_PADDING } },
|
|
1021
|
+
// Positioned against the window, not the editor: the menu then takes no room in the editor's layout (so it can
|
|
1022
|
+
// never grow a scroll bar there or make the text jump) and is not cut off at the editor's edge. No open
|
|
1023
|
+
// animation either, as its transform would make the submenus position against the menu instead.
|
|
1024
|
+
floatingStrategy: "fixed", transitionProps: { duration: 0 }, styles: CONTEXT_MENU_STYLES, classNames: CONTEXT_MENU_CLASS_NAMES, children: [_jsx(Menu.Target, { children: _jsx("span", { "aria-hidden": "true", style: { position: 'fixed', left: contextMenu?.x ?? -9999, top: contextMenu?.y ?? -9999, width: 1, height: 1, pointerEvents: 'none' } }) }), _jsxs(Menu.Dropdown, { children: [contextMenu?.spelling ? (
|
|
1025
|
+
// A misspelled word gets its fixes and the clipboard row, and nothing else.
|
|
1026
|
+
_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: strings.contextMenu.spelling }), contextMenu.spelling.suggestions.length === 0 && _jsx(Menu.Item, { disabled: true, children: strings.contextMenu.noSuggestions }), contextMenu.spelling.suggestions.map((suggestion) => (_jsx(Menu.Item, { onClick: () => {
|
|
1007
1027
|
const match = contextMenu.spelling.match;
|
|
1008
1028
|
editor.update(() => $replaceMatch(match, suggestion), { discrete: true });
|
|
1009
1029
|
editor.focus();
|
|
@@ -1021,16 +1041,18 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
1021
1041
|
}, children: strings.contextMenu.addToDictionary }), onAddAutoCorrect && config.language.autocorrect && (_jsx(Menu.Item, { onClick: () => {
|
|
1022
1042
|
onAddAutoCorrect(contextMenu.spelling.word, contextMenu.spelling.language);
|
|
1023
1043
|
setContextMenu(null);
|
|
1024
|
-
}, children: strings.contextMenu.addToAutoCorrect })), _jsx(Menu.Divider, {})] }))
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1044
|
+
}, children: strings.contextMenu.addToAutoCorrect })), _jsx(Menu.Divider, {})] })) : (
|
|
1045
|
+
// Everything that applies to what is under the pointer, each kind of content behind its own submenu.
|
|
1046
|
+
_jsxs(_Fragment, { children: [contextMenu?.thesaurus && (_jsxs(Menu.Sub, { ...CONTEXT_SUBMENU_PROPS, children: [_jsx(Menu.Sub.Target, { children: _jsx(Menu.Sub.Item, { leftSection: _jsx(IconBook, { size: ICON_SIZE, stroke: ICON_STROKE }), children: strings.thesaurus.synonyms }) }), _jsxs(Menu.Sub.Dropdown, { children: [contextMenu.thesaurus.items === undefined && _jsx(Menu.Item, { disabled: true, children: strings.thesaurus.loading }), contextMenu.thesaurus.items?.length === 0 && _jsx(Menu.Item, { disabled: true, children: strings.thesaurus.none }), contextMenu.thesaurus.items?.map((synonym) => (_jsx(Menu.Item, { onClick: () => {
|
|
1047
|
+
const match = contextMenu.thesaurus.match;
|
|
1048
|
+
editor.update(() => $replaceMatch(match, synonym), { discrete: true });
|
|
1049
|
+
editor.focus();
|
|
1050
|
+
}, children: synonym }, synonym)))] })] })), contextMenu?.link !== undefined && (_jsxs(Menu.Sub, { ...CONTEXT_SUBMENU_PROPS, children: [_jsx(Menu.Sub.Target, { children: _jsx(Menu.Sub.Item, { leftSection: _jsx(IconLink, { size: ICON_SIZE, stroke: ICON_STROKE }), children: strings.link.menuLabel }) }), _jsx(Menu.Sub.Dropdown, { children: _jsx(LinkMenuItems, { mode: "submenu", url: contextMenu.link, onEdit: () => {
|
|
1051
|
+
restoreSelection();
|
|
1052
|
+
openLinkDialog();
|
|
1053
|
+
}, onRemove: removeLink, strings: strings }) })] })), contextMenu?.table && (_jsxs(Menu.Sub, { ...CONTEXT_SUBMENU_PROPS, children: [_jsx(Menu.Sub.Target, { children: _jsx(Menu.Sub.Item, { leftSection: _jsx(IconTable, { size: ICON_SIZE, stroke: ICON_STROKE }), children: strings.tableMenu.menuLabel }) }), _jsx(Menu.Sub.Dropdown, { children: _jsx(TableMenuItems, { mode: "submenu", strings: strings, direction: direction, rows: contextMenu.table.rows, columns: contextMenu.table.columns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] })), contextMenu?.poetry && (_jsxs(Menu.Sub, { ...CONTEXT_SUBMENU_PROPS, children: [_jsx(Menu.Sub.Target, { children: _jsx(Menu.Sub.Item, { leftSection: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }), children: strings.poetryMenu.menuLabel }) }), _jsx(Menu.Sub.Dropdown, { children: _jsx(PoetryMenuItems, { mode: "submenu", strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }) })] })), contextMenu?.text && (_jsx(Menu.Item, { leftSection: _jsx(IconArrowsJoin, { size: ICON_SIZE, stroke: ICON_STROKE }), disabled: !contextMenu.canJoin, onClick: runMenuAction(() => {
|
|
1032
1054
|
$joinSelectedLines();
|
|
1033
|
-
}), children: strings.contextMenu.joinLines }), _jsx(Menu.Divider, {})] })),
|
|
1055
|
+
}), children: strings.contextMenu.joinLines })), (contextMenu?.thesaurus || contextMenu?.link !== undefined || contextMenu?.table || contextMenu?.poetry || contextMenu?.text) && (_jsx(Menu.Divider, {}))] })), _jsxs("div", { className: "likhari-context-row", role: "group", children: [_jsx(Menu.Item, { "aria-label": strings.contextMenu.cut, title: strings.contextMenu.cut, onClick: () => void copyOrCut(true)(), children: _jsx(IconCut, { size: ICON_SIZE, stroke: ICON_STROKE }) }), _jsx(Menu.Item, { "aria-label": strings.contextMenu.copy, title: strings.contextMenu.copy, onClick: () => void copyOrCut(false)(), children: _jsx(IconCopy, { size: ICON_SIZE, stroke: ICON_STROKE }) }), _jsx(Menu.Item, { "aria-label": strings.contextMenu.paste, title: strings.contextMenu.paste, onClick: () => void paste(), children: _jsx(IconClipboard, { size: ICON_SIZE, stroke: ICON_STROKE }) })] }), !contextMenu?.spelling && (_jsxs(_Fragment, { children: [_jsx(Menu.Divider, {}), _jsx(Menu.Item, { leftSection: _jsx(IconSelectAll, { size: ICON_SIZE, stroke: ICON_STROKE }), onClick: runMenuAction(() => $selectAll()), children: strings.contextMenu.selectAll })] }))] })] }));
|
|
1034
1056
|
const dialogsEl = (_jsxs(_Fragment, { children: [(config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.tables && _jsx(TableDialog, { opened: tableDialogOpen, onSubmit: insertTable, onClose: closeTableDialog }), config.columns && _jsx(LayoutDialog, { opened: layoutDialogOpen, onSubmit: insertLayout, onClose: closeLayoutDialog }), 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 })] }));
|
|
1035
1057
|
// The ribbon layout (UI spec §3.4): the same command groups as above, on tabs.
|
|
1036
1058
|
if (ribbon) {
|
package/dist/theme/editor.css
CHANGED
|
@@ -1338,3 +1338,20 @@
|
|
|
1338
1338
|
width: 14px;
|
|
1339
1339
|
height: 14px;
|
|
1340
1340
|
}
|
|
1341
|
+
|
|
1342
|
+
/* Cut, copy and paste as one row of icon buttons in the right-click menu. */
|
|
1343
|
+
.likhari-context-row {
|
|
1344
|
+
display: flex;
|
|
1345
|
+
gap: 2px;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
.likhari-context-row [data-menu-item] {
|
|
1349
|
+
flex: 1 1 0;
|
|
1350
|
+
justify-content: center;
|
|
1351
|
+
padding-block: 5px;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
.likhari-context-row [data-menu-item] > * {
|
|
1355
|
+
display: flex;
|
|
1356
|
+
justify-content: center;
|
|
1357
|
+
}
|