Skip to content

Commit

Permalink
feat(json-crdt-peritext-ui): 🎸 render score when typing
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Nov 10, 2024
1 parent 947b73d commit 40cb826
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/json-crdt-peritext-ui/plugins/minimal/Chrome/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import * as React from 'react';
import {rule} from 'nano-theme';
import {TopToolbar} from '../TopToolbar';
import {useDefaultCtx} from '../context';
import {usePlugin} from '../context';

const blockClass = rule({
bg: 'white',
Expand All @@ -21,7 +21,7 @@ export interface ChromeProps {
}

export const Chrome: React.FC<ChromeProps> = ({children}) => {
const {ctx} = useDefaultCtx();
const {ctx} = usePlugin();

return (
<div className={blockClass}>
Expand Down
25 changes: 25 additions & 0 deletions src/json-crdt-peritext-ui/plugins/minimal/RenderCaret.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {useSyncStore} from '../../react/hooks';
import type {CaretViewProps} from '../../react/selection/CaretView';
import {DefaultRendererColors} from './constants';
import {CommonSliceType} from '../../../json-crdt-extensions';
import {usePlugin} from './context';

const ms = 350;

Expand All @@ -18,6 +19,17 @@ export const moveAnimation = keyframes({
},
});

export const scoreAnimation = keyframes({
from: {
op: .7,
tr: 'scale(1.2)',
},
to: {
op: 0,
tr: 'scale(.7)',
},
});

const blockClass = rule({
pos: 'relative',
d: 'inline-block',
Expand All @@ -44,13 +56,25 @@ const innerClass = rule({
animationFillMode: 'forwards',
});

const scoreClass = rule({
pos: 'absolute',
d: 'inline-block',
b: '0.3em',
l: '.75em',
fz: '.4em',
op: .5,
an: scoreAnimation + ' .5s ease-out',
animationFillMode: 'forwards',
});

export interface RenderCaretProps extends CaretViewProps {
children: React.ReactNode;
}

export const RenderCaret: React.FC<RenderCaretProps> = ({italic, children}) => {
const ctx = usePeritext();
const pending = useSyncStore(ctx.peritext.editor.pending);
const {score} = usePlugin();
const [show, setShow] = React.useState(true);
useHarmonicIntervalFn(() => setShow(Date.now() % (ms + ms) > ms), ms);
const {dom} = usePeritext();
Expand All @@ -70,6 +94,7 @@ export const RenderCaret: React.FC<RenderCaretProps> = ({italic, children}) => {

return (
<span className={blockClass}>
{score.value > 9 && <span className={scoreClass}>{score.value}</span>}
<span className={innerClass} style={style}>
{children}
</span>
Expand Down
24 changes: 22 additions & 2 deletions src/json-crdt-peritext-ui/plugins/minimal/RenderPeritext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// biome-ignore lint: React is used for JSX
import * as React from 'react';
import {Chrome} from './Chrome';
import {context} from './context';
import {context, type MinimalPluginContextValue} from './context';
import {ValueSyncStore} from '../../../util/events/sync-store';
import type {PeritextSurfaceContextValue, PeritextViewProps} from '../../react';

export interface RenderPeritextProps extends PeritextViewProps {
Expand All @@ -10,8 +11,27 @@ export interface RenderPeritextProps extends PeritextViewProps {
}

export const RenderPeritext: React.FC<RenderPeritextProps> = ({ctx, children}) => {
const value: MinimalPluginContextValue = React.useMemo(() => ({
ctx,
score: new ValueSyncStore(0),
}), [ctx]);
React.useEffect(() => {
const dom = ctx?.dom;
if (!dom || !value) return;
let lastNow: number = 0;
const listener = () => {
const now = Date.now();
value.score.next(now - lastNow > 1000 ? 1 : value.score.value + 1);
lastNow = now;
};
dom.et.addEventListener('change', listener);
return () => {
dom.et.removeEventListener('change', listener);
};
}, [ctx?.dom, value]);

return (
<context.Provider value={{ctx}}>
<context.Provider value={value}>
<Chrome>{children}</Chrome>
</context.Provider>
);
Expand Down
8 changes: 5 additions & 3 deletions src/json-crdt-peritext-ui/plugins/minimal/context.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import * as React from 'react';
import type {PeritextSurfaceContextValue} from '../../react';
import type {ValueSyncStore} from '../../../util/events/sync-store';

export interface DebugRenderersContextValue {
export interface MinimalPluginContextValue {
ctx?: PeritextSurfaceContextValue;
score: ValueSyncStore<number>;
}

export const context = React.createContext<DebugRenderersContextValue>({});
export const context = React.createContext<MinimalPluginContextValue>(null!);

export const useDefaultCtx = () => React.useContext(context);
export const usePlugin = () => React.useContext(context);

0 comments on commit 40cb826

Please sign in to comment.