Repository navigation
v1.1.1
blockColor · colour on the block, the way Notion means it. textStyle
already colours text, and a mark is the right model for three words in a
sentence and the wrong one for a paragraph: mark every character and the
background still stops at the last one, then comes apart when somebody types at
the end. This is an attribute on the block instead, so the colour spans the
measure, travels with the block when it is dragged, and stays on an empty
paragraph — none of which a mark can do. setBlockColor, setBlockBackground,
their unsets and unsetBlockColors; the block types are yours to pass, and so
is the palette, because a headless editor that picks your ten colours has
picked your design. 0.37 kB gzipped, measured.
Global attributes that render a style no longer overwrite each other. The
composition rule was applied when a global met the node's own attributes and
not when it met another global, so of textAlign, lineHeight and indent
only the last to run reached the HTML. Centring a paragraph and then setting
its line height silently dropped the centring — and since that HTML is what
gets stored and parsed back, it was data leaving the document rather than a
rendering quirk. Found while adding a fourth extension that renders a style.
A slash menu and an @ menu can finally sit on one editor. suggestion
documented that two of them need two names, and two of them did work — separate
state, separate decorations. The pair of commands they declared did not:
acceptSuggestion and cancelSuggestion were literals whatever the name was,
so the second instance tripped the "two extensions both define the command"
guard and the editor refused to build. The only way to have both was to strip
the commands off one of them. The names are derived from the extension's name
now — suggestion({ char: '/', name: 'slash' }) brings acceptSlash and
cancelSlash, and the default name yields exactly the two names it always did,
so nothing that worked before reads differently. The types follow, so
editor.commands.cancelSlash is known rather than guessed.
colorOf is exported, and is now the only thing that decides what a colour
is. The check had been copied into a second extension and a third was about
to copy it again; a security-critical pattern maintained in three places is one
that gets corrected in one of them.
The drag handle is a drawn grip, aligned to the top of the first line. It
was the braille character ⠿ at 14px, so its weight and size were whatever the
reader's font did with it — faint on most, a tofu box on a machine without the
glyph. Six dots in a CSS grid are the same shape everywhere and can be sized to
the hand rather than to a font. Its colour is var(--matra-drag-handle, currentColor), so a host can set one without restyling the element.
It also sat against the top of the whole block, which read as aligned on a
paragraph and visibly high on a heading. It now measures the first line box and
sits at the top of that.
The drag handle stays put while you reach for it. It lives outside the
editable element, so a pointer travelling from the words to the grip fires
mouseleave on the way. The guard for that compared relatedTarget to the
handle by identity, which stopped working the moment the handle grew a child —
and even fixed, the gap between the text and the grip belongs to neither, so
the pointer is over nothing at all while it crosses. The check uses contains
now, the handle pads out to the block's edge so the gap is part of its target,
and a 240ms grace period covers the rest.
A drag carries the block, not the grip. The browser builds its drag image
from whatever the drag started on, and a drag starts on the handle — so a
nineteen-pixel grip flew around the screen while the paragraph it belonged to
sat still. dragstart now hands setDragImage a copy of the block, the block
it came from dims to show what is being carried, and the drop line takes the
width of the block it would land against.
The copy looks like the block, which took a second pass to get right.
setDragImage needs an element that is in the document, and the obvious place
to put one — document.body — is outside everything the text inherits from:
right words, wrong font, wrong colour, wrong measure, and no background at all,
because an editor's own background-color is usually transparent and the page
paints behind it. The copy now sits in a wrapper carrying the editor's class,
with the inherited properties that come from the page copied across and the
background resolved by walking up to the first ancestor that actually paints
one. Nothing is added to it: no padding, no shadow, no fade.
Three new variables with defaults — --matra-drag-handle,
--matra-drag-ghost-bg and --matra-drop-cursor — let a host colour all of it
without restyling elements it does not own.