@pilotiq/tiptap 0.1.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/Block.d.ts +47 -0
- package/dist/Block.d.ts.map +1 -0
- package/dist/Block.js +56 -0
- package/dist/Block.js.map +1 -0
- package/dist/MentionProvider.d.ts +97 -0
- package/dist/MentionProvider.d.ts.map +1 -0
- package/dist/MentionProvider.js +104 -0
- package/dist/MentionProvider.js.map +1 -0
- package/dist/RichTextField.d.ts +286 -0
- package/dist/RichTextField.d.ts.map +1 -0
- package/dist/RichTextField.js +369 -0
- package/dist/RichTextField.js.map +1 -0
- package/dist/extensions/BlockNodeExtension.d.ts +41 -0
- package/dist/extensions/BlockNodeExtension.d.ts.map +1 -0
- package/dist/extensions/BlockNodeExtension.js +103 -0
- package/dist/extensions/BlockNodeExtension.js.map +1 -0
- package/dist/extensions/DragHandleExtension.d.ts +19 -0
- package/dist/extensions/DragHandleExtension.d.ts.map +1 -0
- package/dist/extensions/DragHandleExtension.js +166 -0
- package/dist/extensions/DragHandleExtension.js.map +1 -0
- package/dist/extensions/GridExtension.d.ts +49 -0
- package/dist/extensions/GridExtension.d.ts.map +1 -0
- package/dist/extensions/GridExtension.js +105 -0
- package/dist/extensions/GridExtension.js.map +1 -0
- package/dist/extensions/MentionExtension.d.ts +71 -0
- package/dist/extensions/MentionExtension.d.ts.map +1 -0
- package/dist/extensions/MentionExtension.js +165 -0
- package/dist/extensions/MentionExtension.js.map +1 -0
- package/dist/extensions/MergeTagExtension.d.ts +24 -0
- package/dist/extensions/MergeTagExtension.d.ts.map +1 -0
- package/dist/extensions/MergeTagExtension.js +57 -0
- package/dist/extensions/MergeTagExtension.js.map +1 -0
- package/dist/extensions/SlashCommandExtension.d.ts +71 -0
- package/dist/extensions/SlashCommandExtension.d.ts.map +1 -0
- package/dist/extensions/SlashCommandExtension.js +244 -0
- package/dist/extensions/SlashCommandExtension.js.map +1 -0
- package/dist/extensions/TextSizeMarks.d.ts +33 -0
- package/dist/extensions/TextSizeMarks.d.ts.map +1 -0
- package/dist/extensions/TextSizeMarks.js +47 -0
- package/dist/extensions/TextSizeMarks.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +18 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +25 -0
- package/dist/plugin.js.map +1 -0
- package/dist/react/BlockNodeView.d.ts +19 -0
- package/dist/react/BlockNodeView.d.ts.map +1 -0
- package/dist/react/BlockNodeView.js +60 -0
- package/dist/react/BlockNodeView.js.map +1 -0
- package/dist/react/BlockSidePanel.d.ts +105 -0
- package/dist/react/BlockSidePanel.d.ts.map +1 -0
- package/dist/react/BlockSidePanel.js +339 -0
- package/dist/react/BlockSidePanel.js.map +1 -0
- package/dist/react/FloatingToolbar.d.ts +13 -0
- package/dist/react/FloatingToolbar.d.ts.map +1 -0
- package/dist/react/FloatingToolbar.js +113 -0
- package/dist/react/FloatingToolbar.js.map +1 -0
- package/dist/react/MentionMenu.d.ts +26 -0
- package/dist/react/MentionMenu.d.ts.map +1 -0
- package/dist/react/MentionMenu.js +64 -0
- package/dist/react/MentionMenu.js.map +1 -0
- package/dist/react/Palette.d.ts +26 -0
- package/dist/react/Palette.d.ts.map +1 -0
- package/dist/react/Palette.js +21 -0
- package/dist/react/Palette.js.map +1 -0
- package/dist/react/SlashMenu.d.ts +24 -0
- package/dist/react/SlashMenu.d.ts.map +1 -0
- package/dist/react/SlashMenu.js +74 -0
- package/dist/react/SlashMenu.js.map +1 -0
- package/dist/react/TableFloatingToolbar.d.ts +7 -0
- package/dist/react/TableFloatingToolbar.d.ts.map +1 -0
- package/dist/react/TableFloatingToolbar.js +108 -0
- package/dist/react/TableFloatingToolbar.js.map +1 -0
- package/dist/react/TiptapEditor.d.ts +20 -0
- package/dist/react/TiptapEditor.d.ts.map +1 -0
- package/dist/react/TiptapEditor.js +398 -0
- package/dist/react/TiptapEditor.js.map +1 -0
- package/dist/react/Toolbar.d.ts +45 -0
- package/dist/react/Toolbar.d.ts.map +1 -0
- package/dist/react/Toolbar.js +204 -0
- package/dist/react/Toolbar.js.map +1 -0
- package/dist/react/toolbarButtons.d.ts +36 -0
- package/dist/react/toolbarButtons.d.ts.map +1 -0
- package/dist/react/toolbarButtons.js +300 -0
- package/dist/react/toolbarButtons.js.map +1 -0
- package/dist/register.d.ts +20 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +27 -0
- package/dist/register.js.map +1 -0
- package/dist/render.d.ts +89 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +439 -0
- package/dist/render.js.map +1 -0
- package/package.json +92 -0
- package/src/Block.ts +75 -0
- package/src/MentionProvider.ts +153 -0
- package/src/RichTextField.test.ts +447 -0
- package/src/RichTextField.ts +508 -0
- package/src/extensions/BlockNodeExtension.ts +134 -0
- package/src/extensions/DragHandleExtension.ts +184 -0
- package/src/extensions/GridExtension.test.ts +31 -0
- package/src/extensions/GridExtension.ts +138 -0
- package/src/extensions/MentionExtension.ts +248 -0
- package/src/extensions/MergeTagExtension.ts +75 -0
- package/src/extensions/SlashCommandExtension.test.ts +147 -0
- package/src/extensions/SlashCommandExtension.ts +332 -0
- package/src/extensions/TextSizeMarks.ts +73 -0
- package/src/index.ts +28 -0
- package/src/plugin.test.ts +19 -0
- package/src/plugin.ts +26 -0
- package/src/react/BlockNodeView.tsx +99 -0
- package/src/react/BlockSidePanel.test.ts +412 -0
- package/src/react/BlockSidePanel.tsx +451 -0
- package/src/react/FloatingToolbar.tsx +304 -0
- package/src/react/MentionMenu.tsx +120 -0
- package/src/react/Palette.tsx +86 -0
- package/src/react/SlashMenu.tsx +129 -0
- package/src/react/TableFloatingToolbar.tsx +154 -0
- package/src/react/TiptapEditor.tsx +535 -0
- package/src/react/Toolbar.tsx +438 -0
- package/src/react/toolbarButtons.tsx +579 -0
- package/src/register.test.ts +14 -0
- package/src/register.ts +27 -0
- package/src/render.test.ts +745 -0
- package/src/render.ts +480 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { ColorSwatch } from '../RichTextField.js';
|
|
3
|
+
interface PaletteProps {
|
|
4
|
+
/** Trigger button — usually the toolbar's `textColor` / `highlight` button. */
|
|
5
|
+
trigger: ReactNode;
|
|
6
|
+
swatches: ColorSwatch[];
|
|
7
|
+
/** Whether to render a free-form color picker below the swatches. */
|
|
8
|
+
custom: boolean;
|
|
9
|
+
/** Currently active color, when known. Used to show the highlight ring. */
|
|
10
|
+
activeColor?: string | undefined;
|
|
11
|
+
/** Pick a swatch (or the custom-picker value). */
|
|
12
|
+
onPick: (value: string) => void;
|
|
13
|
+
/** Clear the color (removes the mark). */
|
|
14
|
+
onClear: () => void;
|
|
15
|
+
clearLabel?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Swatch popover anchored to a toolbar button. Drives `textColor` and
|
|
19
|
+
* `highlight` — both share the same UI shape, only the swatches and the
|
|
20
|
+
* `onPick`/`onClear` wiring differ.
|
|
21
|
+
*
|
|
22
|
+
* Mounts open / closed itself; consumers don't manage the open state.
|
|
23
|
+
*/
|
|
24
|
+
export declare function Palette({ trigger, swatches, custom, activeColor, onPick, onClear, clearLabel, }: PaletteProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=Palette.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Palette.d.ts","sourceRoot":"","sources":["../../src/react/Palette.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEtD,UAAU,YAAY;IACpB,+EAA+E;IAC/E,OAAO,EAAS,SAAS,CAAA;IACzB,QAAQ,EAAQ,WAAW,EAAE,CAAA;IAC7B,qEAAqE;IACrE,MAAM,EAAU,OAAO,CAAA;IACvB,2EAA2E;IAC3E,WAAW,CAAC,EAAI,MAAM,GAAG,SAAS,CAAA;IAClC,kDAAkD;IAClD,MAAM,EAAU,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,0CAA0C;IAC1C,OAAO,EAAS,MAAM,IAAI,CAAA;IAC1B,UAAU,CAAC,EAAK,MAAM,CAAA;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAuB,GACjF,EAAE,YAAY,2CAyDd"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Popover } from '@base-ui/react/popover';
|
|
4
|
+
/**
|
|
5
|
+
* Swatch popover anchored to a toolbar button. Drives `textColor` and
|
|
6
|
+
* `highlight` — both share the same UI shape, only the swatches and the
|
|
7
|
+
* `onPick`/`onClear` wiring differ.
|
|
8
|
+
*
|
|
9
|
+
* Mounts open / closed itself; consumers don't manage the open state.
|
|
10
|
+
*/
|
|
11
|
+
export function Palette({ trigger, swatches, custom, activeColor, onPick, onClear, clearLabel = 'No color', }) {
|
|
12
|
+
const [open, setOpen] = useState(false);
|
|
13
|
+
const close = () => setOpen(false);
|
|
14
|
+
const pick = (value) => { onPick(value); close(); };
|
|
15
|
+
const clear = () => { onClear(); close(); };
|
|
16
|
+
return (_jsxs(Popover.Root, { open: open, onOpenChange: setOpen, children: [_jsx(Popover.Trigger, { render: trigger }), _jsx(Popover.Portal, { children: _jsx(Popover.Positioner, { side: "bottom", align: "start", sideOffset: 6, className: "isolate z-50", children: _jsxs(Popover.Popup, { className: "rounded-md border bg-popover p-2 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", children: [_jsx("div", { className: "grid grid-cols-5 gap-1", children: swatches.map((s) => {
|
|
17
|
+
const isActive = activeColor && activeColor.toLowerCase() === s.value.toLowerCase();
|
|
18
|
+
return (_jsx("button", { type: "button", title: s.label, "aria-label": s.label, "aria-pressed": Boolean(isActive), onClick: () => pick(s.value), className: `h-6 w-6 rounded border transition-transform hover:scale-110 ${isActive ? 'ring-2 ring-ring ring-offset-1' : 'border-border/60'}`, style: { background: s.value } }, s.value));
|
|
19
|
+
}) }), custom && (_jsxs("label", { className: "mt-2 flex items-center justify-between gap-2 text-xs text-muted-foreground", children: [_jsx("span", { children: "Custom" }), _jsx("input", { type: "color", defaultValue: activeColor ?? '#000000', onChange: (e) => onPick(e.target.value), className: "h-6 w-12 cursor-pointer rounded border-0 bg-transparent p-0" })] })), _jsx("button", { type: "button", onClick: clear, className: "mt-2 w-full rounded px-2 py-1 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground", children: clearLabel })] }) }) })] }));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=Palette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Palette.js","sourceRoot":"","sources":["../../src/react/Palette.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAkBhD;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,UAAU,GACnE;IACb,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEvC,MAAM,KAAK,GAAG,GAAS,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACxC,MAAM,IAAI,GAAI,CAAC,KAAa,EAAQ,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAA;IACjE,MAAM,KAAK,GAAG,GAAS,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAA;IAEhD,OAAO,CACL,MAAC,OAAO,CAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aAC7C,KAAC,OAAO,CAAC,OAAO,IAAC,MAAM,EAAE,OAA6B,GAAI,EAC1D,KAAC,OAAO,CAAC,MAAM,cACb,KAAC,OAAO,CAAC,UAAU,IAAC,IAAI,EAAC,QAAQ,EAAC,KAAK,EAAC,OAAO,EAAC,UAAU,EAAE,CAAC,EAAE,SAAS,EAAC,cAAc,YACrF,MAAC,OAAO,CAAC,KAAK,IACZ,SAAS,EAAC,+PAA+P,aAEzQ,cAAK,SAAS,EAAC,wBAAwB,YACpC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;oCAClB,MAAM,QAAQ,GAAG,WAAW,IAAI,WAAW,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAA;oCACnF,OAAO,CACL,iBAEE,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,CAAC,CAAC,KAAK,gBACF,CAAC,CAAC,KAAK,kBACL,OAAO,CAAC,QAAQ,CAAC,EAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAC5B,SAAS,EAAE,+DACT,QAAQ,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,kBAChD,EAAE,EACF,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,IATzB,CAAC,CAAC,KAAK,CAUZ,CACH,CAAA;gCACH,CAAC,CAAC,GACE,EACL,MAAM,IAAI,CACT,iBAAO,SAAS,EAAC,4EAA4E,aAC3F,oCAAmB,EACnB,gBACE,IAAI,EAAC,OAAO,EACZ,YAAY,EAAE,WAAW,IAAI,SAAS,EACtC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACvC,SAAS,EAAC,6DAA6D,GACvE,IACI,CACT,EACD,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,KAAK,EACd,SAAS,EAAC,0GAA0G,YAEnH,UAAU,GACJ,IACK,GACG,GACN,IACJ,CAChB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SlashItem } from '../extensions/SlashCommandExtension.js';
|
|
2
|
+
/**
|
|
3
|
+
* Mutable ref the document-level keydown listener in `TiptapEditor` reads.
|
|
4
|
+
* `SlashMenu` installs its keyboard handler on mount, clears on unmount.
|
|
5
|
+
*/
|
|
6
|
+
export type SlashKeyHandlerRef = {
|
|
7
|
+
current: ((event: KeyboardEvent) => boolean) | null;
|
|
8
|
+
};
|
|
9
|
+
interface SlashMenuProps {
|
|
10
|
+
items: SlashItem[];
|
|
11
|
+
command: (item: SlashItem) => void;
|
|
12
|
+
keyHandlerRef: SlashKeyHandlerRef;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Floating list of slash items. Mounted by the Base UI Popover in
|
|
16
|
+
* TiptapEditor; the popover's anchor is a virtual element, so we don't need
|
|
17
|
+
* to position the menu ourselves.
|
|
18
|
+
*
|
|
19
|
+
* Keys: ArrowUp / ArrowDown to move, Enter to pick. Escape is handled in
|
|
20
|
+
* `SlashCommandExtension.onKeyDown` (closes the popup directly).
|
|
21
|
+
*/
|
|
22
|
+
export declare function SlashMenu({ items, command, keyHandlerRef }: SlashMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=SlashMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlashMenu.d.ts","sourceRoot":"","sources":["../../src/react/SlashMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AAEvE;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAAE,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,GAAG,IAAI,CAAA;CAAE,CAAA;AAExF,UAAU,cAAc;IACtB,KAAK,EAAU,SAAS,EAAE,CAAA;IAC1B,OAAO,EAAQ,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACxC,aAAa,EAAE,kBAAkB,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,cAAc,2CA8F1E"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Floating list of slash items. Mounted by the Base UI Popover in
|
|
5
|
+
* TiptapEditor; the popover's anchor is a virtual element, so we don't need
|
|
6
|
+
* to position the menu ourselves.
|
|
7
|
+
*
|
|
8
|
+
* Keys: ArrowUp / ArrowDown to move, Enter to pick. Escape is handled in
|
|
9
|
+
* `SlashCommandExtension.onKeyDown` (closes the popup directly).
|
|
10
|
+
*/
|
|
11
|
+
export function SlashMenu({ items, command, keyHandlerRef }) {
|
|
12
|
+
const [active, setActive] = useState(0);
|
|
13
|
+
const containerRef = useRef(null);
|
|
14
|
+
// Group items for visual organisation, then derive the flat render-order
|
|
15
|
+
// array. `items` is in plugin order (paragraph, h1, h2, h3, …) but we
|
|
16
|
+
// render grouped (Basic/Headings/Lists/Blocks). The active index must
|
|
17
|
+
// track render order — otherwise ArrowDown highlights item N visually
|
|
18
|
+
// but Enter inserts items[N] from the plugin-order array, which is a
|
|
19
|
+
// different item.
|
|
20
|
+
const grouped = useMemo(() => groupBy(items, (it) => it.group ?? 'Other'), [items]);
|
|
21
|
+
const renderOrder = useMemo(() => Array.from(grouped.values()).flat(), [grouped]);
|
|
22
|
+
// Reset selection when the filtered list changes.
|
|
23
|
+
useEffect(() => { setActive(0); }, [renderOrder]);
|
|
24
|
+
// Keep the active item in view inside the scroll container.
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const el = containerRef.current?.querySelector(`[data-index="${active}"]`);
|
|
27
|
+
el?.scrollIntoView({ block: 'nearest' });
|
|
28
|
+
}, [active]);
|
|
29
|
+
// Install the keyboard bridge for the document-level listener in
|
|
30
|
+
// TiptapEditor.
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
keyHandlerRef.current = (event) => {
|
|
33
|
+
const len = renderOrder.length;
|
|
34
|
+
if (event.key === 'ArrowDown') {
|
|
35
|
+
setActive((i) => (len === 0 ? 0 : (i + 1) % len));
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
if (event.key === 'ArrowUp') {
|
|
39
|
+
setActive((i) => (len === 0 ? 0 : (i - 1 + len) % len));
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (event.key === 'Enter') {
|
|
43
|
+
const item = renderOrder[active];
|
|
44
|
+
if (item)
|
|
45
|
+
command(item);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
50
|
+
return () => { keyHandlerRef.current = null; };
|
|
51
|
+
}, [renderOrder, active, command, keyHandlerRef]);
|
|
52
|
+
if (renderOrder.length === 0) {
|
|
53
|
+
return (_jsx("div", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matches" }));
|
|
54
|
+
}
|
|
55
|
+
let runningIndex = 0;
|
|
56
|
+
return (_jsx("div", { ref: containerRef, className: "max-h-72 w-64 overflow-y-auto p-1 text-sm", children: Array.from(grouped.entries()).map(([groupName, groupItems]) => (_jsxs("div", { children: [_jsx("div", { className: "px-2 pt-2 pb-1 text-[0.7rem] font-medium uppercase tracking-wide text-muted-foreground", children: groupName }), groupItems.map((item) => {
|
|
57
|
+
const idx = runningIndex++;
|
|
58
|
+
const isActive = idx === active;
|
|
59
|
+
return (_jsxs("button", { "data-index": idx, type: "button", onMouseDown: (e) => { e.preventDefault(); command(item); }, onMouseEnter: () => setActive(idx), className: `flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left ${isActive ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/60'}`, children: [item.icon && (_jsx("span", { className: "flex size-6 items-center justify-center rounded border bg-background text-xs", children: item.icon })), _jsx("span", { children: item.label })] }, item.key));
|
|
60
|
+
})] }, groupName))) }));
|
|
61
|
+
}
|
|
62
|
+
function groupBy(items, key) {
|
|
63
|
+
const out = new Map();
|
|
64
|
+
for (const item of items) {
|
|
65
|
+
const k = key(item);
|
|
66
|
+
const list = out.get(k);
|
|
67
|
+
if (list)
|
|
68
|
+
list.push(item);
|
|
69
|
+
else
|
|
70
|
+
out.set(k, [item]);
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=SlashMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlashMenu.js","sourceRoot":"","sources":["../../src/react/SlashMenu.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Editor } from '@tiptap/core';
|
|
2
|
+
interface TableFloatingToolbarProps {
|
|
3
|
+
editor: Editor;
|
|
4
|
+
}
|
|
5
|
+
export declare function TableFloatingToolbar({ editor }: TableFloatingToolbarProps): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=TableFloatingToolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableFloatingToolbar.d.ts","sourceRoot":"","sources":["../../src/react/TableFloatingToolbar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAK1C,UAAU,yBAAyB;IACjC,MAAM,EAAE,MAAM,CAAA;CACf;AAmBD,wBAAgB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAAE,yBAAyB,kDAwEzE"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Tooltip } from '@base-ui/react/tooltip';
|
|
4
|
+
import { TOOLBAR_BUTTONS } from './toolbarButtons.js';
|
|
5
|
+
/**
|
|
6
|
+
* Cell-management toolbar shown whenever the cursor is inside a table. Pinned
|
|
7
|
+
* to the top edge of the enclosing `<table>`, viewport-relative so it tracks
|
|
8
|
+
* scroll without forcing the editor wrapper to be `position: relative`.
|
|
9
|
+
*
|
|
10
|
+
* Buttons map directly onto the table-* ids registered in `toolbarButtons.tsx`,
|
|
11
|
+
* so the icons / disabled gates / commands stay in sync with the top-level
|
|
12
|
+
* toolbar's table buttons.
|
|
13
|
+
*/
|
|
14
|
+
const TABLE_BUTTON_GROUPS = [
|
|
15
|
+
['tableAddColumnBefore', 'tableAddColumnAfter', 'tableDeleteColumn'],
|
|
16
|
+
['tableAddRowBefore', 'tableAddRowAfter', 'tableDeleteRow'],
|
|
17
|
+
['tableMergeCells', 'tableSplitCell'],
|
|
18
|
+
['tableToggleHeaderRow', 'tableToggleHeaderCell'],
|
|
19
|
+
['tableDelete'],
|
|
20
|
+
];
|
|
21
|
+
export function TableFloatingToolbar({ editor }) {
|
|
22
|
+
const [pos, setPos] = useState(null);
|
|
23
|
+
// Force re-render when the selection moves so isActive / isDisabled flip.
|
|
24
|
+
const [, setTick] = useState(0);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
const update = () => {
|
|
27
|
+
if (!editor.isActive('table')) {
|
|
28
|
+
setPos(null);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const tableDom = findEnclosingTable(editor);
|
|
32
|
+
if (!tableDom) {
|
|
33
|
+
setPos(null);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const rect = tableDom.getBoundingClientRect();
|
|
37
|
+
// Lift the toolbar above the table — height of the strip + breathing room.
|
|
38
|
+
// Bump if the strip grows.
|
|
39
|
+
const top = rect.top - 44;
|
|
40
|
+
const left = rect.left + rect.width / 2;
|
|
41
|
+
setPos({ top, left });
|
|
42
|
+
};
|
|
43
|
+
const close = () => setPos(null);
|
|
44
|
+
update();
|
|
45
|
+
editor.on('selectionUpdate', update);
|
|
46
|
+
editor.on('transaction', update);
|
|
47
|
+
editor.on('blur', close);
|
|
48
|
+
window.addEventListener('scroll', update, true);
|
|
49
|
+
window.addEventListener('resize', update);
|
|
50
|
+
return () => {
|
|
51
|
+
editor.off('selectionUpdate', update);
|
|
52
|
+
editor.off('transaction', update);
|
|
53
|
+
editor.off('blur', close);
|
|
54
|
+
window.removeEventListener('scroll', update, true);
|
|
55
|
+
window.removeEventListener('resize', update);
|
|
56
|
+
};
|
|
57
|
+
}, [editor]);
|
|
58
|
+
// Refresh the disabled/active state predicates on every tx — the buttons
|
|
59
|
+
// read these inline against the live editor.
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!editor)
|
|
62
|
+
return;
|
|
63
|
+
const bump = () => setTick((t) => t + 1);
|
|
64
|
+
editor.on('selectionUpdate', bump);
|
|
65
|
+
editor.on('transaction', bump);
|
|
66
|
+
return () => {
|
|
67
|
+
editor.off('selectionUpdate', bump);
|
|
68
|
+
editor.off('transaction', bump);
|
|
69
|
+
};
|
|
70
|
+
}, [editor]);
|
|
71
|
+
if (!pos)
|
|
72
|
+
return null;
|
|
73
|
+
const groups = TABLE_BUTTON_GROUPS
|
|
74
|
+
.map((g) => g.map((id) => TOOLBAR_BUTTONS[id]).filter((b) => Boolean(b?.available)))
|
|
75
|
+
.filter((g) => g.length > 0);
|
|
76
|
+
return (_jsx(Tooltip.Provider, { delay: 400, children: _jsx("div", { className: "fixed z-40 flex items-center gap-0.5 rounded-md border bg-popover px-1 py-1 text-popover-foreground shadow-md", style: { top: pos.top, left: pos.left, transform: 'translateX(-50%)' },
|
|
77
|
+
// mousedown shouldn't steal focus — keeps the cell selection alive
|
|
78
|
+
// while the command runs.
|
|
79
|
+
onMouseDown: (e) => { e.preventDefault(); }, children: groups.map((group, gi) => (_jsxs("div", { className: "flex items-center gap-0.5", children: [gi > 0 && _jsx("span", { "aria-hidden": true, className: "mx-1 h-5 w-px shrink-0 bg-border" }), group.map((btn) => (_jsx(TableButton, { def: btn, editor: editor }, btn.id)))] }, gi))) }) }));
|
|
80
|
+
}
|
|
81
|
+
function TableButton({ def, editor }) {
|
|
82
|
+
const active = def.isActive?.(editor) ?? false;
|
|
83
|
+
const disabled = def.isDisabled?.(editor) ?? false;
|
|
84
|
+
return (_jsxs(Tooltip.Root, { children: [_jsx(Tooltip.Trigger, { render: (props) => (_jsx("button", { ...props, type: "button", disabled: disabled, onClick: () => def.command(editor), className: `inline-flex h-7 w-7 items-center justify-center rounded text-foreground transition-colors disabled:opacity-50 disabled:pointer-events-none ${active ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/60'}`, "aria-label": def.label, "aria-pressed": active, children: def.icon })) }), _jsx(Tooltip.Portal, { children: _jsx(Tooltip.Positioner, { side: "top", sideOffset: 6, className: "isolate z-50", children: _jsx(Tooltip.Popup, { className: "rounded-md bg-foreground px-2 py-1 text-xs text-background shadow-md data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", children: def.label }) }) })] }));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Walk up from the current selection to find the enclosing `<table>` DOM node.
|
|
88
|
+
* Returns `null` if the cursor isn't inside one. Uses `view.domAtPos` rather
|
|
89
|
+
* than walking the document tree — works even when the cell is inside a
|
|
90
|
+
* resize-NodeView wrapper.
|
|
91
|
+
*/
|
|
92
|
+
function findEnclosingTable(editor) {
|
|
93
|
+
const { from } = editor.state.selection;
|
|
94
|
+
let dom;
|
|
95
|
+
try {
|
|
96
|
+
dom = editor.view.domAtPos(from).node;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
while (dom && dom !== editor.view.dom) {
|
|
102
|
+
if (dom instanceof HTMLElement && dom.tagName === 'TABLE')
|
|
103
|
+
return dom;
|
|
104
|
+
dom = dom.parentNode;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=TableFloatingToolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableFloatingToolbar.js","sourceRoot":"","sources":["../../src/react/TableFloatingToolbar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FieldRendererProps } from '@pilotiq/pilotiq/react';
|
|
2
|
+
/**
|
|
3
|
+
* The pilotiq field renderer for `RichTextField`. Registered globally via
|
|
4
|
+
* `registerTiptap()`; pilotiq's `SchemaRenderer` looks it up by `fieldType:
|
|
5
|
+
* 'richtext'` and mounts it inline inside the form.
|
|
6
|
+
*
|
|
7
|
+
* Wiring (Phase A):
|
|
8
|
+
* - StarterKit + Underline + Subscript + Superscript + TextAlign
|
|
9
|
+
* - Placeholder
|
|
10
|
+
* - BlockNodeExtension (custom-block storage + React NodeView)
|
|
11
|
+
* - SlashCommandExtension (`/` opens menu, items derived from `blocks`)
|
|
12
|
+
* - DragHandleExtension (hover gutter handle)
|
|
13
|
+
*
|
|
14
|
+
* Form integration: a hidden `<input type="hidden" name={field}>` carries
|
|
15
|
+
* the editor's serialized output. Storage format depends on the field's
|
|
16
|
+
* `.storage('json' | 'html')` setting — JSON parses on the server,
|
|
17
|
+
* HTML is passed through.
|
|
18
|
+
*/
|
|
19
|
+
export declare function TiptapEditor(props: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=TiptapEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TiptapEditor.d.ts","sourceRoot":"","sources":["../../src/react/TiptapEditor.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAuBhE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,kBAAkB,2CAqBrD"}
|