@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,856 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, onDestroy } from 'svelte';
|
|
3
|
+
import { Editor, Extension, type AnyExtension } from '@tiptap/core';
|
|
4
|
+
import { StarterKit } from '@tiptap/starter-kit';
|
|
5
|
+
import { BubbleMenu } from '@tiptap/extension-bubble-menu';
|
|
6
|
+
import Underline from '@tiptap/extension-underline';
|
|
7
|
+
import TextAlign from '@tiptap/extension-text-align';
|
|
8
|
+
import Link from '@tiptap/extension-link';
|
|
9
|
+
import Subscript from '@tiptap/extension-subscript';
|
|
10
|
+
import Superscript from '@tiptap/extension-superscript';
|
|
11
|
+
import Image from '@tiptap/extension-image';
|
|
12
|
+
import { TableKit } from '@tiptap/extension-table';
|
|
13
|
+
import Color from '@tiptap/extension-color';
|
|
14
|
+
import Placeholder from '@tiptap/extension-placeholder';
|
|
15
|
+
import { TextStyle } from '@tiptap/extension-text-style';
|
|
16
|
+
import Collaboration from '@tiptap/extension-collaboration';
|
|
17
|
+
import { CollaborationCaret } from '@tiptap/extension-collaboration-caret';
|
|
18
|
+
import { Alert, CodeBlockEditor, Div, Span, type CodeBlocksOptions } from './extensions/index.js';
|
|
19
|
+
import type { CollaborationConfig } from './collaboration.js';
|
|
20
|
+
import FormGroup from '../../form/FormGroup.svelte';
|
|
21
|
+
import LinkActionMenu from './LinkActionMenu.svelte';
|
|
22
|
+
import UndoButton from './toolbar/UndoButton.svelte';
|
|
23
|
+
import RedoButton from './toolbar/RedoButton.svelte';
|
|
24
|
+
import HeadingButton from './toolbar/HeadingButton.svelte';
|
|
25
|
+
import BulletListButton from './toolbar/BulletListButton.svelte';
|
|
26
|
+
import OrderedListButton from './toolbar/OrderedListButton.svelte';
|
|
27
|
+
import BoldButton from './toolbar/BoldButton.svelte';
|
|
28
|
+
import ItalicButton from './toolbar/ItalicButton.svelte';
|
|
29
|
+
import StrikethroughButton from './toolbar/StrikethroughButton.svelte';
|
|
30
|
+
import CodeButton from './toolbar/CodeButton.svelte';
|
|
31
|
+
import UnderlineButton from './toolbar/UnderlineButton.svelte';
|
|
32
|
+
import ColorButton from './toolbar/ColorButton.svelte';
|
|
33
|
+
import LinkButton from './toolbar/LinkButton.svelte';
|
|
34
|
+
import SuperscriptButton from './toolbar/SuperscriptButton.svelte';
|
|
35
|
+
import SubscriptButton from './toolbar/SubscriptButton.svelte';
|
|
36
|
+
import AlignLeftButton from './toolbar/AlignLeftButton.svelte';
|
|
37
|
+
import AlignCenterButton from './toolbar/AlignCenterButton.svelte';
|
|
38
|
+
import AlignRightButton from './toolbar/AlignRightButton.svelte';
|
|
39
|
+
import AlignJustifyButton from './toolbar/AlignJustifyButton.svelte';
|
|
40
|
+
import ImageButton from './toolbar/ImageButton.svelte';
|
|
41
|
+
import AlertButton from './toolbar/AlertButton.svelte';
|
|
42
|
+
import HtmlButton from './toolbar/HtmlButton.svelte';
|
|
43
|
+
import DocumentButton from './toolbar/DocumentButton.svelte';
|
|
44
|
+
import TableButton from './toolbar/TableButton.svelte';
|
|
45
|
+
import CodeBlockButton from './toolbar/CodeBlockButton.svelte';
|
|
46
|
+
|
|
47
|
+
/** Result returned from a document upload: the link text and its destination URL */
|
|
48
|
+
export interface DocumentUploadResult {
|
|
49
|
+
/** Visible link text inserted into the editor */
|
|
50
|
+
label: string;
|
|
51
|
+
/** Destination URL the hyperlink points to */
|
|
52
|
+
url: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TipTapProps {
|
|
56
|
+
/** HTML content value (bindable). Ignored when collaboration is enabled. */
|
|
57
|
+
value?: string;
|
|
58
|
+
/** Label text displayed above the editor */
|
|
59
|
+
label?: string;
|
|
60
|
+
/** Mark field as required (shows asterisk) */
|
|
61
|
+
required?: boolean;
|
|
62
|
+
/** CSS classes for the FormGroup wrapper */
|
|
63
|
+
groupClass?: string;
|
|
64
|
+
/** Tooltip text on hover */
|
|
65
|
+
tooltipText?: string;
|
|
66
|
+
/** Position of the tooltip */
|
|
67
|
+
tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
|
|
68
|
+
/** Enable editing mode */
|
|
69
|
+
editable?: boolean;
|
|
70
|
+
/** Placeholder text when editor is empty */
|
|
71
|
+
placeholder?: string;
|
|
72
|
+
/** Additional CSS classes */
|
|
73
|
+
class?: string;
|
|
74
|
+
/** Async handler for image uploads, returns URL or null */
|
|
75
|
+
onImageUpload?: (file: File) => Promise<string | null>;
|
|
76
|
+
/** Async handler for document uploads. The app uploads the file and returns the
|
|
77
|
+
* link label and URL, which are inserted as a hyperlink. Returns null to cancel. */
|
|
78
|
+
onDocumentUpload?: (file: File) => Promise<DocumentUploadResult | null>;
|
|
79
|
+
/** Callback when content changes */
|
|
80
|
+
onUpdate?: (html: string) => void;
|
|
81
|
+
/** Opt-in real-time collaboration config. When provided, content syncs via Yjs. */
|
|
82
|
+
collaboration?: CollaborationConfig;
|
|
83
|
+
/** Opt-in rich code blocks: CodeMirror-powered editing with syntax highlighting,
|
|
84
|
+
* autocompletion and a per-block language picker. Pass true for all languages
|
|
85
|
+
* or a config to narrow the offered languages and set the default. */
|
|
86
|
+
codeBlocks?: boolean | CodeBlocksOptions;
|
|
87
|
+
/** Additional TipTap extensions to register with the editor */
|
|
88
|
+
extensions?: AnyExtension[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let {
|
|
92
|
+
value = $bindable(''),
|
|
93
|
+
label = '',
|
|
94
|
+
required = false,
|
|
95
|
+
groupClass = '',
|
|
96
|
+
tooltipText = undefined,
|
|
97
|
+
tooltipLocation = 'top',
|
|
98
|
+
editable = true,
|
|
99
|
+
placeholder = 'Start typing...',
|
|
100
|
+
class: className = '',
|
|
101
|
+
onImageUpload,
|
|
102
|
+
onDocumentUpload,
|
|
103
|
+
onUpdate,
|
|
104
|
+
collaboration,
|
|
105
|
+
codeBlocks = false,
|
|
106
|
+
extensions: customExtensions = []
|
|
107
|
+
}: TipTapProps = $props();
|
|
108
|
+
|
|
109
|
+
let element: HTMLElement | undefined = $state();
|
|
110
|
+
let linkBubbleMenuElement: HTMLDivElement | undefined = $state();
|
|
111
|
+
let editorState: { editor: Editor | null } = $state({ editor: null });
|
|
112
|
+
let isDragging = $state(false);
|
|
113
|
+
|
|
114
|
+
// Handle dropped files
|
|
115
|
+
async function handleDrop(event: DragEvent) {
|
|
116
|
+
if (!onImageUpload || !editorState.editor) return;
|
|
117
|
+
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
isDragging = false;
|
|
120
|
+
|
|
121
|
+
const files = event.dataTransfer?.files;
|
|
122
|
+
if (!files?.length) return;
|
|
123
|
+
|
|
124
|
+
for (const file of files) {
|
|
125
|
+
if (file.type.startsWith('image/')) {
|
|
126
|
+
const imageUrl = await onImageUpload(file);
|
|
127
|
+
if (imageUrl) {
|
|
128
|
+
editorState.editor.chain().focus().setImage({ src: imageUrl }).run();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Handle drag over
|
|
135
|
+
function handleDragOver(event: DragEvent) {
|
|
136
|
+
if (!onImageUpload) return;
|
|
137
|
+
event.preventDefault();
|
|
138
|
+
isDragging = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Handle drag leave
|
|
142
|
+
function handleDragLeave(event: DragEvent) {
|
|
143
|
+
if (!onImageUpload) return;
|
|
144
|
+
// Only set to false if we're leaving the container entirely
|
|
145
|
+
const relatedTarget = event.relatedTarget as Node | null;
|
|
146
|
+
if (!element?.contains(relatedTarget)) {
|
|
147
|
+
isDragging = false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Handle paste events
|
|
152
|
+
async function handlePaste(event: ClipboardEvent) {
|
|
153
|
+
if (!onImageUpload || !editorState.editor) return;
|
|
154
|
+
|
|
155
|
+
const items = event.clipboardData?.items;
|
|
156
|
+
if (!items) return;
|
|
157
|
+
|
|
158
|
+
for (const item of items) {
|
|
159
|
+
if (item.type.startsWith('image/')) {
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
const file = item.getAsFile();
|
|
162
|
+
if (file) {
|
|
163
|
+
const imageUrl = await onImageUpload(file);
|
|
164
|
+
if (imageUrl) {
|
|
165
|
+
editorState.editor.chain().focus().setImage({ src: imageUrl }).run();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Strip color declarations from inline styles in pasted HTML so pasted text
|
|
174
|
+
// inherits the editor's colours instead of carrying over the source colours.
|
|
175
|
+
function stripPastedColors(html: string): string {
|
|
176
|
+
if (typeof window === 'undefined') return html;
|
|
177
|
+
|
|
178
|
+
const container = document.createElement('div');
|
|
179
|
+
container.innerHTML = html;
|
|
180
|
+
|
|
181
|
+
container.querySelectorAll<HTMLElement>('[style]').forEach((el) => {
|
|
182
|
+
const cleaned = el.style.cssText
|
|
183
|
+
.split(';')
|
|
184
|
+
.map((decl) => decl.trim())
|
|
185
|
+
.filter((decl) => {
|
|
186
|
+
if (!decl) return false;
|
|
187
|
+
const prop = decl.slice(0, decl.indexOf(':')).trim().toLowerCase();
|
|
188
|
+
return prop !== 'color' && prop !== '-webkit-text-fill-color';
|
|
189
|
+
})
|
|
190
|
+
.join('; ');
|
|
191
|
+
|
|
192
|
+
if (cleaned) {
|
|
193
|
+
el.setAttribute('style', cleaned);
|
|
194
|
+
} else {
|
|
195
|
+
el.removeAttribute('style');
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Drop legacy <font color> attributes as well.
|
|
200
|
+
container.querySelectorAll('font[color]').forEach((el) => el.removeAttribute('color'));
|
|
201
|
+
|
|
202
|
+
return container.innerHTML;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function handleEditorClick(event: MouseEvent) {
|
|
206
|
+
const target = event.target as HTMLElement | null;
|
|
207
|
+
const link = target?.closest('a');
|
|
208
|
+
|
|
209
|
+
if (!link || !element?.contains(link)) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
|
|
215
|
+
const position = editorState.editor?.view.posAtCoords({
|
|
216
|
+
left: event.clientX,
|
|
217
|
+
top: event.clientY
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
if (position) {
|
|
221
|
+
editorState.editor?.chain().setTextSelection(position.pos).extendMarkRange('link').run();
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Custom Tab Handler Extension
|
|
226
|
+
const TabHandler = Extension.create({
|
|
227
|
+
name: 'tabHandler',
|
|
228
|
+
|
|
229
|
+
addKeyboardShortcuts() {
|
|
230
|
+
return {
|
|
231
|
+
Tab: ({ editor }) => {
|
|
232
|
+
// Rich code blocks handle Tab inside CodeMirror; never replace a
|
|
233
|
+
// selected code block with spaces
|
|
234
|
+
if (codeBlocks && editor.isActive('codeBlock')) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// If in a list, indent the list item
|
|
239
|
+
if (editor.isActive('listItem')) {
|
|
240
|
+
return editor.commands.sinkListItem('listItem');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// If in a table, move to the next cell
|
|
244
|
+
if (editor.isActive('table')) {
|
|
245
|
+
return editor.commands.goToNextCell();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Otherwise, insert two spaces (or you can use '\t' for a tab character)
|
|
249
|
+
return editor.commands.insertContent(' ');
|
|
250
|
+
},
|
|
251
|
+
'Shift-Tab': ({ editor }) => {
|
|
252
|
+
// If in a list, outdent the list item
|
|
253
|
+
if (editor.isActive('listItem')) {
|
|
254
|
+
return editor.commands.liftListItem('listItem');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// If in a table, move to the previous cell
|
|
258
|
+
if (editor.isActive('table')) {
|
|
259
|
+
return editor.commands.goToPreviousCell();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
onMount(() => {
|
|
269
|
+
const extensions = [
|
|
270
|
+
// Div and Span must come before StarterKit to have higher priority
|
|
271
|
+
Div,
|
|
272
|
+
Span,
|
|
273
|
+
StarterKit.configure({
|
|
274
|
+
undoRedo: collaboration ? false : undefined,
|
|
275
|
+
link: false,
|
|
276
|
+
underline: false,
|
|
277
|
+
codeBlock: codeBlocks ? false : undefined
|
|
278
|
+
}),
|
|
279
|
+
Underline,
|
|
280
|
+
TextStyle,
|
|
281
|
+
Color,
|
|
282
|
+
Placeholder.configure({
|
|
283
|
+
placeholder: placeholder
|
|
284
|
+
}),
|
|
285
|
+
TextAlign.configure({
|
|
286
|
+
types: ['heading', 'paragraph', 'div', 'span']
|
|
287
|
+
}),
|
|
288
|
+
Link.configure({
|
|
289
|
+
openOnClick: false,
|
|
290
|
+
enableClickSelection: true,
|
|
291
|
+
HTMLAttributes: {
|
|
292
|
+
class: 'editor-link'
|
|
293
|
+
}
|
|
294
|
+
}),
|
|
295
|
+
Subscript,
|
|
296
|
+
Superscript,
|
|
297
|
+
Image,
|
|
298
|
+
Alert,
|
|
299
|
+
TabHandler,
|
|
300
|
+
TableKit.configure({ table: { resizable: true } }),
|
|
301
|
+
...customExtensions
|
|
302
|
+
];
|
|
303
|
+
|
|
304
|
+
if (codeBlocks) {
|
|
305
|
+
const codeBlocksConfig = typeof codeBlocks === 'object' ? codeBlocks : {};
|
|
306
|
+
extensions.push(
|
|
307
|
+
CodeBlockEditor.configure({
|
|
308
|
+
languages: codeBlocksConfig.languages ?? null,
|
|
309
|
+
defaultLanguage: codeBlocksConfig.defaultLanguage ?? 'javascript'
|
|
310
|
+
})
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (linkBubbleMenuElement) {
|
|
315
|
+
extensions.push(
|
|
316
|
+
BubbleMenu.configure({
|
|
317
|
+
pluginKey: 'linkActionBubbleMenu',
|
|
318
|
+
element: linkBubbleMenuElement,
|
|
319
|
+
shouldShow: ({ editor }) => Boolean(editor.getAttributes('link').href),
|
|
320
|
+
options: {
|
|
321
|
+
placement: 'top',
|
|
322
|
+
offset: 8
|
|
323
|
+
}
|
|
324
|
+
})
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (collaboration) {
|
|
329
|
+
extensions.push(
|
|
330
|
+
Collaboration.configure({ fragment: collaboration.fragment }),
|
|
331
|
+
CollaborationCaret.configure({
|
|
332
|
+
provider: collaboration.provider,
|
|
333
|
+
user: collaboration.user
|
|
334
|
+
})
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
editorState.editor = new Editor({
|
|
339
|
+
element: element,
|
|
340
|
+
extensions,
|
|
341
|
+
content: collaboration ? undefined : value,
|
|
342
|
+
editable: editable,
|
|
343
|
+
editorProps: {
|
|
344
|
+
transformPastedHTML: stripPastedColors
|
|
345
|
+
},
|
|
346
|
+
onTransaction: ({ editor }) => {
|
|
347
|
+
// Trigger reactivity
|
|
348
|
+
editorState = { editor };
|
|
349
|
+
},
|
|
350
|
+
onUpdate: ({ editor }) => {
|
|
351
|
+
const html = editor.getHTML();
|
|
352
|
+
value = html;
|
|
353
|
+
if (onUpdate) {
|
|
354
|
+
onUpdate(html);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
if (element) {
|
|
360
|
+
element.addEventListener('click', handleEditorClick, true);
|
|
361
|
+
// Add paste event listener for image paste support
|
|
362
|
+
element.addEventListener('paste', handlePaste as unknown as EventListener);
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
onDestroy(() => {
|
|
367
|
+
element?.removeEventListener('click', handleEditorClick, true);
|
|
368
|
+
element?.removeEventListener('paste', handlePaste as unknown as EventListener);
|
|
369
|
+
editorState.editor?.destroy();
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// Public API methods
|
|
373
|
+
export function getHTML(): string {
|
|
374
|
+
const editor = editorState.editor;
|
|
375
|
+
if (!editor || editor.isDestroyed) return '';
|
|
376
|
+
return editor.getHTML();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export function getJSON(): object {
|
|
380
|
+
const editor = editorState.editor;
|
|
381
|
+
if (!editor || editor.isDestroyed) return {};
|
|
382
|
+
return editor.getJSON();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export function setContent(html: string) {
|
|
386
|
+
const editor = editorState.editor;
|
|
387
|
+
if (!editor || editor.isDestroyed) return;
|
|
388
|
+
editor.commands.setContent(html);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export function clear() {
|
|
392
|
+
const editor = editorState.editor;
|
|
393
|
+
if (!editor || editor.isDestroyed) return;
|
|
394
|
+
editor.commands.clearContent();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export function focus() {
|
|
398
|
+
const editor = editorState.editor;
|
|
399
|
+
if (!editor || editor.isDestroyed) return;
|
|
400
|
+
editor.commands.focus();
|
|
401
|
+
}
|
|
402
|
+
</script>
|
|
403
|
+
|
|
404
|
+
<FormGroup {label} {required} class={groupClass} {tooltipLocation} {tooltipText}>
|
|
405
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
406
|
+
<div
|
|
407
|
+
class="editor-container {className}"
|
|
408
|
+
class:dragging={isDragging}
|
|
409
|
+
ondragover={handleDragOver}
|
|
410
|
+
ondragleave={handleDragLeave}
|
|
411
|
+
ondrop={handleDrop}
|
|
412
|
+
>
|
|
413
|
+
{#if editorState.editor && editable}
|
|
414
|
+
<div class="toolbar">
|
|
415
|
+
<div class="toolbar-group">
|
|
416
|
+
<UndoButton editor={editorState.editor} />
|
|
417
|
+
<RedoButton editor={editorState.editor} />
|
|
418
|
+
</div>
|
|
419
|
+
|
|
420
|
+
<div class="toolbar-divider"></div>
|
|
421
|
+
|
|
422
|
+
<div class="toolbar-group">
|
|
423
|
+
<HeadingButton editor={editorState.editor} level={1} />
|
|
424
|
+
<HeadingButton editor={editorState.editor} level={2} />
|
|
425
|
+
<HeadingButton editor={editorState.editor} level={3} />
|
|
426
|
+
</div>
|
|
427
|
+
|
|
428
|
+
<div class="toolbar-divider"></div>
|
|
429
|
+
|
|
430
|
+
<div class="toolbar-group">
|
|
431
|
+
<BoldButton editor={editorState.editor} />
|
|
432
|
+
<ItalicButton editor={editorState.editor} />
|
|
433
|
+
<StrikethroughButton editor={editorState.editor} />
|
|
434
|
+
<CodeButton editor={editorState.editor} />
|
|
435
|
+
{#if codeBlocks}
|
|
436
|
+
<CodeBlockButton editor={editorState.editor} />
|
|
437
|
+
{/if}
|
|
438
|
+
<UnderlineButton editor={editorState.editor} />
|
|
439
|
+
<ColorButton editor={editorState.editor} />
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
<div class="toolbar-divider"></div>
|
|
443
|
+
|
|
444
|
+
<div class="toolbar-group">
|
|
445
|
+
<BulletListButton editor={editorState.editor} />
|
|
446
|
+
<OrderedListButton editor={editorState.editor} />
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
<div class="toolbar-divider"></div>
|
|
450
|
+
|
|
451
|
+
<div class="toolbar-group">
|
|
452
|
+
<TableButton editor={editorState.editor} />
|
|
453
|
+
</div>
|
|
454
|
+
|
|
455
|
+
<div class="toolbar-divider"></div>
|
|
456
|
+
|
|
457
|
+
<div class="toolbar-group">
|
|
458
|
+
<LinkButton editor={editorState.editor} />
|
|
459
|
+
<SuperscriptButton editor={editorState.editor} />
|
|
460
|
+
<SubscriptButton editor={editorState.editor} />
|
|
461
|
+
</div>
|
|
462
|
+
|
|
463
|
+
<div class="toolbar-divider"></div>
|
|
464
|
+
|
|
465
|
+
<div class="toolbar-group">
|
|
466
|
+
<AlignLeftButton editor={editorState.editor} />
|
|
467
|
+
<AlignCenterButton editor={editorState.editor} />
|
|
468
|
+
<AlignRightButton editor={editorState.editor} />
|
|
469
|
+
<AlignJustifyButton editor={editorState.editor} />
|
|
470
|
+
</div>
|
|
471
|
+
|
|
472
|
+
{#if onImageUpload || onDocumentUpload}
|
|
473
|
+
<div class="toolbar-divider"></div>
|
|
474
|
+
|
|
475
|
+
<div class="toolbar-group">
|
|
476
|
+
{#if onImageUpload}
|
|
477
|
+
<ImageButton editor={editorState.editor} {onImageUpload} />
|
|
478
|
+
{/if}
|
|
479
|
+
{#if onDocumentUpload}
|
|
480
|
+
<DocumentButton editor={editorState.editor} {onDocumentUpload} />
|
|
481
|
+
{/if}
|
|
482
|
+
</div>
|
|
483
|
+
{/if}
|
|
484
|
+
|
|
485
|
+
<div class="toolbar-divider"></div>
|
|
486
|
+
|
|
487
|
+
<div class="toolbar-group">
|
|
488
|
+
<AlertButton editor={editorState.editor} />
|
|
489
|
+
</div>
|
|
490
|
+
|
|
491
|
+
<div class="toolbar-divider"></div>
|
|
492
|
+
|
|
493
|
+
<div class="toolbar-group">
|
|
494
|
+
<HtmlButton editor={editorState.editor} />
|
|
495
|
+
</div>
|
|
496
|
+
</div>
|
|
497
|
+
{/if}
|
|
498
|
+
|
|
499
|
+
<div
|
|
500
|
+
bind:this={linkBubbleMenuElement}
|
|
501
|
+
class="link-bubble-menu"
|
|
502
|
+
style="visibility: hidden; opacity: 0; position: absolute;"
|
|
503
|
+
>
|
|
504
|
+
{#if editorState.editor}
|
|
505
|
+
<LinkActionMenu editor={editorState.editor} {editable} />
|
|
506
|
+
{/if}
|
|
507
|
+
</div>
|
|
508
|
+
|
|
509
|
+
<div class="editor-content" bind:this={element}></div>
|
|
510
|
+
</div>
|
|
511
|
+
</FormGroup>
|
|
512
|
+
|
|
513
|
+
<style>
|
|
514
|
+
.editor-container {
|
|
515
|
+
position: relative;
|
|
516
|
+
border: 1px solid var(--border-color);
|
|
517
|
+
border-radius: 6px;
|
|
518
|
+
background: var(--paper-body-bg);
|
|
519
|
+
font-family: var(--ui-font-family);
|
|
520
|
+
transition: border-color 0.2s ease;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.editor-container.dragging {
|
|
524
|
+
border-color: var(--ui-tertiary);
|
|
525
|
+
border-style: dashed;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.toolbar {
|
|
529
|
+
display: flex;
|
|
530
|
+
align-items: center;
|
|
531
|
+
gap: 4px;
|
|
532
|
+
padding: 6px;
|
|
533
|
+
border-bottom: 1px solid var(--border-color);
|
|
534
|
+
background: var(--paper-title-bg);
|
|
535
|
+
border-radius: 6px 6px 0 0;
|
|
536
|
+
flex-wrap: wrap;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.toolbar-group {
|
|
540
|
+
display: flex;
|
|
541
|
+
align-items: center;
|
|
542
|
+
gap: 2px;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.toolbar-divider {
|
|
546
|
+
width: 1px;
|
|
547
|
+
height: 24px;
|
|
548
|
+
background: var(--border-color);
|
|
549
|
+
margin: 0 4px;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
.link-bubble-menu {
|
|
553
|
+
z-index: 1100;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.editor-content {
|
|
557
|
+
padding: 16px;
|
|
558
|
+
min-height: 200px;
|
|
559
|
+
color: var(--text-color);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/* TipTap Editor Styles */
|
|
563
|
+
.editor-content :global(.ProseMirror) {
|
|
564
|
+
outline: none;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.editor-content :global(.ProseMirror p) {
|
|
568
|
+
margin: 0 0 1em 0;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.editor-content :global(.ProseMirror h1) {
|
|
572
|
+
font-size: 2em;
|
|
573
|
+
font-weight: bold;
|
|
574
|
+
margin: 0.67em 0;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.editor-content :global(.ProseMirror h2) {
|
|
578
|
+
font-size: 1.5em;
|
|
579
|
+
font-weight: bold;
|
|
580
|
+
margin: 0.75em 0;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
.editor-content :global(.ProseMirror h3) {
|
|
584
|
+
font-size: 1.17em;
|
|
585
|
+
font-weight: bold;
|
|
586
|
+
margin: 0.83em 0;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.editor-content :global(.ProseMirror ul),
|
|
590
|
+
.editor-content :global(.ProseMirror ol) {
|
|
591
|
+
padding-left: 1.5em;
|
|
592
|
+
margin: 1em 0;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
.editor-content :global(.ProseMirror code) {
|
|
596
|
+
background: var(--page-bg);
|
|
597
|
+
padding: 2px 6px;
|
|
598
|
+
border-radius: 3px;
|
|
599
|
+
font-family: 'Monaco', 'Courier New', monospace;
|
|
600
|
+
font-size: 0.9em;
|
|
601
|
+
color: var(--ui-accent-dark);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
:global(.dark) .editor-content :global(.ProseMirror code) {
|
|
605
|
+
color: var(--ui-accent);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.editor-content :global(.ProseMirror a) {
|
|
609
|
+
color: var(--ui-tertiary-dark);
|
|
610
|
+
text-decoration: underline;
|
|
611
|
+
cursor: pointer;
|
|
612
|
+
pointer-events: auto;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
:global(.dark) .editor-content :global(.ProseMirror a) {
|
|
616
|
+
color: var(--ui-tertiary);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.editor-content :global(.ProseMirror a.editor-link) {
|
|
620
|
+
cursor: pointer;
|
|
621
|
+
pointer-events: auto;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.editor-content :global(.ProseMirror a.editor-link:hover) {
|
|
625
|
+
background: rgba(var(--ui-primary-rgbc), 0.1);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
:global(.dark) .editor-content :global(.ProseMirror a.editor-link:hover) {
|
|
629
|
+
background: rgba(var(--ui-accent-rgbc), 0.1);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/* Ensure the editor remains clickable while links show the action menu. */
|
|
633
|
+
.editor-content :global(.ProseMirror) {
|
|
634
|
+
pointer-events: auto;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
.editor-content :global(.ProseMirror img) {
|
|
638
|
+
max-width: 100%;
|
|
639
|
+
height: auto;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/* Table styles */
|
|
643
|
+
.editor-content :global(.ProseMirror .tableWrapper) {
|
|
644
|
+
overflow-x: auto;
|
|
645
|
+
margin: 1em 0;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.editor-content :global(.ProseMirror table) {
|
|
649
|
+
border-collapse: collapse;
|
|
650
|
+
table-layout: fixed;
|
|
651
|
+
width: 100%;
|
|
652
|
+
overflow: hidden;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.editor-content :global(.ProseMirror th),
|
|
656
|
+
.editor-content :global(.ProseMirror td) {
|
|
657
|
+
position: relative;
|
|
658
|
+
border: 1px solid var(--border-color);
|
|
659
|
+
padding: 6px 10px;
|
|
660
|
+
vertical-align: top;
|
|
661
|
+
min-width: 1em;
|
|
662
|
+
box-sizing: border-box;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.editor-content :global(.ProseMirror th) {
|
|
666
|
+
background: var(--paper-title-bg);
|
|
667
|
+
font-weight: 600;
|
|
668
|
+
text-align: left;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
.editor-content :global(.ProseMirror table p) {
|
|
672
|
+
margin: 0;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
.editor-content :global(.ProseMirror .selectedCell::after) {
|
|
676
|
+
content: '';
|
|
677
|
+
position: absolute;
|
|
678
|
+
inset: 0;
|
|
679
|
+
background: rgba(var(--ui-primary-rgbc), 0.08);
|
|
680
|
+
pointer-events: none;
|
|
681
|
+
z-index: 2;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
:global(.dark) .editor-content :global(.ProseMirror .selectedCell::after) {
|
|
685
|
+
background: rgba(var(--ui-accent-rgbc), 0.12);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.editor-content :global(.ProseMirror .column-resize-handle) {
|
|
689
|
+
position: absolute;
|
|
690
|
+
top: 0;
|
|
691
|
+
bottom: -2px;
|
|
692
|
+
right: -2px;
|
|
693
|
+
width: 4px;
|
|
694
|
+
background: var(--ui-tertiary);
|
|
695
|
+
pointer-events: none;
|
|
696
|
+
z-index: 20;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
.editor-content :global(.ProseMirror.resize-cursor) {
|
|
700
|
+
cursor: col-resize;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
.editor-content :global(.ProseMirror [style*='text-align: left']) {
|
|
704
|
+
text-align: left;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.editor-content :global(.ProseMirror [style*='text-align: center']) {
|
|
708
|
+
text-align: center;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.editor-content :global(.ProseMirror [style*='text-align: right']) {
|
|
712
|
+
text-align: right;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
.editor-content :global(.ProseMirror [style*='text-align: justify']) {
|
|
716
|
+
text-align: justify;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/* Placeholder styles */
|
|
720
|
+
.editor-content :global(.ProseMirror p.is-editor-empty:first-child::before) {
|
|
721
|
+
content: attr(data-placeholder);
|
|
722
|
+
float: left;
|
|
723
|
+
color: var(--placeholder-color);
|
|
724
|
+
pointer-events: none;
|
|
725
|
+
height: 0;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/* Alert styles */
|
|
729
|
+
.editor-content :global(.ProseMirror .alert) {
|
|
730
|
+
display: flex;
|
|
731
|
+
flex-direction: column;
|
|
732
|
+
border-radius: 0.25rem;
|
|
733
|
+
padding: 0.5rem;
|
|
734
|
+
margin: 0.5rem 0;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
.editor-content :global(.ProseMirror .alert-title) {
|
|
738
|
+
margin-bottom: 0.25rem;
|
|
739
|
+
font-weight: 700;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
.editor-content :global(.ProseMirror .alert-title::before) {
|
|
743
|
+
content: attr(data-title-element);
|
|
744
|
+
display: none;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.editor-content :global(.ProseMirror .alert-content) {
|
|
748
|
+
line-height: 1.5;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/* Default variant - use pistachio theme */
|
|
752
|
+
.editor-content :global(.ProseMirror .alert-default) {
|
|
753
|
+
background: rgba(var(--ui-accent-rgbc), 0.3);
|
|
754
|
+
border: 1px solid var(--ui-accent);
|
|
755
|
+
color: var(--text-color);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
.editor-content :global(.ProseMirror .alert-default .alert-title) {
|
|
759
|
+
color: var(--ui-primary);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/* Danger variant */
|
|
763
|
+
.editor-content :global(.ProseMirror .alert-danger) {
|
|
764
|
+
background: #f8d7da;
|
|
765
|
+
color: #58151c;
|
|
766
|
+
border: 1px solid #f1aeb5;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
.editor-content :global(.ProseMirror .alert-danger .alert-title) {
|
|
770
|
+
color: #58151c;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/* Warning variant */
|
|
774
|
+
.editor-content :global(.ProseMirror .alert-warning) {
|
|
775
|
+
background: #fff3cd;
|
|
776
|
+
color: #664d03;
|
|
777
|
+
border: 1px solid #ffe69c;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
.editor-content :global(.ProseMirror .alert-warning .alert-title) {
|
|
781
|
+
color: #664d03;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
/* Dark mode alert variants */
|
|
785
|
+
:global(.dark) .editor-content :global(.ProseMirror .alert-default) {
|
|
786
|
+
background: rgba(var(--ui-primary-rgbc), 0.3);
|
|
787
|
+
border-color: var(--ui-primary);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
:global(.dark) .editor-content :global(.ProseMirror .alert-default .alert-title) {
|
|
791
|
+
color: var(--white);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
:global(.dark) .editor-content :global(.ProseMirror .alert-danger) {
|
|
795
|
+
background: #2c0b0e;
|
|
796
|
+
color: #ea868f;
|
|
797
|
+
border-color: #842029;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
:global(.dark) .editor-content :global(.ProseMirror .alert-danger .alert-title) {
|
|
801
|
+
color: #ea868f;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
:global(.dark) .editor-content :global(.ProseMirror .alert-warning) {
|
|
805
|
+
background: #332701;
|
|
806
|
+
color: #fff3cd;
|
|
807
|
+
border-color: #997404;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
:global(.dark) .editor-content :global(.ProseMirror .alert-warning .alert-title) {
|
|
811
|
+
color: #fff3cd;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
.editor-content :global(.alert p:last-child) {
|
|
815
|
+
margin-bottom: 0;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
.editor-content :global(.tiptap p:last-child) {
|
|
819
|
+
margin-bottom: 0;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.editor-content :global(.alert) {
|
|
823
|
+
margin-bottom: 1rem !important;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/* Collaboration caret styles */
|
|
827
|
+
.editor-content :global(.collaboration-carets__caret) {
|
|
828
|
+
position: relative;
|
|
829
|
+
display: inline;
|
|
830
|
+
border-left: 2px solid;
|
|
831
|
+
margin-left: -1px;
|
|
832
|
+
margin-right: -1px;
|
|
833
|
+
pointer-events: none;
|
|
834
|
+
word-break: normal;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
.editor-content :global(.collaboration-carets__label) {
|
|
838
|
+
position: absolute;
|
|
839
|
+
top: -1.4em;
|
|
840
|
+
left: -1px;
|
|
841
|
+
font-size: 12px;
|
|
842
|
+
font-weight: 600;
|
|
843
|
+
line-height: normal;
|
|
844
|
+
padding: 0.1rem 0.3rem;
|
|
845
|
+
border-radius: 3px 3px 3px 0;
|
|
846
|
+
color: #fff;
|
|
847
|
+
white-space: nowrap;
|
|
848
|
+
user-select: none;
|
|
849
|
+
pointer-events: none;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/* Collaboration selection highlight */
|
|
853
|
+
.editor-content :global(.ProseMirror-yjs-selection) {
|
|
854
|
+
display: inline;
|
|
855
|
+
}
|
|
856
|
+
</style>
|