Skip to content

Commit 2e72e9b

Browse files
committed
feat(json-crdt-peritext-ui): 🎸 add more state to formatting editing
1 parent 5cfa827 commit 2e72e9b

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/json-crdt-peritext-ui/plugins/toolbar/formatting/FormattingsManagePane/FormattingDisplay.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const FormattingDisplay: React.FC<FormattingDisplayProps> = ({formatting,
4646
</div>
4747
<Space horizontal />
4848
<BasicTooltip renderTooltip={() => t('Stop editing')}>
49-
<BasicButton size={32} rounder onClick={() => state.view$.next('view')}>
49+
<BasicButton size={32} rounder onClick={state.switchToViewPanel}>
5050
<Iconista set={'lucide'} icon={'pencil-off'} width={16} height={16} />
5151
</BasicButton>
5252
</BasicTooltip>
@@ -66,7 +66,7 @@ export const FormattingDisplay: React.FC<FormattingDisplayProps> = ({formatting,
6666
<ButtonSeparator />
6767
<Space horizontal size={-2} />
6868
<BasicTooltip renderTooltip={() => t('Edit')}>
69-
<BasicButton size={32} rounder onClick={() => state.view$.next('edit')}>
69+
<BasicButton size={32} rounder onClick={state.switchToEditPanel}>
7070
<Iconista set={'lucide'} icon={'pencil'} width={16} height={16} />
7171
</BasicButton>
7272
</BasicTooltip>
@@ -78,7 +78,7 @@ export const FormattingDisplay: React.FC<FormattingDisplayProps> = ({formatting,
7878
</ContextPaneHeader>
7979
<ContextPaneHeaderSep />
8080
{view === 'edit' ? (
81-
<FormattingEditForm formatting={formatting} onDone={() => state.view$.next('view')} />
81+
<FormattingEditForm formatting={formatting} onDone={state.returnFromEditPanelAndSave} />
8282
) : (
8383
<>
8484
<ContextSep />

src/json-crdt-peritext-ui/plugins/toolbar/formatting/FormattingsManagePane/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export const FormattingsManagePane: React.FC<FormattingsManagePaneProps> = ({inl
1616
// biome-ignore lint: too many dependencies
1717
const state = React.useMemo(() => new FormattingManageState(toolbar, inline), [toolbar, inline?.key()]);
1818
const formattings = useBehaviorSubject(React.useMemo(() => state.getFormattings$(), [state]));
19+
React.useLayoutEffect(() => {
20+
if (formattings.length === 1) {
21+
state.select(formattings[0]);
22+
}
23+
}, [formattings]);
1924
const selected = useBehaviorSubject(state.selected$);
2025

2126
if (selected || formattings.length === 1) {

src/json-crdt-peritext-ui/plugins/toolbar/formatting/FormattingsManagePane/state.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ import {BehaviorSubject} from 'rxjs';
22
import {SavedFormatting} from '../../state/formattings';
33
import {PersistedSlice} from '../../../../../json-crdt-extensions/peritext/slice/PersistedSlice';
44
import {subject} from '../../../../util/rx';
5+
import {toSchema} from '../../../../../json-crdt/schema/toSchema';
6+
import {Model, ObjApi} from '../../../../../json-crdt/model';
7+
import {ObjNode} from '../../../../../json-crdt/nodes';
58
import type {Inline} from '../../../../../json-crdt-extensions';
69
import type {ToolbarState} from '../../state';
710

811
export class FormattingManageState {
912
public readonly selected$ = new BehaviorSubject<SavedFormatting | null>(null);
1013
public readonly view$ = new BehaviorSubject<'view' | 'edit'>('view');
14+
public readonly editing$ = new BehaviorSubject<SavedShadowFormatting | undefined>(undefined);
1115

1216
public constructor(
1317
public readonly state: ToolbarState,
@@ -38,4 +42,40 @@ export class FormattingManageState {
3842
public readonly select = (formatting: SavedFormatting | null) => {
3943
this.selected$.next(formatting);
4044
};
45+
46+
public readonly switchToViewPanel = (): void => {
47+
this.view$.next('view');
48+
// TODO: Clear the `editing$` state
49+
};
50+
51+
public readonly switchToEditPanel = (): void => {
52+
const selected = this.selected$.getValue();
53+
if (!selected) return;
54+
this.view$.next('edit');
55+
const formatting = new SavedShadowFormatting(selected);
56+
this.editing$.next(formatting);
57+
};
58+
59+
public readonly returnFromEditPanelAndSave = (): void => {
60+
console.log('saveEdits');
61+
};
62+
}
63+
64+
export class SavedShadowFormatting<Node extends ObjNode = ObjNode> extends SavedFormatting<Node> {
65+
protected _model: Model<any>;
66+
67+
constructor(protected readonly saved: SavedFormatting<Node>) {
68+
super(saved.behavior, saved.range, saved.state);
69+
const nodeApi = saved.conf();
70+
const schema = nodeApi ? toSchema(nodeApi.node) : void 0;
71+
this._model = Model.create(schema);
72+
}
73+
74+
public conf(): ObjApi<Node> | undefined {
75+
return this._model.api.obj([]) as ObjApi<Node>;
76+
}
77+
78+
public readonly save = () => {
79+
throw new Error('save() not implemented');
80+
};
4181
}

0 commit comments

Comments
 (0)