@inshapardaz/likhari-react 0.1.40 → 0.1.41-dev.319
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/EditorRoot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"EditorRoot.d.ts","sourceRoot":"","sources":["../src/EditorRoot.tsx"],"names":[],"mappings":"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"}
|
package/dist/EditorRoot.js
CHANGED
|
@@ -276,6 +276,9 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, autoCorre
|
|
|
276
276
|
autosaveTimerRef.current = null;
|
|
277
277
|
}
|
|
278
278
|
pendingDraftRef.current = null;
|
|
279
|
+
// What follows the load (plugin transforms, node normalisation) is
|
|
280
|
+
// part of the loaded content, not an edit: see `loadSettlingRef`.
|
|
281
|
+
loadSettlingRef.current = true;
|
|
279
282
|
editor.setEditorState(parsed);
|
|
280
283
|
setIsDirty(false);
|
|
281
284
|
},
|
|
@@ -291,8 +294,43 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, autoCorre
|
|
|
291
294
|
}), [isDirty]);
|
|
292
295
|
const rootElementRef = useRef(null);
|
|
293
296
|
const editorInstanceRef = useRef(null);
|
|
297
|
+
// True from a content load (mount, or `setContent`) until the user first
|
|
298
|
+
// interacts with the editor. Loading doesn't always settle in one update:
|
|
299
|
+
// plugins and Lexical's own normalisation can rewrite the state right
|
|
300
|
+
// afterwards, and comparing that against the content as it arrived would
|
|
301
|
+
// call an untouched document "changed" (and autosave a draft of it). Until
|
|
302
|
+
// the user interacts, a change is therefore folded into the clean baseline
|
|
303
|
+
// instead: no dirty flag, no draft, no `onChange`.
|
|
304
|
+
const loadSettlingRef = useRef(true);
|
|
305
|
+
useEffect(() => {
|
|
306
|
+
const root = rootElementRef.current;
|
|
307
|
+
if (!root)
|
|
308
|
+
return;
|
|
309
|
+
const onInteraction = () => {
|
|
310
|
+
if (!loadSettlingRef.current)
|
|
311
|
+
return;
|
|
312
|
+
loadSettlingRef.current = false;
|
|
313
|
+
// The edit this event leads to has not been applied yet, so the editor's
|
|
314
|
+
// current state is the loaded content, as normalised.
|
|
315
|
+
const editor = editorInstanceRef.current;
|
|
316
|
+
if (editor && !isDirtyRef.current)
|
|
317
|
+
lastSavedJsonRef.current = JSON.stringify(editor.getEditorState().toJSON());
|
|
318
|
+
};
|
|
319
|
+
const events = ['keydown', 'pointerdown', 'beforeinput', 'paste', 'cut', 'drop', 'compositionstart'];
|
|
320
|
+
for (const type of events)
|
|
321
|
+
root.addEventListener(type, onInteraction, true);
|
|
322
|
+
return () => {
|
|
323
|
+
for (const type of events)
|
|
324
|
+
root.removeEventListener(type, onInteraction, true);
|
|
325
|
+
};
|
|
326
|
+
}, []);
|
|
294
327
|
const handleChange = (state) => {
|
|
295
328
|
editorStateRef.current = state;
|
|
329
|
+
if (loadSettlingRef.current) {
|
|
330
|
+
lastSavedJsonRef.current = JSON.stringify(state.toJSON());
|
|
331
|
+
setIsDirty(false);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
296
334
|
const json = JSON.stringify(state.toJSON());
|
|
297
335
|
setIsDirty(json !== lastSavedJsonRef.current);
|
|
298
336
|
onChange?.(state.toJSON());
|
|
@@ -305,6 +343,9 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, autoCorre
|
|
|
305
343
|
};
|
|
306
344
|
/** A draft was restored into the editor: that content is unsaved work. */
|
|
307
345
|
const handleDraftRestored = (entry) => {
|
|
346
|
+
// No clean baseline to compare with: it stays unsaved until it is saved.
|
|
347
|
+
loadSettlingRef.current = false;
|
|
348
|
+
lastSavedJsonRef.current = null;
|
|
308
349
|
setIsDirty(true);
|
|
309
350
|
if (documentId && entry.id === documentId)
|
|
310
351
|
onDraftRestored?.({ documentId, savedAt: entry.draft.savedAt });
|
|
@@ -342,7 +383,7 @@ export const EditorRoot = forwardRef(function EditorRoot({ documentId, autoCorre
|
|
|
342
383
|
? { currentId: draftId, maxBytes: autosaveMaxBytes, adoptOnRestore: !documentId, onRestored: handleDraftRestored }
|
|
343
384
|
: undefined }), documentId && (_jsx(DraftRestore, { draftId: documentId, mode: restoreDraft, initialJson: initialContentJsonRef.current, locale: locale, onRestored: handleDraftRestored })), _jsxs("div", { className: "likhari-canvas-frame", children: [config.findReplace && openPanel === 'find' && _jsx(FindReplaceBar, { strings: strings, dir: dir, onClose: () => setOpenPanel(null) }), config.language.spellCheck && openPanel === 'spell' && (_jsx(SpellcheckPanel, { strings: strings, dir: dir, dictionaryStores: wordStores, onAddAutoCorrect: config.language.autocorrect ? openAutoCorrectFor : undefined, onClose: () => setOpenPanel(null) })), config.language.autocorrect && openPanel === 'autocorrect' && (_jsx(AutoCorrectPanel, { strings: strings, dir: dir, stores: stores, initialFrom: autoCorrectPrefill?.from, initialLanguage: autoCorrectPrefill?.language, onSaved: () => setAutoCorrectVersion((v) => v + 1), onClose: () => setOpenPanel(null) }, autoCorrectPrefill?.id ?? 0)), _jsx("div", { className: "likhari-canvas", children: _jsx(RichTextPlugin, { contentEditable: _jsx(ContentEditable, { className: "likhari-content-editable", dir: dir, spellCheck: false, "aria-label": strings.editor.contentLabel, "data-font-mode": uniform ? 'uniform' : undefined, "data-uniform-font": uniform && uniformFamily ? '' : undefined, style: uniform
|
|
344
385
|
? { '--likhari-zoom': uniformZoom / 100, ...(uniformFamily && { '--likhari-uniform-font': uniformFamily }) }
|
|
345
|
-
: undefined }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) })] }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.pageBreak && _jsx(PageBreakPlugin, {}), config.language.spellCheck && _jsx(SpellHighlightPlugin, {}), config.language.autocomplete && (_jsx(AutocompletePlugin, { label: strings.autoComplete.label, stores: resolvedCompletionStores, language: autoCompleteLanguage })), (config.language.autocorrect || config.language.textCleanup) && _jsx(AutoCorrectPlugin, { stores: stores, version: autoCorrectVersion, enabled: true, typing: config.language.autocorrect, urduNormalization: urduNormalization, punctuation: punctuation }), config.columns && _jsx(LayoutPlugin, {}), config.footnotes && _jsx(FootnotePlugin, {}), config.poetry.enabled && _jsx(PoetryPlugin, {}), config.poetry.enabled && _jsx(PoetryResizer, {}), config.tables && _jsx(TablePlugin, { hasCellMerge: true, hasTabHandler: true }), config.blocks.horizontalRule && _jsx(HorizontalRulePlugin, {}), _jsx(EditorInstancePlugin, { instanceRef: editorInstanceRef }), _jsx(OnChangePlugin, { onChange: handleChange })] }) }), _jsx(LeaveDialog, { opened: leavePrompt !== null, canSave: Boolean(onSave), canSaveDraft: autosave || navigationGuard === 'save-draft', draftFailed: leavePrompt?.draftFailed ?? false, onSave: () => {
|
|
386
|
+
: undefined }), placeholder: _jsx("div", { className: "likhari-placeholder", children: resolvedPlaceholder }), ErrorBoundary: LexicalErrorBoundary }) })] }), config.history && _jsx(HistoryPlugin, {}), (config.lists.bullet || config.lists.numbered || config.lists.check) && _jsx(ListPlugin, {}), config.lists.check && _jsx(CheckListPlugin, {}), config.links && _jsx(LinkPlugin, {}), config.links && _jsx(LinkPastePlugin, {}), config.blocks.pageBreak && _jsx(PageBreakPlugin, {}), config.language.spellCheck && _jsx(SpellHighlightPlugin, {}), config.language.autocomplete && (_jsx(AutocompletePlugin, { label: strings.autoComplete.label, stores: resolvedCompletionStores, language: autoCompleteLanguage })), (config.language.autocorrect || config.language.textCleanup) && _jsx(AutoCorrectPlugin, { stores: stores, version: autoCorrectVersion, enabled: true, typing: config.language.autocorrect, urduNormalization: urduNormalization, punctuation: punctuation }), config.columns && _jsx(LayoutPlugin, {}), config.footnotes && _jsx(FootnotePlugin, {}), config.poetry.enabled && _jsx(PoetryPlugin, {}), config.poetry.enabled && _jsx(PoetryResizer, {}), config.tables && _jsx(TablePlugin, { hasCellMerge: true, hasTabHandler: true }), config.blocks.horizontalRule && _jsx(HorizontalRulePlugin, {}), _jsx(EditorInstancePlugin, { instanceRef: editorInstanceRef }), _jsx(OnChangePlugin, { onChange: handleChange, ignoreSelectionChange: true })] }) }), _jsx(LeaveDialog, { opened: leavePrompt !== null, canSave: Boolean(onSave), canSaveDraft: autosave || navigationGuard === 'save-draft', draftFailed: leavePrompt?.draftFailed ?? false, onSave: () => {
|
|
346
387
|
handleSave();
|
|
347
388
|
settleLeave(true);
|
|
348
389
|
}, onSaveDraft: () => {
|
|
@@ -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;AAujBvD,0FAA0F;AAC1F,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2FAA2F;IAC3F,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,2BAA2B,CAAC;IACpC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,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;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,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;IAC9B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1B;AAED;iFACiF;AACjF,eAAO,MAAM,gBAAgB,8EAA8E,CAAC;AAE5G,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,YAAY,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,QAAsB,EAAE,iBAAiB,EAAE,IAAU,EAAE,yBAAyB,EAAE,YAAY,EAAE,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,YAAY,+
|
|
1
|
+
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -380,6 +380,37 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
380
380
|
};
|
|
381
381
|
const snapshotSelectionRef = useRef(snapshotSelection);
|
|
382
382
|
snapshotSelectionRef.current = snapshotSelection;
|
|
383
|
+
// The "..." overflow menu holds the toolbar's selects, but each select's
|
|
384
|
+
// option list is portaled out of the menu's dropdown. Mantine's Menu closes
|
|
385
|
+
// on any mousedown outside its own dropdown, so picking an option there
|
|
386
|
+
// would unmount the select before its click lands and the change was lost.
|
|
387
|
+
// The menu is therefore controlled, and ignores a close that comes from a
|
|
388
|
+
// press inside a toolbar select's option list.
|
|
389
|
+
const [overflowMenuOpen, setOverflowMenuOpen] = useState(false);
|
|
390
|
+
const pressInSelectListRef = useRef(false);
|
|
391
|
+
useEffect(() => {
|
|
392
|
+
const mark = (event) => {
|
|
393
|
+
const target = event.target;
|
|
394
|
+
pressInSelectListRef.current = target instanceof Element && target.closest('.likhari-toolbar-select-dropdown') !== null;
|
|
395
|
+
// Only meant for the close request this same press causes, so a later
|
|
396
|
+
// Escape or outside click is not swallowed.
|
|
397
|
+
if (pressInSelectListRef.current)
|
|
398
|
+
setTimeout(() => (pressInSelectListRef.current = false), 0);
|
|
399
|
+
};
|
|
400
|
+
document.addEventListener('mousedown', mark, true);
|
|
401
|
+
document.addEventListener('touchstart', mark, true);
|
|
402
|
+
return () => {
|
|
403
|
+
document.removeEventListener('mousedown', mark, true);
|
|
404
|
+
document.removeEventListener('touchstart', mark, true);
|
|
405
|
+
};
|
|
406
|
+
}, []);
|
|
407
|
+
const handleOverflowMenuChange = (next) => {
|
|
408
|
+
if (!next && pressInSelectListRef.current)
|
|
409
|
+
return;
|
|
410
|
+
if (next)
|
|
411
|
+
snapshotSelectionRef.current();
|
|
412
|
+
setOverflowMenuOpen(next);
|
|
413
|
+
};
|
|
383
414
|
// Clears the stand-in highlight once the canvas has a real selection to show again.
|
|
384
415
|
useEffect(() => {
|
|
385
416
|
if (typeof CSS === 'undefined' || !('highlights' in CSS))
|
|
@@ -809,7 +840,13 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
809
840
|
const AlignIcon = ALIGN_ICONS[state.elementFormat] ?? IconAlignLeft;
|
|
810
841
|
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), onMouseDown: snapshotSelection, 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"));
|
|
811
842
|
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), onMouseDown: snapshotSelection, 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"));
|
|
812
|
-
const fontSection = (config.font.family || (config.font.size && !uniform)) && (_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 }), onMouseDown: snapshotSelection, onChange:
|
|
843
|
+
const fontSection = (config.font.family || (config.font.size && !uniform)) && (_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 }), onMouseDown: snapshotSelection, onChange: uniform
|
|
844
|
+
? // A view setting: leave the editor state and selection alone, just hand the caret back.
|
|
845
|
+
(v) => {
|
|
846
|
+
onUniformFontFamilyChange?.(v);
|
|
847
|
+
editor.focus();
|
|
848
|
+
}
|
|
849
|
+
: 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"));
|
|
813
850
|
const insertSection = showInsertGroup && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [config.links &&
|
|
814
851
|
(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: () => {
|
|
815
852
|
restoreSelection();
|
|
@@ -828,28 +865,28 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
828
865
|
const zoomOutTo = [...ZOOM_LEVELS_PERCENT].reverse().find((level) => level < zoom);
|
|
829
866
|
const zoomInTo = ZOOM_LEVELS_PERCENT.find((level) => level > zoom);
|
|
830
867
|
const hasEndUtilities = Boolean(drafts || config.findReplace || helpUrl !== false);
|
|
831
|
-
const zoomGroup = showZoom && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", role: "group", "aria-label": strings.toolbar.zoom, dir: "ltr",
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
// toolbar's end is the left edge in RTL and the right edge in LTR.
|
|
835
|
-
style: rtl ? { marginRight: 'auto' } : { marginLeft: 'auto' }, 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"));
|
|
836
|
-
// Drafts, search and help sit at the far end; the zoom stepper is its own
|
|
837
|
-
// group just before them, and takes over the "push to the end" margin.
|
|
838
|
-
const utilitiesGroup = hasEndUtilities && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", style: showZoom ? undefined : { 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 })), 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 }) }))] }, "end"));
|
|
839
|
-
const endSection = (zoomGroup || utilitiesGroup) && (_jsxs(Fragment, { children: [zoomGroup, utilitiesGroup] }, "end-sections"));
|
|
868
|
+
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"));
|
|
869
|
+
// Drafts, search and help: the far-end group (see `endMovable` below).
|
|
870
|
+
const utilitiesGroup = hasEndUtilities && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", 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 })), 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 }) }))] }, "end"));
|
|
840
871
|
const startSections = [
|
|
841
872
|
showSave && (_jsx(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: _jsx(ToolbarButton, { icon: IconDeviceFloppy, title: strings.toolbar.save, dirty: Boolean(isDirty), onClick: onSave }) }, "save")),
|
|
842
873
|
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")),
|
|
843
874
|
formatSection,
|
|
844
875
|
alignSection,
|
|
845
876
|
];
|
|
846
|
-
|
|
847
|
-
//
|
|
848
|
-
|
|
877
|
+
const present = (sections) => sections.filter((section) => Boolean(section.node));
|
|
878
|
+
// The zoom stepper and the drafts/search/help group sit at the far end of the
|
|
879
|
+
// bar, and are the first things to fold into the "..." menu on a narrow one.
|
|
880
|
+
const endMovable = present([
|
|
881
|
+
{ key: 'zoom', node: zoomGroup },
|
|
882
|
+
{ key: 'utilities', node: utilitiesGroup },
|
|
883
|
+
]);
|
|
884
|
+
const mainMovable = present([
|
|
849
885
|
{ key: 'tools', node: toolsSection },
|
|
850
886
|
{ key: 'font', node: fontSection },
|
|
851
887
|
{ key: 'insert', node: insertSection },
|
|
852
|
-
]
|
|
888
|
+
]);
|
|
889
|
+
const movableSections = [...endMovable.slice().reverse(), ...mainMovable];
|
|
853
890
|
const movableGroupKeys = useMemo(() => movableSections.map((section) => section.key).join(','), [movableSections]);
|
|
854
891
|
// Re-measure whenever the container is resized, or whenever the set of
|
|
855
892
|
// movable sections (and so the hidden clone's content) changes.
|
|
@@ -898,9 +935,12 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
898
935
|
ro.observe(measure);
|
|
899
936
|
return () => ro.disconnect();
|
|
900
937
|
});
|
|
901
|
-
const
|
|
902
|
-
const
|
|
903
|
-
|
|
938
|
+
const isVisible = (section) => !overflowGroupKeys.has(section.key);
|
|
939
|
+
const visibleMovable = mainMovable.filter(isVisible);
|
|
940
|
+
const visibleEnd = endMovable.filter(isVisible);
|
|
941
|
+
// Shown in the menu in toolbar order: the inline sections, then the far-end ones.
|
|
942
|
+
const hiddenMovable = [...mainMovable, ...endMovable].filter((section) => !isVisible(section));
|
|
943
|
+
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), _jsxs(Menu, { opened: contextMenu !== null, onChange: (opened) => {
|
|
904
944
|
if (!opened)
|
|
905
945
|
setContextMenu(null);
|
|
906
946
|
}, 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: () => {
|