@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
179 lines • 5.77 kB
JavaScript
import { useCallback } from 'react';
function useHandleCursorPosition(keysToHandle, scopeRootRef, options) {
const onKeyDown = useCallback(event => {
var _input$selectionStart, _input$selectionEnd;
const input = event.target;
const key = event.key;
const size = getInputVisualSize(input);
const placeholder = input.placeholder || '';
const typedLen = getTypedLengthBasic(input.value || '', placeholder, size);
const selStart = (_input$selectionStart = input.selectionStart) !== null && _input$selectionStart !== void 0 ? _input$selectionStart : 0;
const selEnd = (_input$selectionEnd = input.selectionEnd) !== null && _input$selectionEnd !== void 0 ? _input$selectionEnd : selStart;
const hasSelection = selStart !== selEnd;
const atStart = selStart === 0 && selEnd === 0;
const atEnd = selStart === size && selEnd === size;
const allInputs = listAllInputs((scopeRootRef === null || scopeRootRef === void 0 ? void 0 : scopeRootRef.current) || undefined);
const index = allInputs.findIndex(el => el === input);
const prev = index > 0 ? allInputs[index - 1] : undefined;
const next = index >= 0 ? allInputs[index + 1] : undefined;
if (key === 'Backspace') {
if (typedLen === 0 && prev) {
event.preventDefault();
focusInput(prev, 'end');
}
return;
}
if (key === 'ArrowRight') {
if (hasSelection) {
try {
input.setSelectionRange(selEnd, selEnd);
} catch {}
event.preventDefault();
return;
}
if (atEnd && next) {
event.preventDefault();
focusInput(next, 'start');
}
return;
}
if (key === 'ArrowLeft') {
if (hasSelection) {
try {
input.setSelectionRange(selStart, selStart);
} catch {}
event.preventDefault();
return;
}
if (atStart && prev) {
event.preventDefault();
focusInput(prev, 'end');
}
return;
}
const allowMask = () => {
if (!keysToHandle) {
return true;
}
const reg = getKeysToHandle({
keysToHandle,
input
});
return reg ? reg.test(key) : true;
};
if (key.length === 1 && allowMask()) {
if (!hasSelection && atEnd && typedLen >= size && next) {
var _options$onTransferTo;
event.preventDefault();
options === null || options === void 0 || (_options$onTransferTo = options.onTransferToNext) === null || _options$onTransferTo === void 0 || _options$onTransferTo.call(options, {
key,
currentInput: input,
nextInput: next
});
focusInput(next, 'start');
return;
}
}
}, [keysToHandle, options, scopeRootRef]);
const onInput = useCallback(event => {
var _input$selectionStart2, _input$selectionEnd2;
const input = event.currentTarget;
if (document.activeElement !== input) {
return;
}
const size = getInputVisualSize(input);
const selStart = (_input$selectionStart2 = input.selectionStart) !== null && _input$selectionStart2 !== void 0 ? _input$selectionStart2 : 0;
const selEnd = (_input$selectionEnd2 = input.selectionEnd) !== null && _input$selectionEnd2 !== void 0 ? _input$selectionEnd2 : selStart;
const atEnd = selStart === size && selEnd === size;
if (!atEnd) {
return;
}
const typedLen = getTypedLengthBasic(input.value || '', input.placeholder || '', size);
if (typedLen < size) {
return;
}
const next = getAdjacentInput((scopeRootRef === null || scopeRootRef === void 0 ? void 0 : scopeRootRef.current) || undefined, input, 'next');
if (next) {
deferFocus(() => {
focusInput(next, 'start');
});
}
}, [scopeRootRef]);
return {
onKeyDown,
onInput
};
}
function listAllInputs(scope) {
try {
const root = scope || document;
return Array.from(root.querySelectorAll('.dnb-multi-input-mask__input'));
} catch {
return [];
}
}
function getAdjacentInput(scope, input, direction) {
const allInputs = listAllInputs(scope);
const index = allInputs.findIndex(el => el === input);
if (index < 0) {
return undefined;
}
if (direction === 'prev') {
return index > 0 ? allInputs[index - 1] : undefined;
}
return index < allInputs.length - 1 ? allInputs[index + 1] : undefined;
}
function getTypedLengthBasic(value, placeholder, size) {
if (!size) {
return value.length;
}
const n = Math.min(size, value.length);
let count = 0;
for (let i = 0; i < n; i++) {
if (!placeholder || placeholder[i] !== value[i]) {
count++;
}
}
return count;
}
function getKeysToHandle({
keysToHandle,
input
}) {
if (!keysToHandle) {
return undefined;
}
if (keysToHandle instanceof RegExp) {
return keysToHandle;
}
const masks = keysToHandle[input.dataset.maskId];
const selection = input.selectionStart === input.selectionEnd ? input.selectionStart : undefined;
if (selection === undefined || selection === null) {
return undefined;
}
const maskIndex = selection === input.size ? masks.length - 1 : selection;
return masks[maskIndex];
}
function focusInput(el, _where) {
try {
el.focus();
} catch {}
}
function deferFocus(cb) {
if (typeof queueMicrotask === 'function') {
queueMicrotask(cb);
return;
}
Promise.resolve().then(cb);
}
function getInputVisualSize(input) {
if (typeof input.size === 'number' && input.size > 0) {
return input.size;
}
if (typeof input.maxLength === 'number' && input.maxLength > 0) {
return input.maxLength;
}
return input.value ? input.value.length : 0;
}
export default useHandleCursorPosition;
//# sourceMappingURL=useHandleCursorPosition.js.map