@inshapardaz/likhari-react 0.1.25-dev.232 → 0.1.25-dev.234
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":"AutocompletePlugin.d.ts","sourceRoot":"","sources":["../../src/autocomplete/AutocompletePlugin.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"AutocompletePlugin.d.ts","sourceRoot":"","sources":["../../src/autocomplete/AutocompletePlugin.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAGrE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAyB1D;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,MAAM,EACN,QAAQ,EAAE,cAAc,GACzB,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,EAAE,aAAa,GAAG,MAAM,CAAC;CAClC,sCAuMA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
3
3
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
4
4
|
import { $getSelection, $isRangeSelection, $isTextNode, COMMAND_PRIORITY_HIGH, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, } from 'lexical';
|
|
5
5
|
import { $replaceMatch } from '../find/findReplaceActions.js';
|
|
@@ -99,7 +99,7 @@ export function AutocompletePlugin({ label, stores, language: chosenLanguage, })
|
|
|
99
99
|
if (items.length === 0)
|
|
100
100
|
return hide();
|
|
101
101
|
const rect = caretRect(editor);
|
|
102
|
-
show({ prefix, language, items, index: 0, selected: false,
|
|
102
|
+
show({ prefix, language, items, index: 0, selected: false, ...rect, dir: rtl ? 'rtl' : 'ltr' });
|
|
103
103
|
});
|
|
104
104
|
};
|
|
105
105
|
// Handles an arrow key for the list, and cancels the browser's own caret movement.
|
|
@@ -134,6 +134,11 @@ export function AutocompletePlugin({ label, stores, language: chosenLanguage, })
|
|
|
134
134
|
hide();
|
|
135
135
|
setTimeout(refresh, 0);
|
|
136
136
|
};
|
|
137
|
+
// Text that arrives without a keydown (input methods, some keyboard layouts) is typing too.
|
|
138
|
+
const onInput = () => {
|
|
139
|
+
typing.current = true;
|
|
140
|
+
setTimeout(refresh, 0);
|
|
141
|
+
};
|
|
137
142
|
const onMouseDown = () => {
|
|
138
143
|
typing.current = false;
|
|
139
144
|
hide();
|
|
@@ -142,9 +147,11 @@ export function AutocompletePlugin({ label, stores, language: chosenLanguage, })
|
|
|
142
147
|
const attach = (next) => {
|
|
143
148
|
root?.removeEventListener('keydown', onKeyDown);
|
|
144
149
|
root?.removeEventListener('mousedown', onMouseDown);
|
|
150
|
+
root?.removeEventListener('input', onInput);
|
|
145
151
|
root = next;
|
|
146
152
|
root?.addEventListener('keydown', onKeyDown);
|
|
147
153
|
root?.addEventListener('mousedown', onMouseDown);
|
|
154
|
+
root?.addEventListener('input', onInput);
|
|
148
155
|
};
|
|
149
156
|
const unregisterRoot = editor.registerRootListener((next) => attach(next));
|
|
150
157
|
const unregisterUpdate = editor.registerUpdateListener(() => {
|
|
@@ -197,11 +204,34 @@ export function AutocompletePlugin({ label, stores, language: chosenLanguage, })
|
|
|
197
204
|
}, [stores]);
|
|
198
205
|
if (!popup)
|
|
199
206
|
return null;
|
|
200
|
-
return
|
|
207
|
+
return _jsx(SuggestionList, { popup: popup, label: label, onPick: (item) => {
|
|
208
|
+
acceptItem(editor, item);
|
|
209
|
+
recordAcceptance(popup.language, item);
|
|
210
|
+
show(null);
|
|
211
|
+
} });
|
|
212
|
+
}
|
|
213
|
+
function SuggestionList({ popup, label, onPick }) {
|
|
214
|
+
const ref = useRef(null);
|
|
215
|
+
// Placed after it is drawn, so its real size is known: kept inside the window, on the side of the
|
|
216
|
+
// caret that has room, and right-to-left lists align their right edge with the caret.
|
|
217
|
+
useLayoutEffect(() => {
|
|
218
|
+
const element = ref.current;
|
|
219
|
+
if (!element)
|
|
220
|
+
return;
|
|
221
|
+
const margin = 8;
|
|
222
|
+
const width = element.offsetWidth;
|
|
223
|
+
const height = element.offsetHeight;
|
|
224
|
+
const preferredLeft = popup.dir === 'rtl' ? popup.right - width : popup.left;
|
|
225
|
+
const left = Math.min(Math.max(preferredLeft, margin), window.innerWidth - width - margin);
|
|
226
|
+
const below = popup.bottom + 4;
|
|
227
|
+
const fitsBelow = below + height <= window.innerHeight - margin;
|
|
228
|
+
const top = fitsBelow ? below : Math.max(popup.top - height - 4, margin);
|
|
229
|
+
element.style.left = `${Math.max(left, margin)}px`;
|
|
230
|
+
element.style.top = `${top}px`;
|
|
231
|
+
});
|
|
232
|
+
return (_jsx("div", { ref: ref, className: "likhari-autocomplete", role: "listbox", "aria-label": label, dir: popup.dir, style: { position: 'fixed' }, children: popup.items.map((item, i) => (_jsx("div", { role: "option", "aria-selected": i === popup.index, className: i === popup.index ? 'likhari-autocomplete-item likhari-autocomplete-item--active' : 'likhari-autocomplete-item', onMouseDown: (event) => {
|
|
201
233
|
event.preventDefault();
|
|
202
|
-
|
|
203
|
-
recordAcceptance(popup.language, item);
|
|
204
|
-
show(null);
|
|
234
|
+
onPick(item);
|
|
205
235
|
}, children: item }, item))) }));
|
|
206
236
|
}
|
|
207
237
|
/** The typed part of the word at the caret, when the caret is at its end and the word is long enough to complete. */
|
|
@@ -229,10 +259,12 @@ function caretRect(editor) {
|
|
|
229
259
|
if (selection && selection.rangeCount > 0) {
|
|
230
260
|
const rect = selection.getRangeAt(0).getBoundingClientRect();
|
|
231
261
|
if (rect.width > 0 || rect.height > 0)
|
|
232
|
-
return { left: rect.left, bottom: rect.bottom };
|
|
262
|
+
return { left: rect.left, right: rect.right, top: rect.top, bottom: rect.bottom };
|
|
233
263
|
}
|
|
234
264
|
const root = editor.getRootElement()?.getBoundingClientRect();
|
|
235
|
-
|
|
265
|
+
const left = root?.left ?? 0;
|
|
266
|
+
const top = root?.top ?? 0;
|
|
267
|
+
return { left, right: left, top, bottom: top };
|
|
236
268
|
}
|
|
237
269
|
function acceptItem(editor, item) {
|
|
238
270
|
editor.update(() => {
|