@macrostrat/column-components
Version:
React rendering primitives for stratigraphic columns
298 lines (297 loc) • 8.52 kB
JavaScript
"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