tiptap-markdown-react 0.17.1 → 0.18.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/README.md +75 -3
- package/dist/components/EditorToolbar.d.ts +12 -1
- package/dist/components/EditorToolbar.dom.test.d.ts +1 -0
- package/dist/components/FindReplaceBar.d.ts +0 -7
- package/dist/components/LinkPopover.d.ts +28 -0
- package/dist/components/LinkPopover.dom.test.d.ts +1 -0
- package/dist/components/MarkdownWysiwygEditor.d.ts +12 -0
- package/dist/components/TableHandles.d.ts +19 -0
- package/dist/components/TableHandles.dom.test.d.ts +1 -0
- package/dist/components/findEntry.dom.test.d.ts +1 -0
- package/dist/findReplace.d.ts +18 -4
- package/dist/icons/index.d.ts +6 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1308 -601
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +41 -1
- package/dist/linkEditing.d.ts +45 -0
- package/dist/linkEditing.test.d.ts +1 -0
- package/dist/style-inline.css +339 -118
- package/dist/style.css +339 -118
- package/dist/tableSelection.d.ts +25 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -295,14 +295,34 @@ Override any of these CSS variables on an ancestor (e.g. `:root` or the editor c
|
|
|
295
295
|
| `findBarOffset` | `{ top?, right?, bottom?, left? } \| number = px` | Where the library-rendered bar sits inside its positioning context. Default `{ top: 4, right: 4 }` (top-right); pass e.g. `{ bottom: 8, left: 8 }` to dock it elsewhere. The context is the editor, or your `findBarContainer` element when you supply one — the library adds `position: relative` to that container if it is `static` (otherwise the bar would anchor to some unexpected ancestor). |
|
|
296
296
|
| `findShortcut` | `boolean` | Take over <kbd>Cmd/Ctrl</kbd>+<kbd>F</kbd> while the editor has focus (default `true`; bound only when the editor owns a bar). `false` keeps the browser's native find — wire your own entry with `handle.openFind()`. |
|
|
297
297
|
| `findLabels` | `Partial<FindLabels>` | Localize the find & replace bar. |
|
|
298
|
+
| `onFindOpenChange` | `(open: boolean) => void` | Fired when the bar actually shows or hides (Esc / × included). Use it to drive an external entry such as the toolbar magnifier. Fires only on a real change — never a `false` on mount — and stays `false` while `findBar={false}`, so a host-placed bar never lights up an entry you did not open. |
|
|
298
299
|
| `className` | `string` | Class on the scroll container. |
|
|
299
300
|
|
|
300
301
|
Ref handle (`MarkdownWysiwygEditorHandle`): `getMarkdown()`, `getHTML()`, `getJSON()`, `getEditor()`,
|
|
301
|
-
`focusComment(id)`, `nextComment(dir?)`, `getCommentIds()`, `openFind()`, `closeFind()`.
|
|
302
|
+
`focusComment(id)`, `nextComment(dir?)`, `getCommentIds()`, `openFind()`, `closeFind()`, `toggleFind()`.
|
|
303
|
+
`openFind()` keeps the same "press again" feel as <kbd>Cmd/Ctrl</kbd>+<kbd>F</kbd> — refocus the search field and
|
|
304
|
+
select the query — while `toggleFind()` flips the bar and pairs with an entry that shows an active state
|
|
305
|
+
(`onSearch={() => handle.current?.toggleFind()}`).
|
|
302
306
|
|
|
303
307
|
#### Find & replace
|
|
304
308
|
|
|
305
|
-
<kbd>Cmd/Ctrl</kbd>+<kbd>F</kbd> (while focus is inside the editor) opens a floating bar: match counter inside the search field, wrap-around next/previous, match-case and whole-word toggles, replace and replace-all.
|
|
309
|
+
<kbd>Cmd/Ctrl</kbd>+<kbd>F</kbd> (while focus is inside the editor) opens a floating bar: match counter inside the search field, wrap-around next/previous, match-case and whole-word toggles, replace and replace-all. Read-only editors (`editable={false}`) can search but not replace. <kbd>Enter</kbd> in the search field jumps to the next match — but an <kbd>Enter</kbd> that is committing an IME candidate (Chinese/Japanese input) is left alone, so confirming a word never jumps or replaces.
|
|
310
|
+
|
|
311
|
+
**Closing it.** `Esc` closes the bar, clears the highlights and returns focus to the editor; it works from anywhere that belongs to the editor (focus inside the bar, inside the document, or on the page while this is the only editor), and the keystroke is consumed so a host popover or drawer wrapping the bar does not close along with it. Other ways out: the bar's ×, `handle.closeFind()`, `toggleFind()`, and unmounting the bar. Deliberately **not** closing on: clicking into the document or another input, an empty query, zero results, after replace-all, or switching to read-only (search stays available then — only the replace row goes away). If an editor is swapped out (remounted for a new document), the library reports `onFindOpenChange(false)` so an entry elsewhere never stays lit.
|
|
312
|
+
|
|
313
|
+
`<EditorToolbar>` can carry an entry to the same bar. Pass `onSearch` (wired to the ref handle) and the magnifier appears just left of the More menu; omit it and the button does not render. Feed `searchActive` from `onFindOpenChange` and it lights up while the bar is open — pair it with `toggleFind()` so the lit button also turns the bar back off:
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
const find = useRef<MarkdownWysiwygEditorHandle>(null)
|
|
317
|
+
const [findOpen, setFindOpen] = useState(false)
|
|
318
|
+
|
|
319
|
+
<EditorToolbar
|
|
320
|
+
editor={editor}
|
|
321
|
+
onSearch={() => find.current?.toggleFind()}
|
|
322
|
+
searchActive={findOpen}
|
|
323
|
+
/>
|
|
324
|
+
<MarkdownWysiwygEditor ref={find} onFindOpenChange={setFindOpen} />
|
|
325
|
+
```
|
|
306
326
|
|
|
307
327
|
Matching is done by the official extension, so the semantics are its semantics — worth knowing before you rely on them:
|
|
308
328
|
|
|
@@ -352,13 +372,15 @@ With `findBar={false}` the editor does not bind <kbd>Cmd/Ctrl</kbd>+<kbd>F</kbd>
|
|
|
352
372
|
|
|
353
373
|
`FindReplaceBar` is exported if you'd rather place the bar yourself, `FindLabels` / `defaultFindLabels` for i18n, and `FindAndReplace` for hand-built pipelines. Two details to reuse when driving it yourself: keep `searchDebounceMs: 0` on the extension and debounce in your own UI, and route calls through `runFindCommand()` — it absorbs a Tiptap 3.31.3 transaction mismatch that fires on the first search when the document ends with a code block / table / chart (see the comment on `runFindCommand` for the mechanism).
|
|
354
374
|
|
|
375
|
+
Styling the bar from the outside: its internals use hashed CSS-module classes, so the bar carries stable hooks instead — `[data-find-bar]` on the root, `[data-find-field="search|replace"]` on the inputs, `[data-find-counter]` on the counter, `[data-find-option="match-case|whole-words"]` on the toggles and `[data-find-action="previous|next|close|replace|replace-all"]` on the buttons. Colors stay on the theme variables (`--tmr-find-*` for the highlights, `--tmr-toolbar-*` / `--tmr-accent` for the bar chrome).
|
|
376
|
+
|
|
355
377
|
#### i18n (labels)
|
|
356
378
|
|
|
357
379
|
There is no global locale and no provider: every visible string comes from a `Partial<XLabels>` prop that is merged over built-in English defaults (`{ ...defaultToolbarLabels, ...labels }`). A host ships one object per language and passes it down; switching languages is picking a different object. Override only the keys you care about — everything else falls back to English.
|
|
358
380
|
|
|
359
381
|
| Component | Prop | Type |
|
|
360
382
|
| --- | --- | --- |
|
|
361
|
-
| `<EditorToolbar>` | `labels` | `Partial<ToolbarLabels>` (also covers the Import menu and the
|
|
383
|
+
| `<EditorToolbar>` | `labels` | `Partial<ToolbarLabels>` (also covers the Import menu, the equation popover and the link popover) |
|
|
362
384
|
| `<MarkdownWysiwygEditor>` | `findLabels` | `Partial<FindLabels>` (replace / replace-all appear as icon buttons, so their labels are the tooltip + accessible name) |
|
|
363
385
|
| `<MarkdownWysiwygEditor>` | `codeBlockLabels` | `Partial<CodeBlockLabels>` |
|
|
364
386
|
| `<TocPanel>` | `labels` | `Partial<TocLabels>` |
|
|
@@ -386,6 +408,8 @@ The underlying extensions `MarkdownPaste` / `MarkdownFileDrop` (and the `looksLi
|
|
|
386
408
|
|
|
387
409
|
### `<EditorToolbar>` (client)
|
|
388
410
|
|
|
411
|
+
The row is centred and, when the controls no longer fit the container, **wraps onto a second line** rather than scrolling sideways — a hidden control is worse than a taller toolbar. The full set (search entry included) needs about 1045 px of container width; narrower containers get a wrapped line with 4 px of vertical breathing room. `onSearch` renders the magnifier just left of the More menu.
|
|
412
|
+
|
|
389
413
|
| Prop | Type | Description |
|
|
390
414
|
| --- | --- | --- |
|
|
391
415
|
| `editor` | `Editor` | The instance from `onEditorReady`. |
|
|
@@ -396,9 +420,57 @@ The underlying extensions `MarkdownPaste` / `MarkdownFileDrop` (and the `looksLi
|
|
|
396
420
|
| `importMenuItems` | `ImportMenuItem[]` | Import dropdown options (`label` + `accept`). Hosts that want Markdown / Word / PDF pass three items. |
|
|
397
421
|
| `showImport` | `boolean` | Show the Import dropdown (default `true`). |
|
|
398
422
|
| `labels` | `Partial<ToolbarLabels>` | i18n labels. |
|
|
423
|
+
| `onSearch` | `() => void` | Search entry (magnifier) left of the More menu. Wire it to `handle.toggleFind()` (or `openFind()` if you'd rather it only ever open); omit it and no button renders. Worth passing only when the editor owns a bar (`findBar` on) — a host-placed bar has nothing for it to open. Search works read-only, so the button never greys out. |
|
|
424
|
+
| `searchActive` | `boolean` | Whether the bar is open; drives `aria-pressed` and the active highlight of the search entry (default `false`). Feed it from the editor's `onFindOpenChange`. |
|
|
399
425
|
| `extraToolbarItems` | `ExtraToolbarItem[]` | Custom items appended to the "More" menu. |
|
|
400
426
|
| `labels.inlineMath` / `blockMath` | `string` | More-menu equation items. |
|
|
401
427
|
| `labels.mathPlaceholder` / `mathDone` / `mathNewInline` / `mathNewBlock` | `string` | Equation editor (empty chip/hint, input, Done). |
|
|
428
|
+
| `labels.tableRowMenu` / `tableColumnMenu` | `string` | Aria-labels of the table hover handles. |
|
|
429
|
+
| `labels.linkPrompt` / `linkApply` / `linkOpen` / `linkRemove` / `linkInvalid` | `string` | Link popover: field placeholder, apply, open in new window, remove, rejected-address hint. |
|
|
430
|
+
|
|
431
|
+
#### Table editing (hover handles)
|
|
432
|
+
|
|
433
|
+
Hover any cell and four affordances appear: a `⋮` handle on the row's left edge, a `⋯` handle above the table aligned to the column, a `+` pill on the table's right edge (**append a column**) and a `+` pill below it (**append a row**). They are all sized to what they act on: the row handle spans the row's height, the column handle spans the column's width, and each `+` spans the table's edge it sits on. Clicking a handle selects that whole row / column and opens its menu: add before / after, delete, **Clear content**, **Reset cell styles**, plus **Delete table**. The handles ship with `<EditorToolbar>` (they are its table UI), reuse the same commands as the insert-table grid, and do not appear on read-only editors.
|
|
434
|
+
|
|
435
|
+
Right-click is still wired for exactly one case: a **multi-cell selection** (drag across cells). A handle can only express one row or one column, so batch add/delete of a rectangle keeps the context menu.
|
|
436
|
+
|
|
437
|
+
**Clear content** empties the selected cells but keeps them (a header row therefore never degrades into a data row), and **Reset cell styles** puts `colwidth` / `align` back to their schema defaults while leaving `colspan` / `rowspan` alone — those are structural, and the extension's `mergeCells` / `splitCell` are deliberately **not** exposed here: GFM has no `colspan`, so a merged cell exports as `| 1<br>2 | |` and cannot be restored on reload. Column width is a *column* property managed by the resize plugin, so clearing it needs the whole column selected (from the row handle it is restored from the widest cell in that column, which is the plugin's normal behavior).
|
|
438
|
+
|
|
439
|
+
Styling hooks (internals are hashed CSS-module classes): `[data-table-handle="row|col"]` on the handles, `[data-table-menu]` on the menu. Colors ride `--tmr-table-handle-bg` / `-fg` / `-border` (a light pill by default; hovering turns it into `--tmr-accent`).
|
|
440
|
+
|
|
441
|
+
**Not included: dragging a handle to reorder rows or columns.** That is precisely the part the official `table-node` component implements inside its own source — which is a **paid** Start-plan component (the registry answers 401 for `table-node`, `toc-node`, `drag-context-menu` while free ones answer 200), so it cannot be vendored into this MIT package. The free `@tiptap/extension-table` ships the add/delete/header/merge commands used here but no move commands; reordering would be our own transaction code on top of `TableMap`.
|
|
442
|
+
|
|
443
|
+
### `<LinkPopover>` (client)
|
|
444
|
+
|
|
445
|
+
The toolbar's link button opens this popover — type an address, apply it, open it in a new window, or remove the link. With the caret inside a link it prefills that link's href, so editing a URL no longer means deleting and re-adding it (the old `window.prompt` also could not be edited, gave no feedback for a rejected address, and is unavailable in Electron and some WebViews).
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
<LinkPopover
|
|
449
|
+
editor={editor}
|
|
450
|
+
labels={{ field: 'Paste a link…' }}
|
|
451
|
+
trigger={<button type="button" className="my-btn"><LinkIcon /></button>}
|
|
452
|
+
/>
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
| Prop | Type | Description |
|
|
456
|
+
| --- | --- | --- |
|
|
457
|
+
| `editor` | `Editor` | The editor to operate on. |
|
|
458
|
+
| `trigger` | `ReactNode` | Your own trigger element. Radix's `asChild` takes over its click / ref / aria, so it must be a DOM element or a `forwardRef` component (the toolbar passes its `ToolbarButton`). |
|
|
459
|
+
| `labels` | `Partial<LinkPopoverLabels>` | i18n labels (`defaultLinkPopoverLabels` is exported). |
|
|
460
|
+
| `className` / `style` | `string` / `CSSProperties` | Extra class / inline style on the panel; placement stays with Radix. |
|
|
461
|
+
|
|
462
|
+
Styling hooks (internals are hashed CSS-module classes): `[data-link-popover]` on the panel, `[data-link-field]` on the input, `[data-link-action="apply|open|remove"]` on the buttons, `[data-link-invalid]` on the input while the editor rejects the address. Colors come from the theme variables (`--tmr-accent`, `--tmr-toolbar-border`, `--tmr-toolbar-muted`, `--tmr-text`, `--tmr-danger`).
|
|
463
|
+
|
|
464
|
+
The logic follows the official link-popover component (MIT) — ported, not vendored, so no Tailwind, no primitive design system and no extra runtime deps. It also fixes two flaws in that reference implementation, both caught by tests here: a rejected address used to leave the document modified (the insert-after-a-failed-`setLink` chain), and editing a link whose caret sits inside it replaced the link's text with the URL. What it does:
|
|
465
|
+
|
|
466
|
+
- applies over `extendMarkRange('link')`, so changes hit the whole link;
|
|
467
|
+
- inserts the address as its own text when the selection is empty and there is no link;
|
|
468
|
+
- removes without letting the autolink plugin re-add the link (`preventAutolink`);
|
|
469
|
+
- normalises bare domains and `host:port` with the extension's `defaultProtocol` (typing `example.com` stores `http://example.com`, matching what Tiptap's autolink does on paste — otherwise markdown would export a relative link);
|
|
470
|
+
- opens through a protocol allowlist with `noopener,noreferrer`;
|
|
471
|
+
- keeps its Enter IME-safe (the official panel's handler would apply the link while you commit a Chinese/Japanese candidate).
|
|
472
|
+
|
|
473
|
+
The commands are exported for headless or self-drawn UIs: `applyLink`, `removeLink`, `canSetLink`, `isLinkActive`, `readLinkHref`, `normalizeLinkHref`, `sanitizeLinkUrl`, `openLinkUrl`.
|
|
402
474
|
|
|
403
475
|
### `<MarkdownPreview>` (client)
|
|
404
476
|
|
|
@@ -61,6 +61,17 @@ export interface EditorToolbarProps {
|
|
|
61
61
|
/** 是否显示导入下拉,默认 `true`。卡片等场景可关掉。 */
|
|
62
62
|
showImport?: boolean;
|
|
63
63
|
labels?: Partial<ToolbarLabels>;
|
|
64
|
+
/**
|
|
65
|
+
* 工具栏最右端的搜索入口(放大镜)。**不传就不渲染**——条子本身归
|
|
66
|
+
* `<MarkdownWysiwygEditor>`,这里只给一个入口,宿主接上自己的编辑器句柄即可:
|
|
67
|
+
* `onSearch={() => handle.current?.openFind()}`。
|
|
68
|
+
*
|
|
69
|
+
* 条子归编辑器渲染(`findBar` 开)时才接;`findBar={false}` 的宿主自己摆条子,
|
|
70
|
+
* 这个入口点了也不会弹东西。只读态照样可查,所以不随 `editable` 灰显。
|
|
71
|
+
*/
|
|
72
|
+
onSearch?: () => void;
|
|
73
|
+
/** 条子当前是否开着(驱动按钮的 aria-pressed / 高亮)。不传恒为未激活。 */
|
|
74
|
+
searchActive?: boolean;
|
|
64
75
|
/** 追加到 More 菜单末尾的自定义项。 */
|
|
65
76
|
extraToolbarItems?: ExtraToolbarItem[];
|
|
66
77
|
className?: string;
|
|
@@ -70,4 +81,4 @@ export type { ImportMenuItem };
|
|
|
70
81
|
* 顶部操作栏(antd-free,Radix Popover 菜单 + 内联 SVG 图标)。位置由父级控制,
|
|
71
82
|
* 这里只渲染按钮 + 反映 editor 激活态。不含业务耦合,扩展项经 extraToolbarItems 注入。
|
|
72
83
|
*/
|
|
73
|
-
export declare function EditorToolbar({ editor, onImageUpload, onError, onImportDocument, importAccept, importMenuItems, showImport, labels, extraToolbarItems, className, }: EditorToolbarProps): import("react").JSX.Element;
|
|
84
|
+
export declare function EditorToolbar({ editor, onImageUpload, onError, onImportDocument, importAccept, importMenuItems, showImport, labels, onSearch, searchActive, extraToolbarItems, className, }: EditorToolbarProps): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -17,11 +17,4 @@ export interface FindReplaceBarProps {
|
|
|
17
17
|
/** 根节点内联样式(编辑器用它落 findBarOffset;宿主自绘时也可用)。 */
|
|
18
18
|
style?: CSSProperties;
|
|
19
19
|
}
|
|
20
|
-
/**
|
|
21
|
-
* 查找替换浮动条。匹配、高亮、替换全部由官方
|
|
22
|
-
* `@tiptap/extension-find-and-replace` 承担(含 RE2 安全正则、跨标记匹配、单事务全部替换),
|
|
23
|
-
* 这里只做输入、计数、开关与键位。
|
|
24
|
-
*
|
|
25
|
-
* 打开即把查询推给编辑器,关闭时 `clearSearch()`——高亮是会话级的,不留残影。
|
|
26
|
-
*/
|
|
27
20
|
export declare function FindReplaceBar({ editor, onClose, labels, inputRef, className, style, }: FindReplaceBarProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/react';
|
|
2
|
+
import { CSSProperties, ReactNode } from 'react';
|
|
3
|
+
import { LinkPopoverLabels } from '../labels';
|
|
4
|
+
export interface LinkPopoverProps {
|
|
5
|
+
/** 编辑器实例。 */
|
|
6
|
+
editor: Editor;
|
|
7
|
+
/**
|
|
8
|
+
* 触发器:传宿主自己的按钮元素。Radix 的 `asChild` 要接管它的点击 / ref / aria——
|
|
9
|
+
* 传函数组件时得先 `forwardRef`(本库的 `<EditorToolbar>` 就是这么接的)。
|
|
10
|
+
*/
|
|
11
|
+
trigger: ReactNode;
|
|
12
|
+
labels?: Partial<LinkPopoverLabels>;
|
|
13
|
+
/** 挂到浮层根节点上的 class / 内联样式(定位与层级归宿主,Radix 只管浮层方向)。 */
|
|
14
|
+
className?: string;
|
|
15
|
+
style?: CSSProperties;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 链接编辑浮层:输入地址 + 应用 / 在新窗口打开 / 移除。
|
|
19
|
+
*
|
|
20
|
+
* 逻辑全在 `linkEditing.ts`(从官方 UI Components 的 `useLinkPopover` 搬的),这里只负责输入、
|
|
21
|
+
* 按钮与状态。取代表驱动器的 `window.prompt`:能**编辑已有链接**(打开即预填当前地址,
|
|
22
|
+
* 而旧实现是「在链接里点一下就删除」)、能打开、能移除,且 `window.prompt` 在 Electron /
|
|
23
|
+
* 部分 WebView 里根本不可用。
|
|
24
|
+
*
|
|
25
|
+
* 地址被编辑器拒掉时(Tiptap 的 `isAllowedUri`)浮层不关,输入框转成危险色并带上 title,
|
|
26
|
+
* 让用户改——静默什么都不发生是最难查的。
|
|
27
|
+
*/
|
|
28
|
+
export declare function LinkPopover({ editor, trigger, labels, className, style, }: LinkPopoverProps): import("react").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -32,6 +32,11 @@ export interface MarkdownWysiwygEditorHandle {
|
|
|
32
32
|
openFind: () => void;
|
|
33
33
|
/** 收起自带浮动条,清空高亮并把焦点还给编辑器。findBar={false} 时不生效。 */
|
|
34
34
|
closeFind: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* 反转自带浮动条:关着就开、开着就关。工具栏那个带 active 态的放大镜接它
|
|
37
|
+
* (`onSearch={() => handle.current?.toggleFind()}`)。findBar={false} 时不生效。
|
|
38
|
+
*/
|
|
39
|
+
toggleFind: () => void;
|
|
35
40
|
}
|
|
36
41
|
export interface MarkdownWysiwygEditorProps {
|
|
37
42
|
/** 初始 markdown 内容。 */
|
|
@@ -145,6 +150,13 @@ export interface MarkdownWysiwygEditorProps {
|
|
|
145
150
|
findShortcut?: boolean;
|
|
146
151
|
/** 查找替换浮动条的本地化文案。 */
|
|
147
152
|
findLabels?: Partial<FindLabels>;
|
|
153
|
+
/**
|
|
154
|
+
* 浮动条开合状态变化的通知(条子开着时 `handle.openFind()`、Esc / × 关掉都会触发)。
|
|
155
|
+
* 典型用法是驱动别处的入口按钮:`<EditorToolbar onSearch={open} searchActive={isOpen} />`。
|
|
156
|
+
* 只在真正变化时回调,挂载时不会先报一次 `false`;报的是「条子真的在屏幕上」——
|
|
157
|
+
* `findBar={false}`(宿主自己摆条子)时恒为 `false`,不会因为 `openFind()` 空转就亮起入口。
|
|
158
|
+
*/
|
|
159
|
+
onFindOpenChange?: (open: boolean) => void;
|
|
148
160
|
/**
|
|
149
161
|
* 启用快捷键抽屉:编辑器右下角出现键盘悬浮按钮,点开为
|
|
150
162
|
* 「格式 / 快捷键 / Markdown」三列对照抽屉(默认 true,只读态隐藏)。
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core';
|
|
2
|
+
import { ToolbarLabels } from '../labels';
|
|
3
|
+
export interface TableHandlesProps {
|
|
4
|
+
/** 编辑器实例。只读态不出手柄。 */
|
|
5
|
+
editor: Editor;
|
|
6
|
+
/** 已合并默认值的工具栏文案(行列菜单项与两个手柄的 aria-label 都取自它)。 */
|
|
7
|
+
labels: ToolbarLabels;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 表格的悬停手柄(Notion 式):鼠标落在单元格上时,行左缘出一条竖胶囊(⋮)、表格上方出一条
|
|
11
|
+
* 横胶囊(⋯),点开就是该行 / 该列的操作菜单。
|
|
12
|
+
*
|
|
13
|
+
* 这是原来「表内右键出菜单」的替代——右键只保留**多格选区**的批量增删(手柄只覆盖单行单列,
|
|
14
|
+
* 那个场景手柄表达不了)。命令全部复用 `tableSelection.ts`,与工具栏的「插入表格」共用一套。
|
|
15
|
+
*
|
|
16
|
+
* 手柄是 fixed 定位、渲染在 body 的 portal 里:它要贴着单元格边缘,而工具栏并不在编辑器 DOM
|
|
17
|
+
* 内。滚动 / 缩放时重新量一遍悬停的那颗单元格,让手柄跟着走。
|
|
18
|
+
*/
|
|
19
|
+
export declare function TableHandles({ editor, labels }: TableHandlesProps): import('react').ReactPortal | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/findReplace.d.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/react';
|
|
2
|
+
/** 官方扩展在 `extensionManager` 里的注册名(与官方 UI Components 同款判据)。 */
|
|
3
|
+
export declare const FIND_EXTENSION_NAME = "findAndReplace";
|
|
1
4
|
/**
|
|
2
|
-
*
|
|
5
|
+
* 输入法组合中的这次按键要不要放行。
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
+
* 中文 / 日文输入法里 Enter 是「提交候选词」、Escape 是「取消候选」,都不是「执行」:不拦的话,
|
|
8
|
+
* 每次确认候选词都会触发一次跳转(替换框则直接替换一处),而按 Esc 想取消候选反而把浮动条关掉。
|
|
9
|
+
* 判据取两路——`isComposing` 覆盖常规路径,`keyCode === 229` 兜住 Safari 在组合收尾时的 keydown
|
|
10
|
+
* (与 slashMenu/SlashMenuExtension.ts 的 isComposing() 同一套;那边还多一路 ProseMirror 的
|
|
11
|
+
* `view.composing`,React 事件里拿不到,调用方传 `event.nativeEvent` 即可)。
|
|
7
12
|
*/
|
|
13
|
+
export declare function isComposingKeyEvent(event: Pick<KeyboardEvent, 'isComposing' | 'keyCode'>): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* 查找替换扩展是否已注册。
|
|
16
|
+
*
|
|
17
|
+
* 按 `extensionManager.extensions` 里的注册名查,而不是探 `editor.commands.setSearchTerm`
|
|
18
|
+
* 在不在——命令探测分不清「扩展根本没装」和「命令被别的同名扩展覆盖」,也判不出已销毁的实例。
|
|
19
|
+
* 官方 UI Components 的 `isFindAndReplaceAvailable` 用的是同一条判据。
|
|
20
|
+
*/
|
|
21
|
+
export declare function hasFindReplaceExtension(editor: Editor | null | undefined): boolean;
|
|
8
22
|
/**
|
|
9
23
|
* 输入防抖(毫秒)。
|
|
10
24
|
*
|
package/dist/icons/index.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ export declare const UnderlineIcon: (p: IconProps) => import("react").JSX.Elemen
|
|
|
16
16
|
export declare const StrikethroughIcon: (p: IconProps) => import("react").JSX.Element;
|
|
17
17
|
export declare const CodeIcon: (p: IconProps) => import("react").JSX.Element;
|
|
18
18
|
export declare const LinkIcon: (p: IconProps) => import("react").JSX.Element;
|
|
19
|
+
/** 橡皮擦:表格菜单的「清空内容」。 */
|
|
20
|
+
export declare const EraserIcon: (p: IconProps) => import("react").JSX.Element;
|
|
21
|
+
/** 逆时针回转:表格菜单的「重置单元格样式」。 */
|
|
22
|
+
export declare const RotateCcwIcon: (p: IconProps) => import("react").JSX.Element;
|
|
23
|
+
/** 在新窗口打开(链接浮层的「打开」按钮)。 */
|
|
24
|
+
export declare const ExternalLinkIcon: (p: IconProps) => import("react").JSX.Element;
|
|
19
25
|
export declare const ImageIcon: (p: IconProps) => import("react").JSX.Element;
|
|
20
26
|
export declare const ImportIcon: (p: IconProps) => import("react").JSX.Element;
|
|
21
27
|
export declare const ListUnorderedIcon: (p: IconProps) => import("react").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export { ColorPalette, type ColorPaletteProps } from './components/ColorPalette'
|
|
|
5
5
|
export { TocPanel, type TocPanelProps } from './components/TocPanel';
|
|
6
6
|
export { CodeBlockView } from './components/CodeBlockView';
|
|
7
7
|
export { FindReplaceBar, type FindReplaceBarProps, } from './components/FindReplaceBar';
|
|
8
|
+
export { LinkPopover, type LinkPopoverProps } from './components/LinkPopover';
|
|
9
|
+
export { applyLink, canSetLink, isLinkActive, normalizeLinkHref, openLinkUrl, readLinkHref, removeLink, sanitizeLinkUrl, } from './linkEditing';
|
|
8
10
|
export { ReportContent, type ReportContentProps } from './ReportContent';
|
|
9
11
|
export { CitationInteractive, type CitationInteractiveProps, } from './components/CitationInteractive';
|
|
10
12
|
export { ReportContentInteractive, type ReportContentInteractiveProps, } from './components/ReportContentInteractive';
|
|
@@ -27,7 +29,7 @@ export { MarkdownFileDrop } from './markdownFileDrop';
|
|
|
27
29
|
export { extractToc, type TocItem } from './toc/extractToc';
|
|
28
30
|
export { makeTocGetId } from './toc/tocSlug';
|
|
29
31
|
export { scrollToTocHeading } from './toc/scrollToTocHeading';
|
|
30
|
-
export { defaultChartLabels, defaultCodeBlockLabels, defaultColorPaletteLabels, defaultCommentLabels, defaultFindLabels, defaultShortcutLabels, defaultSlashMenuLabels, defaultTocLabels, defaultToolbarLabels, type ChartLabels, type CodeBlockLabels, type ColorPaletteLabels, type CommentLabels, type FindLabels, type ShortcutLabels, type SlashMenuLabels, type TocLabels, type ToolbarLabels, } from './labels';
|
|
32
|
+
export { defaultChartLabels, defaultCodeBlockLabels, defaultColorPaletteLabels, defaultCommentLabels, defaultFindLabels, defaultLinkPopoverLabels, defaultShortcutLabels, defaultSlashMenuLabels, defaultTocLabels, defaultToolbarLabels, type ChartLabels, type CodeBlockLabels, type ColorPaletteLabels, type CommentLabels, type FindLabels, type LinkPopoverLabels, type ShortcutLabels, type SlashMenuLabels, type TocLabels, type ToolbarLabels, } from './labels';
|
|
31
33
|
export { CommentMark, type CommentMarkOptions, type CommentInterval } from './commentAnchor/CommentMark';
|
|
32
34
|
export { mapCommentAnchors, mergeCommentIntervals, blockTextHash, type CommentSegment, type CommentAnchorInput, type CommentAnchorResult, type CommentAnchorStatus, type CommentRange, } from './commentAnchor/commentMapper';
|
|
33
35
|
export { commentAnchorPlugin, commentAnchorExtension, commentAnchorPluginKey, stripCommentAnchorMarks, COMMENT_ACTIVE_META, COMMENT_CLICK_META, COMMENT_GUTTER_META, type CommentAnchorPluginOptions, type CommentAnchorPluginState, type CommentGutterPayload, } from './commentAnchor/commentAnchorPlugin';
|