@connextar/house 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +286 -28
- package/dist/changelog/changelog.d.ts +60 -0
- package/dist/changelog/changelog.d.ts.map +1 -0
- package/dist/changelog/changelog.js +61 -0
- package/dist/changelog/changelog.js.map +1 -0
- package/dist/changelog/index.d.ts +2 -0
- package/dist/changelog/index.d.ts.map +1 -0
- package/dist/changelog/index.js +2 -0
- package/dist/changelog/index.js.map +1 -0
- package/dist/editor/block-handle.d.ts +15 -0
- package/dist/editor/block-handle.d.ts.map +1 -0
- package/dist/editor/block-handle.js +106 -0
- package/dist/editor/block-handle.js.map +1 -0
- package/dist/editor/blocks.d.ts +35 -0
- package/dist/editor/blocks.d.ts.map +1 -0
- package/dist/editor/blocks.js +114 -0
- package/dist/editor/blocks.js.map +1 -0
- package/dist/editor/bubble-toolbar.d.ts +11 -0
- package/dist/editor/bubble-toolbar.d.ts.map +1 -0
- package/dist/editor/bubble-toolbar.js +87 -0
- package/dist/editor/bubble-toolbar.js.map +1 -0
- package/dist/editor/content-index.d.ts +2 -0
- package/dist/editor/content-index.d.ts.map +1 -0
- package/dist/editor/content-index.js +2 -0
- package/dist/editor/content-index.js.map +1 -0
- package/dist/editor/content.d.ts +30 -0
- package/dist/editor/content.d.ts.map +1 -0
- package/dist/editor/content.js +256 -0
- package/dist/editor/content.js.map +1 -0
- package/dist/editor/editor.d.ts +52 -0
- package/dist/editor/editor.d.ts.map +1 -0
- package/dist/editor/editor.js +160 -0
- package/dist/editor/editor.js.map +1 -0
- package/dist/editor/emoji-index.d.ts +2 -0
- package/dist/editor/emoji-index.d.ts.map +1 -0
- package/dist/editor/emoji-index.js +2 -0
- package/dist/editor/emoji-index.js.map +1 -0
- package/dist/editor/emoji-picker.d.ts +16 -0
- package/dist/editor/emoji-picker.d.ts.map +1 -0
- package/dist/editor/emoji-picker.js +37 -0
- package/dist/editor/emoji-picker.js.map +1 -0
- package/dist/editor/emoji.d.ts +18 -0
- package/dist/editor/emoji.d.ts.map +1 -0
- package/dist/editor/emoji.js +418 -0
- package/dist/editor/emoji.js.map +1 -0
- package/dist/editor/index.d.ts +5 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +6 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/editor/suggestion-popup.d.ts +17 -0
- package/dist/editor/suggestion-popup.d.ts.map +1 -0
- package/dist/editor/suggestion-popup.js +57 -0
- package/dist/editor/suggestion-popup.js.map +1 -0
- package/dist/editor/suggestions.d.ts +93 -0
- package/dist/editor/suggestions.d.ts.map +1 -0
- package/dist/editor/suggestions.js +179 -0
- package/dist/editor/suggestions.js.map +1 -0
- package/dist/editor/ui.d.ts +54 -0
- package/dist/editor/ui.d.ts.map +1 -0
- package/dist/editor/ui.js +58 -0
- package/dist/editor/ui.js.map +1 -0
- package/dist/house.css +333 -0
- package/dist/internal/cx.d.ts +3 -0
- package/dist/internal/cx.d.ts.map +1 -0
- package/dist/internal/cx.js +5 -0
- package/dist/internal/cx.js.map +1 -0
- package/dist/internal/next-link.d.ts +23 -0
- package/dist/internal/next-link.d.ts.map +1 -0
- package/dist/internal/next-link.js +3 -0
- package/dist/internal/next-link.js.map +1 -0
- package/dist/markdown/guide.d.ts +98 -0
- package/dist/markdown/guide.d.ts.map +1 -0
- package/dist/markdown/guide.js +328 -0
- package/dist/markdown/guide.js.map +1 -0
- package/dist/markdown/index.d.ts +4 -0
- package/dist/markdown/index.d.ts.map +1 -0
- package/dist/markdown/index.js +4 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/markdown/table-view.d.ts +28 -0
- package/dist/markdown/table-view.d.ts.map +1 -0
- package/dist/markdown/table-view.js +25 -0
- package/dist/markdown/table-view.js.map +1 -0
- package/dist/markdown/table.d.ts +35 -0
- package/dist/markdown/table.d.ts.map +1 -0
- package/dist/markdown/table.js +79 -0
- package/dist/markdown/table.js.map +1 -0
- package/dist/release/changelog.d.ts +72 -0
- package/dist/release/changelog.d.ts.map +1 -0
- package/dist/release/changelog.js +92 -0
- package/dist/release/changelog.js.map +1 -0
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +3 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/version.d.ts +33 -0
- package/dist/release/version.d.ts.map +1 -0
- package/dist/release/version.js +57 -0
- package/dist/release/version.js.map +1 -0
- package/dist/trail/index.d.ts +3 -0
- package/dist/trail/index.d.ts.map +1 -0
- package/dist/trail/index.js +3 -0
- package/dist/trail/index.js.map +1 -0
- package/dist/trail/rules.d.ts +44 -0
- package/dist/trail/rules.d.ts.map +1 -0
- package/dist/trail/rules.js +74 -0
- package/dist/trail/rules.js.map +1 -0
- package/dist/trail/trail.d.ts +49 -0
- package/dist/trail/trail.d.ts.map +1 -0
- package/dist/trail/trail.js +188 -0
- package/dist/trail/trail.js.map +1 -0
- package/dist/ux/errors.d.ts +26 -0
- package/dist/ux/errors.d.ts.map +1 -0
- package/dist/ux/errors.js +33 -0
- package/dist/ux/errors.js.map +1 -0
- package/dist/ux/feedback.d.ts +23 -0
- package/dist/ux/feedback.d.ts.map +1 -0
- package/dist/ux/feedback.js +22 -0
- package/dist/ux/feedback.js.map +1 -0
- package/dist/ux/index.d.ts +20 -0
- package/dist/ux/index.d.ts.map +1 -0
- package/dist/ux/index.js +20 -0
- package/dist/ux/index.js.map +1 -0
- package/dist/ux/navigation-index.d.ts +10 -0
- package/dist/ux/navigation-index.d.ts.map +1 -0
- package/dist/ux/navigation-index.js +10 -0
- package/dist/ux/navigation-index.js.map +1 -0
- package/dist/ux/navigation-progress.d.ts +53 -0
- package/dist/ux/navigation-progress.d.ts.map +1 -0
- package/dist/ux/navigation-progress.js +245 -0
- package/dist/ux/navigation-progress.js.map +1 -0
- package/dist/ux/optimistic.d.ts +139 -0
- package/dist/ux/optimistic.d.ts.map +1 -0
- package/dist/ux/optimistic.js +242 -0
- package/dist/ux/optimistic.js.map +1 -0
- package/dist/ux/use-action.d.ts +60 -0
- package/dist/ux/use-action.d.ts.map +1 -0
- package/dist/ux/use-action.js +100 -0
- package/dist/ux/use-action.js.map +1 -0
- package/dist/ux/use-optimistic-list.d.ts +69 -0
- package/dist/ux/use-optimistic-list.d.ts.map +1 -0
- package/dist/ux/use-optimistic-list.js +115 -0
- package/dist/ux/use-optimistic-list.js.map +1 -0
- package/dist/ux/use-optimistic-value.d.ts +40 -0
- package/dist/ux/use-optimistic-value.d.ts.map +1 -0
- package/dist/ux/use-optimistic-value.js +68 -0
- package/dist/ux/use-optimistic-value.js.map +1 -0
- package/docs/ReleaseProcess.md +315 -0
- package/package.json +83 -11
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { DragHandle } from "@tiptap/extension-drag-handle-react";
|
|
4
|
+
import { ArrowDown, ArrowUp, Check, Copy, GripVertical, Plus, Trash2 } from "lucide-react";
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { BLOCK_TYPES } from "./blocks.js";
|
|
7
|
+
import { ghostButtonClass, Menu, MenuContent, MenuItem, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, } from "./ui.js";
|
|
8
|
+
/**
|
|
9
|
+
* Stable on purpose: the DragHandle wrapper re-registers its plugin when this
|
|
10
|
+
* changes identity, and a plugin re-registration recreates every plugin view in
|
|
11
|
+
* the editor — see the note in bubble-toolbar.tsx.
|
|
12
|
+
*/
|
|
13
|
+
const HANDLE_POSITION = { placement: "left-start" };
|
|
14
|
+
const handleButtonClass = `${ghostButtonClass} size-6 p-0 text-muted-foreground hover:text-foreground`;
|
|
15
|
+
/**
|
|
16
|
+
* The gutter beside whichever block the pointer is over: a `+` that starts a new
|
|
17
|
+
* block underneath (with the `/` menu already open, as Notion does) and a grip
|
|
18
|
+
* that drags the block to reorder it or, clicked, opens the block menu — turn
|
|
19
|
+
* into, duplicate, move up, move down, delete.
|
|
20
|
+
*
|
|
21
|
+
* Everything works on the block's document position rather than the caret, so a
|
|
22
|
+
* block can be acted on without ever being clicked into. The drag itself is the
|
|
23
|
+
* extension's: it understands nested lists and shows the drop cursor.
|
|
24
|
+
*/
|
|
25
|
+
export function BlockHandle({ editor }) {
|
|
26
|
+
const [hovered, setHovered] = useState(null);
|
|
27
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
28
|
+
const menuOpenRef = useRef(false);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
menuOpenRef.current = menuOpen;
|
|
31
|
+
}, [menuOpen]);
|
|
32
|
+
// Leave the last block in place while its menu is open, so the menu still
|
|
33
|
+
// knows what it belongs to after the pointer wanders. Stable identity for the
|
|
34
|
+
// same reason as HANDLE_POSITION.
|
|
35
|
+
const onNodeChange = useCallback(({ node, pos }) => {
|
|
36
|
+
if (menuOpenRef.current)
|
|
37
|
+
return;
|
|
38
|
+
setHovered(node ? { node, pos } : null);
|
|
39
|
+
}, []);
|
|
40
|
+
const range = (block) => ({ from: block.pos, to: block.pos + block.node.nodeSize });
|
|
41
|
+
/** Turn the whole block into another type, without moving the caret by hand. */
|
|
42
|
+
const turnInto = (block, typeId) => {
|
|
43
|
+
const type = BLOCK_TYPES.find((t) => t.id === typeId);
|
|
44
|
+
if (!type)
|
|
45
|
+
return;
|
|
46
|
+
const inside = { from: block.pos + 1, to: Math.max(block.pos + 1, block.pos + block.node.nodeSize - 1) };
|
|
47
|
+
type.apply(editor.chain().focus().setTextSelection(inside)).run();
|
|
48
|
+
};
|
|
49
|
+
const duplicate = (block) => {
|
|
50
|
+
// The node is immutable, so it can be inserted twice.
|
|
51
|
+
editor
|
|
52
|
+
.chain()
|
|
53
|
+
.focus()
|
|
54
|
+
.insertContentAt(block.pos + block.node.nodeSize, block.node)
|
|
55
|
+
.run();
|
|
56
|
+
};
|
|
57
|
+
const remove = (block) => {
|
|
58
|
+
editor.chain().focus().deleteRange(range(block)).run();
|
|
59
|
+
};
|
|
60
|
+
/** Swap the block with its previous (-1) or next (+1) sibling. */
|
|
61
|
+
const move = (block, direction) => {
|
|
62
|
+
const $pos = editor.state.doc.resolve(block.pos);
|
|
63
|
+
const parent = $pos.parent;
|
|
64
|
+
const siblingIndex = $pos.index() + direction;
|
|
65
|
+
if (siblingIndex < 0 || siblingIndex >= parent.childCount)
|
|
66
|
+
return;
|
|
67
|
+
const sibling = parent.child(siblingIndex);
|
|
68
|
+
const { from, to } = range(block);
|
|
69
|
+
editor
|
|
70
|
+
.chain()
|
|
71
|
+
.focus()
|
|
72
|
+
.command(({ tr }) => {
|
|
73
|
+
tr.delete(from, to);
|
|
74
|
+
const insertAt = direction === -1 ? from - sibling.nodeSize : from + sibling.nodeSize;
|
|
75
|
+
tr.insert(insertAt, block.node);
|
|
76
|
+
return true;
|
|
77
|
+
})
|
|
78
|
+
.run();
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* The `+`: a fresh paragraph under this block with the `/` menu open — or, if
|
|
82
|
+
* this block is already an empty paragraph, just the menu, right here.
|
|
83
|
+
*/
|
|
84
|
+
const insertBelow = (block) => {
|
|
85
|
+
const isEmptyParagraph = block.node.type.name === "paragraph" && block.node.content.size === 0;
|
|
86
|
+
if (isEmptyParagraph) {
|
|
87
|
+
editor
|
|
88
|
+
.chain()
|
|
89
|
+
.focus()
|
|
90
|
+
.setTextSelection(block.pos + 1)
|
|
91
|
+
.insertContent("/")
|
|
92
|
+
.run();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const after = block.pos + block.node.nodeSize;
|
|
96
|
+
editor
|
|
97
|
+
.chain()
|
|
98
|
+
.focus()
|
|
99
|
+
.insertContentAt(after, { type: "paragraph" })
|
|
100
|
+
.setTextSelection(after + 1)
|
|
101
|
+
.insertContent("/")
|
|
102
|
+
.run();
|
|
103
|
+
};
|
|
104
|
+
return (_jsxs(DragHandle, { editor: editor, nested: true, className: "house-block-handle", computePositionConfig: HANDLE_POSITION, onNodeChange: onNodeChange, children: [_jsx("button", { type: "button", className: handleButtonClass, "aria-label": "Add a block below", title: "Add a block below", onClick: () => hovered && insertBelow(hovered), children: _jsx(Plus, { className: "size-4", "aria-hidden": true }) }), _jsxs(Menu, { open: menuOpen, onOpenChange: setMenuOpen, children: [_jsx(MenuTrigger, { asChild: true, children: _jsx("button", { type: "button", className: `${handleButtonClass} cursor-grab active:cursor-grabbing`, "aria-label": "Block options \u2014 drag to move", title: "Drag to move, click for options", children: _jsx(GripVertical, { className: "size-4", "aria-hidden": true }) }) }), _jsxs(MenuContent, { className: "w-48", children: [_jsxs(MenuSub, { children: [_jsx(MenuSubTrigger, { children: "Turn into" }), _jsx(MenuSubContent, { className: "w-48", children: BLOCK_TYPES.map((type) => (_jsxs(MenuItem, { onSelect: () => hovered && turnInto(hovered, type.id), children: [_jsx(type.icon, { className: "size-4", "aria-hidden": true }), _jsx("span", { className: "flex-1", children: type.label }), hovered && type.matchesNode(hovered.node) ? (_jsx(Check, { className: "size-4 text-primary", "aria-hidden": true })) : null] }, type.id))) })] }), _jsxs(MenuItem, { onSelect: () => hovered && duplicate(hovered), children: [_jsx(Copy, { className: "size-4", "aria-hidden": true }), "Duplicate"] }), _jsxs(MenuItem, { onSelect: () => hovered && move(hovered, -1), children: [_jsx(ArrowUp, { className: "size-4", "aria-hidden": true }), "Move up"] }), _jsxs(MenuItem, { onSelect: () => hovered && move(hovered, 1), children: [_jsx(ArrowDown, { className: "size-4", "aria-hidden": true }), "Move down"] }), _jsx(MenuSeparator, {}), _jsxs(MenuItem, { className: "text-destructive focus:text-destructive", onSelect: () => hovered && remove(hovered), children: [_jsx(Trash2, { className: "size-4", "aria-hidden": true }), "Delete"] })] })] })] }));
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=block-handle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"block-handle.js","sourceRoot":"","sources":["../../src/editor/block-handle.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ChainedCommands, Editor } from "@tiptap/core";
|
|
2
|
+
import type { Node as PMNode } from "@tiptap/pm/model";
|
|
3
|
+
import { type LucideIcon } from "lucide-react";
|
|
4
|
+
/**
|
|
5
|
+
* The block vocabulary of the editor — one list, read by three surfaces: the
|
|
6
|
+
* `/` menu, the bubble menu's "Turn into", and each block's grip menu.
|
|
7
|
+
*
|
|
8
|
+
* These are exactly the blocks Markdown can say, which is the whole reason there
|
|
9
|
+
* are no callouts, toggles or columns: the stored format is Markdown text, and a
|
|
10
|
+
* block the read-only renderer (and every printed or emailed copy) could not show
|
|
11
|
+
* would silently degrade on the surfaces people hand to someone else.
|
|
12
|
+
*/
|
|
13
|
+
export interface BlockType {
|
|
14
|
+
id: "paragraph" | "heading1" | "heading2" | "heading3" | "bulletList" | "orderedList" | "taskList" | "blockquote" | "codeBlock";
|
|
15
|
+
label: string;
|
|
16
|
+
description: string;
|
|
17
|
+
icon: LucideIcon;
|
|
18
|
+
/** Extra words the `/` menu matches on. */
|
|
19
|
+
keywords: string[];
|
|
20
|
+
/** Markdown shortcut shown as a hint, e.g. "# ". */
|
|
21
|
+
shortcut: string;
|
|
22
|
+
/**
|
|
23
|
+
* Convert whatever the selection is in. `clearNodes()` first lifts the
|
|
24
|
+
* selection out of lists and quotes, so "turn a quote into a heading" and
|
|
25
|
+
* "turn a list into paragraphs" both work in one step.
|
|
26
|
+
*/
|
|
27
|
+
apply: (chain: ChainedCommands) => ChainedCommands;
|
|
28
|
+
isActive: (editor: Editor) => boolean;
|
|
29
|
+
/** Whether a given block node (from the grip, not the caret) is this type. */
|
|
30
|
+
matchesNode: (node: PMNode) => boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare const BLOCK_TYPES: readonly BlockType[];
|
|
33
|
+
/** The block type the selection currently sits in, for "Turn into" state. */
|
|
34
|
+
export declare function activeBlockType(editor: Editor): BlockType;
|
|
35
|
+
//# sourceMappingURL=blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../src/editor/blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAUL,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EACE,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,YAAY,GACZ,aAAa,GACb,UAAU,GACV,YAAY,GACZ,WAAW,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,UAAU,CAAC;IACjB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,eAAe,CAAC;IACnD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,8EAA8E;IAC9E,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAsBD,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EA0F3C,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAEzD"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Code2, Heading1, Heading2, Heading3, List, ListOrdered, ListTodo, Pilcrow, Quote, } from "lucide-react";
|
|
2
|
+
const named = (name) => (node) => node.type.name === name;
|
|
3
|
+
const headingLevel = (level) => (node) => node.type.name === "heading" && node.attrs.level === level;
|
|
4
|
+
const PARAGRAPH = {
|
|
5
|
+
id: "paragraph",
|
|
6
|
+
label: "Text",
|
|
7
|
+
description: "Plain writing",
|
|
8
|
+
icon: Pilcrow,
|
|
9
|
+
keywords: ["paragraph", "plain", "body"],
|
|
10
|
+
shortcut: "",
|
|
11
|
+
apply: (chain) => chain.clearNodes().setParagraph(),
|
|
12
|
+
isActive: (editor) => editor.isActive("paragraph") &&
|
|
13
|
+
!editor.isActive("bulletList") &&
|
|
14
|
+
!editor.isActive("orderedList") &&
|
|
15
|
+
!editor.isActive("taskList") &&
|
|
16
|
+
!editor.isActive("blockquote"),
|
|
17
|
+
matchesNode: named("paragraph"),
|
|
18
|
+
};
|
|
19
|
+
export const BLOCK_TYPES = [
|
|
20
|
+
PARAGRAPH,
|
|
21
|
+
{
|
|
22
|
+
id: "heading1",
|
|
23
|
+
label: "Heading 1",
|
|
24
|
+
description: "Big section heading",
|
|
25
|
+
icon: Heading1,
|
|
26
|
+
keywords: ["h1", "title", "big"],
|
|
27
|
+
shortcut: "# ",
|
|
28
|
+
apply: (chain) => chain.clearNodes().setHeading({ level: 1 }),
|
|
29
|
+
isActive: (editor) => editor.isActive("heading", { level: 1 }),
|
|
30
|
+
matchesNode: headingLevel(1),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "heading2",
|
|
34
|
+
label: "Heading 2",
|
|
35
|
+
description: "Medium section heading",
|
|
36
|
+
icon: Heading2,
|
|
37
|
+
keywords: ["h2", "subtitle"],
|
|
38
|
+
shortcut: "## ",
|
|
39
|
+
apply: (chain) => chain.clearNodes().setHeading({ level: 2 }),
|
|
40
|
+
isActive: (editor) => editor.isActive("heading", { level: 2 }),
|
|
41
|
+
matchesNode: headingLevel(2),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "heading3",
|
|
45
|
+
label: "Heading 3",
|
|
46
|
+
description: "Small section heading",
|
|
47
|
+
icon: Heading3,
|
|
48
|
+
keywords: ["h3", "subheading"],
|
|
49
|
+
shortcut: "### ",
|
|
50
|
+
apply: (chain) => chain.clearNodes().setHeading({ level: 3 }),
|
|
51
|
+
isActive: (editor) => editor.isActive("heading", { level: 3 }),
|
|
52
|
+
matchesNode: headingLevel(3),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: "bulletList",
|
|
56
|
+
label: "Bulleted list",
|
|
57
|
+
description: "A simple list",
|
|
58
|
+
icon: List,
|
|
59
|
+
keywords: ["bullet", "unordered", "points"],
|
|
60
|
+
shortcut: "- ",
|
|
61
|
+
apply: (chain) => chain.clearNodes().toggleBulletList(),
|
|
62
|
+
isActive: (editor) => editor.isActive("bulletList"),
|
|
63
|
+
matchesNode: named("bulletList"),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "orderedList",
|
|
67
|
+
label: "Numbered list",
|
|
68
|
+
description: "A list with numbers",
|
|
69
|
+
icon: ListOrdered,
|
|
70
|
+
keywords: ["numbered", "ordered", "steps"],
|
|
71
|
+
shortcut: "1. ",
|
|
72
|
+
apply: (chain) => chain.clearNodes().toggleOrderedList(),
|
|
73
|
+
isActive: (editor) => editor.isActive("orderedList"),
|
|
74
|
+
matchesNode: named("orderedList"),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: "taskList",
|
|
78
|
+
label: "To-do list",
|
|
79
|
+
description: "Tick things off",
|
|
80
|
+
icon: ListTodo,
|
|
81
|
+
keywords: ["todo", "task", "checkbox", "tick", "checklist"],
|
|
82
|
+
shortcut: "[] ",
|
|
83
|
+
apply: (chain) => chain.clearNodes().toggleTaskList(),
|
|
84
|
+
isActive: (editor) => editor.isActive("taskList"),
|
|
85
|
+
matchesNode: named("taskList"),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "blockquote",
|
|
89
|
+
label: "Quote",
|
|
90
|
+
description: "Set a passage apart",
|
|
91
|
+
icon: Quote,
|
|
92
|
+
keywords: ["quote", "blockquote", "citation"],
|
|
93
|
+
shortcut: "> ",
|
|
94
|
+
apply: (chain) => chain.clearNodes().setBlockquote(),
|
|
95
|
+
isActive: (editor) => editor.isActive("blockquote"),
|
|
96
|
+
matchesNode: named("blockquote"),
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: "codeBlock",
|
|
100
|
+
label: "Code",
|
|
101
|
+
description: "Monospaced block",
|
|
102
|
+
icon: Code2,
|
|
103
|
+
keywords: ["code", "snippet", "monospace", "pre"],
|
|
104
|
+
shortcut: "``` ",
|
|
105
|
+
apply: (chain) => chain.clearNodes().setCodeBlock(),
|
|
106
|
+
isActive: (editor) => editor.isActive("codeBlock"),
|
|
107
|
+
matchesNode: named("codeBlock"),
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
/** The block type the selection currently sits in, for "Turn into" state. */
|
|
111
|
+
export function activeBlockType(editor) {
|
|
112
|
+
return BLOCK_TYPES.find((type) => type.id !== "paragraph" && type.isActive(editor)) ?? PARAGRAPH;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.js","sourceRoot":"","sources":["../../src/editor/blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Editor } from "@tiptap/react";
|
|
2
|
+
/**
|
|
3
|
+
* The formatting controls, shown only over a text selection — the Notion model.
|
|
4
|
+
* There is no standing toolbar: an empty editor is just a page, and the controls
|
|
5
|
+
* appear when there is something to apply them to. Block changes live under
|
|
6
|
+
* "Turn into", the same list the `/` menu and the block grip use.
|
|
7
|
+
*/
|
|
8
|
+
export declare function BubbleToolbar({ editor }: {
|
|
9
|
+
editor: Editor;
|
|
10
|
+
}): import("react").JSX.Element | null;
|
|
11
|
+
//# sourceMappingURL=bubble-toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bubble-toolbar.d.ts","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAyC5D;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,sCAgE3D"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { TextSelection } from "@tiptap/pm/state";
|
|
4
|
+
import { useEditorState } from "@tiptap/react";
|
|
5
|
+
import { BubbleMenu } from "@tiptap/react/menus";
|
|
6
|
+
import { Bold, Check, ChevronDown, Code, Italic, Link as LinkIcon, Strikethrough } from "lucide-react";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
import { BLOCK_TYPES, activeBlockType } from "./blocks.js";
|
|
9
|
+
import { ghostButtonClass, IconButton, Menu, MenuContent, MenuItem, MenuLabel, MenuTrigger, PopoverContent, PopoverRoot, PopoverTrigger, primaryButtonClass, TextInput, VerticalSeparator, } from "./ui.js";
|
|
10
|
+
/**
|
|
11
|
+
* Everything the BubbleMenu wrapper is handed must be referentially stable. It
|
|
12
|
+
* re-registers its ProseMirror plugin whenever these props change identity, and
|
|
13
|
+
* re-registering reconfigures the editor's plugin set — which destroys and
|
|
14
|
+
* recreates *every* plugin view, including the suggestion popups, mid-session.
|
|
15
|
+
* An inline object here silently killed the `/` menu on its first re-render.
|
|
16
|
+
*/
|
|
17
|
+
const BUBBLE_OPTIONS = { placement: "top", offset: 8 };
|
|
18
|
+
/** Only over a real text selection: not an empty caret, not a node selection (a
|
|
19
|
+
* dragged block), and not inside a code block, where inline marks are noise. */
|
|
20
|
+
const shouldShowBubble = ({ editor: current, state: editorState }) => {
|
|
21
|
+
const { selection } = editorState;
|
|
22
|
+
if (!current.isEditable || selection.empty)
|
|
23
|
+
return false;
|
|
24
|
+
if (!(selection instanceof TextSelection))
|
|
25
|
+
return false;
|
|
26
|
+
if (current.isActive("codeBlock"))
|
|
27
|
+
return false;
|
|
28
|
+
return editorState.doc.textBetween(selection.from, selection.to).trim().length > 0;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The formatting controls, shown only over a text selection — the Notion model.
|
|
32
|
+
* There is no standing toolbar: an empty editor is just a page, and the controls
|
|
33
|
+
* appear when there is something to apply them to. Block changes live under
|
|
34
|
+
* "Turn into", the same list the `/` menu and the block grip use.
|
|
35
|
+
*/
|
|
36
|
+
export function BubbleToolbar({ editor }) {
|
|
37
|
+
const state = useEditorState({
|
|
38
|
+
editor,
|
|
39
|
+
selector: ({ editor: current }) => ({
|
|
40
|
+
bold: current.isActive("bold"),
|
|
41
|
+
italic: current.isActive("italic"),
|
|
42
|
+
strike: current.isActive("strike"),
|
|
43
|
+
code: current.isActive("code"),
|
|
44
|
+
link: current.isActive("link"),
|
|
45
|
+
linkHref: current.getAttributes("link").href ?? "",
|
|
46
|
+
block: activeBlockType(current),
|
|
47
|
+
}),
|
|
48
|
+
});
|
|
49
|
+
if (!state)
|
|
50
|
+
return null;
|
|
51
|
+
const chain = () => editor.chain().focus();
|
|
52
|
+
const BlockIcon = state.block.icon;
|
|
53
|
+
return (_jsxs(BubbleMenu, { editor: editor, pluginKey: "houseFormattingBubble", updateDelay: 120, options: BUBBLE_OPTIONS, shouldShow: shouldShowBubble, className: "house-bubble-menu flex items-center gap-0.5 rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md", children: [_jsxs(Menu, { children: [_jsx(MenuTrigger, { asChild: true, children: _jsxs("button", { type: "button", className: `${ghostButtonClass} h-8 px-2 text-xs`, children: [_jsx(BlockIcon, { className: "size-4", "aria-hidden": true }), state.block.label, _jsx(ChevronDown, { className: "size-3.5 opacity-60", "aria-hidden": true })] }) }), _jsxs(MenuContent, { className: "w-52", children: [_jsx(MenuLabel, { children: "Turn into" }), BLOCK_TYPES.map((type) => (_jsxs(MenuItem, { onSelect: () => void type.apply(chain()).run(), children: [_jsx(type.icon, { className: "size-4", "aria-hidden": true }), _jsx("span", { className: "flex-1", children: type.label }), type.id === state.block.id ? _jsx(Check, { className: "size-4 text-primary", "aria-hidden": true }) : null] }, type.id)))] })] }), _jsx(VerticalSeparator, {}), _jsx(MarkToggle, { label: "Bold", pressed: state.bold, onToggle: () => chain().toggleBold().run(), children: _jsx(Bold, { className: "size-4" }) }), _jsx(MarkToggle, { label: "Italic", pressed: state.italic, onToggle: () => chain().toggleItalic().run(), children: _jsx(Italic, { className: "size-4" }) }), _jsx(MarkToggle, { label: "Strikethrough", pressed: state.strike, onToggle: () => chain().toggleStrike().run(), children: _jsx(Strikethrough, { className: "size-4" }) }), _jsx(MarkToggle, { label: "Inline code", pressed: state.code, onToggle: () => chain().toggleCode().run(), children: _jsx(Code, { className: "size-4" }) }), _jsx(LinkControl, { editor: editor, active: state.link, href: state.linkHref })] }));
|
|
54
|
+
}
|
|
55
|
+
function MarkToggle({ label, pressed, onToggle, children, }) {
|
|
56
|
+
return (_jsx(IconButton, { "aria-label": label, title: label, pressed: pressed, onClick: onToggle, children: children }));
|
|
57
|
+
}
|
|
58
|
+
/** Set, change or clear the link on the current selection. */
|
|
59
|
+
function LinkControl({ editor, active, href }) {
|
|
60
|
+
const [open, setOpen] = useState(false);
|
|
61
|
+
const [draft, setDraft] = useState("");
|
|
62
|
+
const apply = () => {
|
|
63
|
+
const url = draft.trim();
|
|
64
|
+
const valid = /^https?:\/\//i.test(url) || (url.startsWith("/") && !url.startsWith("//"));
|
|
65
|
+
if (url && valid) {
|
|
66
|
+
editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
|
|
67
|
+
}
|
|
68
|
+
else if (!url) {
|
|
69
|
+
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
70
|
+
}
|
|
71
|
+
setOpen(false);
|
|
72
|
+
};
|
|
73
|
+
return (_jsxs(PopoverRoot, { open: open, onOpenChange: (next) => {
|
|
74
|
+
setOpen(next);
|
|
75
|
+
if (next)
|
|
76
|
+
setDraft(href);
|
|
77
|
+
}, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(IconButton, { "aria-label": "Link", title: "Link", pressed: active, children: _jsx(LinkIcon, { className: "size-4" }) }) }), _jsxs(PopoverContent, { className: "w-80 space-y-2", children: [_jsx("p", { className: "text-sm font-medium", children: "Link" }), _jsx(TextInput, { value: draft, onChange: (event) => setDraft(event.target.value), placeholder: "https://\u2026", "aria-label": "Link address", onKeyDown: (event) => {
|
|
78
|
+
if (event.key === "Enter") {
|
|
79
|
+
event.preventDefault();
|
|
80
|
+
apply();
|
|
81
|
+
}
|
|
82
|
+
} }), _jsxs("div", { className: "flex justify-end gap-2", children: [active ? (_jsx("button", { type: "button", className: `${ghostButtonClass} h-8 px-3`, onClick: () => {
|
|
83
|
+
editor.chain().focus().extendMarkRange("link").unsetLink().run();
|
|
84
|
+
setOpen(false);
|
|
85
|
+
}, children: "Remove" })) : null, _jsx("button", { type: "button", className: primaryButtonClass, onClick: apply, children: "Apply" })] })] })] }));
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=bubble-toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bubble-toolbar.js","sourceRoot":"","sources":["../../src/editor/bubble-toolbar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-index.d.ts","sourceRoot":"","sources":["../../src/editor/content-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-index.js","sourceRoot":"","sources":["../../src/editor/content-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only display for what `RichTextEditor` writes — the Markdown dialect the
|
|
3
|
+
* editor produces (headings, lists incl. task lists, quotes, code fences,
|
|
4
|
+
* bold/italic/strike/inline code, links, `@`-references, `#hashtags`), with a
|
|
5
|
+
* bare newline shown as a line break so legacy plain-text values in the same
|
|
6
|
+
* columns read exactly as they always did.
|
|
7
|
+
*
|
|
8
|
+
* Separate from a guide renderer deliberately: a help centre wants guide-scale
|
|
9
|
+
* headings and link rewriting; a note wants task lists, fences and line breaks.
|
|
10
|
+
* Folding both dialects and both type scales into one would serve neither well.
|
|
11
|
+
*
|
|
12
|
+
* This is a trust boundary: whatever is stored in a text column is drawn here,
|
|
13
|
+
* often in front of a *different* person. Everything comes out as React
|
|
14
|
+
* elements with checked hrefs — never as markup.
|
|
15
|
+
*
|
|
16
|
+
* Server-safe: no hooks, so views can render bodies without a client boundary.
|
|
17
|
+
* Styled by `.house-prose` in `@connextar/house/house.css`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function RichTextContent({ content, className }: {
|
|
20
|
+
content: string;
|
|
21
|
+
className?: string;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/** Only hrefs safe to hand a browser; anything else renders as plain text. */
|
|
24
|
+
export declare function safeHref(href: string): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* A plain-text preview of a Markdown body — for list cards and search rows.
|
|
27
|
+
* Strips block and inline syntax rather than rendering it.
|
|
28
|
+
*/
|
|
29
|
+
export declare function richTextPreview(content: string, max?: number): string;
|
|
30
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/editor/content.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAE9F;AAiBD,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBpD;AAsPD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAclE"}
|