halkyon/packages/halkyon_editor
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Tizian 「ティツィアーン」 6356bed37d
fix(editor): a rich text field focused without a cursor puts it at the end
AppFlowy's editor takes the focus without a selection when it is focused
from outside, by Tab or by a field moving it there (Todo's quick add, its
down arrow into the description), so it showed no cursor and took no
typing until clicked. Focused so, it now places the cursor at the end of
its last text.

Whats-New: Moving into a text with Tab or the arrow keys now puts the cursor there, ready to type.
Whats-New-De: Wer mit Tab oder den Pfeiltasten in einen Text wechselt, hat den Cursor jetzt gleich dort und kann tippen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-11-10 14:22:55 +01:00
..
build/f05bfb3d5907fd0115f5797e28554b94 build(editor): halkyon_editor joins the workspace (ADR 0033, D37) 2026-11-07 21:49:47 +01:00
lib fix(editor): a rich text field focused without a cursor puts it at the end 2026-11-10 14:22:55 +01:00
test fix(editor): a rich text field focused without a cursor puts it at the end 2026-11-10 14:22:55 +01:00
.gitignore refactor(learn): the editor's general parts move to halkyon_editor (ADR 0033, D37) 2026-11-07 21:49:48 +01:00
analysis_options.yaml build(editor): halkyon_editor joins the workspace (ADR 0033, D37) 2026-11-07 21:49:47 +01:00
CHANGELOG.md refactor(learn): the editor's general parts move to halkyon_editor (ADR 0033, D37) 2026-11-07 21:49:48 +01:00
l10n.yaml build(editor): halkyon_editor joins the workspace (ADR 0033, D37) 2026-11-07 21:49:47 +01:00
LICENSE build(editor): halkyon_editor joins the workspace (ADR 0033, D37) 2026-11-07 21:49:47 +01:00
pubspec.yaml build(editor): halkyon_editor joins the workspace (ADR 0033, D37) 2026-11-07 21:49:47 +01:00
README.md refactor(learn): the editor's general parts move to halkyon_editor (ADR 0033, D37) 2026-11-07 21:49:48 +01:00

halkyon_editor

Halkyon's rich text, shared by its apps: the document as an app keeps it, the one editor and the one read-only view of it, built on appflowy_editor (our fork, pinned, as every app's), with their texts in British English, American English and German. Moved out of Halkyon Learn on 6 Nov 2026, when Halkyon Todo took editor documents too (ADR 0033, D37).

Using it

An app installs HalkyonEditorLocalizations.delegate beside its other delegates, and halkyon_ui's, whose sheets the Insert menu opens in.

// Stored: RichContent is the editor's document JSON and its format's version.
final content = RichContent.plain('Buy milk'); // or RichContent.empty()
content.plainText; // 'Buy milk'
content.isBlank;   // false
final stored = content.toJson();
RichContent.fromJson(stored);

RichContentEditor(
  initialContent: content,
  onChanged: (content) => save(content),
  formatBar: true,
);
RichContentView(content: content);

What it holds

  • RichContent (lib/src/content/): pure Dart, the document in JSON. content_blocks.dart names every block's type and attributes across the apps, for plainText and for what a block's type is called for good.
  • RichContentEditor, RichContentView (lib/src/editor/): the editor, with the FormatBar docked below it while it has the focus, copying and pasting that keep the formats (EditorClipboard), links (editLink, Ctrl+K) and superscript and subscript; the view, display only, taking the height of its content.
  • EditorBlocks: what an editor knows. basicBlocks is what it knows without an app (the editor's own builders; headings, lists, a checklist, a quote, a divider and a table to insert). An app adds its own blocks, and passes them as blocks: or through EditorBlocksScope, with:
    • builders, insertable (the Insert sheet and the desktop's / menu show the same list) and shortcuts;
    • textMarks, how marks of its own are drawn, each wrapping the one before it, and formatActions, their buttons, after subscript;
    • onEditorClosed, for what its text left outside the editor. plus joins two sets, offering narrows what is offered and nothing else.
  • AtomicBlock, BlockNotice: for an app's block taken whole, selected and removed as one. A type nothing knows shows as needing a newer app, and stays as it is.

RichContentEditor's wrapEditor puts what an app adds around the editor itself, knowing its state and focus (Learn's check of the spelling).

Editors are tested as in Learn: host one in a scrollable body with a slot of fixed height, pump(const Duration(seconds: 1)) after changes, and find its text with findRichText: true.

Licence

GNU Affero General Public License, version 3 or any later version (AGPL-3.0-or-later), as the other packages of the apps; see LICENSE.