@wordpress/block-editor
Version:
115 lines (91 loc) • 3.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useBeforeInputRules = useBeforeInputRules;
var _element = require("@wordpress/element");
var _compose = require("@wordpress/compose");
var _richText = require("@wordpress/rich-text");
var _data = require("@wordpress/data");
var _hooks = require("@wordpress/hooks");
var _store = require("../../store");
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
/**
* When typing over a selection, the selection will we wrapped by a matching
* character pair. The second character is optional, it defaults to the first
* character.
*
* @type {string[]} Array of character pairs.
*/
const wrapSelectionSettings = ['`', '"', "'", '“”', '‘’'];
function useBeforeInputRules(props) {
const {
__unstableMarkLastChangeAsPersistent,
__unstableMarkAutomaticChange
} = (0, _data.useDispatch)(_store.store);
const propsRef = (0, _element.useRef)(props);
propsRef.current = props;
return (0, _compose.useRefEffect)(element => {
function onInput(event) {
const {
inputType,
data
} = event;
const {
value,
onChange
} = propsRef.current; // Only run the rules when inserting text.
if (inputType !== 'insertText') {
return;
}
if ((0, _richText.isCollapsed)(value)) {
return;
}
const pair = (0, _hooks.applyFilters)('blockEditor.wrapSelectionSettings', wrapSelectionSettings).find(([startChar, endChar]) => startChar === data || endChar === data);
if (!pair) {
return;
}
const [startChar, endChar = startChar] = pair;
const start = value.start;
const end = value.end + startChar.length;
let newValue = (0, _richText.insert)(value, startChar, start, start);
newValue = (0, _richText.insert)(newValue, endChar, end, end);
__unstableMarkLastChangeAsPersistent();
onChange(newValue);
__unstableMarkAutomaticChange();
const init = {};
for (const key in event) {
init[key] = event[key];
}
init.data = endChar;
const {
ownerDocument
} = element;
const {
defaultView
} = ownerDocument;
const newEvent = new defaultView.InputEvent('input', init); // Dispatch an `input` event with the new data. This will trigger the
// input rules.
// Postpone the `input` to the next event loop tick so that the dispatch
// doesn't happen synchronously in the middle of `beforeinput` dispatch.
// This is closer to how native `input` event would be timed, and also
// makes sure that the `input` event is dispatched only after the `onChange`
// call few lines above has fully updated the data store state and rerendered
// all affected components.
window.queueMicrotask(() => {
event.target.dispatchEvent(newEvent);
});
event.preventDefault();
}
element.addEventListener('beforeinput', onInput);
return () => {
element.removeEventListener('beforeinput', onInput);
};
}, []);
}
//# sourceMappingURL=use-before-input-rules.js.map