Skip to content

Changelog

All notable changes to @draw/editor. The format follows Keep a Changelog. New entries go under Unreleased.

  • Text styling. TextStyle (fontSize, fontFamily, align), DEFAULT_TEXT_STYLE (20, hand-drawn, left) and Session.textStyle, which new text and new labels use in place of the fixed defaults. A new label is always centred, whatever textStyle.align is. restyleText(session, change, env) and restyleTextSelection(editor, change, env) restyle every selected text and every selected container’s label as one history entry and fit the frames again: auto text re-measures, fixed-width text re-wraps and a container grows to fit its label. A change that alters nothing adds no entry, and restyleText then returns the same session.
  • Live bindings. bindEnd in features/bind.ts binds an arrow end to the shape at a point within bindingDistance(zoom) page units (15 at 100% zoom and above, 20 at zoom 0.5, at most 30). Drawing an arrow binds both ends from the first frame, and a terminal handle drag rebinds or unbinds its end. bindingHighlight returns the target of the end being drawn or dragged, for the shell to outline. CreateGesture and HandleGesture carry the zoom of the press, and beginHandle takes it. createTo, finishCreate and handleTo take an EditorEnv.
  • Text inside shapes (ADR 0010). canOpenText, beginText and startText accept a rectangle, ellipse or diamond as well as a text shape, so doubleClick (after group entry) and the Text tool edit the shape’s label. typeText fits the frame to the label through editLabel, editedText reads it, and finishText clears the label on blank text and keeps the shape. TextEdit.created is true for a shape that had no label, and the edit starts with an empty label so the shell can place its text box.
  • Groups (ADR 0009). groupSelection, ungroupSelection, pickedGroup, membersOf and expandPick in features/group.ts, and the session commands group, ungroup and enter with Session.enteredGroup. A click selects a whole group, a double-click enters it, and a marquee selects a group only when every member is inside. Grouping nests, ungrouping removes the outermost level, and paste and duplicate mint fresh group ids through the new EditorEnv.newGroupId.
  • Shapes the create gestures build start with an empty groupIds, the new Shape field (ADR 0009).
  • Multi-select. Shift+click adds a shape to the selection or removes it on a click release, and a Shift press on a selected shape still drags the whole set. A press on empty canvas starts the new marquee gesture (MarqueeGesture, marqueeBox), which selects every shape whose bounds lie fully inside and adds to the selection with Shift. selectAll selects every shape. pickAt takes an additive flag, and MoveGesture has an optional deselect.
  • Tool.text, Session.editing, TextEdit, startText, setText, endText, doubleClick and editedText. A press with the Text tool, or a double click on text or empty canvas, opens a text edit. Typing previews, and committing is one history entry. Blank text removes the shape, and a created shape that ends blank leaves no entry. perform ends an open edit first.
  • zoomToFit, resetZoom, wheelZoomFactor, FIT_MARGIN and FIT_MAX_ZOOM. Zoom to fit centres all shapes with a 48 px margin and never zooms in past 100%, like Excalidraw’s Shift+1. The wheel factor is exp(-delta / 100) with the delta clamped to 10.
  • Pointer.zoom. pickAt and grabAt take the zoom, and the 6 px pick and handle tolerance is now in screen pixels (6 / zoom page units).
  • Rotation. RotateGesture, GestureKind.rotate, beginRotate, rotateTo, rotationHandlePoint, ROTATION_HANDLE_OFFSET (24 screen pixels, like Excalidraw) and ROTATION_SNAP (15 degrees). grabAt offers the rotation handle above the selection box except for a lone line or arrow. One shape turns about its own centre, several turn together about the centre of their bounds, and a drag is one undo step.
  • Package scaffold.
  • Order and reorderSelection. Brings the selection forward or backward one overlapping step, or to the front or back, as one history entry. Selected shapes keep their relative order, and a reorder that changes nothing pushes no entry.
  • Doc, a branded document of shapes and bindings keyed by id, with the ids written since its base in touched. EMPTY_DOC, putShapes, updateShapes, removeShapes, putBindings and removeBindings write it and record only what they changed. updateShapes keeps the old object when the result is data-equal. fromShapeDocument and toShapeDocument convert to and from the serializable form.
  • Change, Patch, diff, apply, invert, isEmptyPatch and changedShapeIds. diff compares records by reference and reads only touched ids, so it costs O(changes).
  • settle, which drops dangling bindings, detaches an arrow terminal moved away from an unchanged target, and re-resolves affected bound arrows in one pass.
  • Editor, Selection, Entry, History, CommitOptions, createEditor, preview, commit, undo, redo, select and load. One commit is one undo step. Selection is recorded with each edit but never undone alone, and load starts a fresh history.
  • Camera, View, MIN_ZOOM, MAX_ZOOM, screenToPage, pageToScreen, zoomAt, panBy, visibleBox and visibleShapes. The camera lives outside Editor and the history. zoomAt keeps the page point under the anchor fixed and clamps the zoom to 0.1 to 30.
  • Editing features ported from the playground: drag and ink creation, moving the selection, single and group resize, line and arrow handle drags, picking with a tolerance of 6, restyleSelection and deleteSelection. Public: Tool, Pointer, EditorEnv, the gesture records (CreateGesture, InkGesture, MoveGesture, ResizeGesture, HandleGesture, DragTool, PageSample), selectionFrame and shapeHandles.
  • copySelection, parseClip, pasteClip, duplicateSelection and DUPLICATE_OFFSET. A copied selection is a ShapeDocument clip. A paste centres it on a page point, a duplicate offsets it by 10. Both mint fresh ids and seeds, remap or drop bindings, stack the copies on top, select them and push one history entry.
  • Session, ActiveGesture, Gesture, GestureKind, createSession, liveEditor, pointerDown, pointerMove, pointerUp, cancel, perform and restyle. Pointer events go in and editor state comes out. A gesture previews from its base editor on every move and commits once on release. perform cancels an open gesture before undo, redo or any other command.