UNPKG

collaborative-ui

Version:

React component library for building real-time collaborative editing applications.

151 lines (150 loc) 5.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CollaborativeFlexibleInput = void 0; const tslib_1 = require("tslib"); const React = tslib_1.__importStar(require("react")); const nano_theme_1 = require("nano-theme"); const util_1 = require("./util"); const collaborative_input_1 = require("collaborative-input"); const blockClass = (0, nano_theme_1.rule)({ d: 'inline-block', pos: 'relative', w: '100%', }); const inputClass = (0, nano_theme_1.rule)({ d: 'inline-block', va: 'bottom', bxz: 'border-box', ov: 'hidden', pd: 0, mr: 0, bg: 0, out: 0, bd: 0, col: 'inherit', fw: 'inherit', f: 'inherit', lh: 'inherit', ws: 'pre', resize: 'none', }); const sizerClass = (0, nano_theme_1.rule)({ d: 'inline-block', pos: 'absolute', // ov: 'hidden', pe: 'none', us: 'none', bxz: 'border-box', t: 0, l: 0, bd: 0, ws: 'pre', }); const CollaborativeFlexibleInput = ({ str, polling, inp, multiline, wrap, fullWidth, typebefore = '', typeahead = '', extraWidth, minWidth = 8, maxWidth, focus, onFocus, onBlur, onKeyDown, onSubmit, onCancel, onTab, }) => { const inputRef = React.useRef(null); const sizerRef = React.useRef(null); const sizerValueRef = React.useRef(null); const theme = (0, nano_theme_1.useTheme)(); // biome-ignore lint: manual dependency list React.useLayoutEffect(() => { if (!inputRef.current || !sizerRef.current) return; if (focus) inputRef.current.focus(); (0, util_1.copyStyles)(inputRef.current, sizerRef.current, [ 'font', 'fontSize', 'fontFamily', 'fontWeight', 'fontStyle', 'letterSpacing', 'textTransform', 'boxSizing', ]); }, []); // biome-ignore lint: manual dependency list React.useLayoutEffect(() => { const node = str(); if (!node) return; const sync = () => { const sizerValue = sizerValueRef.current; if (sizerValue) sizerValue.textContent = node.view(); const input = inputRef.current; const sizer = sizerRef.current; if (!input || !sizer) return; let width = sizer.scrollWidth; if (extraWidth) width += extraWidth; if (minWidth) width = Math.max(width, minWidth); if (maxWidth) width = Math.min(width, maxWidth); const style = input.style; style.width = width + 'px'; if (multiline) { const height = sizer.scrollHeight; style.height = height + 'px'; } }; return sync(), node.api.onChange.listen(sync); }, [str]); React.useEffect(() => { const input = inputRef.current; if (!input || !str) return; const unbind = (0, collaborative_input_1.bind)(str, input, !!polling); return () => { unbind(); }; }, [str, polling]); const attr = { ref: (input) => { inputRef.current = input; if (inp) inp(input); }, className: inputClass, style: { width: fullWidth ? '100%' : undefined, whiteSpace: wrap ? 'pre-wrap' : 'pre', display: fullWidth ? 'block' : 'inline-block', }, onFocus, onBlur, onKeyDown: (e) => { if (e.key === 'Enter' && (!multiline || e.ctrlKey)) { if (onSubmit) onSubmit(e); } else if (e.key === 'Escape') { if (onCancel) onCancel(e); } else if (e.key === 'Tab') { if (onTab) onTab(e); } if (onKeyDown) onKeyDown(e); }, }; const input = multiline ? React.createElement("textarea", { ...attr }) : React.createElement("input", { ...attr }); const style = { display: fullWidth ? 'block' : 'inline-block', width: fullWidth ? '100%' : undefined, overflowX: fullWidth ? 'auto' : undefined, whiteSpace: wrap ? 'pre-wrap' : 'pre', }; return (React.createElement(React.Fragment, null, !!typebefore && !fullWidth && React.createElement("span", { style: { color: theme.g(0.7), verticalAlign: 'top' } }, typebefore), React.createElement("span", { className: blockClass, style: style }, input, React.createElement("span", { ref: sizerRef, className: sizerClass, style: { width: fullWidth ? '100%' : undefined, whiteSpace: wrap ? 'pre-wrap' : 'pre' } }, React.createElement("span", { ref: sizerValueRef, style: { visibility: 'hidden' } }), '\u200b', !!typeahead && React.createElement("span", { style: { color: theme.g(0.7) } }, typeahead))))); }; exports.CollaborativeFlexibleInput = CollaborativeFlexibleInput;