@inshapardaz/likhari-react 0.1.28-dev.254 → 0.1.28-dev.257
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.map +1 -1
- package/dist/components/Toolbar.js +48 -151
- package/dist/i18n/strings.js +1 -1
- package/dist/theme/editor.css +17 -72
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA0CA,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;AAgDtF,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA0CA,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;AAgDtF,OAAO,EAAgB,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAA6D,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AAItG,OAAO,KAAK,EAAE,MAAM,EAAW,MAAM,iBAAiB,CAAC;AAggBvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,gCAAgC;IAChC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,aAAa,EAAE,CAAC;IACnC,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IACnE,+FAA+F;IAC/F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,wFAAwF;IACxF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,iGAAiG;IACjG,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,wFAAwF;IACxF,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC/B;AAED,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,gBAAqB,EAAE,eAAoB,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAgB,EAAE,YAAY,EAAE,SAAiB,EAAE,aAAa,EAAE,eAAuB,EAAE,mBAAmB,EAAE,WAAkC,EAAE,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,EAAE,YAAY,+BA+/BvU"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
import { Menu, Select } from '@mantine/core';
|
|
2
|
+
import { Fragment, forwardRef, useCallback, useEffect, useRef, useState } from 'react';
|
|
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';
|
|
6
6
|
import { $getSelectionStyleValueForProperty, $patchStyleText, $setBlocksType } from '@lexical/selection';
|
|
@@ -108,15 +108,18 @@ function iconOptionRenderer(icons, fallback) {
|
|
|
108
108
|
return (_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx(Icon, { size: 16, stroke: ICON_STROKE }), option.label] }));
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
|
-
function ToolbarButton({ icon: Icon, title, active, dirty,
|
|
112
|
-
return (_jsx(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
const ToolbarButton = forwardRef(function ToolbarButton({ icon: Icon, title, active, dirty, onMouseDown, ...rest }, ref) {
|
|
112
|
+
return (_jsx(MantineToolbar.Toggle, { ref: ref, "aria-label": title, title: title, active: active, "data-dirty": dirty === undefined ? undefined : dirty ? 'true' : 'false',
|
|
113
|
+
// Keep the editor's selection: a mousedown here would blur the canvas.
|
|
114
|
+
onMouseDown: (e) => {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
onMouseDown?.(e);
|
|
117
|
+
}, ...rest, children: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }) }));
|
|
118
|
+
});
|
|
119
|
+
function withDividers(sections) {
|
|
120
|
+
return sections
|
|
121
|
+
.filter((section) => Boolean(section))
|
|
122
|
+
.flatMap((section, index) => (index === 0 ? [section] : [_jsx(MantineToolbar.Divider, {}, `divider-${index}`), section]));
|
|
120
123
|
}
|
|
121
124
|
/** Mantine Select (combobox) for the toolbar's dropdown controls. The icon
|
|
122
125
|
* labels the control itself, since a dropdown can't show one per option in
|
|
@@ -126,24 +129,9 @@ function ToolbarSelect({ icon: Icon, label, value, data, width, disabled, placeh
|
|
|
126
129
|
const portalTarget = usePortalTarget();
|
|
127
130
|
return (_jsx(Select, { size: "xs", w: width, "aria-label": label, title: disabled && comingSoon ? comingSoon(label) : label, data: data, value: value, placeholder: placeholder, disabled: disabled, searchable: searchable, renderOption: renderOption, nothingFoundMessage: searchable ? noMatchMessage : undefined, allowDeselect: false, leftSection: _jsx(Icon, { size: 15, stroke: ICON_STROKE }), comboboxProps: { withinPortal: true, position: 'bottom-start', middlewares: { flip: true, shift: true }, portalProps: { target: portalTarget } }, classNames: { input: 'likhari-toolbar-select-input', dropdown: 'likhari-toolbar-select-dropdown' }, onChange: (v) => v && onChange?.(v) }));
|
|
128
131
|
}
|
|
129
|
-
|
|
130
|
-
function
|
|
131
|
-
|
|
132
|
-
return false;
|
|
133
|
-
for (const v of a)
|
|
134
|
-
if (!b.has(v))
|
|
135
|
-
return false;
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
/** Renders a movable group's items as normal inline toolbar buttons (used
|
|
139
|
-
* both in the real toolbar and in the hidden width-measuring clone). */
|
|
140
|
-
function MovableGroupButtons({ group }) {
|
|
141
|
-
return (_jsx("div", { className: "likhari-toolbar-group", "data-group-key": group.key, children: group.items.map((item) => (_jsx(ToolbarButton, { icon: item.icon, title: item.label, active: item.active, onClick: item.onClick }, item.key))) }));
|
|
142
|
-
}
|
|
143
|
-
function OverflowItem({ icon: Icon, label, active, onClick, }) {
|
|
144
|
-
return (_jsx(Menu.Item, { leftSection: _jsx(Icon, { size: ICON_SIZE, stroke: ICON_STROKE }), "data-active": active ? 'true' : 'false', className: "likhari-overflow-item",
|
|
145
|
-
// Keep the editor's selection: a mousedown here would blur the canvas.
|
|
146
|
-
onMouseDown: (e) => e.preventDefault(), onClick: onClick, children: label }));
|
|
132
|
+
/** An item in the "..." menu. A mousedown here would blur the canvas, so it is kept. */
|
|
133
|
+
function MoreMenuItem({ icon: Icon, label, active, onClick, }) {
|
|
134
|
+
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 }));
|
|
147
135
|
}
|
|
148
136
|
function LinkMenuItems({ url, onEdit, onRemove, strings }) {
|
|
149
137
|
// Only offer the link as clickable if it's a URL the editor would have accepted.
|
|
@@ -194,15 +182,6 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
194
182
|
const [draftsOpen, setDraftsOpen] = useState(false);
|
|
195
183
|
const rtl = direction === 'rtl';
|
|
196
184
|
const ALIGN_ICONS = rtl ? ALIGN_ICONS_RTL : ALIGN_ICONS_LTR;
|
|
197
|
-
// Responsive "priority+" overflow: the toolbar's outer container and a
|
|
198
|
-
// hidden nowrap clone (rendered with every movable group forced inline)
|
|
199
|
-
// are both measured; whenever the clone's natural width exceeds the
|
|
200
|
-
// container's available width, the lowest-priority movable groups are
|
|
201
|
-
// moved into the "..." menu, lowest-priority first, until what remains
|
|
202
|
-
// inline fits (or there's nothing left to move).
|
|
203
|
-
const toolbarContainerRef = useRef(null);
|
|
204
|
-
const toolbarMeasureRef = useRef(null);
|
|
205
|
-
const [overflowGroupKeys, setOverflowGroupKeys] = useState(EMPTY_OVERFLOW);
|
|
206
185
|
const updateToolbar = useCallback(() => {
|
|
207
186
|
editor.getEditorState().read(() => {
|
|
208
187
|
const selection = $getSelection();
|
|
@@ -342,7 +321,7 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
342
321
|
};
|
|
343
322
|
const snapshotSelectionRef = useRef(snapshotSelection);
|
|
344
323
|
snapshotSelectionRef.current = snapshotSelection;
|
|
345
|
-
const
|
|
324
|
+
const runMenuItem = (action) => () => {
|
|
346
325
|
const saved = menuSelectionRef.current;
|
|
347
326
|
if (saved)
|
|
348
327
|
editor.update(() => $setSelection(saved.clone()), { discrete: true });
|
|
@@ -646,35 +625,22 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
646
625
|
const headingLevels = config.blocks.headingLevels ?? [];
|
|
647
626
|
const fmt = config.formatting;
|
|
648
627
|
const showFormattingGroup = headingLevels.length > 0 || config.lists.bullet || config.lists.numbered || config.lists.check || config.blocks.quote;
|
|
649
|
-
const showInlineGroup = fmt.bold || fmt.italic || fmt.underline;
|
|
650
628
|
const showAlignGroup = config.alignment.start || config.alignment.center || config.alignment.justify || config.alignment.left || config.alignment.right;
|
|
651
|
-
const
|
|
629
|
+
const showInsertGroup = config.links ||
|
|
630
|
+
config.images.linked ||
|
|
652
631
|
config.images.embedded ||
|
|
653
632
|
config.tables ||
|
|
654
633
|
config.blocks.horizontalRule ||
|
|
655
634
|
config.blocks.pageBreak ||
|
|
656
635
|
config.columns ||
|
|
657
636
|
config.footnotes ||
|
|
658
|
-
config.poetry.enabled
|
|
637
|
+
(config.poetry.enabled && locale !== 'en') ||
|
|
638
|
+
(config.tables && state.inTable) ||
|
|
639
|
+
(config.poetry.enabled && state.inPoetry);
|
|
659
640
|
const showLanguageGroup = config.language.autocorrect || config.language.textCleanup || config.language.spellCheck;
|
|
660
|
-
|
|
661
|
-
// as normal inline toolbar groups whenever there's room, and only move
|
|
662
|
-
// into the "..." overflow menu when the measured toolbar content doesn't
|
|
663
|
-
// fit the available width (see the ResizeObserver effect below) — this
|
|
664
|
-
// replaces the old always-on overflow menu, which was driven purely by
|
|
665
|
-
// these config flags regardless of actual space.
|
|
666
|
-
const scriptCleanupItems = [];
|
|
667
|
-
if (fmt.strikethrough) {
|
|
668
|
-
scriptCleanupItems.push({
|
|
669
|
-
key: 'strikethrough',
|
|
670
|
-
icon: IconStrikethrough,
|
|
671
|
-
label: strings.toolbar.strikethrough,
|
|
672
|
-
active: state.activeFormats.has('strikethrough'),
|
|
673
|
-
onClick: () => formatText('strikethrough'),
|
|
674
|
-
});
|
|
675
|
-
}
|
|
641
|
+
const moreItems = [];
|
|
676
642
|
if (fmt.superscript) {
|
|
677
|
-
|
|
643
|
+
moreItems.push({
|
|
678
644
|
key: 'superscript',
|
|
679
645
|
icon: IconSuperscript,
|
|
680
646
|
label: strings.toolbar.superscript,
|
|
@@ -683,7 +649,7 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
683
649
|
});
|
|
684
650
|
}
|
|
685
651
|
if (fmt.subscript) {
|
|
686
|
-
|
|
652
|
+
moreItems.push({
|
|
687
653
|
key: 'subscript',
|
|
688
654
|
icon: IconSubscript,
|
|
689
655
|
label: strings.toolbar.subscript,
|
|
@@ -692,10 +658,10 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
692
658
|
});
|
|
693
659
|
}
|
|
694
660
|
if (fmt.caseTransforms) {
|
|
695
|
-
|
|
661
|
+
moreItems.push({ key: 'upper', icon: IconLetterCaseUpper, label: strings.toolbar.uppercase, onClick: () => applyCaseTransform('upper') }, { key: 'lower', icon: IconLetterCaseLower, label: strings.toolbar.lowercase, onClick: () => applyCaseTransform('lower') }, { key: 'capitalize', icon: IconLetterCase, label: strings.toolbar.capitalize, onClick: () => applyCaseTransform('capitalize') });
|
|
696
662
|
}
|
|
697
663
|
if (fmt.clearFormatting) {
|
|
698
|
-
|
|
664
|
+
moreItems.push({ key: 'clear', icon: IconClearFormatting, label: strings.toolbar.clearFormatting, onClick: clearFormatting });
|
|
699
665
|
}
|
|
700
666
|
// UI spec §5: indent/outdent arrows are direction-relative and swap in RTL
|
|
701
667
|
// (outdent moves content toward the start edge, which is the right in RTL).
|
|
@@ -715,56 +681,6 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
715
681
|
},
|
|
716
682
|
]
|
|
717
683
|
: [];
|
|
718
|
-
// Low to high priority: the first group here is the first one pushed into
|
|
719
|
-
// overflow once content stops fitting (UI spec §3.3).
|
|
720
|
-
const movableGroups = [
|
|
721
|
-
{ key: 'scriptCleanup', items: scriptCleanupItems },
|
|
722
|
-
{ key: 'indentOutdent', items: indentItems },
|
|
723
|
-
].filter((g) => g.items.length > 0);
|
|
724
|
-
const movableGroupKeys = useMemo(() => movableGroups.map((g) => g.key).join(','), [movableGroups]);
|
|
725
|
-
// Re-measure whenever the container is resized, or whenever the set of
|
|
726
|
-
// movable groups (and so the hidden clone's content) changes.
|
|
727
|
-
useLayoutEffect(() => {
|
|
728
|
-
const container = toolbarContainerRef.current;
|
|
729
|
-
const measure = toolbarMeasureRef.current;
|
|
730
|
-
if (!container || !measure)
|
|
731
|
-
return;
|
|
732
|
-
// Rough width of the "..." button itself (icon button + its gap) —
|
|
733
|
-
// only charged against the budget once something has actually moved
|
|
734
|
-
// into it, since it isn't rendered at all otherwise.
|
|
735
|
-
const OVERFLOW_BUTTON_WIDTH = 38;
|
|
736
|
-
const recompute = () => {
|
|
737
|
-
const available = container.clientWidth;
|
|
738
|
-
const total = measure.scrollWidth;
|
|
739
|
-
if (total <= available) {
|
|
740
|
-
setOverflowGroupKeys((prev) => (prev.size === 0 ? prev : EMPTY_OVERFLOW));
|
|
741
|
-
return;
|
|
742
|
-
}
|
|
743
|
-
const widths = new Map();
|
|
744
|
-
measure.querySelectorAll('[data-group-key]').forEach((el) => {
|
|
745
|
-
widths.set(el.dataset.groupKey, el.getBoundingClientRect().width);
|
|
746
|
-
});
|
|
747
|
-
let remaining = total;
|
|
748
|
-
const next = new Set();
|
|
749
|
-
for (const key of movableGroupKeys.split(',').filter(Boolean)) {
|
|
750
|
-
if (remaining <= available)
|
|
751
|
-
break;
|
|
752
|
-
const w = widths.get(key);
|
|
753
|
-
if (w === undefined)
|
|
754
|
-
continue;
|
|
755
|
-
remaining -= w;
|
|
756
|
-
next.add(key);
|
|
757
|
-
}
|
|
758
|
-
if (next.size > 0)
|
|
759
|
-
remaining += OVERFLOW_BUTTON_WIDTH;
|
|
760
|
-
setOverflowGroupKeys((prev) => (setsEqual(prev, next) ? prev : next));
|
|
761
|
-
};
|
|
762
|
-
recompute();
|
|
763
|
-
const ro = new ResizeObserver(recompute);
|
|
764
|
-
ro.observe(container);
|
|
765
|
-
ro.observe(measure);
|
|
766
|
-
return () => ro.disconnect();
|
|
767
|
-
});
|
|
768
684
|
// Grouped for the dropdown when options declare groups (Latin / Urdu).
|
|
769
685
|
const fontData = (() => {
|
|
770
686
|
const data = [];
|
|
@@ -807,36 +723,26 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
807
723
|
];
|
|
808
724
|
const formattingValue = state.listType ?? state.blockType;
|
|
809
725
|
const AlignIcon = ALIGN_ICONS[state.elementFormat] ?? IconAlignLeft;
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
openLinkDialog();
|
|
829
|
-
}, onRemove: removeLink, strings: strings }) })] })) : (_jsx(ToolbarButton, { icon: IconLink, title: strings.toolbar.insertLink, onClick: openLinkDialog })) }, "link")),
|
|
830
|
-
showStubInsertGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", children: [(config.images.linked || config.images.embedded) && (_jsx(ToolbarButton, { icon: IconPhoto, title: strings.toolbar.insertImage, onClick: openImageDialog })), config.blocks.pageBreak && (_jsx(ToolbarButton, { icon: IconPageBreak, title: strings.toolbar.insertPageBreak, onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK_COMMAND, undefined) })), config.tables && _jsx(ToolbarButton, { icon: IconTable, title: strings.toolbar.insertTable, onClick: openTableDialog }), config.columns && _jsx(ToolbarButton, { icon: IconColumns, title: strings.toolbar.insertColumns, onClick: openLayoutDialog }), config.footnotes && (_jsx(ToolbarButton, { icon: IconNumber1Small, title: strings.toolbar.insertFootnote, onClick: () => editor.dispatchCommand(INSERT_FOOTNOTE_COMMAND, undefined) })), config.blocks.horizontalRule && (_jsx(ToolbarButton, { icon: IconSeparatorHorizontal, title: strings.toolbar.insertHorizontalRule, onClick: () => editor.dispatchCommand(INSERT_HORIZONTAL_RULE_COMMAND, undefined) })), config.findReplace && (_jsx(ToolbarButton, { icon: IconSearch, title: strings.findReplace.toggle, active: findOpen, onClick: onToggleFind })), config.poetry.enabled && locale !== 'en' && (_jsx(ToolbarButton, { icon: IconFeather, title: strings.toolbar.insertPoetryCouplet, onClick: () => editor.dispatchCommand(INSERT_POETRY_COUPLET_COMMAND, { layout: config.poetry.defaultLayout }) }))] }, "stubInsert")),
|
|
831
|
-
config.tables && state.inTable && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 240, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.tableOptions, title: strings.toolbar.tableOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconTableOptions, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(TableMenuItems, { strings: strings, direction: direction, rows: state.tableRows, columns: state.tableColumns, canMergeCells: state.canMergeCells, canUnmergeCell: state.canUnmergeCell, onAction: runMenuAction }) })] }) }, "tableActions")),
|
|
832
|
-
config.poetry.enabled && state.inPoetry && (_jsx("div", { className: "likhari-toolbar-group", children: _jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 200, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "data-active": "true", "aria-pressed": "true", "aria-haspopup": "menu", "aria-label": strings.toolbar.poetryOptions, title: strings.toolbar.poetryOptions, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconFeather, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: _jsx(PoetryMenuItems, { strings: strings, layout: state.poetryLayout, scale: state.poetryScale, centered: state.poetryCentered, onAction: runMenuAction }) })] }) }, "poetryActions")),
|
|
833
|
-
showLanguageGroup && (_jsxs("div", { className: "likhari-toolbar-group likhari-toolbar-group--collapse-tablet", 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 }))] }, "language")),
|
|
726
|
+
const formatSection = (showFormattingGroup || fmt.bold || fmt.italic || fmt.underline || fmt.strikethrough || moreItems.length > 0) && (_jsxs(Fragment, { children: [showFormattingGroup && (_jsx(MantineToolbar.Group, { children: _jsx(ToolbarSelect, { icon: IconPilcrow, label: strings.toolbar.formattingLabel, width: 148, value: formattingValue, data: formattingOptions, comingSoon: strings.toolbar.comingSoon, renderOption: iconOptionRenderer(FORMATTING_ICONS, IconPilcrow), onChange: withRefocus((v) => applyFormatting(v)) }) })), (fmt.bold || fmt.italic || fmt.underline || fmt.strikethrough || moreItems.length > 0) && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [fmt.bold && _jsx(ToolbarButton, { icon: IconBold, title: strings.toolbar.bold, active: state.activeFormats.has('bold'), onClick: () => formatText('bold') }), fmt.italic && (_jsx(ToolbarButton, { icon: IconItalic, title: strings.toolbar.italic, active: state.activeFormats.has('italic'), onClick: () => formatText('italic') })), fmt.underline && (_jsx(ToolbarButton, { icon: IconUnderline, title: strings.toolbar.underline, active: state.activeFormats.has('underline'), onClick: () => formatText('underline') })), fmt.strikethrough && (_jsx(ToolbarButton, { icon: IconStrikethrough, title: strings.toolbar.strikethrough, active: state.activeFormats.has('strikethrough'), onClick: () => formatText('strikethrough') })), moreItems.length > 0 && (_jsxs(Menu, { position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 210, closeOnItemClick: true, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx(ToolbarButton, { icon: IconDots, title: strings.toolbar.moreFormatting }) }), _jsx(Menu.Dropdown, { children: moreItems.map((item) => (_jsx(MoreMenuItem, { icon: item.icon, label: item.label, active: item.active, onClick: runMenuItem(item.onClick) }, item.key))) })] }))] }))] }, "format"));
|
|
727
|
+
const alignSection = (showAlignGroup || indentItems.length > 0) && (_jsxs(Fragment, { children: [showAlignGroup && (_jsx(MantineToolbar.Group, { children: _jsx(ToolbarSelect, { icon: AlignIcon, label: strings.toolbar.alignment, width: 138, value: state.elementFormat || 'start', data: alignOptions, renderOption: iconOptionRenderer(ALIGN_ICONS, IconAlignLeft), onChange: withRefocus((v) => formatElement(v)) }) })), indentItems.length > 0 && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: indentItems.map((item) => (_jsx(ToolbarButton, { icon: item.icon, title: item.label, onClick: item.onClick }, item.key))) }))] }, "align"));
|
|
728
|
+
const fontSection = (config.font.family || config.font.size) && (_jsxs(MantineToolbar.Group, { children: [config.font.family && (_jsx(ToolbarSelect, { icon: IconTypography, label: strings.toolbar.fontFamily, width: 150, value: fontOptions.some((f) => f.family === shownFontFamily) ? shownFontFamily : null, placeholder: strings.toolbar.fontFamilyPlaceholder, data: fontData, searchable: true, noMatchMessage: strings.toolbar.noMatch, renderOption: ({ option }) => _jsx("span", { style: { fontFamily: option.value }, children: option.label }), onChange: withRefocus((v) => applyFont('font-family', v)) })), config.font.size && (_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) })), onChange: withRefocus((v) => applyFont('font-size', v)) }))] }, "font"));
|
|
729
|
+
const insertSection = showInsertGroup && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [config.links &&
|
|
730
|
+
(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: () => {
|
|
731
|
+
restoreSelection();
|
|
732
|
+
openLinkDialog();
|
|
733
|
+
}, 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 }) })] }))] }, "insert"));
|
|
734
|
+
const toolsSection = showLanguageGroup && (_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 }))] }, "tools"));
|
|
735
|
+
const endSection = (drafts || config.findReplace) && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", style: { marginInlineStart: 'auto' }, children: [drafts && _jsx(ToolbarButton, { icon: IconHistory, title: strings.toolbar.drafts, onClick: () => setDraftsOpen(true) }), config.findReplace && (_jsx(ToolbarButton, { icon: IconSearch, title: strings.findReplace.toggle, active: findOpen, onClick: onToggleFind }))] }, "end"));
|
|
736
|
+
const startSections = [
|
|
737
|
+
showSave && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: _jsx(ToolbarButton, { icon: IconDeviceFloppy, title: strings.toolbar.save, dirty: Boolean(isDirty), onClick: onSave }) }, "save")),
|
|
738
|
+
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")),
|
|
739
|
+
formatSection,
|
|
740
|
+
alignSection,
|
|
741
|
+
fontSection,
|
|
742
|
+
insertSection,
|
|
743
|
+
toolsSection,
|
|
834
744
|
];
|
|
835
|
-
return (_jsxs(
|
|
836
|
-
.filter((group) => !overflowGroupKeys.has(group.key))
|
|
837
|
-
.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key))), overflowGroupKeys.size > 0 && (_jsxs(Menu, { position: "bottom-end", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 210, closeOnItemClick: true, onOpen: snapshotSelection, children: [_jsx(Menu.Target, { children: _jsx("button", { type: "button", className: "likhari-toolbar-button", "aria-label": strings.toolbar.moreFormatting, title: strings.toolbar.moreFormatting, onMouseDown: (e) => e.preventDefault(), children: _jsx(IconDots, { size: ICON_SIZE, stroke: ICON_STROKE }) }) }), _jsx(Menu.Dropdown, { children: movableGroups
|
|
838
|
-
.filter((group) => overflowGroupKeys.has(group.key))
|
|
839
|
-
.flatMap((group) => group.items.map((item) => (_jsx(OverflowItem, { icon: item.icon, label: item.label, active: item.active, onClick: runOverflowAction(item.onClick) }, item.key)))) })] })), _jsxs(Menu, { opened: contextMenu !== null, onChange: (opened) => {
|
|
745
|
+
return (_jsxs(MantineToolbar, { "aria-label": strings.toolbar.ariaLabel, className: "likhari-toolbar", children: [withDividers(startSections), endSection, _jsxs(Menu, { opened: contextMenu !== null, onChange: (opened) => {
|
|
840
746
|
if (!opened)
|
|
841
747
|
setContextMenu(null);
|
|
842
748
|
}, position: "bottom-start", withinPortal: true, portalProps: { target: portalTarget }, shadow: "sm", width: 260, 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: () => {
|
|
@@ -864,14 +770,5 @@ export function Toolbar({ config, dictionaryStores = [], thesaurusStores = [], o
|
|
|
864
770
|
}, children: synonym }, synonym))), _jsx(Menu.Divider, {})] })), contextMenu?.link !== undefined && (_jsxs(_Fragment, { children: [_jsx(LinkMenuItems, { url: contextMenu.link, onEdit: () => {
|
|
865
771
|
restoreSelection();
|
|
866
772
|
openLinkDialog();
|
|
867
|
-
}, 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, {})] })), _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 })] })] }),
|
|
868
|
-
position: 'absolute',
|
|
869
|
-
visibility: 'hidden',
|
|
870
|
-
pointerEvents: 'none',
|
|
871
|
-
top: 0,
|
|
872
|
-
left: 0,
|
|
873
|
-
display: 'flex',
|
|
874
|
-
flexWrap: 'nowrap',
|
|
875
|
-
gap: 8,
|
|
876
|
-
}, children: [fixedGroups, movableGroups.map((group) => (_jsx(MovableGroupButtons, { group: group }, group.key)))] }), (config.images.linked || config.images.embedded) && (_jsx(ImageDialog, { mode: "insert", opened: imageDialogOpen, onSubmit: insertImage, onClose: closeImageDialog })), config.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 })] }));
|
|
773
|
+
}, 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, {})] })), _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 })] })] }), (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 })] }));
|
|
877
774
|
}
|
package/dist/i18n/strings.js
CHANGED
package/dist/theme/editor.css
CHANGED
|
@@ -19,12 +19,6 @@
|
|
|
19
19
|
its own height so only the canvas below scrolls. */
|
|
20
20
|
.likhari-toolbar {
|
|
21
21
|
display: flex;
|
|
22
|
-
/* Containing block for the hidden width-measuring clone (Toolbar.tsx):
|
|
23
|
-
without this, its position: absolute would resolve against the
|
|
24
|
-
viewport instead, and its intentionally-unwrapped (possibly very wide)
|
|
25
|
-
content could inflate the host page's scroll area instead of being
|
|
26
|
-
clipped by .likhari-root's overflow: hidden. */
|
|
27
|
-
position: relative;
|
|
28
22
|
flex-shrink: 0;
|
|
29
23
|
align-items: center;
|
|
30
24
|
gap: 8px;
|
|
@@ -57,55 +51,6 @@
|
|
|
57
51
|
pointer-events: auto;
|
|
58
52
|
}
|
|
59
53
|
|
|
60
|
-
.likhari-toolbar-group {
|
|
61
|
-
display: flex;
|
|
62
|
-
align-items: center;
|
|
63
|
-
gap: 2px;
|
|
64
|
-
padding: 0 6px;
|
|
65
|
-
border-inline-end: 0.5px solid var(--editor-line);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.likhari-toolbar-group:last-child {
|
|
69
|
-
border-inline-end: none;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.likhari-toolbar-button {
|
|
73
|
-
display: inline-flex;
|
|
74
|
-
align-items: center;
|
|
75
|
-
justify-content: center;
|
|
76
|
-
min-width: 30px;
|
|
77
|
-
height: 30px;
|
|
78
|
-
padding: 0 6px;
|
|
79
|
-
border-radius: 6px;
|
|
80
|
-
border: none;
|
|
81
|
-
background: transparent;
|
|
82
|
-
color: var(--editor-ink);
|
|
83
|
-
cursor: pointer;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.likhari-toolbar-button svg {
|
|
87
|
-
display: block;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.likhari-toolbar-button:hover {
|
|
91
|
-
background: var(--editor-line);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.likhari-toolbar-button[data-active='true'] {
|
|
95
|
-
background: var(--editor-accent-soft);
|
|
96
|
-
color: var(--editor-accent);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
.likhari-toolbar-button:focus-visible {
|
|
100
|
-
outline: 2px solid var(--editor-accent);
|
|
101
|
-
outline-offset: 1px;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.likhari-toolbar-button:disabled {
|
|
105
|
-
opacity: 0.4;
|
|
106
|
-
cursor: not-allowed;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
54
|
/* Mantine Select inside the toolbar — sized to the 30px control height and
|
|
110
55
|
themed from the --editor-* tokens (the closed input only; the dropdown is
|
|
111
56
|
portaled to <body>, outside the token scope, so it uses Mantine's own
|
|
@@ -125,35 +70,35 @@
|
|
|
125
70
|
cursor: not-allowed;
|
|
126
71
|
}
|
|
127
72
|
|
|
128
|
-
.
|
|
129
|
-
|
|
130
|
-
|
|
73
|
+
/* A cluster of related buttons (undo/redo, bold/italic/underline/strikethrough, ...) reads as one control. */
|
|
74
|
+
.likhari-toolbar-cluster {
|
|
75
|
+
border: 1px solid var(--editor-line-strong);
|
|
76
|
+
border-radius: 6px;
|
|
77
|
+
background: var(--editor-paper);
|
|
78
|
+
overflow: hidden;
|
|
131
79
|
}
|
|
132
80
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
display: none;
|
|
141
|
-
}
|
|
81
|
+
.likhari-toolbar-cluster [data-toolbar-toggle] {
|
|
82
|
+
border: none;
|
|
83
|
+
border-radius: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.likhari-toolbar-cluster [data-toolbar-toggle] + [data-toolbar-toggle] {
|
|
87
|
+
border-inline-start: 1px solid var(--editor-line);
|
|
142
88
|
}
|
|
143
89
|
|
|
144
|
-
/* Save
|
|
145
|
-
|
|
146
|
-
.likhari-toolbar-button[data-dirty='true'] {
|
|
90
|
+
/* Save: filled accent while there are unsaved changes, back to the plain outline once saved. */
|
|
91
|
+
.likhari-toolbar [data-dirty='true'] {
|
|
147
92
|
background: var(--editor-accent);
|
|
148
93
|
color: var(--editor-paper);
|
|
149
94
|
}
|
|
150
95
|
|
|
151
|
-
.likhari-toolbar
|
|
96
|
+
.likhari-toolbar [data-dirty='true']:hover {
|
|
152
97
|
background: var(--editor-accent);
|
|
153
98
|
filter: brightness(1.1);
|
|
154
99
|
}
|
|
155
100
|
|
|
156
|
-
.likhari-toolbar
|
|
101
|
+
.likhari-toolbar [data-dirty='false'] {
|
|
157
102
|
color: var(--editor-accent);
|
|
158
103
|
}
|
|
159
104
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inshapardaz/likhari-react",
|
|
3
|
-
"version": "0.1.28-dev.
|
|
3
|
+
"version": "0.1.28-dev.257",
|
|
4
4
|
"description": "React implementation of the Likhari editor, built on @lexical/react.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
"nspell": "^2.1.5"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@mantine/core": "^9.
|
|
51
|
-
"@mantine/hooks": "^9.
|
|
50
|
+
"@mantine/core": "^9.7.0",
|
|
51
|
+
"@mantine/hooks": "^9.7.0",
|
|
52
52
|
"react": "^19.2.0",
|
|
53
53
|
"react-dom": "^19.2.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@mantine/core": "^9.
|
|
57
|
-
"@mantine/hooks": "^9.
|
|
56
|
+
"@mantine/core": "^9.7.0",
|
|
57
|
+
"@mantine/hooks": "^9.7.0",
|
|
58
58
|
"@types/nspell": "^2.1.6"
|
|
59
59
|
}
|
|
60
60
|
}
|