UNPKG

@macrostrat/column-components

Version:

React rendering primitives for stratigraphic columns

1 lines 14.8 kB
{"version":3,"file":"editor.cjs","sources":["../../src/notes/editor.ts"],"sourcesContent":["import { createContext, useState, useContext, ComponentType } from \"react\";\nimport { ModelEditorProvider, useModelEditor, ColumnContext } from \"../context\";\nimport { EditableText } from \"@blueprintjs/core\";\nimport classNames from \"classnames\";\nimport h from \"../hyper\";\nimport { NoteData } from \"./types\";\nimport { ForeignObject } from \"../util\";\nimport { NoteLayoutContext, NoteRect } from \"./layout\";\nimport { NotePositioner, NoteConnector } from \"./connector\";\nimport Draggable from \"react-draggable\";\nimport { hasSpan } from \"./utils\";\nimport { ErrorBoundary } from \"@macrostrat/ui-components\";\nimport { Spec } from \"immutability-helper\";\n\nconst NoteEditorContext = createContext({ inEditMode: false });\n\ninterface NoteEditorProps {\n note: NoteData;\n}\n\nconst NoteTextEditor = function (props: NoteEditorProps) {\n const { updateModel } = useModelEditor();\n const { note } = props;\n return h(EditableText, {\n multiline: true,\n className: \"col-note-label note-editing\",\n defaultValue: note.note,\n isEditing: true,\n onConfirm(newText) {\n return updateModel({ note: { $set: newText } });\n },\n });\n};\n\ninterface NoteEditorProviderProps {\n inEditMode: boolean;\n noteEditor: ComponentType<NoteEditorProps>;\n onUpdateNote?: (n: NoteData) => void;\n onDeleteNote?: (n: NoteData) => void;\n onCreateNote?: Function;\n children?: React.ReactNode;\n}\n\nfunction NoteEditorProvider(props: NoteEditorProviderProps) {\n let { children, inEditMode = false, noteEditor } = props;\n const { notes } = useContext(NoteLayoutContext);\n\n const [editingNote, setEditingNote] = useState(null);\n\n const deleteNote = function () {\n const val = editingNote;\n setEditingNote(null);\n return props.onDeleteNote?.(val);\n };\n\n const onCreateNote = function (pos) {\n const { height, top_height } = pos;\n const val = { height, top_height, note: null, symbol: null };\n return setEditingNote(val);\n };\n\n const value = {\n editingNote,\n setEditingNote,\n deleteNote,\n inEditMode,\n noteEditor,\n onCreateNote,\n };\n\n const onConfirmChanges = function (n) {\n if (n?.note == null && n == editingNote) {\n console.log(\"No changes to note\");\n return;\n }\n if (notes.includes(n)) {\n return;\n }\n return props.onUpdateNote?.(n);\n };\n\n //# Model editor provider gives us a nice store\n return h(NoteEditorContext.Provider, { value }, [\n h(\n ModelEditorProvider,\n {\n model: editingNote,\n onDelete: deleteNote,\n onConfirmChanges,\n logUpdates: true,\n alwaysConfirm: true,\n },\n children,\n ),\n ]);\n}\n\nconst NoteConnectorPath = function (props) {\n const { d, offsetX, className } = props;\n return h(\"path\", {\n d,\n className,\n transform: `translate(${offsetX})`,\n fill: \"transparent\",\n });\n};\n\nconst EditableNoteConnector = function (props) {\n const { notes, nodes, columnIndex, generatePath, createNodeForNote } =\n useContext(NoteLayoutContext);\n let { note, node, index } = props;\n if (note.id != null) {\n node = nodes[note.id];\n }\n if (node == null) {\n node = createNodeForNote(note);\n }\n const x = columnIndex[note.id] * 5 || 0;\n\n const d = generatePath(node, x);\n\n return h([\n h(NoteConnectorPath, {\n className: \"note-connector\",\n d,\n offsetX: x,\n }),\n h(\n ForeignObject,\n {\n width: 30,\n x,\n y: 0,\n height: 1,\n style: { overflowY: \"visible\" },\n },\n h(PositionEditorInner, { note }),\n ),\n ]);\n};\n\nconst PointHandle = function (props) {\n let { height, size, className, ...rest } = props;\n className = classNames(\"handle point-handle\", className);\n if (size == null) {\n size = 10;\n }\n return h(\n Draggable,\n {\n position: { x: 0, y: height },\n axis: \"y\",\n ...rest,\n },\n h(\"div.handle\", {\n style: {\n height: size,\n width: size,\n marginLeft: -size / 2,\n marginTop: -size / 2,\n position: \"absolute\",\n },\n className,\n }),\n );\n};\n\nfunction PositionEditorInner(props) {\n let { margin } = props;\n if (margin == null) {\n margin = 3;\n }\n const { scaleClamped: scale } = useContext(ColumnContext);\n const ctx = useModelEditor();\n if (ctx == null) {\n return null;\n }\n\n const { updatedModel, editedModel } = ctx;\n\n const note = editedModel ?? props.note;\n\n if (note == null) {\n return null;\n }\n\n const noteHasSpan = hasSpan(note);\n\n const bottomHeight = scale(note.height);\n let topHeight = bottomHeight;\n let height = 0;\n if (noteHasSpan) {\n topHeight = scale(note.top_height);\n height = Math.abs(topHeight - bottomHeight);\n }\n\n const moveEntireNote = function (e, data) {\n const { y } = data;\n // Set note height\n const spec: Spec<any> = { height: { $set: scale.invert(y + height) } };\n if (noteHasSpan) {\n // Set note top height\n spec.top_height = { $set: scale.invert(y) };\n }\n return updateModel(spec);\n };\n\n const moveTop = function (e, data) {\n const spec = { top_height: { $set: scale.invert(data.y) } };\n if (Math.abs(data.y - bottomHeight) < 2) {\n spec.top_height = { $set: null };\n }\n return updateModel(spec);\n };\n\n const moveBottom = function (e, data) {\n const spec: Spec<any> = { height: { $set: scale.invert(data.y) } };\n if (Math.abs(data.y - topHeight) < 2) {\n spec.top_height = { $set: null };\n }\n return updateModel(spec);\n };\n\n return h(\n ErrorBoundary,\n null,\n h(\"div.position-editor\", [\n h(\n Draggable,\n {\n handle: \".handle\",\n position: { x: 0, y: topHeight },\n onDrag: moveEntireNote,\n axis: \"y\",\n },\n h(\"div\", [\n h(\"div.handle\", {\n className: \"handle\",\n style: {\n height,\n width: 2 * margin,\n marginLeft: -margin,\n marginTop: -margin,\n position: \"absolute\",\n },\n }),\n ]),\n ),\n h(PointHandle, {\n height: noteHasSpan ? topHeight : topHeight - 15,\n onDrag: moveTop,\n className: classNames(\"top-handle\", {\n \"add-span-handle\": !noteHasSpan,\n }),\n bounds: { bottom: bottomHeight },\n }),\n h(PointHandle, {\n height: bottomHeight,\n onDrag: moveBottom,\n className: \"bottom-handle\",\n bounds: noteHasSpan ? { top: topHeight } : null,\n }),\n ]),\n );\n}\n\nfunction NoteEditorUnderlay() {\n return h(NoteRect, {\n style: { pointerEvents: \"none\" },\n className: \"underlay\",\n });\n}\n\nfunction NoteEditor(props) {\n const { allowPositionEditing } = props;\n const { noteEditor, setEditingNote } = useContext(NoteEditorContext) as any;\n const { notes, nodes, elementHeights, createNodeForNote } =\n useContext(NoteLayoutContext);\n const { editedModel, model } = useModelEditor();\n if (editedModel == null) {\n return null;\n }\n const index = notes.indexOf(editedModel);\n const { id: noteID } = editedModel;\n let node = nodes[noteID] || createNodeForNote(editedModel);\n const noteHeight = elementHeights[noteID] || 20;\n\n if (editedModel.height != null) {\n const newNode = createNodeForNote(editedModel);\n // Set position of note to current position\n newNode.currentPos = node.currentPos;\n\n const pos = newNode.centerPos || newNode.idealPos;\n const dy = pos - node.currentPos;\n if (dy > 50) {\n newNode.currentPos = pos - 50;\n }\n if (dy < -50) {\n newNode.currentPos = pos + 50;\n }\n node = newNode;\n }\n\n const edited = editedModel === model;\n\n return h(ErrorBoundary, [\n h(\"g.note-editor.note\", [\n h(NoteEditorUnderlay),\n h.if(!allowPositionEditing)(NoteConnector, { note: editedModel }),\n h.if(allowPositionEditing)(EditableNoteConnector, {\n note: editedModel,\n node,\n }),\n h(\n NotePositioner,\n {\n offsetY: node.currentPos,\n noteHeight,\n onClick(evt) {\n if (edited) {\n setEditingNote(null);\n evt.stopPropagation();\n }\n },\n },\n [\n h(noteEditor, {\n note: editedModel,\n key: index,\n focused: true,\n edited,\n }),\n ],\n ),\n ]),\n ]);\n}\n\nexport type { NoteData };\nexport { NoteEditorProvider, NoteEditorContext, NoteTextEditor, NoteEditor };\n"],"names":["createContext","updateModel","useModelEditor","h","EditableText","useContext","NoteLayoutContext","useState","ModelEditorProvider","index","ForeignObject","classNames","Draggable","ColumnContext","hasSpan","ErrorBoundary","NoteRect","NoteConnector","NotePositioner"],"mappings":"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"}