alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
364 lines (360 loc) • 13.4 kB
JavaScript
import "../../chunks/chunk-U5RRZUYZ.js";
// src/input/richtext/RichTextToolbar.tsx
import { fromModule, HStack, Icon, px, Typo } from "alinea/ui";
import { DropdownMenu } from "alinea/ui/DropdownMenu";
import { IcAlignCenter } from "alinea/ui/icons/IcAlignCenter";
import { IcAlignJustify } from "alinea/ui/icons/IcAlignJustify";
import { IcAlignLeft } from "alinea/ui/icons/IcAlignLeft";
import { IcAlignRight } from "alinea/ui/icons/IcAlignRight";
import { IcRoundFormatBold } from "alinea/ui/icons/IcRoundFormatBold";
import { IcRoundFormatClear } from "alinea/ui/icons/IcRoundFormatClear";
import { IcRoundFormatItalic } from "alinea/ui/icons/IcRoundFormatItalic";
import { IcRoundFormatListBulleted } from "alinea/ui/icons/IcRoundFormatListBulleted";
import { IcRoundFormatListNumbered } from "alinea/ui/icons/IcRoundFormatListNumbered";
import { IcRoundHorizontalRule } from "alinea/ui/icons/IcRoundHorizontalRule";
import { IcRoundLink } from "alinea/ui/icons/IcRoundLink";
import { IcRoundQuote } from "alinea/ui/icons/IcRoundQuote";
import { IcRoundTextFields } from "alinea/ui/icons/IcRoundTextFields";
import { IcRoundUnfoldMore } from "alinea/ui/icons/IcRoundUnfoldMore";
import { FieldToolbar } from "alinea/dashboard/view/entry/FieldToolbar";
import { IconButton } from "alinea/dashboard/view/IconButton";
import { forwardRef } from "react";
import { attributesToReference, referenceToAttributes } from "./ReferenceLink.js";
// src/input/richtext/RichTextToolbar.module.scss
var RichTextToolbar_module_default = {
"root": "alinea-RichTextToolbar",
"root-separator": "alinea-RichTextToolbar-separator",
"rootSeparator": "alinea-RichTextToolbar-separator",
"root-dropdown": "alinea-RichTextToolbar-dropdown",
"rootDropdown": "alinea-RichTextToolbar-dropdown"
};
// src/input/richtext/RichTextToolbar.tsx
import { jsx, jsxs } from "react/jsx-runtime";
var styles = fromModule(RichTextToolbar_module_default);
var Styles = /* @__PURE__ */ ((Styles2) => {
Styles2["paragraph"] = "Normal text";
Styles2["h1"] = "Heading 1";
Styles2["h2"] = "Heading 2";
Styles2["h3"] = "Heading 3";
Styles2["h4"] = "Heading 4";
Styles2["h5"] = "Heading 5";
return Styles2;
})(Styles || {});
var RichTextToolbar = forwardRef(function RichTextToolbar2({ pickLink, editor, focusToggle }, ref) {
function exec() {
return editor.chain().focus(null, { scrollIntoView: false });
}
const selectedStyle = editor.isActive("heading", { level: 1 }) ? "h1" : editor.isActive("heading", { level: 2 }) ? "h2" : editor.isActive("heading", { level: 3 }) ? "h3" : editor.isActive("heading", { level: 4 }) ? "h4" : editor.isActive("heading", { level: 5 }) ? "h5" : "paragraph";
function handleLink() {
const attrs = editor.getAttributes("link");
const existing = attributesToReference(attrs);
const { view, state } = editor;
const { from, to } = view.state.selection;
const isSelection = from !== to;
return pickLink({
link: existing,
title: attrs.title,
blank: attrs.target === "_blank",
hasLink: Boolean(existing),
requireDescription: !isSelection
}).then((picked) => {
if (!picked || !picked.link) {
exec().unsetLink().run();
return;
}
const link = picked.link;
const attrs2 = {
title: picked.title,
...referenceToAttributes(link),
target: link.target ?? (picked.blank ? "_blank" : void 0)
};
if (existing) {
exec().extendMarkRange("link").setLink(attrs2).run();
} else if (isSelection) {
exec().setLink(attrs2).run();
} else {
exec().insertContent({
type: "text",
text: picked.title || link.title || link.url || "",
marks: [{ type: "link", attrs: attrs2 }]
}).run();
}
}).catch(console.error);
}
return /* @__PURE__ */ jsx(FieldToolbar.Slot, { children: /* @__PURE__ */ jsx(
"div",
{
ref,
tabIndex: -1,
className: styles.root(),
onFocus: (e) => focusToggle(e.currentTarget),
onBlur: (e) => focusToggle(e.relatedTarget),
children: /* @__PURE__ */ jsxs(HStack, { gap: 10, center: true, style: { height: "100%", padding: `${px(4)} 0` }, children: [
/* @__PURE__ */ jsxs(DropdownMenu.Root, { top: true, children: [
/* @__PURE__ */ jsx(
DropdownMenu.Trigger,
{
title: "Heading/paragraph",
className: styles.root.dropdown(),
children: /* @__PURE__ */ jsxs(HStack, { gap: 10, center: true, children: [
/* @__PURE__ */ jsx("span", { children: Styles[selectedStyle] }),
/* @__PURE__ */ jsx(Icon, { icon: IcRoundUnfoldMore })
] })
}
),
/* @__PURE__ */ jsxs(DropdownMenu.Items, { children: [
/* @__PURE__ */ jsx(DropdownMenu.Item, { onClick: () => exec().clearNodes().run(), children: /* @__PURE__ */ jsx(Typo.P, { children: "Normal text" }) }),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setHeading({ level: 1 }).run(),
children: /* @__PURE__ */ jsx(Typo.H1, { flat: true, children: "Heading 1" })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setHeading({ level: 2 }).run(),
children: /* @__PURE__ */ jsx(Typo.H2, { flat: true, children: "Heading 2" })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setHeading({ level: 3 }).run(),
children: /* @__PURE__ */ jsx(Typo.H3, { flat: true, children: "Heading 3" })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setHeading({ level: 4 }).run(),
children: /* @__PURE__ */ jsx(Typo.H4, { flat: true, children: "Heading 4" })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setHeading({ level: 5 }).run(),
children: /* @__PURE__ */ jsx(Typo.H5, { flat: true, children: "Heading 5" })
}
)
] })
] }),
/* @__PURE__ */ jsx("div", { className: styles.root.separator() }),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundFormatBold,
size: 18,
title: "Bold",
onClick: (e) => {
e.preventDefault();
exec().toggleBold().run();
},
active: editor.isActive("bold")
}
),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundFormatItalic,
size: 18,
title: "Italic",
onClick: (e) => {
e.preventDefault();
exec().toggleItalic().run();
},
active: editor.isActive("italic")
}
),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundTextFields,
size: 18,
title: "Small",
onClick: (e) => {
e.preventDefault();
exec().toggleSmall().run();
},
active: editor.isActive("small")
}
),
/* @__PURE__ */ jsxs(DropdownMenu.Root, { top: true, children: [
/* @__PURE__ */ jsx(
DropdownMenu.Trigger,
{
title: "Alignment",
className: styles.root.dropdown(),
children: /* @__PURE__ */ jsxs(HStack, { gap: 10, center: true, children: [
/* @__PURE__ */ jsx(
Icon,
{
icon: editor.isActive({ textAlign: "center" }) ? IcAlignCenter : editor.isActive({ textAlign: "right" }) ? IcAlignRight : editor.isActive({ textAlign: "justify" }) ? IcAlignJustify : IcAlignLeft,
size: 18
}
),
/* @__PURE__ */ jsx(Icon, { icon: IcRoundUnfoldMore })
] })
}
),
/* @__PURE__ */ jsxs(DropdownMenu.Items, { children: [
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setTextAlign("left").run(),
children: /* @__PURE__ */ jsxs(HStack, { gap: 8, center: true, children: [
/* @__PURE__ */ jsx(
Icon,
{
round: true,
icon: IcAlignLeft,
title: "Align left",
active: editor.isActive({ textAlign: "left" })
}
),
/* @__PURE__ */ jsx("span", { children: "Left" })
] })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setTextAlign("center").run(),
children: /* @__PURE__ */ jsxs(HStack, { gap: 8, center: true, children: [
/* @__PURE__ */ jsx(
Icon,
{
round: true,
icon: IcAlignCenter,
title: "Align center",
active: editor.isActive({ textAlign: "center" })
}
),
/* @__PURE__ */ jsx("span", { children: "Center" })
] })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setTextAlign("right").run(),
children: /* @__PURE__ */ jsxs(HStack, { gap: 8, center: true, children: [
/* @__PURE__ */ jsx(
Icon,
{
round: true,
icon: IcAlignRight,
title: "Align right",
active: editor.isActive({ textAlign: "right" })
}
),
/* @__PURE__ */ jsx("span", { children: "Right" })
] })
}
),
/* @__PURE__ */ jsx(
DropdownMenu.Item,
{
onClick: () => exec().setTextAlign("justify").run(),
children: /* @__PURE__ */ jsxs(HStack, { gap: 8, center: true, children: [
/* @__PURE__ */ jsx(
Icon,
{
round: true,
icon: IcAlignJustify,
title: "Align justify",
active: editor.isActive({ textAlign: "justify" })
}
),
/* @__PURE__ */ jsx("span", { children: "Justify" })
] })
}
)
] })
] }),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundFormatClear,
size: 18,
title: "Clear format",
onClick: (e) => {
e.preventDefault();
exec().unsetAllMarks().run();
exec().unsetTextAlign().run();
}
}
),
/* @__PURE__ */ jsx("div", { className: styles.root.separator() }),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundFormatListBulleted,
size: 18,
title: "Bullet list",
onClick: (e) => {
e.preventDefault();
exec().toggleBulletList().run();
},
active: editor.isActive("bulletList")
}
),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundFormatListNumbered,
size: 18,
title: "Ordered list",
onClick: (e) => {
e.preventDefault();
exec().toggleOrderedList().run();
},
active: editor.isActive("orderedList")
}
),
/* @__PURE__ */ jsx("div", { className: styles.root.separator() }),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundLink,
size: 18,
title: "Link",
onClick: handleLink,
active: editor.isActive("link")
}
),
/* @__PURE__ */ jsx("div", { className: styles.root.separator() }),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundQuote,
size: 18,
title: "Blockquote",
onClick: (e) => {
e.preventDefault();
exec().toggleBlockquote().run();
},
active: editor.isActive("blockquote")
}
),
/* @__PURE__ */ jsx(
IconButton,
{
icon: IcRoundHorizontalRule,
size: 18,
title: "Horizontal Rule",
onClick: (e) => {
e.preventDefault();
exec().setHorizontalRule().run();
}
}
)
] })
}
) });
});
export {
RichTextToolbar
};