@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,286 @@
|
|
|
1
|
+
import { Field, type FieldMeta, type RenderContext } from '@pilotiq/pilotiq';
|
|
2
|
+
import { Block, type BlockMeta } from './Block.js';
|
|
3
|
+
import { MentionProvider, type MentionItem, type MentionProviderMeta, type MentionResolverContext } from './MentionProvider.js';
|
|
4
|
+
/**
|
|
5
|
+
* Identifier for a single toolbar action. The renderer maps each id to a
|
|
6
|
+
* Tiptap command + an icon. Unknown ids are rendered as nothing — keeps the
|
|
7
|
+
* surface forward-compatible: a config that targets a button shipped in a
|
|
8
|
+
* later version stays inert today instead of crashing.
|
|
9
|
+
*
|
|
10
|
+
* Buttons that aren't yet shipped (textColor, highlight, attachFiles, table
|
|
11
|
+
* variants, …) still appear in the union — registering them in user code is
|
|
12
|
+
* a no-op today and lights up automatically when a later phase wires them.
|
|
13
|
+
*/
|
|
14
|
+
export type ToolbarButtonId = 'bold' | 'italic' | 'underline' | 'strike' | 'subscript' | 'superscript' | 'code' | 'lead' | 'small' | 'paragraph' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'alignStart' | 'alignCenter' | 'alignEnd' | 'alignJustify' | 'blockquote' | 'codeBlock' | 'bulletList' | 'orderedList' | 'horizontalRule' | 'clearFormatting' | 'link' | 'undo' | 'redo' | 'textColor' | 'highlight' | 'attachFiles' | 'table' | 'tableAddColumnBefore' | 'tableAddColumnAfter' | 'tableDeleteColumn' | 'tableAddRowBefore' | 'tableAddRowAfter' | 'tableDeleteRow' | 'tableMergeCells' | 'tableSplitCell' | 'tableToggleHeaderRow' | 'tableToggleHeaderCell' | 'tableDelete' | 'details' | 'grid' | 'gridDelete';
|
|
15
|
+
export type ToolbarGroups = ToolbarButtonId[][];
|
|
16
|
+
/** Default top-level toolbar groups — mirrors the reference admin's layout. */
|
|
17
|
+
export declare const DEFAULT_TOOLBAR_GROUPS: ToolbarGroups;
|
|
18
|
+
export type RichTextStorage = 'json' | 'html';
|
|
19
|
+
/**
|
|
20
|
+
* One swatch in a text-color or highlight palette. `value` is what gets
|
|
21
|
+
* written into the editor (a CSS color); `dark` is an optional override
|
|
22
|
+
* shown when the editor's parent is in dark mode.
|
|
23
|
+
*/
|
|
24
|
+
export interface ColorSwatch {
|
|
25
|
+
value: string;
|
|
26
|
+
label: string;
|
|
27
|
+
dark?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Tailwind-flavored fallback palette. Used when the field doesn't override
|
|
31
|
+
* the colors via `.textColors([...])`. Mirrors the reference admin's
|
|
32
|
+
* "popular Tailwind hues" default.
|
|
33
|
+
*/
|
|
34
|
+
export declare const DEFAULT_TEXT_COLORS: ColorSwatch[];
|
|
35
|
+
export declare const DEFAULT_HIGHLIGHT_COLORS: ColorSwatch[];
|
|
36
|
+
export type RichTextAttachmentVisibility = 'public' | 'private';
|
|
37
|
+
export interface RichTextFieldMeta extends FieldMeta {
|
|
38
|
+
blocks: BlockMeta[];
|
|
39
|
+
slashCommand: boolean;
|
|
40
|
+
/** Always-on top-level toolbar groups. `null` = hidden. */
|
|
41
|
+
toolbarGroups: ToolbarGroups | null;
|
|
42
|
+
/** Selection-anchored quick-format toolbar. */
|
|
43
|
+
floatingToolbar: boolean;
|
|
44
|
+
storage: RichTextStorage;
|
|
45
|
+
/** Text-color palette shown when the `textColor` button opens. */
|
|
46
|
+
textColors: ColorSwatch[];
|
|
47
|
+
/** Whether to expose a free-form color picker below the swatches. */
|
|
48
|
+
customTextColors: boolean;
|
|
49
|
+
/** Highlight palette shown when the `highlight` button opens. */
|
|
50
|
+
highlightColors: ColorSwatch[];
|
|
51
|
+
/** Allow drag-resize of inserted images via a corner handle. */
|
|
52
|
+
resizableImages: boolean;
|
|
53
|
+
/** MIME-type allowlist for the `attachFiles` picker (e.g. `['image/*']`). */
|
|
54
|
+
fileAttachmentsAcceptedFileTypes?: string[];
|
|
55
|
+
/** Per-file size cap in bytes; the upload route also enforces this. */
|
|
56
|
+
fileAttachmentsMaxSize?: number;
|
|
57
|
+
/** Sub-directory hint forwarded to the upload adapter. */
|
|
58
|
+
fileAttachmentsDirectory?: string;
|
|
59
|
+
/** Adapter-defined visibility hint — `'public'` or `'private'`. */
|
|
60
|
+
fileAttachmentsVisibility?: RichTextAttachmentVisibility;
|
|
61
|
+
/** URL of the panel's `_uploads` route. Only stamped when both
|
|
62
|
+
* `RenderContext.uploadUrl` and `RenderContext.hasUploadAdapter` are
|
|
63
|
+
* set — so its presence is itself the "adapter is wired" signal that
|
|
64
|
+
* the slash-menu Image entry consults. */
|
|
65
|
+
uploadUrl?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Identifier list for `{{ tag }}` placeholders surfaced in the slash menu.
|
|
68
|
+
* Empty array = no merge tags.
|
|
69
|
+
*/
|
|
70
|
+
mergeTags: string[];
|
|
71
|
+
/**
|
|
72
|
+
* Mention providers — one entry per trigger character (`@`, `#`, …) with
|
|
73
|
+
* its static item list. Empty array = no mentions wired.
|
|
74
|
+
*/
|
|
75
|
+
mentions: MentionProviderMeta[];
|
|
76
|
+
/**
|
|
77
|
+
* Endpoint stamped by `tagRichTextMentionUrls` when this field has at
|
|
78
|
+
* least one async provider (`MentionProvider.itemsUsing(fn)`). The
|
|
79
|
+
* client POSTs `{ field, trigger, query }` per keystroke; the server
|
|
80
|
+
* runs the user resolver and returns `{ ok, items }`. Absent when
|
|
81
|
+
* every provider on this field is static.
|
|
82
|
+
*/
|
|
83
|
+
mentionsUrl?: string;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Field that renders a Tiptap-based rich-text editor with slash menu,
|
|
87
|
+
* draggable blocks, and a custom-block API.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* RichTextField.make('body')
|
|
92
|
+
* .label('Article body')
|
|
93
|
+
* .placeholder('Start writing…')
|
|
94
|
+
* .toolbarButtons([
|
|
95
|
+
* ['bold', 'italic', 'underline', 'strike', 'link'],
|
|
96
|
+
* ['h2', 'h3'],
|
|
97
|
+
* ['bulletList', 'orderedList'],
|
|
98
|
+
* ['undo', 'redo'],
|
|
99
|
+
* ])
|
|
100
|
+
* .blocks([
|
|
101
|
+
* Block.make('callout').label('Callout').icon('💡').schema([
|
|
102
|
+
* TextField.make('title'),
|
|
103
|
+
* TextareaField.make('content').required(),
|
|
104
|
+
* ]),
|
|
105
|
+
* ])
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export declare class RichTextField extends Field {
|
|
109
|
+
private _blocks;
|
|
110
|
+
private _slashCommand;
|
|
111
|
+
/** `undefined` = use default, `null` = hidden, array = explicit override. */
|
|
112
|
+
private _toolbarOverride;
|
|
113
|
+
private _enabled;
|
|
114
|
+
private _disabled;
|
|
115
|
+
private _floatingToolbar;
|
|
116
|
+
private _storage;
|
|
117
|
+
private _textColors;
|
|
118
|
+
private _customTextColors;
|
|
119
|
+
private _highlightColors;
|
|
120
|
+
private _resizableImages;
|
|
121
|
+
private _fileAttachmentsAcceptedFileTypes?;
|
|
122
|
+
private _fileAttachmentsMaxSize?;
|
|
123
|
+
private _fileAttachmentsDirectory?;
|
|
124
|
+
private _fileAttachmentsVisibility?;
|
|
125
|
+
private _mergeTags;
|
|
126
|
+
private _mentions;
|
|
127
|
+
private _mentionsUrl?;
|
|
128
|
+
private constructor();
|
|
129
|
+
static make(name: string): RichTextField;
|
|
130
|
+
/** Custom blocks available via the slash menu. */
|
|
131
|
+
blocks(blocks: Block[]): this;
|
|
132
|
+
/** Toggle the slash menu (`/`) on/off. Defaults to `true`. */
|
|
133
|
+
slashCommand(enabled: boolean): this;
|
|
134
|
+
/**
|
|
135
|
+
* Replace the top-level toolbar layout. Pass nested arrays — each inner
|
|
136
|
+
* array becomes a button group separated by a thin divider.
|
|
137
|
+
*
|
|
138
|
+
* Pass `null` (or call `toolbar(false)`) to hide the toolbar entirely.
|
|
139
|
+
*/
|
|
140
|
+
toolbarButtons(groups: ToolbarGroups | null): this;
|
|
141
|
+
/** Add buttons on top of whichever layout is active. */
|
|
142
|
+
enableToolbarButtons(buttons: ToolbarButtonId[]): this;
|
|
143
|
+
/** Remove buttons from whichever layout is active. */
|
|
144
|
+
disableToolbarButtons(buttons: ToolbarButtonId[]): this;
|
|
145
|
+
/**
|
|
146
|
+
* Toolbar visibility shortcut.
|
|
147
|
+
*
|
|
148
|
+
* - `true` (default) — show the top-level toolbar with the default groups
|
|
149
|
+
* unless `toolbarButtons([...])` was called.
|
|
150
|
+
* - `false` — hide the top-level toolbar.
|
|
151
|
+
*
|
|
152
|
+
* Selection-anchored floating toolbar is controlled separately via
|
|
153
|
+
* {@link floatingToolbar}.
|
|
154
|
+
*/
|
|
155
|
+
toolbar(enabled: boolean): this;
|
|
156
|
+
/** Toggle the selection-anchored quick-format toolbar. Defaults to `true`. */
|
|
157
|
+
floatingToolbar(enabled: boolean): this;
|
|
158
|
+
/**
|
|
159
|
+
* Storage format for the field's value.
|
|
160
|
+
*
|
|
161
|
+
* - `'json'` (default) — Tiptap JSON document, parsed via `JSON.parse`.
|
|
162
|
+
* - `'html'` — serialized HTML string, useful for display surfaces that
|
|
163
|
+
* can't render JSON (e.g. existing blog/CMS columns).
|
|
164
|
+
*/
|
|
165
|
+
storage(format: RichTextStorage): this;
|
|
166
|
+
/**
|
|
167
|
+
* Replace the text-color palette opened by the `textColor` toolbar button.
|
|
168
|
+
* Pass `null` to fall back to the default Tailwind-derived palette.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* RichTextField.make('body').textColors([
|
|
173
|
+
* { value: '#1e293b', label: 'Slate' },
|
|
174
|
+
* { value: '#dc2626', label: 'Red', dark: '#fca5a5' },
|
|
175
|
+
* ])
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
textColors(palette: ColorSwatch[] | null): this;
|
|
179
|
+
/** Show a free-form color picker below the swatches. */
|
|
180
|
+
customTextColors(enabled?: boolean): this;
|
|
181
|
+
/** Replace the highlight palette opened by the `highlight` toolbar button. */
|
|
182
|
+
highlightColors(palette: ColorSwatch[] | null): this;
|
|
183
|
+
/**
|
|
184
|
+
* Allow drag-resizing of inserted images via a corner handle. Off by
|
|
185
|
+
* default — when enabled, the editor mounts a NodeView that wraps the
|
|
186
|
+
* image in a resize-aware wrapper and writes `width` / `height` attrs
|
|
187
|
+
* back into the document.
|
|
188
|
+
*/
|
|
189
|
+
resizableImages(enabled?: boolean): this;
|
|
190
|
+
/**
|
|
191
|
+
* Restrict the `attachFiles` picker to specific MIME types — passed
|
|
192
|
+
* verbatim to the file input's `accept` attribute and re-checked
|
|
193
|
+
* server-side by the upload route.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* RichTextField.make('body').fileAttachmentsAcceptedFileTypes(['image/*'])
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
fileAttachmentsAcceptedFileTypes(types: string[]): this;
|
|
201
|
+
/** Per-file size cap in bytes for `attachFiles`. */
|
|
202
|
+
fileAttachmentsMaxSize(bytes: number): this;
|
|
203
|
+
/**
|
|
204
|
+
* Sub-directory hint forwarded to the upload adapter alongside the
|
|
205
|
+
* `attachFiles` payload. Adapters honor it differently (`localUpload`
|
|
206
|
+
* writes to `<root>/<directory>/...`, S3 prepends to the key, etc.).
|
|
207
|
+
*/
|
|
208
|
+
fileAttachmentsDirectory(d: string): this;
|
|
209
|
+
/** Adapter-defined visibility hint — `'public'` or `'private'`. */
|
|
210
|
+
fileAttachmentsVisibility(v: RichTextAttachmentVisibility): this;
|
|
211
|
+
/**
|
|
212
|
+
* Surface a `{{ tag }}` placeholder for each id in the slash menu under
|
|
213
|
+
* the "Merge tags" group. The placeholder stores as a `mergeTag` atom
|
|
214
|
+
* node and renders read-side via
|
|
215
|
+
* `renderRichTextToHtml(content, { mergeTags: { name: 'Sleman', … } })` —
|
|
216
|
+
* the substitution map replaces each id with the resolved value
|
|
217
|
+
* (HTML-escaped).
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```ts
|
|
221
|
+
* RichTextField.make('body').mergeTags(['firstName', 'company'])
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
mergeTags(tags: string[]): this;
|
|
225
|
+
/**
|
|
226
|
+
* Wire one or more mention providers. Each provider owns a trigger
|
|
227
|
+
* character (`@` / `#` / …) and a static item list. Typing the trigger
|
|
228
|
+
* opens a popover anchored to the cursor; picking an item inserts a
|
|
229
|
+
* `mention` atom node carrying `id`, `label`, and `trigger`.
|
|
230
|
+
*
|
|
231
|
+
* Read-side rendering uses the cached label by default; pass
|
|
232
|
+
* `renderRichTextToHtml(content, { resolveMention: (trigger, id) =>
|
|
233
|
+
* latestLabel })` to override at display time.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* RichTextField.make('body').mentions([
|
|
238
|
+
* MentionProvider.make('@').items([
|
|
239
|
+
* { id: 'sleman', label: 'Sleman' },
|
|
240
|
+
* { id: 'alex', label: 'Alex' },
|
|
241
|
+
* ]),
|
|
242
|
+
* ])
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
mentions(providers: MentionProvider[]): this;
|
|
246
|
+
getBlocks(): readonly Block[];
|
|
247
|
+
getMergeTags(): readonly string[];
|
|
248
|
+
getMentionProviders(): readonly MentionProvider[];
|
|
249
|
+
/**
|
|
250
|
+
* `true` iff at least one provider was configured with `itemsUsing(fn)`.
|
|
251
|
+
* Pilotiq's `tagRichTextMentionUrls` walker uses this to gate URL
|
|
252
|
+
* stamping — fields with only static providers stay URL-less.
|
|
253
|
+
*/
|
|
254
|
+
hasAsyncMentions(): boolean;
|
|
255
|
+
/**
|
|
256
|
+
* Look up a provider by trigger char and run its resolver with `query`
|
|
257
|
+
* and `ctx`. Returns the matched items, or `null` when no provider
|
|
258
|
+
* carries that trigger. Static providers run too (using their cached
|
|
259
|
+
* list) — keeps the dispatcher uniform; the client just won't call
|
|
260
|
+
* the endpoint for static providers.
|
|
261
|
+
*/
|
|
262
|
+
resolveMention(trigger: string, query: string, ctx: MentionResolverContext): Promise<MentionItem[] | null>;
|
|
263
|
+
/**
|
|
264
|
+
* Render-time setter — pilotiq stamps the URL after schema resolution
|
|
265
|
+
* via `tagRichTextMentionUrls`. The setter is idempotent; the last
|
|
266
|
+
* call wins.
|
|
267
|
+
*/
|
|
268
|
+
withMentionsUrl(url: string): this;
|
|
269
|
+
isSlashEnabled(): boolean;
|
|
270
|
+
getStorage(): RichTextStorage;
|
|
271
|
+
isResizableImages(): boolean;
|
|
272
|
+
getFileAttachmentsAcceptedFileTypes(): string[] | undefined;
|
|
273
|
+
getFileAttachmentsMaxSize(): number | undefined;
|
|
274
|
+
getFileAttachmentsDirectory(): string | undefined;
|
|
275
|
+
getFileAttachmentsVisibility(): RichTextAttachmentVisibility | undefined;
|
|
276
|
+
/**
|
|
277
|
+
* Resolve the actual button layout — base layout (override or default) with
|
|
278
|
+
* `enableToolbarButtons` appended to the last group and
|
|
279
|
+
* `disableToolbarButtons` filtered out across every group. Empty groups
|
|
280
|
+
* are dropped. Returns `null` when the toolbar is hidden.
|
|
281
|
+
*/
|
|
282
|
+
getToolbarGroups(): ToolbarGroups | null;
|
|
283
|
+
isFloatingToolbarEnabled(): boolean;
|
|
284
|
+
toMeta(ctx?: RenderContext): RichTextFieldMeta;
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=RichTextField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RichTextField.d.ts","sourceRoot":"","sources":["../src/RichTextField.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { Field } from '@pilotiq/pilotiq';
|
|
2
|
+
/** Default top-level toolbar groups — mirrors the reference admin's layout. */
|
|
3
|
+
export const DEFAULT_TOOLBAR_GROUPS = [
|
|
4
|
+
['bold', 'italic', 'underline', 'strike', 'subscript', 'superscript', 'link'],
|
|
5
|
+
['h2', 'h3'],
|
|
6
|
+
['alignStart', 'alignCenter', 'alignEnd'],
|
|
7
|
+
['blockquote', 'codeBlock', 'bulletList', 'orderedList'],
|
|
8
|
+
['undo', 'redo'],
|
|
9
|
+
];
|
|
10
|
+
/**
|
|
11
|
+
* Tailwind-flavored fallback palette. Used when the field doesn't override
|
|
12
|
+
* the colors via `.textColors([...])`. Mirrors the reference admin's
|
|
13
|
+
* "popular Tailwind hues" default.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_TEXT_COLORS = [
|
|
16
|
+
{ value: '#ef4444', label: 'Red' },
|
|
17
|
+
{ value: '#f97316', label: 'Orange' },
|
|
18
|
+
{ value: '#eab308', label: 'Yellow' },
|
|
19
|
+
{ value: '#22c55e', label: 'Green' },
|
|
20
|
+
{ value: '#06b6d4', label: 'Cyan' },
|
|
21
|
+
{ value: '#3b82f6', label: 'Blue' },
|
|
22
|
+
{ value: '#a855f7', label: 'Purple' },
|
|
23
|
+
{ value: '#ec4899', label: 'Pink' },
|
|
24
|
+
{ value: '#000000', label: 'Black', dark: '#ffffff' },
|
|
25
|
+
{ value: '#6b7280', label: 'Gray' },
|
|
26
|
+
];
|
|
27
|
+
export const DEFAULT_HIGHLIGHT_COLORS = [
|
|
28
|
+
{ value: '#fef08a', label: 'Yellow' },
|
|
29
|
+
{ value: '#fed7aa', label: 'Orange' },
|
|
30
|
+
{ value: '#fecaca', label: 'Red' },
|
|
31
|
+
{ value: '#bbf7d0', label: 'Green' },
|
|
32
|
+
{ value: '#bfdbfe', label: 'Blue' },
|
|
33
|
+
{ value: '#e9d5ff', label: 'Purple' },
|
|
34
|
+
{ value: '#f5d0fe', label: 'Pink' },
|
|
35
|
+
{ value: '#e5e7eb', label: 'Gray' },
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Field that renders a Tiptap-based rich-text editor with slash menu,
|
|
39
|
+
* draggable blocks, and a custom-block API.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* RichTextField.make('body')
|
|
44
|
+
* .label('Article body')
|
|
45
|
+
* .placeholder('Start writing…')
|
|
46
|
+
* .toolbarButtons([
|
|
47
|
+
* ['bold', 'italic', 'underline', 'strike', 'link'],
|
|
48
|
+
* ['h2', 'h3'],
|
|
49
|
+
* ['bulletList', 'orderedList'],
|
|
50
|
+
* ['undo', 'redo'],
|
|
51
|
+
* ])
|
|
52
|
+
* .blocks([
|
|
53
|
+
* Block.make('callout').label('Callout').icon('💡').schema([
|
|
54
|
+
* TextField.make('title'),
|
|
55
|
+
* TextareaField.make('content').required(),
|
|
56
|
+
* ]),
|
|
57
|
+
* ])
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export class RichTextField extends Field {
|
|
61
|
+
_blocks = [];
|
|
62
|
+
_slashCommand = true;
|
|
63
|
+
/** `undefined` = use default, `null` = hidden, array = explicit override. */
|
|
64
|
+
_toolbarOverride = undefined;
|
|
65
|
+
_enabled = [];
|
|
66
|
+
_disabled = [];
|
|
67
|
+
_floatingToolbar = true;
|
|
68
|
+
_storage = 'json';
|
|
69
|
+
_textColors = null;
|
|
70
|
+
_customTextColors = false;
|
|
71
|
+
_highlightColors = null;
|
|
72
|
+
_resizableImages = false;
|
|
73
|
+
_fileAttachmentsAcceptedFileTypes;
|
|
74
|
+
_fileAttachmentsMaxSize;
|
|
75
|
+
_fileAttachmentsDirectory;
|
|
76
|
+
_fileAttachmentsVisibility;
|
|
77
|
+
_mergeTags = [];
|
|
78
|
+
_mentions = [];
|
|
79
|
+
_mentionsUrl;
|
|
80
|
+
constructor(name) {
|
|
81
|
+
super(name, 'richtext');
|
|
82
|
+
}
|
|
83
|
+
static make(name) {
|
|
84
|
+
return new RichTextField(name);
|
|
85
|
+
}
|
|
86
|
+
/** Custom blocks available via the slash menu. */
|
|
87
|
+
blocks(blocks) {
|
|
88
|
+
this._blocks = blocks;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
/** Toggle the slash menu (`/`) on/off. Defaults to `true`. */
|
|
92
|
+
slashCommand(enabled) {
|
|
93
|
+
this._slashCommand = enabled;
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Replace the top-level toolbar layout. Pass nested arrays — each inner
|
|
98
|
+
* array becomes a button group separated by a thin divider.
|
|
99
|
+
*
|
|
100
|
+
* Pass `null` (or call `toolbar(false)`) to hide the toolbar entirely.
|
|
101
|
+
*/
|
|
102
|
+
toolbarButtons(groups) {
|
|
103
|
+
this._toolbarOverride = groups;
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
/** Add buttons on top of whichever layout is active. */
|
|
107
|
+
enableToolbarButtons(buttons) {
|
|
108
|
+
this._enabled = [...this._enabled, ...buttons];
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
/** Remove buttons from whichever layout is active. */
|
|
112
|
+
disableToolbarButtons(buttons) {
|
|
113
|
+
this._disabled = [...this._disabled, ...buttons];
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Toolbar visibility shortcut.
|
|
118
|
+
*
|
|
119
|
+
* - `true` (default) — show the top-level toolbar with the default groups
|
|
120
|
+
* unless `toolbarButtons([...])` was called.
|
|
121
|
+
* - `false` — hide the top-level toolbar.
|
|
122
|
+
*
|
|
123
|
+
* Selection-anchored floating toolbar is controlled separately via
|
|
124
|
+
* {@link floatingToolbar}.
|
|
125
|
+
*/
|
|
126
|
+
toolbar(enabled) {
|
|
127
|
+
if (!enabled)
|
|
128
|
+
this._toolbarOverride = null;
|
|
129
|
+
else if (this._toolbarOverride === null)
|
|
130
|
+
this._toolbarOverride = undefined;
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
/** Toggle the selection-anchored quick-format toolbar. Defaults to `true`. */
|
|
134
|
+
floatingToolbar(enabled) {
|
|
135
|
+
this._floatingToolbar = enabled;
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Storage format for the field's value.
|
|
140
|
+
*
|
|
141
|
+
* - `'json'` (default) — Tiptap JSON document, parsed via `JSON.parse`.
|
|
142
|
+
* - `'html'` — serialized HTML string, useful for display surfaces that
|
|
143
|
+
* can't render JSON (e.g. existing blog/CMS columns).
|
|
144
|
+
*/
|
|
145
|
+
storage(format) {
|
|
146
|
+
this._storage = format;
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Replace the text-color palette opened by the `textColor` toolbar button.
|
|
151
|
+
* Pass `null` to fall back to the default Tailwind-derived palette.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* RichTextField.make('body').textColors([
|
|
156
|
+
* { value: '#1e293b', label: 'Slate' },
|
|
157
|
+
* { value: '#dc2626', label: 'Red', dark: '#fca5a5' },
|
|
158
|
+
* ])
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
textColors(palette) {
|
|
162
|
+
this._textColors = palette;
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
165
|
+
/** Show a free-form color picker below the swatches. */
|
|
166
|
+
customTextColors(enabled = true) {
|
|
167
|
+
this._customTextColors = enabled;
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
/** Replace the highlight palette opened by the `highlight` toolbar button. */
|
|
171
|
+
highlightColors(palette) {
|
|
172
|
+
this._highlightColors = palette;
|
|
173
|
+
return this;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Allow drag-resizing of inserted images via a corner handle. Off by
|
|
177
|
+
* default — when enabled, the editor mounts a NodeView that wraps the
|
|
178
|
+
* image in a resize-aware wrapper and writes `width` / `height` attrs
|
|
179
|
+
* back into the document.
|
|
180
|
+
*/
|
|
181
|
+
resizableImages(enabled = true) {
|
|
182
|
+
this._resizableImages = enabled;
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Restrict the `attachFiles` picker to specific MIME types — passed
|
|
187
|
+
* verbatim to the file input's `accept` attribute and re-checked
|
|
188
|
+
* server-side by the upload route.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* RichTextField.make('body').fileAttachmentsAcceptedFileTypes(['image/*'])
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
fileAttachmentsAcceptedFileTypes(types) {
|
|
196
|
+
this._fileAttachmentsAcceptedFileTypes = types;
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
/** Per-file size cap in bytes for `attachFiles`. */
|
|
200
|
+
fileAttachmentsMaxSize(bytes) {
|
|
201
|
+
this._fileAttachmentsMaxSize = bytes;
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Sub-directory hint forwarded to the upload adapter alongside the
|
|
206
|
+
* `attachFiles` payload. Adapters honor it differently (`localUpload`
|
|
207
|
+
* writes to `<root>/<directory>/...`, S3 prepends to the key, etc.).
|
|
208
|
+
*/
|
|
209
|
+
fileAttachmentsDirectory(d) {
|
|
210
|
+
this._fileAttachmentsDirectory = d;
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
/** Adapter-defined visibility hint — `'public'` or `'private'`. */
|
|
214
|
+
fileAttachmentsVisibility(v) {
|
|
215
|
+
this._fileAttachmentsVisibility = v;
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Surface a `{{ tag }}` placeholder for each id in the slash menu under
|
|
220
|
+
* the "Merge tags" group. The placeholder stores as a `mergeTag` atom
|
|
221
|
+
* node and renders read-side via
|
|
222
|
+
* `renderRichTextToHtml(content, { mergeTags: { name: 'Sleman', … } })` —
|
|
223
|
+
* the substitution map replaces each id with the resolved value
|
|
224
|
+
* (HTML-escaped).
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* RichTextField.make('body').mergeTags(['firstName', 'company'])
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
mergeTags(tags) {
|
|
232
|
+
this._mergeTags = tags;
|
|
233
|
+
return this;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Wire one or more mention providers. Each provider owns a trigger
|
|
237
|
+
* character (`@` / `#` / …) and a static item list. Typing the trigger
|
|
238
|
+
* opens a popover anchored to the cursor; picking an item inserts a
|
|
239
|
+
* `mention` atom node carrying `id`, `label`, and `trigger`.
|
|
240
|
+
*
|
|
241
|
+
* Read-side rendering uses the cached label by default; pass
|
|
242
|
+
* `renderRichTextToHtml(content, { resolveMention: (trigger, id) =>
|
|
243
|
+
* latestLabel })` to override at display time.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* RichTextField.make('body').mentions([
|
|
248
|
+
* MentionProvider.make('@').items([
|
|
249
|
+
* { id: 'sleman', label: 'Sleman' },
|
|
250
|
+
* { id: 'alex', label: 'Alex' },
|
|
251
|
+
* ]),
|
|
252
|
+
* ])
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
mentions(providers) {
|
|
256
|
+
this._mentions = providers;
|
|
257
|
+
return this;
|
|
258
|
+
}
|
|
259
|
+
getBlocks() { return this._blocks; }
|
|
260
|
+
getMergeTags() { return this._mergeTags; }
|
|
261
|
+
getMentionProviders() { return this._mentions; }
|
|
262
|
+
/**
|
|
263
|
+
* `true` iff at least one provider was configured with `itemsUsing(fn)`.
|
|
264
|
+
* Pilotiq's `tagRichTextMentionUrls` walker uses this to gate URL
|
|
265
|
+
* stamping — fields with only static providers stay URL-less.
|
|
266
|
+
*/
|
|
267
|
+
hasAsyncMentions() {
|
|
268
|
+
return this._mentions.some(p => p.isAsync());
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Look up a provider by trigger char and run its resolver with `query`
|
|
272
|
+
* and `ctx`. Returns the matched items, or `null` when no provider
|
|
273
|
+
* carries that trigger. Static providers run too (using their cached
|
|
274
|
+
* list) — keeps the dispatcher uniform; the client just won't call
|
|
275
|
+
* the endpoint for static providers.
|
|
276
|
+
*/
|
|
277
|
+
async resolveMention(trigger, query, ctx) {
|
|
278
|
+
const provider = this._mentions.find(p => p.getTrigger() === trigger);
|
|
279
|
+
if (!provider)
|
|
280
|
+
return null;
|
|
281
|
+
return await provider.runResolver(query, ctx);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Render-time setter — pilotiq stamps the URL after schema resolution
|
|
285
|
+
* via `tagRichTextMentionUrls`. The setter is idempotent; the last
|
|
286
|
+
* call wins.
|
|
287
|
+
*/
|
|
288
|
+
withMentionsUrl(url) {
|
|
289
|
+
this._mentionsUrl = url;
|
|
290
|
+
return this;
|
|
291
|
+
}
|
|
292
|
+
isSlashEnabled() { return this._slashCommand; }
|
|
293
|
+
getStorage() { return this._storage; }
|
|
294
|
+
isResizableImages() { return this._resizableImages; }
|
|
295
|
+
getFileAttachmentsAcceptedFileTypes() { return this._fileAttachmentsAcceptedFileTypes; }
|
|
296
|
+
getFileAttachmentsMaxSize() { return this._fileAttachmentsMaxSize; }
|
|
297
|
+
getFileAttachmentsDirectory() { return this._fileAttachmentsDirectory; }
|
|
298
|
+
getFileAttachmentsVisibility() { return this._fileAttachmentsVisibility; }
|
|
299
|
+
/**
|
|
300
|
+
* Resolve the actual button layout — base layout (override or default) with
|
|
301
|
+
* `enableToolbarButtons` appended to the last group and
|
|
302
|
+
* `disableToolbarButtons` filtered out across every group. Empty groups
|
|
303
|
+
* are dropped. Returns `null` when the toolbar is hidden.
|
|
304
|
+
*/
|
|
305
|
+
getToolbarGroups() {
|
|
306
|
+
const override = this._toolbarOverride;
|
|
307
|
+
const base = override === null ? null :
|
|
308
|
+
override === undefined ? DEFAULT_TOOLBAR_GROUPS :
|
|
309
|
+
override;
|
|
310
|
+
if (base === null)
|
|
311
|
+
return null;
|
|
312
|
+
const enabled = this._enabled;
|
|
313
|
+
const disabled = new Set(this._disabled);
|
|
314
|
+
const groups = base.map((group) => group.filter((id) => !disabled.has(id)));
|
|
315
|
+
if (enabled.length > 0) {
|
|
316
|
+
const extras = enabled.filter((id) => !disabled.has(id));
|
|
317
|
+
if (groups.length === 0)
|
|
318
|
+
groups.push(extras);
|
|
319
|
+
else {
|
|
320
|
+
const last = groups[groups.length - 1];
|
|
321
|
+
groups[groups.length - 1] = [...last, ...extras];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return groups.filter((g) => g.length > 0);
|
|
325
|
+
}
|
|
326
|
+
isFloatingToolbarEnabled() {
|
|
327
|
+
return this._floatingToolbar;
|
|
328
|
+
}
|
|
329
|
+
toMeta(ctx) {
|
|
330
|
+
// RichTextField has no async resolvers, so the parent always returns
|
|
331
|
+
// the sync FieldMeta branch — cast away the union for the spread.
|
|
332
|
+
const base = super.toMeta(ctx);
|
|
333
|
+
// Strip `attachFiles` server-side when the panel hasn't registered an
|
|
334
|
+
// upload adapter — same posture as `MarkdownField` and the editor
|
|
335
|
+
// chrome stays clean. `uploadUrl` is the wire-side URL for the picker
|
|
336
|
+
// dialog; only stamped when adapter is wired (otherwise the button is
|
|
337
|
+
// already gone from the toolbar groups).
|
|
338
|
+
const groups = this.getToolbarGroups();
|
|
339
|
+
const filteredGroups = ctx?.hasUploadAdapter
|
|
340
|
+
? groups
|
|
341
|
+
: groups?.map(g => g.filter(b => b !== 'attachFiles'))
|
|
342
|
+
.filter(g => g.length > 0) ?? null;
|
|
343
|
+
return {
|
|
344
|
+
...base,
|
|
345
|
+
blocks: this._blocks.map((b) => b.toMeta()),
|
|
346
|
+
slashCommand: this._slashCommand,
|
|
347
|
+
toolbarGroups: filteredGroups,
|
|
348
|
+
floatingToolbar: this._floatingToolbar,
|
|
349
|
+
storage: this._storage,
|
|
350
|
+
textColors: this._textColors ?? DEFAULT_TEXT_COLORS,
|
|
351
|
+
customTextColors: this._customTextColors,
|
|
352
|
+
highlightColors: this._highlightColors ?? DEFAULT_HIGHLIGHT_COLORS,
|
|
353
|
+
resizableImages: this._resizableImages,
|
|
354
|
+
...(this._fileAttachmentsAcceptedFileTypes !== undefined
|
|
355
|
+
? { fileAttachmentsAcceptedFileTypes: this._fileAttachmentsAcceptedFileTypes } : {}),
|
|
356
|
+
...(this._fileAttachmentsMaxSize !== undefined
|
|
357
|
+
? { fileAttachmentsMaxSize: this._fileAttachmentsMaxSize } : {}),
|
|
358
|
+
...(this._fileAttachmentsDirectory !== undefined
|
|
359
|
+
? { fileAttachmentsDirectory: this._fileAttachmentsDirectory } : {}),
|
|
360
|
+
...(this._fileAttachmentsVisibility !== undefined
|
|
361
|
+
? { fileAttachmentsVisibility: this._fileAttachmentsVisibility } : {}),
|
|
362
|
+
...(ctx?.uploadUrl && ctx?.hasUploadAdapter ? { uploadUrl: ctx.uploadUrl } : {}),
|
|
363
|
+
mergeTags: [...this._mergeTags],
|
|
364
|
+
mentions: this._mentions.map((p) => p.toMeta()),
|
|
365
|
+
...(this._mentionsUrl !== undefined ? { mentionsUrl: this._mentionsUrl } : {}),
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=RichTextField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RichTextField.js","sourceRoot":"","sources":["../src/RichTextField.ts"],"names":[],"mappings":"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"}
|