Skip to content

Commit 2f8ec5f

Browse files
authored
Merge pull request #842 from streamich/peritext-block-element-improvements
Peritext block element improvements
2 parents 4a8b0ff + 3bd43b5 commit 2f8ec5f

File tree

10 files changed

+77
-24
lines changed

10 files changed

+77
-24
lines changed

src/json-crdt-peritext-ui/__demos__/components/App.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,22 @@ import {PeritextView} from '../../react';
66
import {CursorPlugin} from '../../plugins/cursor';
77
import {ToolbarPlugin} from '../../plugins/toolbar';
88
import {DebugPlugin} from '../../plugins/debug';
9+
import {BlocksPlugin} from '../../plugins/blocks';
910

1011
const markdown =
1112
'The German __automotive sector__ is in the process of *cutting ' +
1213
'thousands of jobs* as it grapples with a global shift toward electric vehicles ' +
1314
'— a transformation Musk himself has been at the forefront of.' +
1415
'\n\n' +
16+
'> To be, or not to be: that is the question.' +
17+
'\n\n' +
1518
'A `ClipboardEvent` is dispatched for copy, cut, and paste events, and it contains ' +
1619
'a `clipboardData` property of type `DataTransfer`. The `DataTransfer` object ' +
1720
'is used by the Clipboard Events API to hold multiple representations of data.';
1821

1922
export const App: React.FC = () => {
2023
const [[model, peritext]] = React.useState(() => {
21-
const model = ModelWithExt.create(
22-
ext.peritext.new(
23-
'',
24-
// 'The German automotive sector is in the process of cutting thousands of jobs as it grapples with a global shift toward electric vehicles — a transformation Musk himself has been at the forefront of.',
25-
),
26-
);
24+
const model = ModelWithExt.create(ext.peritext.new(''));
2725
const peritext = model.s.toExt().txt;
2826
peritext.refresh();
2927
// const transfer = new PeritextDataTransfer(peritext);
@@ -40,8 +38,9 @@ export const App: React.FC = () => {
4038
const plugins = React.useMemo(() => {
4139
const cursorPlugin = new CursorPlugin();
4240
const toolbarPlugin = new ToolbarPlugin();
41+
const blocksPlugin = new BlocksPlugin();
4342
const debugPlugin = new DebugPlugin({enabled: false});
44-
return [cursorPlugin, toolbarPlugin, debugPlugin];
43+
return [cursorPlugin, toolbarPlugin, blocksPlugin, debugPlugin];
4544
}, []);
4645

4746
return (

src/json-crdt-peritext-ui/dom/InputController.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export class InputController implements UiLifeCycles {
7474
case 'insertFromYank':
7575
case 'insertReplacementText': // insert or replace existing text by means of a spell checker, auto-correct, writing suggestions or similar
7676
case 'insertText': {
77+
// TODO: handle `dataTransfer` Image drops, URL drops
78+
// TODO: handle `dataTransfer` HTML drops
7779
event.preventDefault();
7880
if (typeof event.data === 'string') {
7981
et.insert(event.data);
@@ -129,8 +131,11 @@ export class InputController implements UiLifeCycles {
129131
et.delete(-1, 'word');
130132
break;
131133
}
132-
// case 'insertLineBreak': { // insert a line break
133-
// }
134+
case 'insertLineBreak': {
135+
event.preventDefault();
136+
et.insert('\n');
137+
break;
138+
}
134139
// case 'insertOrderedList': { // insert a numbered list
135140
// }
136141
// case 'insertUnorderedList': { // insert a bulleted list

src/json-crdt-peritext-ui/events/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ export interface AnnalsDetail {
329329
* The list of {@link Patch} that will be applied to the document to undo or
330330
* redo the action, unless the action is cancelled.
331331
*/
332-
batch: [Patch];
332+
batch: Patch[];
333333
}
334334

335335
/**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// biome-ignore lint: React is used for JSX
2+
import * as React from 'react';
3+
import {rule} from 'nano-theme';
4+
import type {BlockViewProps} from '../../react/BlockView';
5+
6+
const blockClass = rule({
7+
bg: 'rgba(0,0,0,.02)',
8+
bdl: '8px solid rgba(0,0,0,.1)',
9+
mr: 0,
10+
pd: '.05em .5em .05em 1.5em',
11+
bdrad: '4px',
12+
});
13+
14+
export interface BlockquoteProps extends BlockViewProps {
15+
children: React.ReactNode;
16+
}
17+
18+
export const Blockquote: React.FC<BlockquoteProps> = ({block, children}) => {
19+
return <blockquote className={blockClass}>{children}</blockquote>;
20+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as React from 'react';
2+
import {RenderBlock} from './RenderBlock';
3+
import type {PeritextPlugin} from '../../react/types';
4+
5+
const h = React.createElement;
6+
7+
export class BlocksPlugin implements PeritextPlugin {
8+
public readonly block: PeritextPlugin['block'] = (props, children) => h(RenderBlock, props as any, children);
9+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// biome-ignore lint: React is used for JSX
2+
import * as React from 'react';
3+
import {CommonSliceType} from '../../../json-crdt-extensions';
4+
import {Blockquote} from './Blockquote';
5+
import type {BlockViewProps} from '../../react/BlockView';
6+
7+
export interface RenderBlockProps extends BlockViewProps {
8+
children: React.ReactNode;
9+
}
10+
11+
export const RenderBlock: React.FC<RenderBlockProps> = (props) => {
12+
const {block, children} = props;
13+
const tag = block.tag();
14+
switch (tag) {
15+
case '':
16+
return children;
17+
case CommonSliceType.blockquote: {
18+
return <Blockquote {...props} />;
19+
}
20+
default: {
21+
return <p style={{padding: '16px 0'}}>{children}</p>;
22+
}
23+
}
24+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {BlocksPlugin} from './BlocksPlugin';

src/json-crdt-peritext-ui/plugins/debug/RenderBlock.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as React from 'react';
33
import {drule} from 'nano-theme';
44
import {useDebugCtx} from './context';
55
import type {BlockViewProps} from '../../react/BlockView';
6+
import {CommonSliceType} from '../../../json-crdt-extensions';
67

78
const blockClass = drule({
89
pos: 'relative',
@@ -41,7 +42,10 @@ export const RenderBlock: React.FC<RenderBlockProps> = ({block, hash, children})
4142
display: 'inline-block',
4243
}}
4344
>
44-
{hash.toString(36)}
45+
{hash.toString(36)}{' '}
46+
{block.path
47+
.map((type) => (typeof type === 'number' ? `<${CommonSliceType[type] ?? type}>` : `<${type}>`))
48+
.join('.')}
4549
</span>
4650
</div>
4751
<div style={{outline: '1px dotted blue'}}>{children}</div>
Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// biome-ignore lint: React is used for JSX
22
import * as React from 'react';
3-
import {CommonSliceType} from '../../../json-crdt-extensions';
43
import type {BlockViewProps} from '../../react/BlockView';
54

65
export interface RenderBlockProps extends BlockViewProps {
@@ -9,14 +8,6 @@ export interface RenderBlockProps extends BlockViewProps {
98

109
export const RenderBlock: React.FC<RenderBlockProps> = ({block, children}) => {
1110
const tag = block.tag();
12-
switch (tag) {
13-
case '':
14-
return children;
15-
case CommonSliceType.blockquote: {
16-
return <blockquote>{children}</blockquote>;
17-
}
18-
default: {
19-
return <div style={{padding: '16px 0'}}>{children}</div>;
20-
}
21-
}
11+
12+
return children;
2213
};

src/json-crdt-peritext-ui/react/BlockView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ export const BlockView: React.FC<BlockViewProps> = React.memo(
7474
}
7575

7676
let children: React.ReactNode = (
77-
<div ref={(element) => el?.(element)} style={{position: 'relative'}}>
77+
<span ref={(element) => el?.(element)} style={{position: 'relative', display: 'block'}}>
7878
{elements.length ? elements : Char.ZeroLengthSpace}
79-
</div>
79+
</span>
8080
);
8181
for (const map of plugins) children = map.block?.(props, children) ?? children;
8282
return children;

0 commit comments

Comments
 (0)