UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

157 lines (156 loc) 6.22 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 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', d: 'inline-block', pe: 'none', us: 'none', w: '0px', h: '100%', bg: 'black', va: 'center', }); const innerClass = (0, nano_theme_1.rule)({ pos: 'absolute', d: 'inline-block', b: '-0.4em', l: '-0.065em', w: 'calc(max(.2em, 3px))', h: '1.5em', 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 RenderCaret = ({ italic, 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.usePlugin)(); 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", { className: blockClass }, score !== plugin.lastVisScore.value && React.createElement(CaretScore, { score: score, delta: delta }), React.createElement("span", { className: innerClass, style: style }, children))); }; exports.RenderCaret = RenderCaret; const scoreAnimation = (0, nano_theme_1.keyframes)({ from: { op: 0.7, tr: 'scale(1.2)', }, to: { op: 0, tr: 'scale(.7)', vis: 'hidden', }, }); const shakingAnimation = (0, nano_theme_1.keyframes)({ '0%': { tr: 'translateX(0), scale(1.2)', op: 1 }, '10%': { tr: 'translateX(-2px)' }, '20%': { tr: 'translateX(2px)' }, '30%': { tr: 'translateX(-1px)' }, '40%': { tr: 'translateX(1px)' }, '50%': { tr: 'translateX(0), scale(1)' }, '100%': { op: 0, vis: 'hidden' }, }); const scoreClass = (0, nano_theme_1.rule)({ pos: 'absolute', d: 'inline-block', b: '0.3em', l: '.75em', fz: '.4em', op: 0.5, an: scoreAnimation + ' .5s ease-out forwards', ws: 'nowrap', pe: 'none', us: 'none', }); const scoreDeltaClass = (0, nano_theme_1.rule)({ pos: 'absolute', d: 'inline-block', b: '0.9em', l: '1.2em', fz: '.5em', op: 0.5, col: 'blue', an: scoreAnimation + ' .3s ease-out forwards', pe: 'none', us: 'none', }); const CaretScore = React.memo(({ score, delta }) => { const plugin = (0, context_2.usePlugin)(); // biome-ignore lint: lint/correctness/useExhaustiveDependencies React.useEffect(() => { plugin.lastVisScore.value = score; }, []); const scoreMsg = score > 100 && score <= 120 ? 'Typing Spree!' : score > 200 && score <= 208 ? 'Go, go, go!' : score > 300 && score <= 320 ? 'Rampage!' : score > 400 && score <= 408 ? "Let's go!" : score > 500 && score <= 520 ? 'Unstoppable!' : score > 600 && score <= 608 ? 'Good stuff!' : score > 700 && score <= 708 ? 'Alright, alright!' : score > 1000 && score <= 1030 ? 'Godlike!' : score > 1500 && score <= 1530 ? 'Bingo, bango, bongo!' : score > 2000 && score <= 2030 ? 'Legendary!' : score > 3000 && score <= 3040 ? 'Beyond Godlike!' : score > 5000 && score <= 5040 ? 'Wicked Sick!' : score > 10000 && score <= 10050 ? 'Monster Type!' : score > 20000 && score <= 20050 ? 'Ultra Type!' : score > 50000 && score <= 50100 ? 'M-M-M-Monster Type!' : score; return (React.createElement(React.Fragment, null, score >= 24 && (React.createElement("span", { contentEditable: false, className: scoreClass, style: { animation: typeof scoreMsg === 'string' ? shakingAnimation + ' .7s ease-out forwards' : undefined } }, scoreMsg)), (typeof scoreMsg === 'string' || (score > 42 && delta > 1)) && (React.createElement("span", { contentEditable: false, className: scoreDeltaClass }, "+", delta)))); });