Rich text / foldkit-mixins-richtext
The link editor
An address field with two buttons: link the selection (or change the link around the caret),
and remove that link. The address being typed is the application's; what it sends is the
editor's AppliedMark or ClearedMark through wrap, so the editor applies either as one
transition and one undo step.
import * as RichText from 'foldkit-richtext'
import { linkEditor } from 'foldkit-mixins-richtext'
// Opening the editor: start the draft from the link the selection is in, if any.
const linkDraft = RichText.linkAt(model.document, model.editor.selection)?.href ?? ''
// In a view:
linkEditor<Message>()(
{
document: model.document,
selection: model.editor.selection,
draft: model.linkDraft,
drafted: href => DraftedLink({ href }),
wrap: edited,
},
h,
)What it sends is RichText.safeUrl(draft), so the address is cleaned and a javascript: or
data: one is never sent. Applying needs such an address and something to link: a range of
text, or a caret inside a link. Otherwise the apply button is disabled and Enter in the field
falls through. The remove button is drawn only inside a link. Where the editor appears, and
when it opens or closes, is the application's; give it closed and Escape in the field sends
it. Focusing the field as the editor opens, so a link can be pasted at once, is a Command the
application runs (Dom.focus('[data-link="address"]')).
The view decides what its button sends from the draft it was drawn with, which is a frame behind
keys typed fast: Enter straight after the last character would apply the draft before it. Give
it submitted, and Enter sends that instead, for update to apply
linkEdit(document, selection, draft) to the draft the Model holds; linkEdit is the same
decision the button makes, as an Option of the editor's Message.
| Slot | Capability | Renders |
|---|---|---|
root | Container | the editor's wrapper, role="group" |
input | TextInput | the address field, data-link="address", "Paste or type a link" |
apply | Interactive | the apply button, data-link="apply", labelled Apply or Update |
remove | Interactive | the remove button, data-link="remove", inside a link only |