@inshapardaz/likhari-react 0.1.47 → 0.1.48-dev.354
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 +203 -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 +219 -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, 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,17 @@ 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
|
+
const CONTEXT_MENU_STYLES = {
|
|
74
|
+
dropdown: { overflowY: 'auto', padding: 4 },
|
|
75
|
+
item: { fontSize: 'var(--mantine-font-size-xs)', padding: '4px 8px', minHeight: 0 },
|
|
76
|
+
label: { fontSize: 'var(--mantine-font-size-xs)', padding: '2px 8px' },
|
|
77
|
+
divider: { margin: '3px 0' },
|
|
78
|
+
};
|
|
68
79
|
/** The CSS Custom Highlight name; editor.css paints it like a native text selection. */
|
|
69
80
|
const SELECTION_HIGHLIGHT = 'likhari-toolbar-selection';
|
|
70
81
|
/** Paints the current native selection through the CSS Custom Highlight API, so it
|
|
@@ -172,27 +183,34 @@ function ToolbarSelect({ icon: Icon, label, value, data, width, disabled, placeh
|
|
|
172
183
|
function MoreMenuItem({ icon: Icon, label, active, onClick, }) {
|
|
173
184
|
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
185
|
}
|
|
175
|
-
|
|
186
|
+
/** One command, as a menu item or as a ribbon button (the label becomes its tooltip and name). */
|
|
187
|
+
function CommandItem({ mode, icon: Icon, label, onClick, disabled, color, }) {
|
|
188
|
+
if (mode === 'ribbon') {
|
|
189
|
+
return _jsx(ToolbarButton, { icon: Icon, title: label, disabled: disabled, "data-danger": color === 'red' ? 'true' : undefined, onClick: onClick });
|
|
190
|
+
}
|
|
191
|
+
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
|
+
}
|
|
193
|
+
/** A group heading in a menu; the ribbon's tab already names the group, so it shows nothing there. */
|
|
194
|
+
const ItemLabel = ({ mode, children }) => (mode === 'ribbon' ? null : _jsx(Menu.Label, { children: children }));
|
|
195
|
+
const ItemDivider = ({ mode }) => (mode === 'ribbon' ? _jsx(MantineToolbar.Divider, {}) : _jsx(Menu.Divider, {}));
|
|
196
|
+
function LinkMenuItems({ url, onEdit, onRemove, strings, mode = 'menu' }) {
|
|
176
197
|
// Only offer the link as clickable if it's a URL the editor would have accepted.
|
|
177
198
|
const safeUrl = normalizeLinkUrl(url);
|
|
178
|
-
return (_jsxs(_Fragment, { children: [_jsx(
|
|
199
|
+
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
200
|
// 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(
|
|
201
|
+
_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
202
|
}
|
|
182
203
|
/** The table actions menu's contents — shared by the toolbar button and the
|
|
183
204
|
* right-click menu. Each acts on the selected cell, or on every row/column a
|
|
184
205
|
* multi-cell selection covers. */
|
|
185
|
-
function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canUnmergeCell, onAction, }) {
|
|
206
|
+
function TableMenuItems({ strings, direction, rows, columns, canMergeCells, canUnmergeCell, onAction, mode = 'menu', }) {
|
|
186
207
|
const t = strings.tableMenu;
|
|
187
208
|
// "Before" is the start side, which is on the right in an RTL table.
|
|
188
209
|
const rtl = direction === 'rtl';
|
|
189
210
|
const manyRows = rows > 1;
|
|
190
211
|
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')] }));
|
|
212
|
+
const item = (icon, label, action, color) => (_jsx(CommandItem, { mode: mode, icon: icon, label: label, onClick: onAction(action), color: color }));
|
|
213
|
+
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
214
|
}
|
|
197
215
|
/** Whether a one-notch step from `value` stays on the scale — a step that
|
|
198
216
|
* would fall off either end is disabled rather than silently clamped. */
|
|
@@ -200,18 +218,15 @@ function canStep(scale, value, step) {
|
|
|
200
218
|
const next = scale.indexOf(value) + step;
|
|
201
219
|
return next >= 0 && next < scale.length;
|
|
202
220
|
}
|
|
203
|
-
function PoetryMenuItems({ strings, layout, scale, centered, onAction, }) {
|
|
221
|
+
function PoetryMenuItems({ strings, layout, scale, centered, onAction, mode = 'menu', }) {
|
|
204
222
|
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
|
-
};
|
|
223
|
+
const item = (icon, label, action, active = false, color) => (_jsx(CommandItem, { mode: mode, icon: icon, label: label, onClick: onAction(action), disabled: active, color: color }));
|
|
209
224
|
const setLayout = (next) => () => {
|
|
210
225
|
const node = $getPoetryBlockFromSelection();
|
|
211
226
|
if (node)
|
|
212
227
|
$setPoetryLayout(node, next);
|
|
213
228
|
};
|
|
214
|
-
return (_jsxs(_Fragment, { children: [_jsx(
|
|
229
|
+
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
230
|
}
|
|
216
231
|
/** `docs/markdown-dialect.md` at the repository's default branch — the Markdown
|
|
217
232
|
* format this editor reads and writes, including the poetry container syntax. */
|
|
@@ -220,6 +235,7 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
220
235
|
const bordered = toolbarStyle?.bordered ?? true;
|
|
221
236
|
const variant = toolbarStyle?.variant ?? 'light';
|
|
222
237
|
const overflowEnabled = toolbarStyle?.overflow ?? true;
|
|
238
|
+
const ribbon = toolbarStyle?.layout === 'ribbon';
|
|
223
239
|
const [editor] = useLexicalComposerContext();
|
|
224
240
|
const [state, setState] = useState(INITIAL_STATE);
|
|
225
241
|
const strings = useStrings(locale);
|
|
@@ -559,6 +575,34 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
559
575
|
editor.focus();
|
|
560
576
|
};
|
|
561
577
|
const [contextMenu, setContextMenu] = useState(null);
|
|
578
|
+
const [ribbonTab, setRibbonTab] = useState('home');
|
|
579
|
+
const ribbonId = useId();
|
|
580
|
+
// Collapsed: only the tabs show. Clicking a tab then "peeks" at its commands in a panel over the canvas.
|
|
581
|
+
const [ribbonCollapsed, setRibbonCollapsed] = useState(false);
|
|
582
|
+
const [ribbonPeek, setRibbonPeek] = useState(false);
|
|
583
|
+
const ribbonRootRef = useRef(null);
|
|
584
|
+
useEffect(() => {
|
|
585
|
+
if (!ribbonPeek)
|
|
586
|
+
return;
|
|
587
|
+
// A click outside the ribbon closes the peek, but not one in a menu or dropdown it opened: those
|
|
588
|
+
// render in the editor's portal anchor, outside the ribbon's own DOM.
|
|
589
|
+
const onPointerDown = (event) => {
|
|
590
|
+
const target = event.target;
|
|
591
|
+
if (target && (ribbonRootRef.current?.contains(target) || target.closest?.('.likhari-portal-target')))
|
|
592
|
+
return;
|
|
593
|
+
setRibbonPeek(false);
|
|
594
|
+
};
|
|
595
|
+
const onKeyDown = (event) => {
|
|
596
|
+
if (event.key === 'Escape')
|
|
597
|
+
setRibbonPeek(false);
|
|
598
|
+
};
|
|
599
|
+
document.addEventListener('pointerdown', onPointerDown, true);
|
|
600
|
+
document.addEventListener('keydown', onKeyDown);
|
|
601
|
+
return () => {
|
|
602
|
+
document.removeEventListener('pointerdown', onPointerDown, true);
|
|
603
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
604
|
+
};
|
|
605
|
+
}, [ribbonPeek]);
|
|
562
606
|
useEffect(() => {
|
|
563
607
|
const onContextMenu = async (event) => {
|
|
564
608
|
event.preventDefault();
|
|
@@ -847,17 +891,22 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
847
891
|
editor.focus();
|
|
848
892
|
}
|
|
849
893
|
: 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
|
-
|
|
894
|
+
/** The insert commands. `contextual` also puts the link, table and poetry option menus among them (the classic
|
|
895
|
+
* toolbar); the ribbon shows those on their own tabs instead. */
|
|
896
|
+
const insertButtons = (contextual) => (_jsxs(_Fragment, { children: [config.links &&
|
|
897
|
+
(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
898
|
restoreSelection();
|
|
853
899
|
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 }) })] }))] }
|
|
900
|
+
}, 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 }) })] }))] }));
|
|
901
|
+
const insertSection = showInsertGroup && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: insertButtons(true) }, "insert"));
|
|
855
902
|
const joinLines = () => {
|
|
856
903
|
editor.update(() => {
|
|
857
904
|
$joinSelectedLines();
|
|
858
905
|
}, { discrete: true });
|
|
859
906
|
editor.focus();
|
|
860
907
|
};
|
|
908
|
+
// The tools group is always built, even when every command in it is off, so the ribbon asks first.
|
|
909
|
+
const hasToolsGroup = config.language.autocorrect || config.language.textCleanup || config.language.spellCheck || config.joinLines;
|
|
861
910
|
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
911
|
// Uniform mode's zoom: [-] 100% [+], stepping through the preset levels; the
|
|
863
912
|
// percentage resets to 100%. Always laid out left-to-right, like a number.
|
|
@@ -866,13 +915,18 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
866
915
|
const zoomInTo = ZOOM_LEVELS_PERCENT.find((level) => level > zoom);
|
|
867
916
|
const hasEndUtilities = Boolean(drafts || config.findReplace || helpUrl !== false);
|
|
868
917
|
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"));
|
|
918
|
+
const draftsButton = drafts && _jsx(ToolbarButton, { icon: IconHistory, title: strings.toolbar.drafts, onClick: () => setDraftsOpen(true) });
|
|
919
|
+
const findButton = config.findReplace && (_jsx(ToolbarButton, { icon: IconSearch, title: strings.findReplace.toggle, active: findOpen, onClick: onToggleFind }));
|
|
920
|
+
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
921
|
// Drafts, search and help: the far-end group (see `endMovable` below).
|
|
870
|
-
const utilitiesGroup = hasEndUtilities && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [
|
|
922
|
+
const utilitiesGroup = hasEndUtilities && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [draftsButton, findButton, helpButton] }, "end"));
|
|
923
|
+
const saveGroup = showSave && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: _jsx(ToolbarButton, { icon: IconDeviceFloppy, title: strings.toolbar.save, dirty: Boolean(isDirty),
|
|
924
|
+
// Nothing to save until the content has changed since it was loaded or last saved.
|
|
925
|
+
disabled: !isDirty, onClick: onSave }) }, "save"));
|
|
926
|
+
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
927
|
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")),
|
|
928
|
+
saveGroup,
|
|
929
|
+
historyGroup,
|
|
876
930
|
formatSection,
|
|
877
931
|
alignSection,
|
|
878
932
|
];
|
|
@@ -942,35 +996,128 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
942
996
|
const visibleEnd = endMovable.filter(isVisible);
|
|
943
997
|
// Shown in the menu in toolbar order: the inline sections, then the far-end ones.
|
|
944
998
|
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
|
-
|
|
999
|
+
// The right-click menu and the dialogs are the same in both layouts.
|
|
1000
|
+
const contextMenuEl = (_jsxs(Menu, { opened: contextMenu !== null, onChange: (opened) => {
|
|
1001
|
+
if (!opened)
|
|
1002
|
+
setContextMenu(null);
|
|
1003
|
+
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: CONTEXT_MENU_WIDTH,
|
|
1004
|
+
// Stays inside the visible area: flips above the click or shifts sideways when it fits that
|
|
1005
|
+
// 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 } }, 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 && (_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
|
+
const match = contextMenu.spelling.match;
|
|
1008
|
+
editor.update(() => $replaceMatch(match, suggestion), { discrete: true });
|
|
1009
|
+
editor.focus();
|
|
1010
|
+
}, children: suggestion }, suggestion))), _jsx(Menu.Item, { onClick: () => {
|
|
1011
|
+
ignoreWord(contextMenu.spelling.language, contextMenu.spelling.word);
|
|
1012
|
+
setContextMenu(null);
|
|
1013
|
+
}, children: strings.contextMenu.ignore }), _jsx(Menu.Item, { onClick: () => {
|
|
1014
|
+
const { language, word } = contextMenu.spelling;
|
|
1015
|
+
// Without a writable store, the word is ignored for this session instead.
|
|
1016
|
+
void addUserWord(dictionaryStores, language, word).then((added) => {
|
|
1017
|
+
if (!added)
|
|
1018
|
+
ignoreWord(language, word);
|
|
1019
|
+
});
|
|
1020
|
+
setContextMenu(null);
|
|
1021
|
+
}, children: strings.contextMenu.addToDictionary }), onAddAutoCorrect && config.language.autocorrect && (_jsx(Menu.Item, { onClick: () => {
|
|
1022
|
+
onAddAutoCorrect(contextMenu.spelling.word, contextMenu.spelling.language);
|
|
1023
|
+
setContextMenu(null);
|
|
1024
|
+
}, children: strings.contextMenu.addToAutoCorrect })), _jsx(Menu.Divider, {})] })), contextMenu?.thesaurus && (_jsxs(_Fragment, { children: [_jsx(Menu.Label, { children: strings.thesaurus.synonyms }), 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: () => {
|
|
1025
|
+
const match = contextMenu.thesaurus.match;
|
|
1026
|
+
editor.update(() => $replaceMatch(match, synonym), { discrete: true });
|
|
1027
|
+
editor.focus();
|
|
1028
|
+
}, children: synonym }, synonym))), _jsx(Menu.Divider, {})] })), contextMenu?.link !== undefined && (_jsxs(_Fragment, { children: [_jsx(LinkMenuItems, { url: contextMenu.link, onEdit: () => {
|
|
1029
|
+
restoreSelection();
|
|
1030
|
+
openLinkDialog();
|
|
1031
|
+
}, onRemove: removeLink, strings: strings }), _jsx(Menu.Divider, {})] })), contextMenu?.table && (_jsxs(_Fragment, { children: [_jsx(TableMenuItems, { strings: strings, direction: direction, rows: contextMenu.table.rows, columns: contextMenu.table.columns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }), _jsx(Menu.Divider, {})] })), contextMenu?.poetry && (_jsxs(_Fragment, { children: [_jsx(PoetryMenuItems, { strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }), _jsx(Menu.Divider, {})] })), contextMenu?.text && (_jsxs(_Fragment, { children: [_jsx(Menu.Item, { leftSection: _jsx(IconArrowsJoin, { size: ICON_SIZE, stroke: ICON_STROKE }), disabled: !contextMenu.canJoin, onClick: runMenuAction(() => {
|
|
1032
|
+
$joinSelectedLines();
|
|
1033
|
+
}), children: strings.contextMenu.joinLines }), _jsx(Menu.Divider, {})] })), _jsx(Menu.Item, { leftSection: _jsx(IconCut, { size: ICON_SIZE, stroke: ICON_STROKE }), onClick: () => void copyOrCut(true)(), children: strings.contextMenu.cut }), _jsx(Menu.Item, { leftSection: _jsx(IconCopy, { size: ICON_SIZE, stroke: ICON_STROKE }), onClick: () => void copyOrCut(false)(), children: strings.contextMenu.copy }), _jsx(Menu.Item, { leftSection: _jsx(IconClipboard, { size: ICON_SIZE, stroke: ICON_STROKE }), onClick: () => void paste(), children: strings.contextMenu.paste }), _jsx(Menu.Item, { leftSection: _jsx(IconSelectAll, { size: ICON_SIZE, stroke: ICON_STROKE }), onClick: runMenuAction(() => $selectAll()), children: strings.contextMenu.selectAll })] })] }));
|
|
1034
|
+
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
|
+
// The ribbon layout (UI spec §3.4): the same command groups as above, on tabs.
|
|
1036
|
+
if (ribbon) {
|
|
1037
|
+
const rt = strings.toolbar.ribbon;
|
|
1038
|
+
const cluster = (key, children) => (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: children }, key));
|
|
1039
|
+
const groupsByTab = {
|
|
1040
|
+
home: [formatSection, alignSection, fontSection],
|
|
1041
|
+
insert: [showInsertGroup && cluster('insert', insertButtons(false))],
|
|
1042
|
+
tools: [hasToolsGroup && toolsSection],
|
|
1043
|
+
table: [
|
|
1044
|
+
config.tables &&
|
|
1045
|
+
state.inTable &&
|
|
1046
|
+
cluster('table', _jsx(TableMenuItems, { mode: "ribbon", strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction })),
|
|
1047
|
+
],
|
|
1048
|
+
poetry: [
|
|
1049
|
+
config.poetry.enabled &&
|
|
1050
|
+
state.inPoetry &&
|
|
1051
|
+
cluster('poetry', _jsx(PoetryMenuItems, { mode: "ribbon", strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction })),
|
|
1052
|
+
],
|
|
1053
|
+
link: [
|
|
1054
|
+
config.links &&
|
|
1055
|
+
state.isLink &&
|
|
1056
|
+
cluster('link', _jsx(LinkMenuItems, { mode: "ribbon", url: state.linkUrl, onEdit: () => {
|
|
1057
|
+
restoreSelection();
|
|
1058
|
+
openLinkDialog();
|
|
1059
|
+
}, onRemove: removeLink, strings: strings })),
|
|
1060
|
+
],
|
|
1061
|
+
};
|
|
1062
|
+
const CONTEXTUAL = ['table', 'poetry', 'link'];
|
|
1063
|
+
// A tab with nothing to show (its features are off, or the caret is not in that content) is left out.
|
|
1064
|
+
const tabs = ['home', 'insert', 'tools', ...CONTEXTUAL]
|
|
1065
|
+
.map((id) => ({ id, label: rt[id], groups: groupsByTab[id].filter(Boolean) }))
|
|
1066
|
+
.filter((tab) => tab.groups.length > 0);
|
|
1067
|
+
const activeTab = tabs.find((tab) => tab.id === ribbonTab) ?? tabs[0];
|
|
1068
|
+
// A context tab that went away (the caret left the table) must not come back selected on its own later.
|
|
1069
|
+
if (activeTab && activeTab.id !== ribbonTab)
|
|
1070
|
+
setRibbonTab(activeTab.id);
|
|
1071
|
+
const panelVisible = !ribbonCollapsed || ribbonPeek;
|
|
1072
|
+
const toggleCollapsed = () => {
|
|
1073
|
+
setRibbonCollapsed((collapsed) => !collapsed);
|
|
1074
|
+
setRibbonPeek(false);
|
|
1075
|
+
};
|
|
1076
|
+
const tabDomId = (id) => `${ribbonId}-tab-${id}`;
|
|
1077
|
+
const onTabKeyDown = (event) => {
|
|
1078
|
+
if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key) || tabs.length === 0)
|
|
1079
|
+
return;
|
|
1080
|
+
const index = Math.max(0, tabs.findIndex((tab) => tab.id === activeTab?.id));
|
|
1081
|
+
const forward = event.key === (direction === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
|
|
1082
|
+
const next = event.key === 'Home' ? 0 : event.key === 'End' ? tabs.length - 1 : (index + (forward ? 1 : -1) + tabs.length) % tabs.length;
|
|
1083
|
+
event.preventDefault();
|
|
1084
|
+
setRibbonTab(tabs[next].id);
|
|
1085
|
+
event.currentTarget.querySelectorAll('[role="tab"]')[next]?.focus();
|
|
1086
|
+
};
|
|
1087
|
+
// Save, undo and redo come before the tabs; drafts, search and help come after them. Neither is on a tab,
|
|
1088
|
+
// so both stay in reach whichever tab is open (and when there are no tabs).
|
|
1089
|
+
const quickAccess = [saveGroup, historyGroup].filter(Boolean);
|
|
1090
|
+
const utilities = (draftsButton || findButton || helpButton) &&
|
|
1091
|
+
cluster('utilities', _jsxs(_Fragment, { children: [draftsButton, findButton, helpButton] }));
|
|
1092
|
+
// The collapse button belongs to the row, not to a tab, and is only offered when there are tabs to hide the commands of.
|
|
1093
|
+
const collapseGroup = tabs.length > 0 &&
|
|
1094
|
+
cluster('collapse', _jsx(ToolbarButton, { icon: ribbonCollapsed ? IconChevronDown : IconChevronUp, title: ribbonCollapsed ? rt.expand : rt.collapse, "aria-expanded": !ribbonCollapsed, onClick: toggleCollapsed }));
|
|
1095
|
+
// Zoom (uniform font mode) is a view setting, not a tab: it leads the document tools.
|
|
1096
|
+
const utilityBar = [zoomGroup, utilities, collapseGroup].filter(Boolean);
|
|
1097
|
+
return (_jsxs("div", { ref: ribbonRootRef, className: ['likhari-ribbon', bordered ? '' : 'likhari-ribbon--plain', ribbonCollapsed ? 'likhari-ribbon--collapsed' : ''].filter(Boolean).join(' '), onKeyDown: (event) => {
|
|
1098
|
+
// Ctrl+F1 collapses and expands the ribbon, as in office suites.
|
|
1099
|
+
if (event.key === 'F1' && event.ctrlKey && tabs.length > 0) {
|
|
1100
|
+
event.preventDefault();
|
|
1101
|
+
toggleCollapsed();
|
|
1102
|
+
}
|
|
1103
|
+
}, 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) => {
|
|
1104
|
+
// While the ribbon is collapsed a tab only counts as selected when its panel is peeking open.
|
|
1105
|
+
const selected = panelVisible && tab.id === activeTab?.id;
|
|
1106
|
+
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,
|
|
1107
|
+
// Keep the editor's selection: a mousedown here would blur the canvas.
|
|
1108
|
+
onMouseDown: (e) => e.preventDefault(), onClick: () => {
|
|
1109
|
+
setRibbonTab(tab.id);
|
|
1110
|
+
// Collapsed: a tab opens its commands over the canvas, and clicking it again closes them.
|
|
1111
|
+
if (ribbonCollapsed)
|
|
1112
|
+
setRibbonPeek(!(ribbonPeek && tab.id === activeTab?.id));
|
|
1113
|
+
}, onDoubleClick: toggleCollapsed, children: tab.label }, tab.id));
|
|
1114
|
+
}) })), 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) => {
|
|
1115
|
+
// A command chosen from the peeking panel closes it, as in office suites. A button that opens a
|
|
1116
|
+
// menu (More formatting) keeps it open, so the menu is not pulled away from under the pointer.
|
|
1117
|
+
const button = event.target.closest('button, a');
|
|
1118
|
+
if (ribbonCollapsed && button && !button.hasAttribute('aria-haspopup'))
|
|
1119
|
+
setRibbonPeek(false);
|
|
1120
|
+
}, 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] }));
|
|
1121
|
+
}
|
|
1122
|
+
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
1123
|
}
|
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,222 @@
|
|
|
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
|
+
}
|