UNPKG

@eccenca/gui-elements

Version:

GUI elements based on other libraries, usable in React application, written in Typescript.

109 lines 4.86 kB
var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; import React from "react"; import chars from "../../common/utils/characters.js"; /** Validates the string value for invisible characters. */ export var useTextValidation = function (_a) { var value = _a.value, onChange = _a.onChange, invisibleCharacterWarning = _a.invisibleCharacterWarning; var callback = invisibleCharacterWarning === null || invisibleCharacterWarning === void 0 ? void 0 : invisibleCharacterWarning.callback; var callbackDelay = invisibleCharacterWarning === null || invisibleCharacterWarning === void 0 ? void 0 : invisibleCharacterWarning.callbackDelay; var state = React.useRef({ detectedCodePoints: new Set() }); var clearState = React.useCallback(function () { state.current.timeout && clearTimeout(state.current.timeout); state.current.checkedValue = undefined; state.current.detectedCodePoints = new Set(); }, []); var detectionRegex = React.useMemo(function () { return chars.invisibleZeroWidthCharacters.createRegex(); }, []); var segmenter = React.useMemo(function () { return new Intl.Segmenter(undefined, { granularity: "grapheme" }); }, []); var emojiRegex = React.useMemo(function () { return new RegExp("\\p{Extended_Pictographic}|\\u20E3", "u"); }, []); var detectIssues = React.useCallback(function (value) { var e_1, _a; try { for (var _b = __values(segmenter.segment(value)), _c = _b.next(); !_c.done; _c = _b.next()) { var segment = _c.value.segment; if (emojiRegex.test(segment)) { // skip emoji clusters since they legitimately contain variation selectors, ZWJ, tags, etc. } else { detectionRegex.lastIndex = 0; var matchArray = detectionRegex.exec(segment); while (matchArray) { var codePoint = matchArray[0].codePointAt(0); if (codePoint) { state.current.detectedCodePoints.add(codePoint); } matchArray = detectionRegex.exec(segment); } } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } }, [detectionRegex, segmenter, emojiRegex]); // Checks if the value contains any problematic characters with a small delay. var checkValue = React.useCallback(function (value) { state.current.detectedCodePoints = new Set(); if (typeof value === "number") { clearState(); } else if (typeof value === "string") { detectIssues(value); } else { value.forEach(function (arrayValue) { return detectIssues(arrayValue); }); } callback === null || callback === void 0 ? void 0 : callback(state.current.detectedCodePoints); }, [callback, clearState, detectIssues]); var scheduleCheck = React.useCallback(function (value) { if (state.current.checkedValue === value) { return; } state.current.checkedValue = value; state.current.timeout = window.setTimeout(function () { if (state.current.checkedValue === value) { checkValue(value); clearState(); } }, callbackDelay !== null && callbackDelay !== void 0 ? callbackDelay : 500); }, [checkValue, clearState, callbackDelay]); // Do check via onChange handler var wrappedOnChangeHandler = React.useCallback(function (event) { var value = event.target.value; if (value != null && typeof value === "string") { scheduleCheck(value); } else { clearState(); } onChange === null || onChange === void 0 ? void 0 : onChange(event); }, [clearState, onChange, scheduleCheck]); // No callback, return if (!callback) { return onChange; } if (value == null && onChange == null) { return onChange; } if (value != null) { scheduleCheck(value); return onChange; } else { return wrappedOnChangeHandler; } }; //# sourceMappingURL=useTextValidation.js.map