@inshapardaz/likhari-react 0.1.47 → 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.
- package/dist/components/Toolbar.d.ts +6 -0
- package/dist/components/Toolbar.d.ts.map +1 -1
- package/dist/components/Toolbar.js +225 -56
- package/dist/i18n/strings.d.ts +19 -0
- package/dist/i18n/strings.d.ts.map +1 -1
- package/dist/i18n/strings.js +39 -0
- package/dist/theme/editor.css +236 -0
- package/package.json +1 -1
|
@@ -7,6 +7,12 @@ import { type FontMode, type FontOption } from '../fonts/index.js';
|
|
|
7
7
|
import type { Locale } from '../i18n/strings.js';
|
|
8
8
|
/** Appearance of the toolbar. The accent colour comes from the editor's `accentColor`. */
|
|
9
9
|
export interface ToolbarStyle {
|
|
10
|
+
/**
|
|
11
|
+
* `classic` is the single row of command groups (UI spec §3.1); `ribbon` puts the same
|
|
12
|
+
* commands on tabs (Home, Insert, Tools, View) with Table, Poetry and Link tabs that
|
|
13
|
+
* appear while the caret is in that kind of content (UI spec §3.4). Default `classic`.
|
|
14
|
+
*/
|
|
15
|
+
layout?: 'classic' | 'ribbon';
|
|
10
16
|
/** Outline the toolbar and each button cluster. Default true. */
|
|
11
17
|
bordered?: boolean;
|
|
12
18
|
/** `light` tints the active button, `filled` fills it with the accent. Default `light`. */
|
|
@@ -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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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { Fragment, forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Fragment, forwardRef, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { Menu, Select, Toolbar as MantineToolbar } from '@mantine/core';
|
|
4
4
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
5
5
|
import { $getSelection, $isRangeSelection, $isElementNode, $setSelection, $getRoot, $selectAll, $getNearestNodeFromDOMNode, $createTextNode, KEY_MODIFIER_COMMAND, COMMAND_PRIORITY_NORMAL, FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND, UNDO_COMMAND, REDO_COMMAND, SELECTION_CHANGE_COMMAND, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, COMMAND_PRIORITY_LOW, } from 'lexical';
|
|
@@ -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, 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). */
|
|
@@ -65,6 +65,23 @@ const INITIAL_STATE = {
|
|
|
65
65
|
};
|
|
66
66
|
const ICON_SIZE = 17;
|
|
67
67
|
const ICON_STROKE = 1.75;
|
|
68
|
+
/** The right-click menu: compact items, and a gap kept between it and the edge of the window. */
|
|
69
|
+
const CONTEXT_MENU_WIDTH = 220;
|
|
70
|
+
const CONTEXT_MENU_VIEWPORT_PADDING = 8;
|
|
71
|
+
/** `likhari-context-menu` (editor.css) shrinks the icons to match the smaller text. */
|
|
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
|
+
};
|
|
79
|
+
const CONTEXT_MENU_STYLES = {
|
|
80
|
+
dropdown: { overflowY: 'auto', padding: 4 },
|
|
81
|
+
item: { fontSize: 'var(--mantine-font-size-xs)', padding: '4px 8px', minHeight: 0 },
|
|
82
|
+
label: { fontSize: 'var(--mantine-font-size-xs)', padding: '2px 8px' },
|
|
83
|
+
divider: { margin: '3px 0' },
|
|
84
|
+
};
|
|
68
85
|
/** The CSS Custom Highlight name; editor.css paints it like a native text selection. */
|
|
69
86
|
const SELECTION_HIGHLIGHT = 'likhari-toolbar-selection';
|
|
70
87
|
/** Paints the current native selection through the CSS Custom Highlight API, so it
|
|
@@ -172,27 +189,34 @@ function ToolbarSelect({ icon: Icon, label, value, data, width, disabled, placeh
|
|
|
172
189
|
function MoreMenuItem({ icon: Icon, label, active, onClick, }) {
|
|
173
190
|
return (_jsx(Menu.Item, { leftSection: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }), "data-active": active ? 'true' : 'false', onMouseDown: (e) => e.preventDefault(), onClick: onClick, children: label }));
|
|
174
191
|
}
|
|
175
|
-
|
|
192
|
+
/** One command, as a menu item or as a ribbon button (the label becomes its tooltip and name). */
|
|
193
|
+
function CommandItem({ mode, icon: Icon, label, onClick, disabled, color, }) {
|
|
194
|
+
if (mode === 'ribbon') {
|
|
195
|
+
return _jsx(ToolbarButton, { icon: Icon, title: label, disabled: disabled, "data-danger": color === 'red' ? 'true' : undefined, onClick: onClick });
|
|
196
|
+
}
|
|
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 }));
|
|
198
|
+
}
|
|
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);
|
|
201
|
+
const ItemDivider = ({ mode }) => (mode === 'ribbon' ? _jsx(MantineToolbar.Divider, {}) : _jsx(Menu.Divider, {}));
|
|
202
|
+
function LinkMenuItems({ url, onEdit, onRemove, strings, mode = 'menu' }) {
|
|
176
203
|
// Only offer the link as clickable if it's a URL the editor would have accepted.
|
|
177
204
|
const safeUrl = normalizeLinkUrl(url);
|
|
178
|
-
return (_jsxs(_Fragment, { children: [_jsx(
|
|
205
|
+
return (_jsxs(_Fragment, { children: [_jsx(ItemLabel, { mode: mode, children: strings.link.menuLabel }), mode === 'ribbon' ? (safeUrl && (_jsx(MantineToolbar.Toggle, { component: "a", href: safeUrl, target: "_blank", rel: "noopener noreferrer", "aria-label": url, title: url, children: _jsx(IconExternalLink, { size: ICON_SIZE, stroke: ICON_STROKE }) }))) : safeUrl ? (_jsx(Menu.Item, { component: "a", href: safeUrl, target: "_blank", rel: "noopener noreferrer", leftSection: _jsx(IconExternalLink, { size: ICON_SIZE, stroke: ICON_STROKE }), title: url, className: "likhari-link-menu-url", children: url })) : (
|
|
179
206
|
// Not a URL the editor would accept (e.g. loaded from a document): show it, don't make it clickable.
|
|
180
|
-
_jsx(Menu.Item, { disabled: true, title: url, className: "likhari-link-menu-url", children: url || strings.link.noUrl })), _jsx(
|
|
207
|
+
_jsx(Menu.Item, { disabled: true, title: url, className: "likhari-link-menu-url", children: url || strings.link.noUrl })), _jsx(CommandItem, { mode: mode, icon: IconPencil, label: strings.link.editLink, onClick: onEdit }), _jsx(CommandItem, { mode: mode, icon: IconLinkOff, label: strings.link.removeLink, onClick: onRemove, color: "red" })] }));
|
|
181
208
|
}
|
|
182
209
|
/** The table actions menu's contents — shared by the toolbar button and the
|
|
183
210
|
* right-click menu. Each acts on the selected cell, or on every row/column a
|
|
184
211
|
* multi-cell selection covers. */
|
|
185
|
-
function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canUnmergeCell, onAction, }) {
|
|
212
|
+
function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canUnmergeCell, onAction, mode = 'menu', }) {
|
|
186
213
|
const t = strings.tableMenu;
|
|
187
214
|
// "Before" is the start side, which is on the right in an RTL table.
|
|
188
215
|
const rtl = direction === 'rtl';
|
|
189
216
|
const manyRows = rows > 1;
|
|
190
217
|
const manyColumns = columns > 1;
|
|
191
|
-
const item = (icon, label, action, color) => {
|
|
192
|
-
|
|
193
|
-
return (_jsx(Menu.Item, { color: color, leftSection: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }), onMouseDown: (e) => e.preventDefault(), onClick: onAction(action), children: label }));
|
|
194
|
-
};
|
|
195
|
-
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')] }));
|
|
218
|
+
const item = (icon, label, action, color) => (_jsx(CommandItem, { mode: mode, icon: icon, label: label, onClick: onAction(action), color: color }));
|
|
219
|
+
return (_jsxs(_Fragment, { children: [_jsx(ItemLabel, { mode: mode, 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(ItemDivider, { mode: mode }), canMergeCells && item(IconArrowMergeBoth, t.mergeCells, $mergeTableCells), canUnmergeCell && item(IconArrowsSplit2, t.unmergeCell, $unmergeTableCell), _jsx(ItemDivider, { mode: mode }), item(IconRowRemove, manyRows ? t.deleteRows : t.deleteRow, $deleteTableRows), item(IconColumnRemove, manyColumns ? t.deleteColumns : t.deleteColumn, $deleteTableColumns), item(IconTableMinus, t.deleteTable, $deleteTable, 'red')] }));
|
|
196
220
|
}
|
|
197
221
|
/** Whether a one-notch step from `value` stays on the scale — a step that
|
|
198
222
|
* would fall off either end is disabled rather than silently clamped. */
|
|
@@ -200,18 +224,15 @@ function canStep(scale, value, step) {
|
|
|
200
224
|
const next = scale.indexOf(value) + step;
|
|
201
225
|
return next >= 0 && next < scale.length;
|
|
202
226
|
}
|
|
203
|
-
function PoetryMenuItems({ strings, layout, scale, centered, onAction, }) {
|
|
227
|
+
function PoetryMenuItems({ strings, layout, scale, centered, onAction, mode = 'menu', }) {
|
|
204
228
|
const t = strings.poetryMenu;
|
|
205
|
-
const item = (icon, label, action, active = false, color) => {
|
|
206
|
-
const Icon = icon;
|
|
207
|
-
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 }));
|
|
208
|
-
};
|
|
229
|
+
const item = (icon, label, action, active = false, color) => (_jsx(CommandItem, { mode: mode, icon: icon, label: label, onClick: onAction(action), disabled: active, color: color }));
|
|
209
230
|
const setLayout = (next) => () => {
|
|
210
231
|
const node = $getPoetryBlockFromSelection();
|
|
211
232
|
if (node)
|
|
212
233
|
$setPoetryLayout(node, next);
|
|
213
234
|
};
|
|
214
|
-
return (_jsxs(_Fragment, { children: [_jsx(
|
|
235
|
+
return (_jsxs(_Fragment, { children: [_jsx(ItemLabel, { mode: mode, 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(ItemDivider, { mode: mode }), _jsx(ItemDivider, { mode: mode }), 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)), centered && (_jsxs(_Fragment, { children: [item(IconArrowsMinimize, t.narrowerCenter, () => $adjustPoetryCenterWidth(-1), !canStep(POETRY_CENTER_WIDTHS, scale.centerWidth, -1)), item(IconArrowsMaximize, t.widerCenter, () => $adjustPoetryCenterWidth(1), !canStep(POETRY_CENTER_WIDTHS, scale.centerWidth, 1))] })), 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')] }));
|
|
215
236
|
}
|
|
216
237
|
/** `docs/markdown-dialect.md` at the repository's default branch — the Markdown
|
|
217
238
|
* format this editor reads and writes, including the poetry container syntax. */
|
|
@@ -220,6 +241,7 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
220
241
|
const bordered = toolbarStyle?.bordered ?? true;
|
|
221
242
|
const variant = toolbarStyle?.variant ?? 'light';
|
|
222
243
|
const overflowEnabled = toolbarStyle?.overflow ?? true;
|
|
244
|
+
const ribbon = toolbarStyle?.layout === 'ribbon';
|
|
223
245
|
const [editor] = useLexicalComposerContext();
|
|
224
246
|
const [state, setState] = useState(INITIAL_STATE);
|
|
225
247
|
const strings = useStrings(locale);
|
|
@@ -559,6 +581,34 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
559
581
|
editor.focus();
|
|
560
582
|
};
|
|
561
583
|
const [contextMenu, setContextMenu] = useState(null);
|
|
584
|
+
const [ribbonTab, setRibbonTab] = useState('home');
|
|
585
|
+
const ribbonId = useId();
|
|
586
|
+
// Collapsed: only the tabs show. Clicking a tab then "peeks" at its commands in a panel over the canvas.
|
|
587
|
+
const [ribbonCollapsed, setRibbonCollapsed] = useState(false);
|
|
588
|
+
const [ribbonPeek, setRibbonPeek] = useState(false);
|
|
589
|
+
const ribbonRootRef = useRef(null);
|
|
590
|
+
useEffect(() => {
|
|
591
|
+
if (!ribbonPeek)
|
|
592
|
+
return;
|
|
593
|
+
// A click outside the ribbon closes the peek, but not one in a menu or dropdown it opened: those
|
|
594
|
+
// render in the editor's portal anchor, outside the ribbon's own DOM.
|
|
595
|
+
const onPointerDown = (event) => {
|
|
596
|
+
const target = event.target;
|
|
597
|
+
if (target && (ribbonRootRef.current?.contains(target) || target.closest?.('.likhari-portal-target')))
|
|
598
|
+
return;
|
|
599
|
+
setRibbonPeek(false);
|
|
600
|
+
};
|
|
601
|
+
const onKeyDown = (event) => {
|
|
602
|
+
if (event.key === 'Escape')
|
|
603
|
+
setRibbonPeek(false);
|
|
604
|
+
};
|
|
605
|
+
document.addEventListener('pointerdown', onPointerDown, true);
|
|
606
|
+
document.addEventListener('keydown', onKeyDown);
|
|
607
|
+
return () => {
|
|
608
|
+
document.removeEventListener('pointerdown', onPointerDown, true);
|
|
609
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
610
|
+
};
|
|
611
|
+
}, [ribbonPeek]);
|
|
562
612
|
useEffect(() => {
|
|
563
613
|
const onContextMenu = async (event) => {
|
|
564
614
|
event.preventDefault();
|
|
@@ -622,6 +672,14 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
622
672
|
}
|
|
623
673
|
}
|
|
624
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
|
+
}
|
|
625
683
|
setContextMenu(menu);
|
|
626
684
|
if (word && menu.thesaurus) {
|
|
627
685
|
// Synonyms can take a while (the first WordNet lookup downloads the database), so the menu
|
|
@@ -847,17 +905,22 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
847
905
|
editor.focus();
|
|
848
906
|
}
|
|
849
907
|
: withRefocus((v) => applyFont('font-family', v)) })), config.font.size && !uniform && (_jsx(ToolbarSelect, { icon: IconTextSize, label: strings.toolbar.fontSize, width: 84, value: FONT_SIZES_PX.some((px) => `${px}px` === shownFontSize) ? shownFontSize : null, placeholder: strings.toolbar.fontSizePlaceholder, data: FONT_SIZES_PX.map((px) => ({ value: `${px}px`, label: String(px) })), onMouseDown: snapshotSelection, onChange: withRefocus((v) => applyFont('font-size', v)) }))] }, "font"));
|
|
850
|
-
|
|
851
|
-
|
|
908
|
+
/** The insert commands. `contextual` also puts the link, table and poetry option menus among them (the classic
|
|
909
|
+
* toolbar); the ribbon shows those on their own tabs instead. */
|
|
910
|
+
const insertButtons = (contextual) => (_jsxs(_Fragment, { children: [config.links &&
|
|
911
|
+
(contextual && state.isLink ? (_jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.linkOptions, active: true, "aria-haspopup": "menu" }) }), _jsx(Menu.Dropdown, { children: _jsx(LinkMenuItems, { url: state.linkUrl, onEdit: () => {
|
|
852
912
|
restoreSelection();
|
|
853
913
|
openLinkDialog();
|
|
854
|
-
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog }))), (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.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.tables && state.inTable && (_jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconTableOptions, title: strings.toolbar.tableOptions, active: true, "aria-haspopup": "menu" }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] })), 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.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_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 }) })), config.poetry.enabled && state.inPoetry && (_jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconFeather, title: strings.toolbar.poetryOptions, active: true, "aria-haspopup": "menu" }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }) })] }))] }
|
|
914
|
+
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog }))), (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.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), contextual && config.tables && state.inTable && (_jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconTableOptions, title: strings.toolbar.tableOptions, active: true, "aria-haspopup": "menu" }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] })), 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.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_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 }) })), contextual && config.poetry.enabled && state.inPoetry && (_jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconFeather, title: strings.toolbar.poetryOptions, active: true, "aria-haspopup": "menu" }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }) })] }))] }));
|
|
915
|
+
const insertSection = showInsertGroup && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: insertButtons(true) }, "insert"));
|
|
855
916
|
const joinLines = () => {
|
|
856
917
|
editor.update(() => {
|
|
857
918
|
$joinSelectedLines();
|
|
858
919
|
}, { discrete: true });
|
|
859
920
|
editor.focus();
|
|
860
921
|
};
|
|
922
|
+
// The tools group is always built, even when every command in it is off, so the ribbon asks first.
|
|
923
|
+
const hasToolsGroup = config.language.autocorrect || config.language.textCleanup || config.language.spellCheck || config.joinLines;
|
|
861
924
|
const toolsSection = (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [config.language.autocorrect && (_jsx(ToolbarButton, { icon: IconWand, title: strings.toolbar.autocorrect, active: autoCorrectOpen, onClick: onToggleAutoCorrect })), config.language.textCleanup && (_jsx(ToolbarButton, { icon: IconSparkles, title: strings.autoCorrect.correctDocument, onClick: () => editor.dispatchCommand(CORRECT_DOCUMENT_COMMAND, undefined) })), config.language.spellCheck && (_jsx(ToolbarButton, { icon: IconAbc, title: strings.toolbar.spellChecker, active: spellOpen, onClick: onToggleSpell })), config.joinLines && (_jsx(ToolbarButton, { icon: IconArrowsJoin, title: strings.toolbar.joinLines, disabled: !state.canJoinLines, onClick: joinLines }))] }, "tools"));
|
|
862
925
|
// Uniform mode's zoom: [-] 100% [+], stepping through the preset levels; the
|
|
863
926
|
// percentage resets to 100%. Always laid out left-to-right, like a number.
|
|
@@ -866,13 +929,18 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
866
929
|
const zoomInTo = ZOOM_LEVELS_PERCENT.find((level) => level > zoom);
|
|
867
930
|
const hasEndUtilities = Boolean(drafts || config.findReplace || helpUrl !== false);
|
|
868
931
|
const zoomGroup = showZoom && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", role: "group", "aria-label": strings.toolbar.zoom, dir: "ltr", children: [_jsx(ToolbarButton, { icon: IconMinus, title: strings.toolbar.zoomOut, disabled: zoomOutTo === undefined, onClick: () => zoomOutTo !== undefined && onZoomChange?.(zoomOutTo) }), _jsxs(MantineToolbar.Toggle, { title: strings.toolbar.zoomReset, "aria-label": `${strings.toolbar.zoomReset} (${zoom}%)`, onMouseDown: (e) => e.preventDefault(), onClick: () => onZoomChange?.(100), style: { width: 'auto', minWidth: 52, padding: '0 6px', fontSize: 12 }, children: [zoom, "%"] }), _jsx(ToolbarButton, { icon: IconPlus, title: strings.toolbar.zoomIn, disabled: zoomInTo === undefined, onClick: () => zoomInTo !== undefined && onZoomChange?.(zoomInTo) })] }, "zoom"));
|
|
932
|
+
const draftsButton = drafts && _jsx(ToolbarButton, { icon: IconHistory, title: strings.toolbar.drafts, onClick: () => setDraftsOpen(true) });
|
|
933
|
+
const findButton = config.findReplace && (_jsx(ToolbarButton, { icon: IconSearch, title: strings.findReplace.toggle, active: findOpen, onClick: onToggleFind }));
|
|
934
|
+
const helpButton = helpUrl !== false && (_jsx(MantineToolbar.Toggle, { component: "a", href: helpUrl ?? DEFAULT_HELP_URL, target: "_blank", rel: "noopener noreferrer", "aria-label": strings.toolbar.help, title: strings.toolbar.help, children: _jsx(IconHelpCircle, { size: ICON_SIZE, stroke: ICON_STROKE }) }));
|
|
869
935
|
// Drafts, search and help: the far-end group (see `endMovable` below).
|
|
870
|
-
const utilitiesGroup = hasEndUtilities && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [
|
|
936
|
+
const utilitiesGroup = hasEndUtilities && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [draftsButton, findButton, helpButton] }, "end"));
|
|
937
|
+
const saveGroup = showSave && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: _jsx(ToolbarButton, { icon: IconDeviceFloppy, title: strings.toolbar.save, dirty: Boolean(isDirty),
|
|
938
|
+
// Nothing to save until the content has changed since it was loaded or last saved.
|
|
939
|
+
disabled: !isDirty, onClick: onSave }) }, "save"));
|
|
940
|
+
const historyGroup = config.history && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [_jsx(ToolbarButton, { icon: IconArrowBackUp, title: strings.toolbar.undo, disabled: !state.canUndo, onClick: () => editor.dispatchCommand(UNDO_COMMAND, undefined) }), _jsx(ToolbarButton, { icon: IconArrowForwardUp, title: strings.toolbar.redo, disabled: !state.canRedo, onClick: () => editor.dispatchCommand(REDO_COMMAND, undefined) })] }, "history"));
|
|
871
941
|
const startSections = [
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
disabled: !isDirty, onClick: onSave }) }, "save")),
|
|
875
|
-
config.history && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [_jsx(ToolbarButton, { icon: IconArrowBackUp, title: strings.toolbar.undo, disabled: !state.canUndo, onClick: () => editor.dispatchCommand(UNDO_COMMAND, undefined) }), _jsx(ToolbarButton, { icon: IconArrowForwardUp, title: strings.toolbar.redo, disabled: !state.canRedo, onClick: () => editor.dispatchCommand(REDO_COMMAND, undefined) })] }, "history")),
|
|
942
|
+
saveGroup,
|
|
943
|
+
historyGroup,
|
|
876
944
|
formatSection,
|
|
877
945
|
alignSection,
|
|
878
946
|
];
|
|
@@ -942,35 +1010,136 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
942
1010
|
const visibleEnd = endMovable.filter(isVisible);
|
|
943
1011
|
// Shown in the menu in toolbar order: the inline sections, then the far-end ones.
|
|
944
1012
|
const hiddenMovable = [...mainMovable, ...endMovable].filter((section) => !isVisible(section));
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1013
|
+
// The right-click menu and the dialogs are the same in both layouts.
|
|
1014
|
+
const contextMenuEl = (_jsxs(Menu, { opened: contextMenu !== null, onChange: (opened) => {
|
|
1015
|
+
if (!opened)
|
|
1016
|
+
setContextMenu(null);
|
|
1017
|
+
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: CONTEXT_MENU_WIDTH,
|
|
1018
|
+
// Stays inside the visible area: flips above the click or shifts sideways when it fits that
|
|
1019
|
+
// way, and otherwise is cut to the room there is and scrolls (a long menu in a short window).
|
|
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: () => {
|
|
1027
|
+
const match = contextMenu.spelling.match;
|
|
1028
|
+
editor.update(() => $replaceMatch(match, suggestion), { discrete: true });
|
|
1029
|
+
editor.focus();
|
|
1030
|
+
}, children: suggestion }, suggestion))), _jsx(Menu.Item, { onClick: () => {
|
|
1031
|
+
ignoreWord(contextMenu.spelling.language, contextMenu.spelling.word);
|
|
1032
|
+
setContextMenu(null);
|
|
1033
|
+
}, children: strings.contextMenu.ignore }), _jsx(Menu.Item, { onClick: () => {
|
|
1034
|
+
const { language, word } = contextMenu.spelling;
|
|
1035
|
+
// Without a writable store, the word is ignored for this session instead.
|
|
1036
|
+
void addUserWord(dictionaryStores, language, word).then((added) => {
|
|
1037
|
+
if (!added)
|
|
1038
|
+
ignoreWord(language, word);
|
|
1039
|
+
});
|
|
1040
|
+
setContextMenu(null);
|
|
1041
|
+
}, children: strings.contextMenu.addToDictionary }), onAddAutoCorrect && config.language.autocorrect && (_jsx(Menu.Item, { onClick: () => {
|
|
1042
|
+
onAddAutoCorrect(contextMenu.spelling.word, contextMenu.spelling.language);
|
|
1043
|
+
setContextMenu(null);
|
|
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(() => {
|
|
1054
|
+
$joinSelectedLines();
|
|
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 })] }))] })] }));
|
|
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 })] }));
|
|
1057
|
+
// The ribbon layout (UI spec §3.4): the same command groups as above, on tabs.
|
|
1058
|
+
if (ribbon) {
|
|
1059
|
+
const rt = strings.toolbar.ribbon;
|
|
1060
|
+
const cluster = (key, children) => (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: children }, key));
|
|
1061
|
+
const groupsByTab = {
|
|
1062
|
+
home: [formatSection, alignSection, fontSection],
|
|
1063
|
+
insert: [showInsertGroup && cluster('insert', insertButtons(false))],
|
|
1064
|
+
tools: [hasToolsGroup && toolsSection],
|
|
1065
|
+
table: [
|
|
1066
|
+
config.tables &&
|
|
1067
|
+
state.inTable &&
|
|
1068
|
+
cluster('table', _jsx(TableMenuItems, { mode: "ribbon", strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction })),
|
|
1069
|
+
],
|
|
1070
|
+
poetry: [
|
|
1071
|
+
config.poetry.enabled &&
|
|
1072
|
+
state.inPoetry &&
|
|
1073
|
+
cluster('poetry', _jsx(PoetryMenuItems, { mode: "ribbon", strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction })),
|
|
1074
|
+
],
|
|
1075
|
+
link: [
|
|
1076
|
+
config.links &&
|
|
1077
|
+
state.isLink &&
|
|
1078
|
+
cluster('link', _jsx(LinkMenuItems, { mode: "ribbon", url: state.linkUrl, onEdit: () => {
|
|
1079
|
+
restoreSelection();
|
|
1080
|
+
openLinkDialog();
|
|
1081
|
+
}, onRemove: removeLink, strings: strings })),
|
|
1082
|
+
],
|
|
1083
|
+
};
|
|
1084
|
+
const CONTEXTUAL = ['table', 'poetry', 'link'];
|
|
1085
|
+
// A tab with nothing to show (its features are off, or the caret is not in that content) is left out.
|
|
1086
|
+
const tabs = ['home', 'insert', 'tools', ...CONTEXTUAL]
|
|
1087
|
+
.map((id) => ({ id, label: rt[id], groups: groupsByTab[id].filter(Boolean) }))
|
|
1088
|
+
.filter((tab) => tab.groups.length > 0);
|
|
1089
|
+
const activeTab = tabs.find((tab) => tab.id === ribbonTab) ?? tabs[0];
|
|
1090
|
+
// A context tab that went away (the caret left the table) must not come back selected on its own later.
|
|
1091
|
+
if (activeTab && activeTab.id !== ribbonTab)
|
|
1092
|
+
setRibbonTab(activeTab.id);
|
|
1093
|
+
const panelVisible = !ribbonCollapsed || ribbonPeek;
|
|
1094
|
+
const toggleCollapsed = () => {
|
|
1095
|
+
setRibbonCollapsed((collapsed) => !collapsed);
|
|
1096
|
+
setRibbonPeek(false);
|
|
1097
|
+
};
|
|
1098
|
+
const tabDomId = (id) => `${ribbonId}-tab-${id}`;
|
|
1099
|
+
const onTabKeyDown = (event) => {
|
|
1100
|
+
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key) || tabs.length === 0)
|
|
1101
|
+
return;
|
|
1102
|
+
const index = Math.max(0, tabs.findIndex((tab) => tab.id === activeTab?.id));
|
|
1103
|
+
const forward = event.key === (direction === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
|
|
1104
|
+
const next = event.key === 'Home' ? 0 : event.key === 'End' ? tabs.length - 1 : (index + (forward ? 1 : -1) + tabs.length) % tabs.length;
|
|
1105
|
+
event.preventDefault();
|
|
1106
|
+
setRibbonTab(tabs[next].id);
|
|
1107
|
+
event.currentTarget.querySelectorAll('[role="tab"]')[next]?.focus();
|
|
1108
|
+
};
|
|
1109
|
+
// Save, undo and redo come before the tabs; drafts, search and help come after them. Neither is on a tab,
|
|
1110
|
+
// so both stay in reach whichever tab is open (and when there are no tabs).
|
|
1111
|
+
const quickAccess = [saveGroup, historyGroup].filter(Boolean);
|
|
1112
|
+
const utilities = (draftsButton || findButton || helpButton) &&
|
|
1113
|
+
cluster('utilities', _jsxs(_Fragment, { children: [draftsButton, findButton, helpButton] }));
|
|
1114
|
+
// The collapse button belongs to the row, not to a tab, and is only offered when there are tabs to hide the commands of.
|
|
1115
|
+
const collapseGroup = tabs.length > 0 &&
|
|
1116
|
+
cluster('collapse', _jsx(ToolbarButton, { icon: ribbonCollapsed ? IconChevronDown : IconChevronUp, title: ribbonCollapsed ? rt.expand : rt.collapse, "aria-expanded": !ribbonCollapsed, onClick: toggleCollapsed }));
|
|
1117
|
+
// Zoom (uniform font mode) is a view setting, not a tab: it leads the document tools.
|
|
1118
|
+
const utilityBar = [zoomGroup, utilities, collapseGroup].filter(Boolean);
|
|
1119
|
+
return (_jsxs("div", { ref: ribbonRootRef, className: ['likhari-ribbon', bordered ? '' : 'likhari-ribbon--plain', ribbonCollapsed ? 'likhari-ribbon--collapsed' : ''].filter(Boolean).join(' '), onKeyDown: (event) => {
|
|
1120
|
+
// Ctrl+F1 collapses and expands the ribbon, as in office suites.
|
|
1121
|
+
if (event.key === 'F1' && event.ctrlKey && tabs.length > 0) {
|
|
1122
|
+
event.preventDefault();
|
|
1123
|
+
toggleCollapsed();
|
|
1124
|
+
}
|
|
1125
|
+
}, children: [_jsxs("div", { className: "likhari-ribbon-top", children: [quickAccess.length > 0 && (_jsx(MantineToolbar, { "aria-label": rt.quickAccess, className: "likhari-ribbon-quick", withBorder: false, variant: variant, color: "var(--editor-accent)", children: withDividers(quickAccess) })), tabs.length > 0 && (_jsx("div", { role: "tablist", "aria-label": rt.tabsLabel, className: "likhari-ribbon-tabs", onKeyDown: onTabKeyDown, children: tabs.map((tab) => {
|
|
1126
|
+
// While the ribbon is collapsed a tab only counts as selected when its panel is peeking open.
|
|
1127
|
+
const selected = panelVisible && tab.id === activeTab?.id;
|
|
1128
|
+
return (_jsx("button", { type: "button", role: "tab", id: tabDomId(tab.id), "aria-selected": selected, "aria-controls": selected ? `${ribbonId}-panel` : undefined, tabIndex: tab.id === activeTab?.id ? 0 : -1, className: "likhari-ribbon-tab", "data-contextual": CONTEXTUAL.includes(tab.id) ? 'true' : undefined,
|
|
1129
|
+
// Keep the editor's selection: a mousedown here would blur the canvas.
|
|
1130
|
+
onMouseDown: (e) => e.preventDefault(), onClick: () => {
|
|
1131
|
+
setRibbonTab(tab.id);
|
|
1132
|
+
// Collapsed: a tab opens its commands over the canvas, and clicking it again closes them.
|
|
1133
|
+
if (ribbonCollapsed)
|
|
1134
|
+
setRibbonPeek(!(ribbonPeek && tab.id === activeTab?.id));
|
|
1135
|
+
}, onDoubleClick: toggleCollapsed, children: tab.label }, tab.id));
|
|
1136
|
+
}) })), utilityBar.length > 0 && (_jsx(MantineToolbar, { "aria-label": rt.utilities, className: "likhari-ribbon-utilities", withBorder: false, variant: variant, color: "var(--editor-accent)", children: withDividers(utilityBar) }))] }), panelVisible && activeTab && (_jsx("div", { role: "tabpanel", id: `${ribbonId}-panel`, "aria-labelledby": tabDomId(activeTab.id), className: ribbonCollapsed ? 'likhari-ribbon-panel-wrap likhari-ribbon-panel-wrap--peek' : 'likhari-ribbon-panel-wrap', onClick: (event) => {
|
|
1137
|
+
// A command chosen from the peeking panel closes it, as in office suites. A button that opens a
|
|
1138
|
+
// menu (More formatting) keeps it open, so the menu is not pulled away from under the pointer.
|
|
1139
|
+
const button = event.target.closest('button, a');
|
|
1140
|
+
if (ribbonCollapsed && button && !button.hasAttribute('aria-haspopup'))
|
|
1141
|
+
setRibbonPeek(false);
|
|
1142
|
+
}, children: _jsx(MantineToolbar, { "aria-label": strings.toolbar.ariaLabel, className: bordered ? 'likhari-toolbar likhari-ribbon-panel' : 'likhari-toolbar likhari-toolbar--plain likhari-ribbon-panel', withBorder: bordered, variant: variant, color: "var(--editor-accent)", children: withDividers(activeTab.groups) }) })), contextMenuEl, dialogsEl] }));
|
|
1143
|
+
}
|
|
1144
|
+
return (_jsxs(MantineToolbar, { ref: toolbarContainerRef, "aria-label": strings.toolbar.ariaLabel, className: bordered ? 'likhari-toolbar' : 'likhari-toolbar likhari-toolbar--plain', withBorder: bordered, variant: variant, color: "var(--editor-accent)", children: [withDividers(startSections), visibleMovable.map((section) => (_jsxs(Fragment, { children: [_jsx(MantineToolbar.Divider, {}), section.node] }, section.key))), hiddenMovable.length > 0 && (_jsxs(_Fragment, { children: [_jsx(MantineToolbar.Divider, {}), _jsxs(Menu, { opened: overflowMenuOpen, onChange: handleOverflowMenuChange, position: "bottom-end", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: "max-content", closeOnItemClick: false, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconDots, title: strings.toolbar.moreFormatting }) }), _jsx(Menu.Dropdown, { p: 6, children: _jsx(MantineToolbar, { withBorder: false, variant: variant, color: "var(--editor-accent)", style: { maxWidth: 320 }, children: withDividers(hiddenMovable.map((section) => section.node)) }) })] })] })), _jsx("span", { "aria-hidden": "true", style: { flex: '1 1 auto' } }), visibleEnd.map((section) => section.node), contextMenuEl, overflowEnabled && (_jsxs(MantineToolbar, { "aria-hidden": "true", ref: toolbarMeasureRef, withBorder: bordered, variant: variant, color: "var(--editor-accent)", style: { position: 'absolute', visibility: 'hidden', pointerEvents: 'none', top: 0, left: 0, flexWrap: 'nowrap', width: 'max-content' }, children: [withDividers(startSections), movableSections.map((section) => (_jsxs(Fragment, { children: [_jsx(MantineToolbar.Divider, {}), _jsx("span", { "data-group-key": section.key, style: { display: 'inline-flex' }, children: section.node })] }, section.key)))] })), dialogsEl] }));
|
|
976
1145
|
}
|
package/dist/i18n/strings.d.ts
CHANGED
|
@@ -74,6 +74,25 @@ export interface Strings {
|
|
|
74
74
|
clearFormatting: string;
|
|
75
75
|
outdent: string;
|
|
76
76
|
indent: string;
|
|
77
|
+
/** The ribbon layout (`toolbarStyle.layout: 'ribbon'`): its tab strip and tabs. */
|
|
78
|
+
ribbon: {
|
|
79
|
+
/** aria-label on the tab strip. */
|
|
80
|
+
tabsLabel: string;
|
|
81
|
+
/** aria-label on the group before the tabs that holds save, undo and redo. */
|
|
82
|
+
quickAccess: string;
|
|
83
|
+
/** aria-label on the group after the tabs that holds drafts, search and help. */
|
|
84
|
+
utilities: string;
|
|
85
|
+
/** The button that hides the command row, leaving only the tabs, and the one that brings it back. */
|
|
86
|
+
collapse: string;
|
|
87
|
+
expand: string;
|
|
88
|
+
home: string;
|
|
89
|
+
insert: string;
|
|
90
|
+
tools: string;
|
|
91
|
+
/** Contextual tabs, shown only while the caret is in that kind of content. */
|
|
92
|
+
table: string;
|
|
93
|
+
poetry: string;
|
|
94
|
+
link: string;
|
|
95
|
+
};
|
|
77
96
|
formattingOptions: {
|
|
78
97
|
paragraph: string;
|
|
79
98
|
heading: (level: number) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../src/i18n/strings.ts"],"names":[],"mappings":"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
|
|
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
|
@@ -62,6 +62,19 @@ const en = {
|
|
|
62
62
|
clearFormatting: 'Clear formatting',
|
|
63
63
|
outdent: 'Outdent',
|
|
64
64
|
indent: 'Indent',
|
|
65
|
+
ribbon: {
|
|
66
|
+
tabsLabel: 'Ribbon tabs',
|
|
67
|
+
quickAccess: 'Quick access',
|
|
68
|
+
utilities: 'Document tools',
|
|
69
|
+
collapse: 'Collapse the ribbon',
|
|
70
|
+
expand: 'Expand the ribbon',
|
|
71
|
+
home: 'Home',
|
|
72
|
+
insert: 'Insert',
|
|
73
|
+
tools: 'Tools',
|
|
74
|
+
table: 'Table',
|
|
75
|
+
poetry: 'Poetry',
|
|
76
|
+
link: 'Link',
|
|
77
|
+
},
|
|
65
78
|
formattingOptions: {
|
|
66
79
|
paragraph: 'Paragraph',
|
|
67
80
|
heading: (level) => `Heading ${level}`,
|
|
@@ -347,6 +360,19 @@ const ur = {
|
|
|
347
360
|
clearFormatting: 'فارمیٹنگ ختم کریں',
|
|
348
361
|
outdent: 'حاشیہ کم کریں',
|
|
349
362
|
indent: 'حاشیہ بڑھائیں',
|
|
363
|
+
ribbon: {
|
|
364
|
+
tabsLabel: 'ربن کے ٹیب',
|
|
365
|
+
quickAccess: 'فوری رسائی',
|
|
366
|
+
utilities: 'دستاویز کے اوزار',
|
|
367
|
+
collapse: 'ربن چھپائیں',
|
|
368
|
+
expand: 'ربن دکھائیں',
|
|
369
|
+
home: 'ہوم',
|
|
370
|
+
insert: 'شامل کریں',
|
|
371
|
+
tools: 'اوزار',
|
|
372
|
+
table: 'جدول',
|
|
373
|
+
poetry: 'شاعری',
|
|
374
|
+
link: 'لنک',
|
|
375
|
+
},
|
|
350
376
|
formattingOptions: {
|
|
351
377
|
paragraph: 'پیراگراف',
|
|
352
378
|
heading: (level) => `عنوان ${level}`,
|
|
@@ -632,6 +658,19 @@ const paShahmukhi = {
|
|
|
632
658
|
clearFormatting: 'فارمیٹنگ ہٹاؤ',
|
|
633
659
|
outdent: 'حاشیہ گھٹاؤ',
|
|
634
660
|
indent: 'حاشیہ ودھاؤ',
|
|
661
|
+
ribbon: {
|
|
662
|
+
tabsLabel: 'ربن دے ٹیب',
|
|
663
|
+
quickAccess: 'جھٹ رسائی',
|
|
664
|
+
utilities: 'دستاویز دے اوزار',
|
|
665
|
+
collapse: 'ربن لکو',
|
|
666
|
+
expand: 'ربن وکھاؤ',
|
|
667
|
+
home: 'ہوم',
|
|
668
|
+
insert: 'شامل کرو',
|
|
669
|
+
tools: 'اوزار',
|
|
670
|
+
table: 'جدول',
|
|
671
|
+
poetry: 'شاعری',
|
|
672
|
+
link: 'لنک',
|
|
673
|
+
},
|
|
635
674
|
formattingOptions: {
|
|
636
675
|
paragraph: 'پیراگراف',
|
|
637
676
|
heading: (level) => `سرلیکھ ${level}`,
|
package/dist/theme/editor.css
CHANGED
|
@@ -1119,3 +1119,239 @@
|
|
|
1119
1119
|
background: var(--editor-accent-soft);
|
|
1120
1120
|
}
|
|
1121
1121
|
|
|
1122
|
+
|
|
1123
|
+
/* Ribbon layout (toolbarStyle.layout: 'ribbon', UI spec §3.4): a strip of tabs over one row of the active
|
|
1124
|
+
tab's command groups, with save, undo and redo before the tabs and drafts, search and help after them. */
|
|
1125
|
+
.likhari-ribbon {
|
|
1126
|
+
display: flex;
|
|
1127
|
+
flex-direction: column;
|
|
1128
|
+
flex-shrink: 0;
|
|
1129
|
+
/* The containing block, and a stacking level above the canvas, for the panel that peeks out when collapsed. */
|
|
1130
|
+
position: relative;
|
|
1131
|
+
z-index: 5;
|
|
1132
|
+
background: var(--editor-paper-dim);
|
|
1133
|
+
/* Lets the row below react to the editor's own width, not the window's. */
|
|
1134
|
+
container-type: inline-size;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
/* Collapsed: only the tab row stays, closed off with a line where the command row was. */
|
|
1138
|
+
.likhari-ribbon--collapsed .likhari-ribbon-top {
|
|
1139
|
+
padding-bottom: 2px;
|
|
1140
|
+
border-bottom: 1px solid var(--editor-line);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/* In a narrow editor the save/undo group and the document tools take all the width and squeeze the tabs to
|
|
1144
|
+
nothing, so the tabs drop to a line of their own (scrolling sideways if need be). */
|
|
1145
|
+
@container (max-width: 560px) {
|
|
1146
|
+
.likhari-ribbon-top {
|
|
1147
|
+
flex-wrap: wrap;
|
|
1148
|
+
row-gap: 0;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
.likhari-ribbon-tabs {
|
|
1152
|
+
order: 3;
|
|
1153
|
+
flex: 1 1 100%;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/* A collapsed tab's commands open over the canvas instead of pushing it down, so the page does not jump. */
|
|
1158
|
+
.likhari-ribbon-panel-wrap--peek {
|
|
1159
|
+
position: absolute;
|
|
1160
|
+
inset-inline: 0;
|
|
1161
|
+
top: 100%;
|
|
1162
|
+
z-index: 30;
|
|
1163
|
+
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.16);
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
.likhari-ribbon-top {
|
|
1167
|
+
display: flex;
|
|
1168
|
+
align-items: center;
|
|
1169
|
+
justify-content: space-between;
|
|
1170
|
+
gap: 8px;
|
|
1171
|
+
padding: 2px 8px 0;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
.likhari-ribbon-tabs {
|
|
1175
|
+
display: flex;
|
|
1176
|
+
gap: 2px;
|
|
1177
|
+
min-width: 0;
|
|
1178
|
+
/* Narrow screens scroll the tabs sideways rather than wrapping them. */
|
|
1179
|
+
overflow-x: auto;
|
|
1180
|
+
scrollbar-width: none;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
.likhari-ribbon-tab {
|
|
1184
|
+
appearance: none;
|
|
1185
|
+
flex: 0 0 auto;
|
|
1186
|
+
margin: 0;
|
|
1187
|
+
padding: 6px 12px;
|
|
1188
|
+
border: 0;
|
|
1189
|
+
border-bottom: 2px solid transparent;
|
|
1190
|
+
border-radius: 4px 4px 0 0;
|
|
1191
|
+
background: transparent;
|
|
1192
|
+
color: var(--editor-ink-soft);
|
|
1193
|
+
font: inherit;
|
|
1194
|
+
font-size: 13px;
|
|
1195
|
+
line-height: 1.2;
|
|
1196
|
+
white-space: nowrap;
|
|
1197
|
+
cursor: pointer;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
.likhari-ribbon-tab:hover {
|
|
1201
|
+
background: var(--editor-accent-soft);
|
|
1202
|
+
color: var(--editor-ink);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
.likhari-ribbon-tab[aria-selected='true'] {
|
|
1206
|
+
border-bottom-color: var(--editor-accent);
|
|
1207
|
+
color: var(--editor-accent);
|
|
1208
|
+
font-weight: 600;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/* A context tab (Table, Poetry, Link) is tinted so it reads as appearing because of where the caret is. */
|
|
1212
|
+
.likhari-ribbon-tab[data-contextual] {
|
|
1213
|
+
background: var(--editor-accent-soft);
|
|
1214
|
+
color: var(--editor-accent);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.likhari-ribbon-tab:focus-visible {
|
|
1218
|
+
outline: 2px solid var(--editor-accent);
|
|
1219
|
+
outline-offset: -2px;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
.likhari-ribbon-quick,
|
|
1223
|
+
.likhari-ribbon-utilities {
|
|
1224
|
+
display: flex;
|
|
1225
|
+
flex: 0 0 auto;
|
|
1226
|
+
flex-wrap: nowrap;
|
|
1227
|
+
align-items: center;
|
|
1228
|
+
gap: 8px;
|
|
1229
|
+
min-height: 0;
|
|
1230
|
+
padding: 0;
|
|
1231
|
+
background: transparent;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
/* Drafts, search and help at the end of the row, also when there are no tabs to push them there. */
|
|
1235
|
+
.likhari-ribbon-utilities {
|
|
1236
|
+
margin-inline-start: auto;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/* The panel scrolls sideways when its groups do not fit, instead of wrapping onto a second row. */
|
|
1240
|
+
.likhari-ribbon-panel {
|
|
1241
|
+
flex-wrap: nowrap;
|
|
1242
|
+
overflow-x: auto;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
.likhari-ribbon-panel > * {
|
|
1246
|
+
flex: 0 0 auto;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
/* A destructive command (delete table, delete couplet) on the ribbon, as red as it is in the menus. */
|
|
1250
|
+
.likhari-ribbon-panel [data-danger='true'] {
|
|
1251
|
+
color: var(--mantine-color-red-6, #e03131);
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
/* The buttons on the tab row, outside every tab (save, undo, redo; drafts, search, help): flat icons with no
|
|
1255
|
+
border or background at rest. Hover tints them; "on" and "unsaved" are shown by colour and a mark instead
|
|
1256
|
+
of a fill, so the row stays light next to the tabs. */
|
|
1257
|
+
.likhari-ribbon-quick .likhari-toolbar-cluster,
|
|
1258
|
+
.likhari-ribbon-utilities .likhari-toolbar-cluster {
|
|
1259
|
+
border: none;
|
|
1260
|
+
border-radius: 0;
|
|
1261
|
+
background: transparent;
|
|
1262
|
+
overflow: visible;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
.likhari-ribbon-quick [data-toolbar-toggle],
|
|
1266
|
+
.likhari-ribbon-utilities [data-toolbar-toggle] {
|
|
1267
|
+
position: relative;
|
|
1268
|
+
border: none;
|
|
1269
|
+
border-radius: 6px;
|
|
1270
|
+
background: transparent !important;
|
|
1271
|
+
color: var(--editor-ink-soft);
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
.likhari-ribbon-quick .likhari-toolbar-cluster [data-toolbar-toggle] + [data-toolbar-toggle],
|
|
1275
|
+
.likhari-ribbon-utilities .likhari-toolbar-cluster [data-toolbar-toggle] + [data-toolbar-toggle] {
|
|
1276
|
+
border-inline-start: none;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
.likhari-ribbon-quick [data-toolbar-toggle]:hover:not(:disabled):not([data-disabled]),
|
|
1280
|
+
.likhari-ribbon-utilities [data-toolbar-toggle]:hover:not(:disabled):not([data-disabled]) {
|
|
1281
|
+
background: var(--editor-accent-soft) !important;
|
|
1282
|
+
color: var(--editor-ink);
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
.likhari-ribbon-quick [data-toolbar-toggle]:disabled,
|
|
1286
|
+
.likhari-ribbon-quick [data-toolbar-toggle][data-disabled],
|
|
1287
|
+
.likhari-ribbon-utilities [data-toolbar-toggle]:disabled,
|
|
1288
|
+
.likhari-ribbon-utilities [data-toolbar-toggle][data-disabled] {
|
|
1289
|
+
color: var(--editor-ink-soft);
|
|
1290
|
+
opacity: 0.45;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
/* A button that is on (find and replace open): accent icon with a short bar under it. */
|
|
1294
|
+
.likhari-ribbon-quick [data-toolbar-toggle][aria-pressed='true'],
|
|
1295
|
+
.likhari-ribbon-utilities [data-toolbar-toggle][aria-pressed='true'] {
|
|
1296
|
+
color: var(--editor-accent);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
.likhari-ribbon-quick [data-toolbar-toggle][aria-pressed='true']::after,
|
|
1300
|
+
.likhari-ribbon-utilities [data-toolbar-toggle][aria-pressed='true']::after {
|
|
1301
|
+
content: '';
|
|
1302
|
+
position: absolute;
|
|
1303
|
+
inset-inline: 7px;
|
|
1304
|
+
bottom: 2px;
|
|
1305
|
+
height: 2px;
|
|
1306
|
+
border-radius: 1px;
|
|
1307
|
+
background: var(--editor-accent);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
/* Save with unsaved changes: accent icon and a dot, not the filled button the classic toolbar uses. */
|
|
1311
|
+
.likhari-ribbon-quick [data-dirty='true'] {
|
|
1312
|
+
color: var(--editor-accent);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
.likhari-ribbon-quick [data-dirty='true']::after {
|
|
1316
|
+
content: '';
|
|
1317
|
+
position: absolute;
|
|
1318
|
+
top: 4px;
|
|
1319
|
+
inset-inline-end: 4px;
|
|
1320
|
+
width: 7px;
|
|
1321
|
+
height: 7px;
|
|
1322
|
+
border-radius: 50%;
|
|
1323
|
+
background: var(--editor-accent);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
.likhari-ribbon-quick [data-dirty='true']:hover,
|
|
1327
|
+
.likhari-ribbon-quick [data-dirty='false'] {
|
|
1328
|
+
color: var(--editor-accent);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
.likhari-ribbon-quick [data-dirty='false']:disabled,
|
|
1332
|
+
.likhari-ribbon-quick [data-dirty='false'][data-disabled] {
|
|
1333
|
+
color: var(--editor-ink-soft);
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
/* The right-click menu is compact: its icons follow the smaller item text (sizes set in Toolbar.tsx). */
|
|
1337
|
+
.likhari-context-menu svg {
|
|
1338
|
+
width: 14px;
|
|
1339
|
+
height: 14px;
|
|
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
|
+
}
|