UNPKG

@macrostrat/column-components

Version:

React rendering primitives for stratigraphic columns

298 lines (297 loc) 8.52 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const React = require("react"); const core = require("@blueprintjs/core"); const classNames = require("classnames"); const hyper = require("../hyper.cjs"); const index = require("../util/index.cjs"); const layout = require("./layout.cjs"); const connector = require("./connector.cjs"); const Draggable = require("react-draggable"); const utils = require("./utils.cjs"); const uiComponents = require("@macrostrat/ui-components"); const modelEditor = require("../context/model-editor.cjs"); const column = require("../context/column.cjs"); const _interopDefault = (e) => e && e.__esModule ? e : { default: e }; const classNames__default = /* @__PURE__ */ _interopDefault(classNames); const Draggable__default = /* @__PURE__ */ _interopDefault(Draggable); const NoteEditorContext = React.createContext({ inEditMode: false }); const NoteTextEditor = function(props) { const { updateModel: updateModel2 } = modelEditor.useModelEditor(); const { note } = props; return hyper(core.EditableText, { multiline: true, className: "col-note-label note-editing", defaultValue: note.note, isEditing: true, onConfirm(newText) { return updateModel2({ note: { $set: newText } }); } }); }; function NoteEditorProvider(props) { let { children, inEditMode = false, noteEditor } = props; const { notes } = React.useContext(layout.NoteLayoutContext); const [editingNote, setEditingNote] = React.useState(null); const deleteNote = function() { const val = editingNote; setEditingNote(null); return props.onDeleteNote?.(val); }; const onCreateNote = function(pos) { const { height, top_height } = pos; const val = { height, top_height, note: null, symbol: null }; return setEditingNote(val); }; const value = { editingNote, setEditingNote, deleteNote, inEditMode, noteEditor, onCreateNote }; const onConfirmChanges = function(n) { if (n?.note == null && n == editingNote) { console.log("No changes to note"); return; } if (notes.includes(n)) { return; } return props.onUpdateNote?.(n); }; return hyper(NoteEditorContext.Provider, { value }, [ hyper( modelEditor.ModelEditorProvider, { model: editingNote, onDelete: deleteNote, onConfirmChanges, logUpdates: true, alwaysConfirm: true }, children ) ]); } const NoteConnectorPath = function(props) { const { d, offsetX, className } = props; return hyper("path", { d, className, transform: `translate(${offsetX})`, fill: "transparent" }); }; const EditableNoteConnector = function(props) { const { notes, nodes, columnIndex, generatePath, createNodeForNote } = React.useContext(layout.NoteLayoutContext); let { note, node, index: index$1 } = props; if (note.id != null) { node = nodes[note.id]; } if (node == null) { node = createNodeForNote(note); } const x = columnIndex[note.id] * 5 || 0; const d = generatePath(node, x); return hyper([ hyper(NoteConnectorPath, { className: "note-connector", d, offsetX: x }), hyper( index.ForeignObject, { width: 30, x, y: 0, height: 1, style: { overflowY: "visible" } }, hyper(PositionEditorInner, { note }) ) ]); }; const PointHandle = function(props) { let { height, size, className, ...rest } = props; className = classNames__default.default("handle point-handle", className); if (size == null) { size = 10; } return hyper( Draggable__default.default, { position: { x: 0, y: height }, axis: "y", ...rest }, hyper("div.handle", { style: { height: size, width: size, marginLeft: -size / 2, marginTop: -size / 2, position: "absolute" }, className }) ); }; function PositionEditorInner(props) { let { margin } = props; if (margin == null) { margin = 3; } const { scaleClamped: scale } = React.useContext(column.ColumnContext); const ctx = modelEditor.useModelEditor(); if (ctx == null) { return null; } const { updatedModel, editedModel } = ctx; const note = editedModel ?? props.note; if (note == null) { return null; } const noteHasSpan = utils.hasSpan(note); const bottomHeight = scale(note.height); let topHeight = bottomHeight; let height = 0; if (noteHasSpan) { topHeight = scale(note.top_height); height = Math.abs(topHeight - bottomHeight); } const moveEntireNote = function(e, data) { const { y } = data; const spec = { height: { $set: scale.invert(y + height) } }; if (noteHasSpan) { spec.top_height = { $set: scale.invert(y) }; } return updateModel(spec); }; const moveTop = function(e, data) { const spec = { top_height: { $set: scale.invert(data.y) } }; if (Math.abs(data.y - bottomHeight) < 2) { spec.top_height = { $set: null }; } return updateModel(spec); }; const moveBottom = function(e, data) { const spec = { height: { $set: scale.invert(data.y) } }; if (Math.abs(data.y - topHeight) < 2) { spec.top_height = { $set: null }; } return updateModel(spec); }; return hyper( uiComponents.ErrorBoundary, null, hyper("div.position-editor", [ hyper( Draggable__default.default, { handle: ".handle", position: { x: 0, y: topHeight }, onDrag: moveEntireNote, axis: "y" }, hyper("div", [ hyper("div.handle", { className: "handle", style: { height, width: 2 * margin, marginLeft: -margin, marginTop: -margin, position: "absolute" } }) ]) ), hyper(PointHandle, { height: noteHasSpan ? topHeight : topHeight - 15, onDrag: moveTop, className: classNames__default.default("top-handle", { "add-span-handle": !noteHasSpan }), bounds: { bottom: bottomHeight } }), hyper(PointHandle, { height: bottomHeight, onDrag: moveBottom, className: "bottom-handle", bounds: noteHasSpan ? { top: topHeight } : null }) ]) ); } function NoteEditorUnderlay() { return hyper(layout.NoteRect, { style: { pointerEvents: "none" }, className: "underlay" }); } function NoteEditor(props) { const { allowPositionEditing } = props; const { noteEditor, setEditingNote } = React.useContext(NoteEditorContext); const { notes, nodes, elementHeights, createNodeForNote } = React.useContext(layout.NoteLayoutContext); const { editedModel, model } = modelEditor.useModelEditor(); if (editedModel == null) { return null; } const index2 = notes.indexOf(editedModel); const { id: noteID } = editedModel; let node = nodes[noteID] || createNodeForNote(editedModel); const noteHeight = elementHeights[noteID] || 20; if (editedModel.height != null) { const newNode = createNodeForNote(editedModel); newNode.currentPos = node.currentPos; const pos = newNode.centerPos || newNode.idealPos; const dy = pos - node.currentPos; if (dy > 50) { newNode.currentPos = pos - 50; } if (dy < -50) { newNode.currentPos = pos + 50; } node = newNode; } const edited = editedModel === model; return hyper(uiComponents.ErrorBoundary, [ hyper("g.note-editor.note", [ hyper(NoteEditorUnderlay), hyper.if(!allowPositionEditing)(connector.NoteConnector, { note: editedModel }), hyper.if(allowPositionEditing)(EditableNoteConnector, { note: editedModel, node }), hyper( connector.NotePositioner, { offsetY: node.currentPos, noteHeight, onClick(evt) { if (edited) { setEditingNote(null); evt.stopPropagation(); } } }, [ hyper(noteEditor, { note: editedModel, key: index2, focused: true, edited }) ] ) ]) ]); } exports.NoteEditor = NoteEditor; exports.NoteEditorContext = NoteEditorContext; exports.NoteEditorProvider = NoteEditorProvider; exports.NoteTextEditor = NoteTextEditor; //# sourceMappingURL=editor.cjs.map