NoteToolbar.tsx

4.4 KB · raw

1export type ToolbarExec = (cmd: string, val?: string) => void;23const BoldIcon = () => (4  <svg viewBox="0 0 14 14" aria-hidden="true">5    <path d="M4 2h3.75a2.5 2.5 0 0 1 0 5H4V2Zm0 5h4.25a2.5 2.5 0 0 1 0 5H4V7Z" />6  </svg>7);89const ItalicIcon = () => (10  <svg viewBox="0 0 14 14" aria-hidden="true">11    <path d="M6 2h5M3 12h5M8.5 2l-3 10" />12  </svg>13);1415const UnderlineIcon = () => (16  <svg viewBox="0 0 14 14" aria-hidden="true">17    <path d="M3.5 2v4.25a3.5 3.5 0 0 0 7 0V2M2.5 12h9" />18  </svg>19);2021const StrikeIcon = () => (22  <svg viewBox="0 0 14 14" aria-hidden="true">23    <path d="M10.5 3.25C9.75 2.4 8.65 2 7.2 2 5.35 2 4 2.8 4 4.2c0 1.2.95 1.75 2.55 2.15M3.5 10.5c.85 1 2.1 1.5 3.75 1.5 1.9 0 3.25-.8 3.25-2.2 0-1.15-.9-1.75-2.45-2.15M2 7h10" />24  </svg>25);2627const HeadingIcon = () => (28  <svg viewBox="0 0 14 14" aria-hidden="true">29    <path d="M2 2.5v9M8 2.5v9M2 7h6M10 9.25c.25-.6.7-.9 1.35-.9.8 0 1.3.45 1.3 1.1 0 .55-.35.95-1.2 1.55L10.2 12h2.65" />30  </svg>31);3233const QuoteIcon = () => (34  <svg viewBox="0 0 14 14" aria-hidden="true">35    <path d="M2.25 4.25h3v3h-2c0 1.4.55 2.45 1.65 3.15M8.25 4.25h3v3h-2c0 1.4.55 2.45 1.65 3.15" />36  </svg>37);3839const BulletIcon = () => (40  <svg viewBox="0 0 14 14" aria-hidden="true">41    <path d="M5 3h7M5 7h7M5 11h7" />42    <circle cx="2" cy="3" r=".75" />43    <circle cx="2" cy="7" r=".75" />44    <circle cx="2" cy="11" r=".75" />45  </svg>46);4748const NumberedIcon = () => (49  <svg viewBox="0 0 14 14" aria-hidden="true">50    <path d="M5 3h7M5 7h7M5 11h7M1.25 2.25h.8V4M1.2 6.15c.2-.35.5-.55.95-.55.55 0 .9.3.9.75 0 .4-.25.65-.8 1.05l-1 .7h1.9M1.2 10.15c.25-.3.55-.45.95-.45.55 0 .9.25.9.65 0 .35-.25.6-.7.65.5.05.8.3.8.7 0 .45-.4.75-1 .75-.45 0-.8-.15-1.05-.45" />51  </svg>52);5354const RuleIcon = () => (55  <svg viewBox="0 0 14 14" aria-hidden="true">56    <path d="M1.5 7h11" />57  </svg>58);5960function applyBold(exec: ToolbarExec) { exec("bold"); }61function applyItalic(exec: ToolbarExec) { exec("italic"); }62function applyUnderline(exec: ToolbarExec) { exec("underline"); }63function applyStrike(exec: ToolbarExec) { exec("strikeThrough"); }64function applyHeading(exec: ToolbarExec) {65  const val = document.queryCommandValue("formatBlock").toLowerCase();66  exec("formatBlock", val === "h2" ? "p" : "h2");67}68function applyQuote(exec: ToolbarExec) {69  const val = document.queryCommandValue("formatBlock").toLowerCase();70  exec("formatBlock", val === "blockquote" ? "p" : "blockquote");71}72function applyBullet(exec: ToolbarExec) { exec("insertUnorderedList"); }73function applyNumbered(exec: ToolbarExec) { exec("insertOrderedList"); }74function applyRule(exec: ToolbarExec) { exec("insertHorizontalRule"); }7576interface ToolbarProps {77  exec: ToolbarExec;78  class?: string;79}8081export function NoteToolbar(props: ToolbarProps) {82  return (83    <div class={props.class ?? "peach-note-toolbar-desktop-inline"}>84      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyBold(props.exec); }} title="Bold" aria-label="Bold"><BoldIcon /></button>85      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyItalic(props.exec); }} title="Italic" aria-label="Italic"><ItalicIcon /></button>86      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyUnderline(props.exec); }} title="Underline" aria-label="Underline"><UnderlineIcon /></button>87      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyStrike(props.exec); }} title="Strikethrough" aria-label="Strikethrough"><StrikeIcon /></button>88      <div class="peach-note-toolbar-divider" />89      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyHeading(props.exec); }} title="Heading" aria-label="Heading"><HeadingIcon /></button>90      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyQuote(props.exec); }} title="Quote" aria-label="Quote"><QuoteIcon /></button>91      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyBullet(props.exec); }} title="Bullet list" aria-label="Bullet list"><BulletIcon /></button>92      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyNumbered(props.exec); }} title="Numbered list" aria-label="Numbered list"><NumberedIcon /></button>93      <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyRule(props.exec); }} title="Divider" aria-label="Divider"><RuleIcon /></button>94    </div>95  );96}