@eccenca/gui-elements
Version:
GUI elements based on other libraries, usable in React application, written in Typescript.
109 lines • 4.86 kB
JavaScript
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