@inshapardaz/likhari-react 0.1.33-dev.276 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbar.d.ts","sourceRoot":"","sources":["../../src/components/Toolbar.tsx"],"names":[],"mappings":"AA2CA,OAAO,EAAc,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAA2B,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;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":"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;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;AA8gBvD,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,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,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,SAAiB,EAAE,MAAa,EAAE,MAAM,EAAE,EAAE,YAAY,+BAuqCrV"}
|
|
@@ -65,27 +65,6 @@ const INITIAL_STATE = {
|
|
|
65
65
|
};
|
|
66
66
|
const ICON_SIZE = 17;
|
|
67
67
|
const ICON_STROKE = 1.75;
|
|
68
|
-
/** The CSS Custom Highlight name; editor.css paints it like a native text selection. */
|
|
69
|
-
const SELECTION_HIGHLIGHT = 'likhari-toolbar-selection';
|
|
70
|
-
/** Paints the current native selection through the CSS Custom Highlight API, so it
|
|
71
|
-
* stays visible once a toolbar control (a Select, a Menu, a dialog) takes focus —
|
|
72
|
-
* which, unlike a ToolbarButton's onMouseDown/preventDefault, it must be able to do.
|
|
73
|
-
* The browser clears `window.getSelection()` on blur; this is called at the one
|
|
74
|
-
* moment before that happens (mousedown, or opening a menu/dialog), alongside the
|
|
75
|
-
* Lexical-level selection snapshot these controls already restore from. */
|
|
76
|
-
function paintSelectionHighlight() {
|
|
77
|
-
if (typeof CSS === 'undefined' || !('highlights' in CSS))
|
|
78
|
-
return;
|
|
79
|
-
const domSelection = window.getSelection();
|
|
80
|
-
if (!domSelection || domSelection.isCollapsed || domSelection.rangeCount === 0) {
|
|
81
|
-
CSS.highlights.delete(SELECTION_HIGHLIGHT);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const ranges = [];
|
|
85
|
-
for (let i = 0; i < domSelection.rangeCount; i++)
|
|
86
|
-
ranges.push(domSelection.getRangeAt(i).cloneRange());
|
|
87
|
-
CSS.highlights.set(SELECTION_HIGHLIGHT, new Highlight(...ranges));
|
|
88
|
-
}
|
|
89
68
|
const ALIGN_ICONS_LTR = {
|
|
90
69
|
start: IconAlignLeft,
|
|
91
70
|
left: IconAlignLeft,
|
|
@@ -156,17 +135,10 @@ function setsEqual(a, b) {
|
|
|
156
135
|
/** Mantine Select (combobox) for the toolbar's dropdown controls. The icon
|
|
157
136
|
* labels the control itself, since a dropdown can't show one per option in
|
|
158
137
|
* its closed state. The dropdown portals to <body>, so it is not clipped by
|
|
159
|
-
* the editor's `overflow: hidden` frame.
|
|
160
|
-
|
|
161
|
-
* Unlike a ToolbarButton, this can't keep focus on the canvas with
|
|
162
|
-
* onMouseDown/preventDefault — a combobox needs focus to open. So picking an
|
|
163
|
-
* option blurs the canvas first, which clears Lexical's selection; `onMouseDown`
|
|
164
|
-
* is the caller's chance to snapshot it (the browser moves focus only after
|
|
165
|
-
* mousedown's listeners run), to restore before applying the change
|
|
166
|
-
* (see Toolbar's `withRefocus`). */
|
|
167
|
-
function ToolbarSelect({ icon: Icon, label, value, data, width, disabled, placeholder, searchable, renderOption, onChange, onMouseDown, comingSoon, noMatchMessage }) {
|
|
138
|
+
* the editor's `overflow: hidden` frame. */
|
|
139
|
+
function ToolbarSelect({ icon: Icon, label, value, data, width, disabled, placeholder, searchable, renderOption, onChange, comingSoon, noMatchMessage }) {
|
|
168
140
|
const portalTarget = usePortalTarget();
|
|
169
|
-
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,
|
|
141
|
+
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) }));
|
|
170
142
|
}
|
|
171
143
|
/** An item in the "..." menu. A mousedown here would blur the canvas, so it is kept. */
|
|
172
144
|
function MoreMenuItem({ icon: Icon, label, active, onClick, }) {
|
|
@@ -373,24 +345,9 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
373
345
|
const selection = $getSelection();
|
|
374
346
|
menuSelectionRef.current = selection ? selection.clone() : null;
|
|
375
347
|
});
|
|
376
|
-
paintSelectionHighlight();
|
|
377
348
|
};
|
|
378
349
|
const snapshotSelectionRef = useRef(snapshotSelection);
|
|
379
350
|
snapshotSelectionRef.current = snapshotSelection;
|
|
380
|
-
// Clears the stand-in highlight once the canvas has a real selection to show again.
|
|
381
|
-
useEffect(() => {
|
|
382
|
-
if (typeof CSS === 'undefined' || !('highlights' in CSS))
|
|
383
|
-
return;
|
|
384
|
-
const clear = () => CSS.highlights.delete(SELECTION_HIGHLIGHT);
|
|
385
|
-
const unregister = editor.registerRootListener((root, previous) => {
|
|
386
|
-
previous?.removeEventListener('focus', clear);
|
|
387
|
-
root?.addEventListener('focus', clear);
|
|
388
|
-
});
|
|
389
|
-
return () => {
|
|
390
|
-
unregister();
|
|
391
|
-
clear();
|
|
392
|
-
};
|
|
393
|
-
}, [editor]);
|
|
394
351
|
const runMenuItem = (action) => () => {
|
|
395
352
|
const saved = menuSelectionRef.current;
|
|
396
353
|
if (saved)
|
|
@@ -653,12 +610,7 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
653
610
|
return true;
|
|
654
611
|
}, COMMAND_PRIORITY_NORMAL);
|
|
655
612
|
}, [editor, config.links, openLinkDialog]);
|
|
656
|
-
// The Select has already blurred the canvas by the time this runs (see
|
|
657
|
-
// ToolbarSelect's doc comment), so the selection snapshotted on its
|
|
658
|
-
// mousedown is restored first, then the canvas regains focus afterward —
|
|
659
|
-
// the combobox otherwise keeps it, so typing after picking would go nowhere.
|
|
660
613
|
const withRefocus = (fn) => (value) => {
|
|
661
|
-
restoreSelection();
|
|
662
614
|
fn(value);
|
|
663
615
|
editor.focus();
|
|
664
616
|
};
|
|
@@ -801,9 +753,9 @@ export function Toolbar({ config, toolbarStyle, dictionaryStores = [], thesaurus
|
|
|
801
753
|
];
|
|
802
754
|
const formattingValue = state.listType ?? state.blockType;
|
|
803
755
|
const AlignIcon = ALIGN_ICONS[state.elementFormat] ?? IconAlignLeft;
|
|
804
|
-
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),
|
|
805
|
-
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),
|
|
806
|
-
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 }),
|
|
756
|
+
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"));
|
|
757
|
+
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"));
|
|
758
|
+
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"));
|
|
807
759
|
const insertSection = showInsertGroup && (_jsxs(MantineToolbar.Group, { className: "likhari-toolbar-cluster", children: [config.links &&
|
|
808
760
|
(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: () => {
|
|
809
761
|
restoreSelection();
|
package/dist/theme/editor.css
CHANGED
|
@@ -934,13 +934,6 @@
|
|
|
934
934
|
text-decoration-skip-ink: none;
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
-
/* Stands in for the native text selection while a toolbar control (which must
|
|
938
|
-
take focus, e.g. a Select) has it — otherwise the browser clears it the
|
|
939
|
-
moment focus leaves the canvas, making a selection look lost mid-edit. */
|
|
940
|
-
::highlight(likhari-toolbar-selection) {
|
|
941
|
-
background-color: var(--editor-accent-soft);
|
|
942
|
-
}
|
|
943
|
-
|
|
944
937
|
.likhari-spell-nav {
|
|
945
938
|
display: flex;
|
|
946
939
|
align-items: center;
|