UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

121 lines (120 loc) 4.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RenderCaret = void 0; const tslib_1 = require("tslib"); const React = tslib_1.__importStar(require("react")); const useHarmonicIntervalFn_1 = tslib_1.__importDefault(require("react-use/lib/useHarmonicIntervalFn")); const nano_theme_1 = require("nano-theme"); const context_1 = require("../../web/react/context"); const hooks_1 = require("../../web/react/hooks"); const constants_1 = require("./constants"); const json_crdt_extensions_1 = require("../../../json-crdt-extensions"); const context_2 = require("./context"); const CaretScore_1 = require("../../components/CaretScore"); const constants_2 = require("../../../json-crdt-extensions/peritext/rga/constants"); const height = 1.5; const ms = 350; const moveAnimation = (0, nano_theme_1.keyframes)({ from: { tr: 'scale(1.2)', }, to: { tr: 'scale(1)', }, }); const blockClass = (0, nano_theme_1.rule)({ pos: 'relative', pe: 'none', us: 'none', w: '0px', h: '100%', bg: 'black', va: 'bottom', }); const innerClass = (0, nano_theme_1.rule)({ pos: 'absolute', b: '-.18em', l: '-.065em', w: 'calc(max(.2em, 2px))', h: `${height}em`, bg: constants_1.DefaultRendererColors.ActiveCursor, bdl: `1px dotted ${constants_1.DefaultRendererColors.InactiveCursor}`, bdrad: '0.0625em', 'mix-blend-mode': 'multiply', an: moveAnimation + ' .25s ease-out forwards', }); const innerClass2 = (0, nano_theme_1.rule)({ 'mix-blend-mode': 'hard-light', }); const dotClass = (0, nano_theme_1.rule)({ pos: 'absolute', pe: 'none', us: 'none', w: '2px', h: '2px', bdrad: '50%', z: 9999, top: '-8px', left: '4px', bg: constants_1.DefaultRendererColors.InactiveCursor, }); const RenderCaret = ({ italic, point, children }) => { const ctx = (0, context_1.usePeritext)(); const pending = (0, hooks_1.useSyncStore)(ctx.peritext.editor.pending); const [show, setShow] = React.useState(true); (0, useHarmonicIntervalFn_1.default)(() => setShow(Date.now() % (ms + ms) > ms), ms); const { dom } = (0, context_1.usePeritext)(); const focus = (0, hooks_1.useSyncStoreOpt)(dom?.cursor.focus) || false; const plugin = (0, context_2.useCursorPlugin)(); const ref = React.useRef(null); // Place caret at the end of line wrap. React.useEffect(() => { const el = ref.current; if (!el) return; const style = el.style; style.top = '0px'; style.left = '0px'; if (point.anchor === constants_2.Anchor.After) { if (point.isAbs()) return; const rect = ctx.dom.getCharRect(point.id); if (!rect) return; const nextPoint = point.copy((p) => p.refBefore()); if (nextPoint.isAbs()) return; const rect2 = ctx.dom.getCharRect(nextPoint.id); if (!rect2) return; if (rect.x > rect2.x) { const dx = rect.x + rect.width - rect2.x; const dy = rect.y - rect2.y; style.top = dy + 'px'; style.left = dx + 'px'; } } }, [point, ctx.dom.getCharRect]); const anchorForward = point.anchor === constants_2.Anchor.Before; const score = plugin.score.value; const delta = plugin.scoreDelta.value; const style = { background: !focus ? constants_1.DefaultRendererColors.InactiveCursor : show ? constants_1.DefaultRendererColors.ActiveCursor : 'transparent', }; if (italic || pending.has(json_crdt_extensions_1.CommonSliceType.i)) { style.rotate = '11deg'; } return (React.createElement("span", { ref: ref, className: blockClass }, children, score !== plugin.lastVisScore.value && (React.createElement(CaretScore_1.CaretScore, { score: score, delta: delta, onRender: () => { plugin.lastVisScore.value = score; } })), anchorForward && React.createElement("span", { className: dotClass }), React.createElement("span", { className: innerClass + innerClass2, style: style }), React.createElement("span", { className: innerClass, style: style }))); }; exports.RenderCaret = RenderCaret;