json-joy
Version:
Collection of libraries for building collaborative editing apps.
121 lines (120 loc) • 4.41 kB
JavaScript
"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;