Skip to content

Commit

Permalink
feat(json-crdt-peritext-ui): 🎸 add initial block type switching funct…
Browse files Browse the repository at this point in the history
…ionality
  • Loading branch information
streamich committed Nov 11, 2024
1 parent 3700013 commit cd8f771
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 23 deletions.
19 changes: 19 additions & 0 deletions src/json-crdt-peritext-ui/components/ButtonSeparator/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// biome-ignore lint: React is used for JSX
import * as React from 'react';
import {rule} from 'nano-theme';

const blockClass = rule({
bd: 0,
w: '3px',
h: '26px',
bdrad: '2px',
mr: '0 4px',
pd: 0,
bg: 'rgba(61, 37, 20, .04)',
});

export const ButtonSeparator: React.FC = () => {
return (
<div className={blockClass} />
);
};
2 changes: 1 addition & 1 deletion src/json-crdt-peritext-ui/dom/InputController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class InputController implements UiLifeCycles {
switch (inputType) {
case 'insertParagraph': {
event.preventDefault();
et.marker('ins');
et.marker({action: 'ins'});
break;
}
// case 'insertFromComposition':
Expand Down
8 changes: 8 additions & 0 deletions src/json-crdt-peritext-ui/events/PeritextEventDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ export class PeritextEventDefaults implements PeritextEventHandlerMap {
this.txt.editor.split(type, data);
break;
}
case 'tog': {
const marker = this.txt.overlay.getOrNextLowerMarker(this.txt.editor.cursor.start);
if (marker) {
marker.marker.update({type});
}
console.log('togggling..', marker)
break;
}
}
};
}
3 changes: 1 addition & 2 deletions src/json-crdt-peritext-ui/events/PeritextEventTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ export class PeritextEventTarget extends TypedEventTarget<PeritextEventMap> {
this.dispatch('format', detail);
}

public marker(action: MarkerDetail['action'], type?: MarkerDetail['type'], data?: MarkerDetail['data']): void {
const detail: MarkerDetail = {action, type, data};
public marker(detail: MarkerDetail): void {
this.dispatch('marker', detail);
}
}
8 changes: 7 additions & 1 deletion src/json-crdt-peritext-ui/events/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,18 +244,24 @@ export interface FormatDetail {
export interface MarkerDetail {
/**
* The action to perform.
*
* @default 'tog'
*/
action: 'ins' | 'del' | 'upd';
action?: 'tog' | 'ins' | 'del' | 'upd';

/**
* The type tag applied to the new block, if the action is `'ins'`. If the
* action is `'upd'`, the type tag is used to update the block type.
*
* @default SliceType.Paragraph
*/
type?: SliceType;

/**
* Block-specific custom data. For example, a paragraph block may store
* the alignment and indentation information in this field.
*
* @default undefined
*/
data?: unknown;
}
Expand Down
55 changes: 36 additions & 19 deletions src/json-crdt-peritext-ui/plugins/minimal/TopToolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {CommonSliceType} from '../../../../json-crdt-extensions';
import {ButtonGroup} from '../../../components/ButtonGroup';
import {useSyncStore} from '../../../react/hooks';
import type {PeritextSurfaceContextValue} from '../../../react';
import {ButtonSeparator} from '../../../components/ButtonSeparator';

export interface TopToolbarProps {
ctx: PeritextSurfaceContextValue;
Expand All @@ -15,7 +16,7 @@ export const TopToolbar: React.FC<TopToolbarProps> = ({ctx}) => {

const [complete] = ctx.peritext.overlay.stat(ctx.peritext.editor.cursor);

const button = (type: string | number, name: React.ReactNode) => (
const inlineGroupButton = (type: string | number, name: React.ReactNode) => (
<Button
onClick={() => ctx.dom.et.format(type)}
onMouseDown={(e) => e.preventDefault()}
Expand All @@ -25,37 +26,53 @@ export const TopToolbar: React.FC<TopToolbarProps> = ({ctx}) => {
</Button>
);

const button2 = (name: React.ReactNode, onClick: React.MouseEventHandler) => (
const button = (name: React.ReactNode, onClick: React.MouseEventHandler) => (
<Button onClick={onClick} onMouseDown={(e) => e.preventDefault()}>
{name}
</Button>
);

const blockGroupButtom = (type: string | number, name: React.ReactNode) => (
<Button
onClick={() => ctx.dom.et.marker({action: 'tog', type})}
onMouseDown={(e) => e.preventDefault()}
active={(complete.has(type) && !pending.has(type)) || (!complete.has(type) && pending.has(type))}
>
{name}
</Button>
);

return (
<ButtonGroup style={{marginBottom: 8}}>
{button(CommonSliceType.b, 'Bold')}
{button(CommonSliceType.i, 'Italic')}
{button(CommonSliceType.u, 'Underline')}
{button(CommonSliceType.s, 'Strikethrough')}
{button(CommonSliceType.code, 'Code')}
{button(CommonSliceType.mark, 'Mark')}
{button(CommonSliceType.del, 'Deleted')}
{button(CommonSliceType.ins, 'Inserted')}
{button(CommonSliceType.sup, 'Superscript')}
{button(CommonSliceType.sub, 'Subscript')}
{button(CommonSliceType.math, 'Math')}
{button(CommonSliceType.kbd, 'Key')}
{button(CommonSliceType.hidden, 'Spoiler')}
{button(CommonSliceType.bookmark, 'Bookmark')}
{button2('Blue', () => {
{inlineGroupButton(CommonSliceType.b, 'Bold')}
{inlineGroupButton(CommonSliceType.i, 'Italic')}
{inlineGroupButton(CommonSliceType.u, 'Underline')}
{inlineGroupButton(CommonSliceType.s, 'Strikethrough')}
{inlineGroupButton(CommonSliceType.code, 'Code')}
{inlineGroupButton(CommonSliceType.mark, 'Mark')}
{inlineGroupButton(CommonSliceType.del, 'Deleted')}
{inlineGroupButton(CommonSliceType.ins, 'Inserted')}
{inlineGroupButton(CommonSliceType.sup, 'Superscript')}
{inlineGroupButton(CommonSliceType.sub, 'Subscript')}
{inlineGroupButton(CommonSliceType.math, 'Math')}
{inlineGroupButton(CommonSliceType.kbd, 'Key')}
{inlineGroupButton(CommonSliceType.hidden, 'Spoiler')}
{inlineGroupButton(CommonSliceType.bookmark, 'Bookmark')}
<ButtonSeparator />
{button('Blue', () => {
ctx.dom.et.format(CommonSliceType.col, 'one', '#07f');
})}
{button2('Erase', () => {
<ButtonSeparator />
{button('Erase', () => {
ctx.dom.et.format({behavior: 'erase'});
})}
{button2('Clear', () => {
{button('Clear', () => {
ctx.dom.et.format({behavior: 'clear'});
})}
<ButtonSeparator />
{blockGroupButtom(CommonSliceType.p, 'Paragraph')}
{blockGroupButtom(CommonSliceType.blockquote, 'Blockquote')}
{blockGroupButtom(CommonSliceType.codeblock, 'Code Block')}
</ButtonGroup>
);
};

0 comments on commit cd8f771

Please sign in to comment.