UNPKG

@macrostrat/column-components

Version:

React rendering primitives for stratigraphic columns

243 lines (223 loc) 5.36 kB
import { ComponentType, useCallback, useContext, useState } from "react"; import h from "../hyper"; import { NotesList } from "./note"; import NoteDefs from "./defs"; import { NoteData } from "./types"; import { useModelEditor, ColumnContext } from "../context"; import { NoteLayoutProvider, NoteUnderlay } from "./layout"; import { NoteEditor, NoteTextEditor, NoteEditorContext, NoteEditorProvider, } from "./editor"; import { NewNotePositioner } from "./new"; import { NodeConnectorOptions } from "./connector"; export * from "./types"; import type { ReactNode } from "react"; interface NoteComponentProps { visibility: string; note: NoteData; onClick: Function; } function NoteComponent(props: NoteComponentProps) { const { visibility, note, onClick } = props; const text = note.note; return h( "p.col-note-label", { style: { visibility }, onClick, }, text, ); } const CancelEditUnderlay = function () { const { setEditingNote } = useContext(NoteEditorContext) as any; return h(NoteUnderlay, { onClick(evt) { setEditingNote(null); evt.stopPropagation(); }, }); }; interface NotesColumnBaseProps extends NodeConnectorOptions { width?: number; paddingLeft?: number; transform?: string; notes?: NoteData[]; noteComponent?: ComponentType<any>; onClickNote?: (note: NoteData) => void; children?: ReactNode; forceOptions?: object; } interface EditableNotesColumnProps extends NotesColumnBaseProps { inEditMode?: boolean; onUpdateNote?: (n: NoteData) => void; onDeleteNote?: (n: NoteData) => void; onCreateNote?: Function; noteEditor?: ComponentType<any>; allowPositionEditing?: boolean; } interface FocusedNotesColumnProps extends NotesColumnBaseProps { focusedNote?: NoteData | null; onFocusNote?: (note: NoteData | null) => void; focusedNoteComponent?: ComponentType<any>; } function EditableNotesColumn(props: EditableNotesColumnProps) { const { width, paddingLeft = 60, transform, notes, inEditMode = false, onUpdateNote, onDeleteNote, onCreateNote, noteComponent = NoteComponent, noteEditor = NoteTextEditor, allowPositionEditing = false, forceOptions, onClickNote, } = props; const innerWidth = width - paddingLeft; return h( NoteLayoutProvider, { notes, width: innerWidth, paddingLeft, noteComponent, forceOptions, }, [ h( NoteEditorProvider, { inEditMode, noteEditor, onCreateNote, onUpdateNote, onDeleteNote, }, [ h("g.section-log", { transform, className: "focusable editable" }, [ h(NoteDefs), h(CancelEditUnderlay), h(NotesList, { onClickNote, }), h(NewNotePositioner), h(NoteEditor, { allowPositionEditing }), ]), ], ), ], ); } function FocusableNoteColumn(props: FocusedNotesColumnProps) { /** A notes column with selection capabilities. */ const { width, paddingLeft = 60, transform, notes, forceOptions, noteComponent = NoteComponent, focusedNoteComponent = NoteComponent, deltaConnectorAttachment, onClickNote, } = props; const innerWidth = width - paddingLeft; return h( NoteLayoutProvider, { notes, width: innerWidth, paddingLeft, noteComponent, forceOptions, }, [ h( NoteEditorProvider, { inEditMode: true, noteEditor: focusedNoteComponent, }, [ h("g.section-log", { transform, className: "focusable" }, [ h(NoteDefs), h(CancelEditUnderlay), h(NotesList, { onClickNote, deltaConnectorAttachment, }), h(NoteEditor, { allowPositionEditing: false }), ]), ], ), ], ); } function StaticNotesColumn(props: NotesColumnBaseProps) { /** A non-editable notes column. */ const { width, paddingLeft = 60, transform, notes, noteComponent = NoteComponent, deltaConnectorAttachment, onClickNote, forceOptions, children, } = props; const innerWidth = width - paddingLeft; return h( NoteLayoutProvider, { notes, width: innerWidth, paddingLeft, noteComponent, forceOptions, }, [ h("g.section-log", { transform }, [ h(NoteDefs), h(NotesList, { deltaConnectorAttachment, onClickNote, }), children, ]), ], ); } function NotesColumn(props: NotesColumnProps) { const { editable = false, ...rest } = props; const ctx = useContext(ColumnContext); // not sure why we have this here. if (ctx?.scaleClamped == null) return null; let c: ComponentType = StaticNotesColumn; if (editable) { c = EditableNotesColumn; } else if (rest.focusedNoteComponent != null) { c = FocusableNoteColumn; } return h(c, rest); } interface NotesColumnProps extends FocusedNotesColumnProps, EditableNotesColumnProps { editable?: boolean; } export { NotesColumn, NoteComponent, NoteTextEditor, NoteEditor, NoteEditorContext, NotesColumnProps, StaticNotesColumn, };