NoteToolbar.tsx

4.4 KB · raw

1import { Show } from "solid-js";2import { isNativePlatform } from "../../shared/native";34export type ToolbarExec = (cmd: string, val?: string) => void;56function applyBold(exec: ToolbarExec) { exec("bold"); }7function applyItalic(exec: ToolbarExec) { exec("italic"); }8function applyUnderline(exec: ToolbarExec) { exec("underline"); }9function applyStrike(exec: ToolbarExec) { exec("strikeThrough"); }10function applyHeading(exec: ToolbarExec) {11  const val = document.queryCommandValue("formatBlock").toLowerCase();12  exec("formatBlock", val === "h2" ? "p" : "h2");13}14function applyQuote(exec: ToolbarExec) {15  const val = document.queryCommandValue("formatBlock").toLowerCase();16  exec("formatBlock", val === "blockquote" ? "p" : "blockquote");17}18function applyBullet(exec: ToolbarExec) { exec("insertUnorderedList"); }19function applyNumbered(exec: ToolbarExec) { exec("insertOrderedList"); }20function applyRule(exec: ToolbarExec) { exec("insertHorizontalRule"); }2122interface ToolbarProps {23  exec: ToolbarExec;24  keyboardVisible?: boolean;25  onDismissKeyboard?: () => void;26  class?: string;27}2829export function NoteToolbar(props: ToolbarProps) {30  return (31    <Show32      when={isNativePlatform()}33      fallback={34        // Desktop: toolbar rendered inline above the body, shown always35        <div class={props.class ?? "peach-note-toolbar-desktop-inline"}>36          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyBold(props.exec); }} title="Bold">B</button>37          <button class="peach-note-toolbar-btn peach-note-toolbar-btn--italic" onMouseDown={(e) => { e.preventDefault(); applyItalic(props.exec); }} title="Italic">I</button>38          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyUnderline(props.exec); }} title="Underline">U</button>39          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyStrike(props.exec); }} title="Strikethrough">S</button>40          <div class="peach-note-toolbar-divider" />41          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyHeading(props.exec); }} title="Heading">H</button>42          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyQuote(props.exec); }} title="Quote">"</button>43          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyBullet(props.exec); }} title="Bullet">•</button>44          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyNumbered(props.exec); }} title="Numbered">1.</button>45          <button class="peach-note-toolbar-btn" onMouseDown={(e) => { e.preventDefault(); applyRule(props.exec); }} title="Divider">—</button>46        </div>47      }48    >49      {/* Mobile: sits above keyboard when keyboard is visible */}50      <Show when={props.keyboardVisible}>51        <div class={props.class ?? "peach-note-toolbar-mobile"}>52          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyBold(props.exec); }}>B</button>53          <button class="peach-note-toolbar-btn peach-note-toolbar-btn--italic" onPointerDown={(e) => { e.preventDefault(); applyItalic(props.exec); }}>I</button>54          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyUnderline(props.exec); }}>U</button>55          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyStrike(props.exec); }}>S</button>56          <div class="peach-note-toolbar-divider" />57          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyHeading(props.exec); }}>H</button>58          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyQuote(props.exec); }}>"</button>59          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyBullet(props.exec); }}>•</button>60          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyNumbered(props.exec); }}>1.</button>61          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); applyRule(props.exec); }}>—</button>62          <div class="peach-note-toolbar-spacer" />63          <button class="peach-note-toolbar-btn" onPointerDown={(e) => { e.preventDefault(); props.onDismissKeyboard?.(); }}>⌨</button>64        </div>65      </Show>66    </Show>67  );68}