@placeholderco/placeholder-ui 1.0.12 → 2.0.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 +1 -1
- package/README.md +134 -130
- package/dist/app.css +178 -0
- package/dist/bootstrap.min.css +3600 -0
- package/dist/cards/GitCard.svelte +115 -0
- package/dist/cards/GitCard.svelte.d.ts +22 -0
- package/dist/display/Avatar.svelte +29 -17
- package/dist/display/Avatar.svelte.d.ts +12 -2
- package/dist/display/LinkCollection.svelte +40 -18
- package/dist/display/LinkCollection.svelte.d.ts +9 -2
- package/dist/display/Paper.svelte +31 -19
- package/dist/display/Paper.svelte.d.ts +12 -3
- package/dist/display/alert/Alert.svelte +129 -0
- package/dist/display/alert/Alert.svelte.d.ts +15 -0
- package/dist/display/alert/AlertVariant.d.ts +1 -0
- package/dist/display/alert/AlertVariant.js +1 -0
- package/dist/display/filetree/FileTree.svelte +259 -0
- package/dist/display/filetree/FileTree.svelte.d.ts +76 -0
- package/dist/display/filetree/FileTreeItem.svelte +396 -0
- package/dist/display/filetree/FileTreeItem.svelte.d.ts +40 -0
- package/dist/display/filetree/FileTreeNode.d.ts +46 -0
- package/dist/display/filetree/FileTreeNode.js +115 -0
- package/dist/display/filetree/index.d.ts +5 -0
- package/dist/display/filetree/index.js +3 -0
- package/dist/editors/CodeMirror.svelte +306 -0
- package/dist/editors/CodeMirror.svelte.d.ts +31 -0
- package/dist/editors/tiptap/LinkActionMenu.svelte +307 -0
- package/dist/editors/tiptap/LinkActionMenu.svelte.d.ts +8 -0
- package/dist/editors/tiptap/TipTap.svelte +856 -0
- package/dist/editors/tiptap/TipTap.svelte.d.ts +54 -0
- package/dist/editors/tiptap/TipTapBubble.svelte +790 -0
- package/dist/editors/tiptap/TipTapBubble.svelte.d.ts +44 -0
- package/dist/editors/tiptap/collaboration.d.ts +55 -0
- package/dist/editors/tiptap/collaboration.js +1 -0
- package/dist/editors/tiptap/extensions/Alert.d.ts +18 -0
- package/dist/editors/tiptap/extensions/Alert.js +72 -0
- package/dist/editors/tiptap/extensions/CodeBlockEditor.d.ts +21 -0
- package/dist/editors/tiptap/extensions/CodeBlockEditor.js +326 -0
- package/dist/editors/tiptap/extensions/Div.d.ts +19 -0
- package/dist/editors/tiptap/extensions/Div.js +89 -0
- package/dist/editors/tiptap/extensions/Span.d.ts +5 -0
- package/dist/editors/tiptap/extensions/Span.js +56 -0
- package/dist/editors/tiptap/extensions/codeBlockEditor.css +236 -0
- package/dist/editors/tiptap/extensions/codeBlockLanguages.d.ts +17 -0
- package/dist/editors/tiptap/extensions/codeBlockLanguages.js +124 -0
- package/dist/editors/tiptap/extensions/index.d.ts +7 -0
- package/dist/editors/tiptap/extensions/index.js +5 -0
- package/dist/editors/tiptap/toolbar/AlertButton.svelte +261 -0
- package/dist/editors/tiptap/toolbar/AlertButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignRightButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignRightButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/BoldButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/BoldButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/BulletListButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/BulletListButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/CodeButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/CodeButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ColorButton.svelte +299 -0
- package/dist/editors/tiptap/toolbar/ColorButton.svelte.d.ts +20 -0
- package/dist/editors/tiptap/toolbar/DocumentButton.svelte +58 -0
- package/dist/editors/tiptap/toolbar/DocumentButton.svelte.d.ts +9 -0
- package/dist/editors/tiptap/toolbar/HeadingButton.svelte +30 -0
- package/dist/editors/tiptap/toolbar/HeadingButton.svelte.d.ts +8 -0
- package/dist/editors/tiptap/toolbar/HtmlButton.svelte +68 -0
- package/dist/editors/tiptap/toolbar/HtmlButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ImageButton.svelte +54 -0
- package/dist/editors/tiptap/toolbar/ImageButton.svelte.d.ts +8 -0
- package/dist/editors/tiptap/toolbar/ItalicButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/ItalicButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/LinkButton.svelte +257 -0
- package/dist/editors/tiptap/toolbar/LinkButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/OrderedListButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/OrderedListButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/RedoButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/RedoButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/SubscriptButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/SubscriptButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/TableButton.svelte +258 -0
- package/dist/editors/tiptap/toolbar/TableButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ToolbarButton.svelte +84 -0
- package/dist/editors/tiptap/toolbar/ToolbarButton.svelte.d.ts +10 -0
- package/dist/editors/tiptap/toolbar/UnderlineButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/UnderlineButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/UndoButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/UndoButton.svelte.d.ts +7 -0
- package/dist/form/Autocomplete.svelte +86 -135
- package/dist/form/Autocomplete.svelte.d.ts +6 -8
- package/dist/form/AutocompleteMulti.svelte +385 -227
- package/dist/form/AutocompleteMulti.svelte.d.ts +59 -10
- package/dist/form/Checkbox.svelte +59 -54
- package/dist/form/Checkbox.svelte.d.ts +14 -5
- package/dist/form/Chips.svelte +29 -13
- package/dist/form/Chips.svelte.d.ts +16 -2
- package/dist/form/ComboBox.svelte +30 -20
- package/dist/form/ComboBox.svelte.d.ts +1 -1
- package/dist/form/ComboBoxItemBuilder.svelte +161 -188
- package/dist/form/ComboBoxItemBuilder.svelte.d.ts +19 -2
- package/dist/form/ComboBoxMulti.svelte +38 -24
- package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
- package/dist/form/CronBuilder.svelte +84 -67
- package/dist/form/CronBuilder.svelte.d.ts +16 -3
- package/dist/form/DatePicker.svelte +148 -195
- package/dist/form/DateRangePicker.svelte +101 -98
- package/dist/form/DateTimePicker.svelte +167 -208
- package/dist/form/DateTimePicker.svelte.d.ts +10 -2
- package/dist/form/FormGroup.svelte +33 -10
- package/dist/form/FormGroup.svelte.d.ts +12 -2
- package/dist/form/Number.svelte +70 -47
- package/dist/form/Number.svelte.d.ts +36 -6
- package/dist/form/Radio.svelte +18 -18
- package/dist/form/RadioGroup.svelte +23 -12
- package/dist/form/RadioGroup.svelte.d.ts +13 -2
- package/dist/form/SegmentedControl.svelte +76 -56
- package/dist/form/SegmentedControl.svelte.d.ts +9 -4
- package/dist/form/Select.svelte +150 -233
- package/dist/form/Select.svelte.d.ts +29 -5
- package/dist/form/SelectMulti.svelte +163 -277
- package/dist/form/SelectMulti.svelte.d.ts +36 -7
- package/dist/form/Slider.svelte +183 -269
- package/dist/form/Slider.svelte.d.ts +32 -17
- package/dist/form/StringArrayBuilder.svelte +249 -0
- package/dist/form/StringArrayBuilder.svelte.d.ts +15 -0
- package/dist/form/Switch.svelte +164 -106
- package/dist/form/Switch.svelte.d.ts +22 -3
- package/dist/form/TextArea.svelte +49 -29
- package/dist/form/TextArea.svelte.d.ts +23 -3
- package/dist/form/Textbox.svelte +69 -68
- package/dist/form/Textbox.svelte.d.ts +32 -4
- package/dist/form/TimePicker.svelte +42 -47
- package/dist/form/TimePicker.svelte.d.ts +12 -2
- package/dist/form/comboBoxCore.svelte.d.ts +99 -0
- package/dist/form/comboBoxCore.svelte.js +243 -0
- package/dist/icon/Icon.svelte +8 -3
- package/dist/icon/Icon.svelte.d.ts +8 -3
- package/dist/icon/file-type-bmp.svg +1 -0
- package/dist/icon/file-type-csv.svg +1 -0
- package/dist/icon/file-type-doc.svg +1 -0
- package/dist/icon/file-type-docx.svg +1 -0
- package/dist/icon/file-type-jpg.svg +1 -0
- package/dist/icon/file-type-pdf.svg +1 -0
- package/dist/icon/file-type-png.svg +1 -0
- package/dist/icon/file-type-ppt.svg +1 -0
- package/dist/icon/file-type-svg.svg +1 -0
- package/dist/icon/file-type-txt.svg +1 -0
- package/dist/icon/file-type-xls.svg +1 -0
- package/dist/icon/file-type-zip.svg +1 -0
- package/dist/icon/index.d.ts +166 -151
- package/dist/icon/index.js +166 -152
- package/dist/icon/logo-placeholder.svg +6 -0
- package/dist/icon/source-code.svg +1 -0
- package/dist/icon/sun-moon.svg +1 -0
- package/dist/icon/table.svg +6 -0
- package/dist/index.d.ts +87 -26
- package/dist/index.js +25 -28
- package/dist/layout/AppShell.svelte +12 -162
- package/dist/layout/AppShell.svelte.d.ts +6 -27
- package/dist/layout/CustomNavbar.svelte +9 -7
- package/dist/layout/CustomNavbar.svelte.d.ts +4 -2
- package/dist/layout/Navbar.svelte +161 -129
- package/dist/layout/Navbar.svelte.d.ts +29 -15
- package/dist/layout/NavbarItemDisplay.svelte +2 -2
- package/dist/layout/NavbarItemView.svelte +182 -0
- package/dist/layout/NavbarItemView.svelte.d.ts +10 -0
- package/dist/layout/Sidenav.svelte +280 -341
- package/dist/layout/Sidenav.svelte.d.ts +36 -4
- package/dist/models/ComboBoxItem.d.ts +2 -0
- package/dist/models/Employee.d.ts +53 -0
- package/dist/models/Employee.js +23 -0
- package/dist/models/Hyperlink.d.ts +3 -1
- package/dist/models/LinkCollectionItem.d.ts +3 -1
- package/dist/models/NavbarItem.d.ts +6 -2
- package/dist/theme.svelte.d.ts +0 -1
- package/dist/theme.svelte.js +46 -58
- package/dist/ui/Accordion.svelte +81 -242
- package/dist/ui/Accordion.svelte.d.ts +37 -14
- package/dist/ui/AccordionItem.svelte +303 -0
- package/dist/ui/AccordionItem.svelte.d.ts +21 -0
- package/dist/ui/ActionIcon.svelte +25 -21
- package/dist/ui/ActionIcon.svelte.d.ts +15 -2
- package/dist/ui/Badge.svelte +163 -171
- package/dist/ui/Badge.svelte.d.ts +13 -5
- package/dist/ui/Button.svelte +178 -205
- package/dist/ui/Button.svelte.d.ts +19 -2
- package/dist/ui/ButtonVariant.d.ts +15 -1
- package/dist/ui/ContextMenu.svelte +146 -0
- package/dist/ui/ContextMenu.svelte.d.ts +37 -0
- package/dist/ui/ContextMenuList.svelte +188 -0
- package/dist/ui/ContextMenuList.svelte.d.ts +12 -0
- package/dist/ui/Dialog.svelte +183 -111
- package/dist/ui/Dialog.svelte.d.ts +21 -4
- package/dist/ui/Drawer.svelte +237 -184
- package/dist/ui/Drawer.svelte.d.ts +20 -2
- package/dist/ui/Dropdown.svelte +24 -14
- package/dist/ui/Dropdown.svelte.d.ts +11 -2
- package/dist/ui/Dropzone.svelte +159 -57
- package/dist/ui/Dropzone.svelte.d.ts +29 -2
- package/dist/ui/Link.svelte +12 -4
- package/dist/ui/Link.svelte.d.ts +8 -2
- package/dist/ui/Loader.svelte +23 -18
- package/dist/ui/Loader.svelte.d.ts +5 -2
- package/dist/ui/Logo.svelte +37 -0
- package/dist/ui/Logo.svelte.d.ts +16 -0
- package/dist/ui/MultiSortable.svelte +287 -0
- package/dist/ui/MultiSortable.svelte.d.ts +50 -0
- package/dist/ui/Pagination.svelte +15 -9
- package/dist/ui/Pagination.svelte.d.ts +6 -2
- package/dist/ui/Popover.svelte +43 -65
- package/dist/ui/Popover.svelte.d.ts +14 -5
- package/dist/ui/ProgressBar.svelte +28 -30
- package/dist/ui/ProgressBarVariant.d.ts +7 -1
- package/dist/ui/SegmentedControl.svelte +0 -0
- package/dist/ui/SegmentedControl.svelte.d.ts +26 -0
- package/dist/ui/Sortable.svelte +163 -0
- package/dist/ui/Sortable.svelte.d.ts +47 -0
- package/dist/ui/Table.svelte +383 -80
- package/dist/ui/Table.svelte.d.ts +43 -2
- package/dist/ui/Tabs.svelte +22 -18
- package/dist/ui/Tabs.svelte.d.ts +6 -2
- package/dist/ui/ThemeSwitcher.svelte +26 -7
- package/dist/ui/ThemeSwitcher.svelte.d.ts +4 -2
- package/dist/ui/Tooltip.svelte +312 -180
- package/dist/ui/Tooltip.svelte.d.ts +4 -3
- package/dist/uiTheme.svelte.d.ts +86 -0
- package/dist/uiTheme.svelte.js +214 -0
- package/dist/util/DateFunctions.js +1 -1
- package/dist/util/DragDrop.d.ts +50 -0
- package/dist/util/DragDrop.js +154 -0
- package/dist/util/NavigateTo.js +2 -2
- package/dist/util/dayjs.d.ts +4 -0
- package/dist/util/dayjs.js +15 -0
- package/package.json +66 -26
- package/dist/display/Alert.svelte +0 -179
- package/dist/display/Alert.svelte.d.ts +0 -13
- package/dist/form/FileInput.svelte +0 -235
- package/dist/form/FileInput.svelte.d.ts +0 -23
- package/dist/form/PasswordInput.svelte +0 -253
- package/dist/form/PasswordInput.svelte.d.ts +0 -34
- package/dist/form/Rating.svelte +0 -235
- package/dist/form/Rating.svelte.d.ts +0 -21
- package/dist/styles/components.css +0 -199
- package/dist/styles/dark.css +0 -146
- package/dist/styles/index.css +0 -116
- package/dist/styles/reset.css +0 -110
- package/dist/styles/semantic.css +0 -86
- package/dist/styles/tokens.css +0 -203
- package/dist/styles/utilities.css +0 -523
- package/dist/ui/Breadcrumbs.svelte +0 -131
- package/dist/ui/Breadcrumbs.svelte.d.ts +0 -16
- package/dist/ui/LoadingOverlay.svelte +0 -53
- package/dist/ui/LoadingOverlay.svelte.d.ts +0 -11
- package/dist/ui/Progress.svelte +0 -191
- package/dist/ui/Progress.svelte.d.ts +0 -15
- package/dist/ui/RingProgress.svelte +0 -141
- package/dist/ui/RingProgress.svelte.d.ts +0 -18
- package/dist/ui/Skeleton.svelte +0 -85
- package/dist/ui/Skeleton.svelte.d.ts +0 -12
- package/dist/ui/Stepper.svelte +0 -355
- package/dist/ui/Stepper.svelte.d.ts +0 -24
- package/dist/ui/Timeline.svelte +0 -225
- package/dist/ui/Timeline.svelte.d.ts +0 -23
- /package/dist/{actions → util}/ClickOutside.d.ts +0 -0
- /package/dist/{actions → util}/ClickOutside.js +0 -0
- /package/dist/{transitions → util}/Transitions.d.ts +0 -0
- /package/dist/{transitions → util}/Transitions.js +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type AnyExtension } from '@tiptap/core';
|
|
2
|
+
import { type CodeBlocksOptions } from './extensions/index.js';
|
|
3
|
+
import type { CollaborationConfig } from './collaboration.js';
|
|
4
|
+
export interface TipTapBubbleProps {
|
|
5
|
+
/** HTML content value (bindable). Ignored when collaboration is enabled. */
|
|
6
|
+
value?: string;
|
|
7
|
+
/** Label text displayed above the editor */
|
|
8
|
+
label?: string;
|
|
9
|
+
/** Mark field as required (shows asterisk) */
|
|
10
|
+
required?: boolean;
|
|
11
|
+
/** CSS classes for the FormGroup wrapper */
|
|
12
|
+
groupClass?: string;
|
|
13
|
+
/** Tooltip text on hover */
|
|
14
|
+
tooltipText?: string;
|
|
15
|
+
/** Position of the tooltip */
|
|
16
|
+
tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
|
|
17
|
+
/** Enable editing mode */
|
|
18
|
+
editable?: boolean;
|
|
19
|
+
/** Placeholder text when editor is empty */
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
/** Additional CSS classes */
|
|
22
|
+
class?: string;
|
|
23
|
+
/** Async handler for image uploads, returns URL or null */
|
|
24
|
+
onImageUpload?: (file: File) => Promise<string | null>;
|
|
25
|
+
/** Callback when content changes */
|
|
26
|
+
onUpdate?: (html: string) => void;
|
|
27
|
+
/** Opt-in real-time collaboration config. When provided, content syncs via Yjs. */
|
|
28
|
+
collaboration?: CollaborationConfig;
|
|
29
|
+
/** Opt-in rich code blocks: CodeMirror-powered editing with syntax highlighting,
|
|
30
|
+
* autocompletion and a per-block language picker. Pass true for all languages
|
|
31
|
+
* or a config to narrow the offered languages and set the default. */
|
|
32
|
+
codeBlocks?: boolean | CodeBlocksOptions;
|
|
33
|
+
/** Additional TipTap extensions to register with the editor */
|
|
34
|
+
extensions?: AnyExtension[];
|
|
35
|
+
}
|
|
36
|
+
declare const TipTapBubble: import("svelte").Component<TipTapBubbleProps, {
|
|
37
|
+
getHTML: () => string;
|
|
38
|
+
getJSON: () => object;
|
|
39
|
+
setContent: (html: string) => void;
|
|
40
|
+
clear: () => void;
|
|
41
|
+
focus: () => void;
|
|
42
|
+
}, "value">;
|
|
43
|
+
type TipTapBubble = ReturnType<typeof TipTapBubble>;
|
|
44
|
+
export default TipTapBubble;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { XmlFragment } from 'yjs';
|
|
2
|
+
/** User identity shown on remote collaboration cursors. */
|
|
3
|
+
export interface CollaborationUser {
|
|
4
|
+
/** Display name shown on the cursor label */
|
|
5
|
+
name: string;
|
|
6
|
+
/** 6-digit hex color for the cursor and selection highlight (e.g. `'#f59e0b'`). Must be hex format — HSL, RGB, and named colors are not supported. */
|
|
7
|
+
color: `#${string}`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for real-time collaborative editing.
|
|
11
|
+
*
|
|
12
|
+
* **Required peer dependencies** (install in your app):
|
|
13
|
+
* - `yjs` — CRDT document model
|
|
14
|
+
* - A Yjs network provider such as `y-websocket`, `y-webrtc`, or `@hocuspocus/provider`
|
|
15
|
+
*
|
|
16
|
+
* **Usage:**
|
|
17
|
+
* ```ts
|
|
18
|
+
* import * as Y from 'yjs';
|
|
19
|
+
* import { WebsocketProvider } from 'y-websocket';
|
|
20
|
+
*
|
|
21
|
+
* const ydoc = new Y.Doc();
|
|
22
|
+
* const provider = new WebsocketProvider('wss://your-server.com', 'room-id', ydoc);
|
|
23
|
+
*
|
|
24
|
+
* const collaboration = {
|
|
25
|
+
* fragment: ydoc.getXmlFragment('content'),
|
|
26
|
+
* provider,
|
|
27
|
+
* user: { name: 'Alice', color: '#f59e0b' }
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* **Notes:**
|
|
32
|
+
* - When collaboration is enabled, the `value` prop is ignored — Yjs is the source of truth.
|
|
33
|
+
* - The built-in undo/redo is replaced by Yjs collaborative history.
|
|
34
|
+
* - Your app is responsible for managing the provider lifecycle (connect/disconnect).
|
|
35
|
+
*/
|
|
36
|
+
export interface CollaborationConfig {
|
|
37
|
+
/**
|
|
38
|
+
* A Yjs XML fragment to sync editor content.
|
|
39
|
+
*
|
|
40
|
+
* Create with `ydoc.getXmlFragment('content')`. All clients sharing
|
|
41
|
+
* the same Y.Doc and fragment name will see each other's edits.
|
|
42
|
+
*/
|
|
43
|
+
fragment: XmlFragment;
|
|
44
|
+
/**
|
|
45
|
+
* A Yjs provider instance that handles network transport.
|
|
46
|
+
*
|
|
47
|
+
* Common choices:
|
|
48
|
+
* - `WebsocketProvider` from `y-websocket` (requires a WebSocket server)
|
|
49
|
+
* - `WebrtcProvider` from `y-webrtc` (peer-to-peer, no server)
|
|
50
|
+
* - `HocuspocusProvider` from `@hocuspocus/provider` (TipTap's managed solution)
|
|
51
|
+
*/
|
|
52
|
+
provider: any;
|
|
53
|
+
/** Current user info displayed on remote cursors */
|
|
54
|
+
user: CollaborationUser;
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
export interface AlertOptions {
|
|
3
|
+
HTMLAttributes: Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
alert: {
|
|
8
|
+
/**
|
|
9
|
+
* Insert an alert block
|
|
10
|
+
*/
|
|
11
|
+
setAlert: (attributes?: {
|
|
12
|
+
variant?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
}) => ReturnType;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export declare const Alert: Node<AlertOptions, any>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Node, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
export const Alert = Node.create({
|
|
3
|
+
name: 'alert',
|
|
4
|
+
group: 'block',
|
|
5
|
+
content: 'block+',
|
|
6
|
+
defining: true,
|
|
7
|
+
addAttributes() {
|
|
8
|
+
return {
|
|
9
|
+
variant: {
|
|
10
|
+
default: 'default',
|
|
11
|
+
parseHTML: (element) => element.getAttribute('data-variant'),
|
|
12
|
+
renderHTML: (attributes) => {
|
|
13
|
+
return {
|
|
14
|
+
'data-variant': attributes.variant,
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
title: {
|
|
19
|
+
default: 'Alert',
|
|
20
|
+
parseHTML: (element) => element.getAttribute('data-title'),
|
|
21
|
+
renderHTML: (attributes) => {
|
|
22
|
+
return {
|
|
23
|
+
'data-title': attributes.title,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
parseHTML() {
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
tag: 'div[data-type="alert"]',
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
},
|
|
36
|
+
renderHTML({ HTMLAttributes }) {
|
|
37
|
+
return [
|
|
38
|
+
'div',
|
|
39
|
+
mergeAttributes(HTMLAttributes, {
|
|
40
|
+
'data-type': 'alert',
|
|
41
|
+
class: `alert alert-${HTMLAttributes['data-variant'] || 'default'}`,
|
|
42
|
+
}),
|
|
43
|
+
[
|
|
44
|
+
'div',
|
|
45
|
+
{ class: 'alert-title', 'data-title-element': 'true' },
|
|
46
|
+
HTMLAttributes['data-title'] || 'Alert',
|
|
47
|
+
],
|
|
48
|
+
['div', { class: 'alert-content' }, 0],
|
|
49
|
+
];
|
|
50
|
+
},
|
|
51
|
+
addCommands() {
|
|
52
|
+
return {
|
|
53
|
+
setAlert: (attributes) => ({ commands }) => {
|
|
54
|
+
return commands.insertContent({
|
|
55
|
+
type: this.name,
|
|
56
|
+
attrs: attributes,
|
|
57
|
+
content: [
|
|
58
|
+
{
|
|
59
|
+
type: 'paragraph',
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: 'text',
|
|
63
|
+
text: 'Enter your alert message here...',
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CodeBlockOptions } from '@tiptap/extension-code-block';
|
|
2
|
+
import { type CodeBlockLanguageId } from './codeBlockLanguages.js';
|
|
3
|
+
import './codeBlockEditor.css';
|
|
4
|
+
/** Configuration accepted by the `codeBlocks` prop on TipTap / TipTapBubble */
|
|
5
|
+
export interface CodeBlocksOptions {
|
|
6
|
+
/** Languages offered in the code block language picker (default: all registered) */
|
|
7
|
+
languages?: CodeBlockLanguageId[];
|
|
8
|
+
/** Language applied to newly inserted code blocks (default 'javascript') */
|
|
9
|
+
defaultLanguage?: CodeBlockLanguageId;
|
|
10
|
+
}
|
|
11
|
+
export interface CodeBlockEditorOptions extends CodeBlockOptions {
|
|
12
|
+
/** Language ids offered in the picker; null offers every registered language */
|
|
13
|
+
languages: CodeBlockLanguageId[] | null;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* CodeBlock extension whose blocks are full CodeMirror editors: syntax
|
|
17
|
+
* highlighting, autocompletion, bracket matching and smart indentation, with a
|
|
18
|
+
* per-block language picker. Serializes to standard
|
|
19
|
+
* `<pre><code class="language-...">` HTML, so content round-trips unchanged.
|
|
20
|
+
*/
|
|
21
|
+
export declare const CodeBlockEditor: import("@tiptap/core").Node<CodeBlockEditorOptions, any>;
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { CodeBlock } from '@tiptap/extension-code-block';
|
|
2
|
+
import { Selection, TextSelection } from '@tiptap/pm/state';
|
|
3
|
+
import { exitCode } from '@tiptap/pm/commands';
|
|
4
|
+
import { EditorView as CodeMirrorView, drawSelection, keymap } from '@codemirror/view';
|
|
5
|
+
import { Compartment, EditorState as CodeMirrorState } from '@codemirror/state';
|
|
6
|
+
import { defaultKeymap, indentWithTab } from '@codemirror/commands';
|
|
7
|
+
import { autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
|
|
8
|
+
import { bracketMatching, indentOnInput, syntaxHighlighting } from '@codemirror/language';
|
|
9
|
+
import { classHighlighter } from '@lezer/highlight';
|
|
10
|
+
import { codeBlockLanguages, resolveCodeBlockLanguage } from './codeBlockLanguages.js';
|
|
11
|
+
import './codeBlockEditor.css';
|
|
12
|
+
/**
|
|
13
|
+
* Renders each code block as an embedded CodeMirror editor, following the
|
|
14
|
+
* ProseMirror codemirror node view pattern: CodeMirror owns the block's text and
|
|
15
|
+
* selection while focused, and every change is forwarded to ProseMirror so the
|
|
16
|
+
* document (and collaboration/undo) stay authoritative.
|
|
17
|
+
*/
|
|
18
|
+
class CodeBlockView {
|
|
19
|
+
dom;
|
|
20
|
+
node;
|
|
21
|
+
editor;
|
|
22
|
+
getPos;
|
|
23
|
+
cm;
|
|
24
|
+
select;
|
|
25
|
+
languageCompartment = new Compartment();
|
|
26
|
+
updating = false;
|
|
27
|
+
constructor(node, editor, getPos, languages) {
|
|
28
|
+
this.node = node;
|
|
29
|
+
this.editor = editor;
|
|
30
|
+
this.getPos = getPos;
|
|
31
|
+
const editable = editor.isEditable;
|
|
32
|
+
this.cm = new CodeMirrorView({
|
|
33
|
+
doc: node.textContent,
|
|
34
|
+
extensions: [
|
|
35
|
+
keymap.of([
|
|
36
|
+
...closeBracketsKeymap,
|
|
37
|
+
...completionKeymap,
|
|
38
|
+
...this.codeMirrorKeymap(),
|
|
39
|
+
...defaultKeymap,
|
|
40
|
+
indentWithTab
|
|
41
|
+
]),
|
|
42
|
+
drawSelection(),
|
|
43
|
+
syntaxHighlighting(classHighlighter),
|
|
44
|
+
bracketMatching(),
|
|
45
|
+
closeBrackets(),
|
|
46
|
+
autocompletion(),
|
|
47
|
+
indentOnInput(),
|
|
48
|
+
CodeMirrorView.lineWrapping,
|
|
49
|
+
this.languageCompartment.of(this.languageExtension()),
|
|
50
|
+
CodeMirrorView.editable.of(editable),
|
|
51
|
+
CodeMirrorState.readOnly.of(!editable),
|
|
52
|
+
CodeMirrorView.updateListener.of((update) => this.forwardUpdate(update))
|
|
53
|
+
]
|
|
54
|
+
});
|
|
55
|
+
this.select = this.buildLanguageSelect(languages, editable);
|
|
56
|
+
this.dom = document.createElement('div');
|
|
57
|
+
this.dom.className = 'code-block-editor';
|
|
58
|
+
this.dom.appendChild(this.select);
|
|
59
|
+
this.dom.appendChild(this.cm.dom);
|
|
60
|
+
}
|
|
61
|
+
// The ProseMirror view is looked up lazily because node views are constructed
|
|
62
|
+
// while the outer view itself is still being created.
|
|
63
|
+
get view() {
|
|
64
|
+
return this.editor.view;
|
|
65
|
+
}
|
|
66
|
+
languageExtension() {
|
|
67
|
+
return resolveCodeBlockLanguage(this.node.attrs.language)?.load() ?? [];
|
|
68
|
+
}
|
|
69
|
+
buildLanguageSelect(languages, editable) {
|
|
70
|
+
const select = document.createElement('select');
|
|
71
|
+
select.className = 'code-block-language';
|
|
72
|
+
select.setAttribute('aria-label', 'Code language');
|
|
73
|
+
select.contentEditable = 'false';
|
|
74
|
+
for (const def of languages) {
|
|
75
|
+
const option = document.createElement('option');
|
|
76
|
+
option.value = def.id;
|
|
77
|
+
option.textContent = def.label;
|
|
78
|
+
select.appendChild(option);
|
|
79
|
+
}
|
|
80
|
+
select.disabled = !editable;
|
|
81
|
+
this.syncSelect(select);
|
|
82
|
+
select.addEventListener('change', () => {
|
|
83
|
+
const pos = this.getPos();
|
|
84
|
+
if (pos === undefined)
|
|
85
|
+
return;
|
|
86
|
+
this.view.dispatch(this.view.state.tr.setNodeMarkup(pos, undefined, {
|
|
87
|
+
...this.node.attrs,
|
|
88
|
+
language: select.value
|
|
89
|
+
}));
|
|
90
|
+
this.cm.focus();
|
|
91
|
+
});
|
|
92
|
+
return select;
|
|
93
|
+
}
|
|
94
|
+
// Reflect the node's language in the picker, adding a fallback option for
|
|
95
|
+
// languages present in parsed content but missing from the configured list.
|
|
96
|
+
syncSelect(select = this.select) {
|
|
97
|
+
const raw = this.node.attrs.language;
|
|
98
|
+
const current = resolveCodeBlockLanguage(raw)?.id ?? raw ?? 'plaintext';
|
|
99
|
+
if (![...select.options].some((option) => option.value === current)) {
|
|
100
|
+
const option = document.createElement('option');
|
|
101
|
+
option.value = current;
|
|
102
|
+
option.textContent = current;
|
|
103
|
+
select.appendChild(option);
|
|
104
|
+
}
|
|
105
|
+
select.value = current;
|
|
106
|
+
}
|
|
107
|
+
// Map CodeMirror document/selection changes onto the ProseMirror document.
|
|
108
|
+
forwardUpdate(update) {
|
|
109
|
+
if (this.updating || !this.cm.hasFocus)
|
|
110
|
+
return;
|
|
111
|
+
const pos = this.getPos();
|
|
112
|
+
if (pos === undefined)
|
|
113
|
+
return;
|
|
114
|
+
let offset = pos + 1;
|
|
115
|
+
const { main } = update.state.selection;
|
|
116
|
+
const selFrom = offset + main.from;
|
|
117
|
+
const selTo = offset + main.to;
|
|
118
|
+
const pmSelection = this.view.state.selection;
|
|
119
|
+
if (update.docChanged || pmSelection.from !== selFrom || pmSelection.to !== selTo) {
|
|
120
|
+
const tr = this.view.state.tr;
|
|
121
|
+
update.changes.iterChanges((fromA, toA, fromB, toB, text) => {
|
|
122
|
+
if (text.length) {
|
|
123
|
+
tr.replaceWith(offset + fromA, offset + toA, this.view.state.schema.text(text.toString()));
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
tr.delete(offset + fromA, offset + toA);
|
|
127
|
+
}
|
|
128
|
+
offset += toB - fromB - (toA - fromA);
|
|
129
|
+
});
|
|
130
|
+
tr.setSelection(TextSelection.create(tr.doc, selFrom, selTo));
|
|
131
|
+
this.view.dispatch(tr);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
codeMirrorKeymap() {
|
|
135
|
+
return [
|
|
136
|
+
{ key: 'ArrowUp', run: () => this.maybeEscape('line', -1) },
|
|
137
|
+
{ key: 'ArrowLeft', run: () => this.maybeEscape('char', -1) },
|
|
138
|
+
{ key: 'ArrowDown', run: () => this.maybeEscape('line', 1) },
|
|
139
|
+
{ key: 'ArrowRight', run: () => this.maybeEscape('char', 1) },
|
|
140
|
+
{ key: 'Escape', run: () => this.escape() },
|
|
141
|
+
{
|
|
142
|
+
key: 'Mod-Enter',
|
|
143
|
+
run: () => {
|
|
144
|
+
if (!exitCode(this.view.state, this.view.dispatch))
|
|
145
|
+
return false;
|
|
146
|
+
this.view.focus();
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{ key: 'Backspace', run: () => this.removeWhenEmpty() },
|
|
151
|
+
{ key: 'Mod-z', run: () => this.editor.commands.undo() },
|
|
152
|
+
{ key: 'Mod-y', run: () => this.editor.commands.redo() },
|
|
153
|
+
{ key: 'Shift-Mod-z', run: () => this.editor.commands.redo() }
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
// Move the selection out of the block when an arrow key is pressed at its edge.
|
|
157
|
+
maybeEscape(unit, dir) {
|
|
158
|
+
const { state } = this.cm;
|
|
159
|
+
const { main } = state.selection;
|
|
160
|
+
if (!main.empty)
|
|
161
|
+
return false;
|
|
162
|
+
if (unit === 'line') {
|
|
163
|
+
const line = state.doc.lineAt(main.head);
|
|
164
|
+
if (dir < 0 ? line.from > 0 : line.to < state.doc.length)
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
else if (dir < 0 ? main.from > 0 : main.to < state.doc.length) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
const pos = this.getPos();
|
|
171
|
+
if (pos === undefined)
|
|
172
|
+
return false;
|
|
173
|
+
const after = pos + this.node.nodeSize;
|
|
174
|
+
// Arrowing down out of a trailing code block: create a paragraph to land in.
|
|
175
|
+
if (dir > 0 && unit === 'line' && after >= this.view.state.doc.content.size) {
|
|
176
|
+
const paragraph = this.view.state.schema.nodes.paragraph.createAndFill();
|
|
177
|
+
if (!paragraph)
|
|
178
|
+
return false;
|
|
179
|
+
const tr = this.view.state.tr.insert(after, paragraph);
|
|
180
|
+
tr.setSelection(TextSelection.create(tr.doc, after + 1));
|
|
181
|
+
this.view.dispatch(tr.scrollIntoView());
|
|
182
|
+
this.view.focus();
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
const selection = Selection.near(this.view.state.doc.resolve(dir < 0 ? pos : after), dir);
|
|
186
|
+
this.view.dispatch(this.view.state.tr.setSelection(selection).scrollIntoView());
|
|
187
|
+
this.view.focus();
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
escape() {
|
|
191
|
+
const pos = this.getPos();
|
|
192
|
+
if (pos === undefined)
|
|
193
|
+
return false;
|
|
194
|
+
const selection = Selection.near(this.view.state.doc.resolve(pos + this.node.nodeSize), 1);
|
|
195
|
+
this.view.dispatch(this.view.state.tr.setSelection(selection).scrollIntoView());
|
|
196
|
+
this.view.focus();
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
// Backspace in an empty block converts it back to a paragraph.
|
|
200
|
+
removeWhenEmpty() {
|
|
201
|
+
if (this.cm.state.doc.length > 0)
|
|
202
|
+
return false;
|
|
203
|
+
const pos = this.getPos();
|
|
204
|
+
if (pos === undefined)
|
|
205
|
+
return false;
|
|
206
|
+
const paragraph = this.view.state.schema.nodes.paragraph.createAndFill();
|
|
207
|
+
if (!paragraph)
|
|
208
|
+
return false;
|
|
209
|
+
const tr = this.view.state.tr.replaceWith(pos, pos + this.node.nodeSize, paragraph);
|
|
210
|
+
tr.setSelection(TextSelection.create(tr.doc, pos + 1));
|
|
211
|
+
this.view.dispatch(tr);
|
|
212
|
+
this.view.focus();
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
// Apply external changes (undo, collaboration, setContent) to CodeMirror.
|
|
216
|
+
update(node) {
|
|
217
|
+
if (node.type !== this.node.type)
|
|
218
|
+
return false;
|
|
219
|
+
const previousLanguage = this.node.attrs.language;
|
|
220
|
+
this.node = node;
|
|
221
|
+
if (node.attrs.language !== previousLanguage) {
|
|
222
|
+
this.syncSelect();
|
|
223
|
+
this.cm.dispatch({
|
|
224
|
+
effects: this.languageCompartment.reconfigure(this.languageExtension())
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
const newText = node.textContent;
|
|
228
|
+
const currentText = this.cm.state.doc.toString();
|
|
229
|
+
if (newText !== currentText) {
|
|
230
|
+
let start = 0;
|
|
231
|
+
let currentEnd = currentText.length;
|
|
232
|
+
let newEnd = newText.length;
|
|
233
|
+
while (start < currentEnd &&
|
|
234
|
+
start < newEnd &&
|
|
235
|
+
currentText.charCodeAt(start) === newText.charCodeAt(start)) {
|
|
236
|
+
start++;
|
|
237
|
+
}
|
|
238
|
+
while (currentEnd > start &&
|
|
239
|
+
newEnd > start &&
|
|
240
|
+
currentText.charCodeAt(currentEnd - 1) === newText.charCodeAt(newEnd - 1)) {
|
|
241
|
+
currentEnd--;
|
|
242
|
+
newEnd--;
|
|
243
|
+
}
|
|
244
|
+
this.updating = true;
|
|
245
|
+
this.cm.dispatch({
|
|
246
|
+
changes: { from: start, to: currentEnd, insert: newText.slice(start, newEnd) }
|
|
247
|
+
});
|
|
248
|
+
this.updating = false;
|
|
249
|
+
}
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
setSelection(anchor, head) {
|
|
253
|
+
this.cm.focus();
|
|
254
|
+
this.updating = true;
|
|
255
|
+
this.cm.dispatch({ selection: { anchor, head } });
|
|
256
|
+
this.updating = false;
|
|
257
|
+
}
|
|
258
|
+
selectNode() {
|
|
259
|
+
this.cm.focus();
|
|
260
|
+
}
|
|
261
|
+
stopEvent() {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
ignoreMutation() {
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
destroy() {
|
|
268
|
+
this.cm.destroy();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Let arrow keys move the cursor from an adjacent textblock into a code block;
|
|
272
|
+
// ProseMirror can't do this itself because the block's content lives in CodeMirror.
|
|
273
|
+
function arrowIntoCodeBlock(direction) {
|
|
274
|
+
return ({ editor }) => {
|
|
275
|
+
const { state, view } = editor;
|
|
276
|
+
if (!state.selection.empty || !view.endOfTextblock(direction))
|
|
277
|
+
return false;
|
|
278
|
+
const side = direction === 'left' || direction === 'up' ? -1 : 1;
|
|
279
|
+
const { $head } = state.selection;
|
|
280
|
+
try {
|
|
281
|
+
const nextPos = Selection.near(state.doc.resolve(side > 0 ? $head.after() : $head.before()), side);
|
|
282
|
+
if (nextPos.$head && nextPos.$head.parent.type.name === 'codeBlock') {
|
|
283
|
+
view.dispatch(state.tr.setSelection(nextPos));
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
// selection sits at the document boundary — nothing to move into
|
|
289
|
+
}
|
|
290
|
+
return false;
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* CodeBlock extension whose blocks are full CodeMirror editors: syntax
|
|
295
|
+
* highlighting, autocompletion, bracket matching and smart indentation, with a
|
|
296
|
+
* per-block language picker. Serializes to standard
|
|
297
|
+
* `<pre><code class="language-...">` HTML, so content round-trips unchanged.
|
|
298
|
+
*/
|
|
299
|
+
export const CodeBlockEditor = CodeBlock.extend({
|
|
300
|
+
addOptions() {
|
|
301
|
+
const parent = this.parent?.() ?? {};
|
|
302
|
+
return {
|
|
303
|
+
...parent,
|
|
304
|
+
defaultLanguage: 'javascript',
|
|
305
|
+
languages: null
|
|
306
|
+
};
|
|
307
|
+
},
|
|
308
|
+
addKeyboardShortcuts() {
|
|
309
|
+
return {
|
|
310
|
+
...this.parent?.(),
|
|
311
|
+
ArrowLeft: arrowIntoCodeBlock('left'),
|
|
312
|
+
ArrowRight: arrowIntoCodeBlock('right'),
|
|
313
|
+
ArrowUp: arrowIntoCodeBlock('up'),
|
|
314
|
+
ArrowDown: arrowIntoCodeBlock('down')
|
|
315
|
+
};
|
|
316
|
+
},
|
|
317
|
+
addNodeView() {
|
|
318
|
+
const configured = this.options.languages;
|
|
319
|
+
const languages = configured
|
|
320
|
+
? configured
|
|
321
|
+
.map((id) => resolveCodeBlockLanguage(id))
|
|
322
|
+
.filter((def) => Boolean(def))
|
|
323
|
+
: codeBlockLanguages;
|
|
324
|
+
return ({ node, editor, getPos }) => new CodeBlockView(node, editor, getPos, languages);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Node } from '@tiptap/core';
|
|
2
|
+
export interface DivOptions {
|
|
3
|
+
HTMLAttributes: Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
declare module '@tiptap/core' {
|
|
6
|
+
interface Commands<ReturnType> {
|
|
7
|
+
div: {
|
|
8
|
+
/**
|
|
9
|
+
* Set the current node as a div
|
|
10
|
+
*/
|
|
11
|
+
setDiv: () => ReturnType;
|
|
12
|
+
/**
|
|
13
|
+
* Toggle between div and paragraph
|
|
14
|
+
*/
|
|
15
|
+
toggleDiv: () => ReturnType;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export declare const Div: Node<DivOptions, any>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Node, mergeAttributes } from '@tiptap/core';
|
|
2
|
+
export const Div = Node.create({
|
|
3
|
+
name: 'div',
|
|
4
|
+
group: 'block',
|
|
5
|
+
content: 'block*',
|
|
6
|
+
isolating: false,
|
|
7
|
+
defining: false,
|
|
8
|
+
addOptions() {
|
|
9
|
+
return {
|
|
10
|
+
HTMLAttributes: {},
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
parseHTML() {
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
tag: 'div',
|
|
17
|
+
// Preserve all attributes
|
|
18
|
+
getAttrs: (node) => {
|
|
19
|
+
if (typeof node === 'string')
|
|
20
|
+
return false;
|
|
21
|
+
const element = node;
|
|
22
|
+
// Skip if it's an alert or other custom node with data-type
|
|
23
|
+
if (element.getAttribute('data-type'))
|
|
24
|
+
return false;
|
|
25
|
+
// Preserve all attributes
|
|
26
|
+
const attrs = {};
|
|
27
|
+
Array.from(element.attributes).forEach(attr => {
|
|
28
|
+
attrs[attr.name] = attr.value;
|
|
29
|
+
});
|
|
30
|
+
return attrs;
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
},
|
|
35
|
+
renderHTML({ HTMLAttributes }) {
|
|
36
|
+
return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
|
|
37
|
+
},
|
|
38
|
+
addCommands() {
|
|
39
|
+
return {
|
|
40
|
+
setDiv: () => ({ commands }) => {
|
|
41
|
+
return commands.setNode(this.name);
|
|
42
|
+
},
|
|
43
|
+
toggleDiv: () => ({ commands }) => {
|
|
44
|
+
return commands.toggleNode(this.name, 'paragraph');
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
addAttributes() {
|
|
49
|
+
return {
|
|
50
|
+
// Preserve all HTML attributes
|
|
51
|
+
class: {
|
|
52
|
+
default: null,
|
|
53
|
+
parseHTML: element => element.getAttribute('class'),
|
|
54
|
+
renderHTML: attributes => {
|
|
55
|
+
if (!attributes.class)
|
|
56
|
+
return {};
|
|
57
|
+
return { class: attributes.class };
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
style: {
|
|
61
|
+
default: null,
|
|
62
|
+
parseHTML: element => element.getAttribute('style'),
|
|
63
|
+
renderHTML: attributes => {
|
|
64
|
+
if (!attributes.style)
|
|
65
|
+
return {};
|
|
66
|
+
return { style: attributes.style };
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
id: {
|
|
70
|
+
default: null,
|
|
71
|
+
parseHTML: element => element.getAttribute('id'),
|
|
72
|
+
renderHTML: attributes => {
|
|
73
|
+
if (!attributes.id)
|
|
74
|
+
return {};
|
|
75
|
+
return { id: attributes.id };
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
'data-type': {
|
|
79
|
+
default: null,
|
|
80
|
+
parseHTML: element => element.getAttribute('data-type'),
|
|
81
|
+
renderHTML: attributes => {
|
|
82
|
+
if (!attributes['data-type'])
|
|
83
|
+
return {};
|
|
84
|
+
return { 'data-type': attributes['data-type'] };
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
});
|