mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-20 07:10:02 +00:00
Uber 555 (#3572)
Signed-off-by: Maxim Karmatskikh <mkarmatskih@gmail.com>
This commit is contained in:
parent
c628a0a0d1
commit
16d079bb88
File diff suppressed because it is too large
Load Diff
@ -75,6 +75,7 @@
|
|||||||
"@tiptap/extension-table-cell": "^2.0.3",
|
"@tiptap/extension-table-cell": "^2.0.3",
|
||||||
"@tiptap/extension-table-header": "^2.0.3",
|
"@tiptap/extension-table-header": "^2.0.3",
|
||||||
"@tiptap/extension-table-row": "^2.0.3",
|
"@tiptap/extension-table-row": "^2.0.3",
|
||||||
"@tiptap/extension-code": "^2.0.3"
|
"@tiptap/extension-code": "^2.0.3",
|
||||||
|
"@tiptap/extension-bubble-menu": "^2.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,11 +37,7 @@
|
|||||||
import TextEditor from './TextEditor.svelte'
|
import TextEditor from './TextEditor.svelte'
|
||||||
import { completionConfig } from './extensions'
|
import { completionConfig } from './extensions'
|
||||||
import Attach from './icons/Attach.svelte'
|
import Attach from './icons/Attach.svelte'
|
||||||
import Bold from './icons/Bold.svelte'
|
|
||||||
import Code from './icons/Code.svelte'
|
|
||||||
import CodeBlock from './icons/CodeBlock.svelte'
|
import CodeBlock from './icons/CodeBlock.svelte'
|
||||||
import Italic from './icons/Italic.svelte'
|
|
||||||
import Link from './icons/Link.svelte'
|
|
||||||
import ListBullet from './icons/ListBullet.svelte'
|
import ListBullet from './icons/ListBullet.svelte'
|
||||||
import ListNumber from './icons/ListNumber.svelte'
|
import ListNumber from './icons/ListNumber.svelte'
|
||||||
import Quote from './icons/Quote.svelte'
|
import Quote from './icons/Quote.svelte'
|
||||||
@ -52,8 +48,6 @@
|
|||||||
import RIMention from './icons/RIMention.svelte'
|
import RIMention from './icons/RIMention.svelte'
|
||||||
import RIStrikethrough from './icons/RIStrikethrough.svelte'
|
import RIStrikethrough from './icons/RIStrikethrough.svelte'
|
||||||
import Send from './icons/Send.svelte'
|
import Send from './icons/Send.svelte'
|
||||||
import Strikethrough from './icons/Strikethrough.svelte'
|
|
||||||
import TextStyle from './icons/TextStyle.svelte'
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
export let content: string = ''
|
export let content: string = ''
|
||||||
@ -69,7 +63,8 @@
|
|||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
let textEditor: TextEditor
|
let textEditor: TextEditor
|
||||||
let isFormatting = false
|
let textEditorToolbar: HTMLElement
|
||||||
|
|
||||||
let activeModes = new Set<FormatMode>()
|
let activeModes = new Set<FormatMode>()
|
||||||
let isSelectionEmpty = true
|
let isSelectionEmpty = true
|
||||||
let isEmpty = true
|
let isEmpty = true
|
||||||
@ -90,14 +85,6 @@
|
|||||||
},
|
},
|
||||||
order: 1001
|
order: 1001
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Link,
|
|
||||||
icon: RILink,
|
|
||||||
action: () => {
|
|
||||||
if (!(isSelectionEmpty && !activeModes.has('link'))) formatLink()
|
|
||||||
},
|
|
||||||
order: 2000
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: textEditorPlugin.string.Mention,
|
label: textEditorPlugin.string.Mention,
|
||||||
icon: RIMention,
|
icon: RIMention,
|
||||||
@ -121,51 +108,6 @@
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
order: 4001
|
order: 4001
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.TextStyle,
|
|
||||||
icon: TextStyle,
|
|
||||||
action: () => {
|
|
||||||
isFormatting = !isFormatting
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Bold,
|
|
||||||
icon: RIBold,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleBold()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6010
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Italic,
|
|
||||||
icon: RIItalic,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleItalic()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6020
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Strikethrough,
|
|
||||||
icon: RIStrikethrough,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleStrike()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6030
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Code,
|
|
||||||
icon: RICode,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleCode()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6040
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -255,10 +197,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ref-container">
|
<div class="ref-container">
|
||||||
{#if isFormatting}
|
<div class="formatPanel buttons-group xsmall-gap mb-4" class:withoutTopBorder bind:this={textEditorToolbar}>
|
||||||
<div class="formatPanelRef buttons-group xsmall-gap" class:withoutTopBorder>
|
|
||||||
<Button
|
<Button
|
||||||
icon={Bold}
|
icon={RIBold}
|
||||||
kind={'ghost'}
|
kind={'ghost'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
selected={activeModes.has('bold')}
|
selected={activeModes.has('bold')}
|
||||||
@ -266,7 +207,7 @@
|
|||||||
on:click={getToggler(textEditor.toggleBold)}
|
on:click={getToggler(textEditor.toggleBold)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={Italic}
|
icon={RIItalic}
|
||||||
kind={'ghost'}
|
kind={'ghost'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
selected={activeModes.has('italic')}
|
selected={activeModes.has('italic')}
|
||||||
@ -274,7 +215,7 @@
|
|||||||
on:click={getToggler(textEditor.toggleItalic)}
|
on:click={getToggler(textEditor.toggleItalic)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={Strikethrough}
|
icon={RIStrikethrough}
|
||||||
kind={'ghost'}
|
kind={'ghost'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
selected={activeModes.has('strike')}
|
selected={activeModes.has('strike')}
|
||||||
@ -282,7 +223,7 @@
|
|||||||
on:click={getToggler(textEditor.toggleStrike)}
|
on:click={getToggler(textEditor.toggleStrike)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={Link}
|
icon={RILink}
|
||||||
kind={'ghost'}
|
kind={'ghost'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
selected={activeModes.has('link')}
|
selected={activeModes.has('link')}
|
||||||
@ -318,7 +259,7 @@
|
|||||||
/>
|
/>
|
||||||
<div class="buttons-divider" />
|
<div class="buttons-divider" />
|
||||||
<Button
|
<Button
|
||||||
icon={Code}
|
icon={RICode}
|
||||||
kind={'ghost'}
|
kind={'ghost'}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
selected={activeModes.has('code')}
|
selected={activeModes.has('code')}
|
||||||
@ -334,8 +275,7 @@
|
|||||||
on:click={getToggler(textEditor.toggleCodeBlock)}
|
on:click={getToggler(textEditor.toggleCodeBlock)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<div class="textInput" class:withoutTopBorder>
|
||||||
<div class="textInput" class:withoutTopBorder={withoutTopBorder || isFormatting}>
|
|
||||||
<div class="inputMsg">
|
<div class="inputMsg">
|
||||||
<TextEditor
|
<TextEditor
|
||||||
bind:content
|
bind:content
|
||||||
@ -361,6 +301,7 @@
|
|||||||
on:selection-update={updateFormattingState}
|
on:selection-update={updateFormattingState}
|
||||||
on:update
|
on:update
|
||||||
placeholder={placeholder ?? textEditorPlugin.string.EditorPlaceholder}
|
placeholder={placeholder ?? textEditorPlugin.string.EditorPlaceholder}
|
||||||
|
{textEditorToolbar}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if showSend}
|
{#if showSend}
|
||||||
@ -383,7 +324,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-between clear-mins" style:margin={'.75rem .75rem 0'}>
|
<div class="flex-between clear-mins" style:margin={'.75rem .75rem 0'}>
|
||||||
<div class="buttons-group {shrinkButtons ? 'medium-gap' : 'large-gap'}">
|
<div class="buttons-group medium-gap">
|
||||||
{#each actions as a}
|
{#each actions as a}
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<div
|
<div
|
||||||
@ -534,5 +475,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.formatPanel {
|
||||||
|
margin: -0.5rem -0.25rem 0.5rem;
|
||||||
|
padding: 0.375rem;
|
||||||
|
background-color: var(--theme-comp-header-color);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
box-shadow: var(--theme-popup-shadow);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -23,9 +23,7 @@
|
|||||||
IconSize,
|
IconSize,
|
||||||
Scroller,
|
Scroller,
|
||||||
SelectPopup,
|
SelectPopup,
|
||||||
showPopup,
|
showPopup
|
||||||
deviceOptionsStore as deviceInfo,
|
|
||||||
checkAdaptiveMatching
|
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { Level } from '@tiptap/extension-heading'
|
import { Level } from '@tiptap/extension-heading'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
@ -33,13 +31,9 @@
|
|||||||
import { FORMAT_MODES, FormatMode, RefInputAction, RefInputActionItem, TextEditorHandler } from '../types'
|
import { FORMAT_MODES, FormatMode, RefInputAction, RefInputActionItem, TextEditorHandler } from '../types'
|
||||||
import { headingLevels, mInsertTable } from './extensions'
|
import { headingLevels, mInsertTable } from './extensions'
|
||||||
import Attach from './icons/Attach.svelte'
|
import Attach from './icons/Attach.svelte'
|
||||||
import Bold from './icons/Bold.svelte'
|
|
||||||
import Code from './icons/Code.svelte'
|
|
||||||
import CodeBlock from './icons/CodeBlock.svelte'
|
import CodeBlock from './icons/CodeBlock.svelte'
|
||||||
import Header from './icons/Header.svelte'
|
import Header from './icons/Header.svelte'
|
||||||
import IconTable from './icons/IconTable.svelte'
|
import IconTable from './icons/IconTable.svelte'
|
||||||
import Italic from './icons/Italic.svelte'
|
|
||||||
import Link from './icons/Link.svelte'
|
|
||||||
import ListBullet from './icons/ListBullet.svelte'
|
import ListBullet from './icons/ListBullet.svelte'
|
||||||
import ListNumber from './icons/ListNumber.svelte'
|
import ListNumber from './icons/ListNumber.svelte'
|
||||||
import Quote from './icons/Quote.svelte'
|
import Quote from './icons/Quote.svelte'
|
||||||
@ -48,7 +42,6 @@
|
|||||||
import RIItalic from './icons/RIItalic.svelte'
|
import RIItalic from './icons/RIItalic.svelte'
|
||||||
import RILink from './icons/RILink.svelte'
|
import RILink from './icons/RILink.svelte'
|
||||||
import RIStrikethrough from './icons/RIStrikethrough.svelte'
|
import RIStrikethrough from './icons/RIStrikethrough.svelte'
|
||||||
import Strikethrough from './icons/Strikethrough.svelte'
|
|
||||||
// import RIMention from './icons/RIMention.svelte'
|
// import RIMention from './icons/RIMention.svelte'
|
||||||
import { AnyExtension } from '@tiptap/core'
|
import { AnyExtension } from '@tiptap/core'
|
||||||
import AddColAfter from './icons/table/AddColAfter.svelte'
|
import AddColAfter from './icons/table/AddColAfter.svelte'
|
||||||
@ -58,7 +51,6 @@
|
|||||||
import DeleteCol from './icons/table/DeleteCol.svelte'
|
import DeleteCol from './icons/table/DeleteCol.svelte'
|
||||||
import DeleteRow from './icons/table/DeleteRow.svelte'
|
import DeleteRow from './icons/table/DeleteRow.svelte'
|
||||||
import DeleteTable from './icons/table/DeleteTable.svelte'
|
import DeleteTable from './icons/table/DeleteTable.svelte'
|
||||||
import TextStyle from './icons/TextStyle.svelte'
|
|
||||||
import LinkPopup from './LinkPopup.svelte'
|
import LinkPopup from './LinkPopup.svelte'
|
||||||
import StyleButton from './StyleButton.svelte'
|
import StyleButton from './StyleButton.svelte'
|
||||||
import TextEditor from './TextEditor.svelte'
|
import TextEditor from './TextEditor.svelte'
|
||||||
@ -82,6 +74,8 @@
|
|||||||
export let extensions: AnyExtension[] = []
|
export let extensions: AnyExtension[] = []
|
||||||
|
|
||||||
let textEditor: TextEditor
|
let textEditor: TextEditor
|
||||||
|
let textEditorToolbar: HTMLElement
|
||||||
|
|
||||||
let isEmpty = true
|
let isEmpty = true
|
||||||
let contentHeight: number
|
let contentHeight: number
|
||||||
|
|
||||||
@ -127,7 +121,6 @@
|
|||||||
? 'max-content'
|
? 'max-content'
|
||||||
: maxHeight
|
: maxHeight
|
||||||
|
|
||||||
let isFormatting = enableFormatting
|
|
||||||
let activeModes = new Set<FormatMode>()
|
let activeModes = new Set<FormatMode>()
|
||||||
let isSelectionEmpty = true
|
let isSelectionEmpty = true
|
||||||
|
|
||||||
@ -147,20 +140,6 @@
|
|||||||
},
|
},
|
||||||
order: 1001
|
order: 1001
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Link,
|
|
||||||
icon: RILink,
|
|
||||||
action: () => {
|
|
||||||
if (!(isSelectionEmpty && !activeModes.has('link'))) formatLink()
|
|
||||||
},
|
|
||||||
order: 2000
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// label: textEditorPlugin.string.Mention,
|
|
||||||
// icon: RIMention,
|
|
||||||
// action: () => textEditor.insertText('@'),
|
|
||||||
// order: 3000
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
label: textEditorPlugin.string.Emoji,
|
label: textEditorPlugin.string.Emoji,
|
||||||
icon: IconEmoji,
|
icon: IconEmoji,
|
||||||
@ -178,51 +157,6 @@
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
order: 4001
|
order: 4001
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.TextStyle,
|
|
||||||
icon: TextStyle,
|
|
||||||
action: () => {
|
|
||||||
isFormatting = !isFormatting
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Bold,
|
|
||||||
icon: RIBold,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleBold()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6010
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Italic,
|
|
||||||
icon: RIItalic,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleItalic()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6020
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Strikethrough,
|
|
||||||
icon: RIStrikethrough,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleStrike()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6030
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: textEditorPlugin.string.Code,
|
|
||||||
icon: RICode,
|
|
||||||
action: () => {
|
|
||||||
textEditor.toggleCode()
|
|
||||||
textEditor.focus()
|
|
||||||
},
|
|
||||||
order: 6040
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -448,8 +382,8 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: devSize = $deviceInfo.size
|
const buttonsGap = 'small-gap'
|
||||||
$: buttonsGap = checkAdaptiveMatching(devSize, 'sm') ? 'small-gap' : 'large-gap'
|
|
||||||
$: buttonsHeight =
|
$: buttonsHeight =
|
||||||
buttonSize === 'large' || buttonSize === 'x-large' || buttonSize === 'full'
|
buttonSize === 'large' || buttonSize === 'x-large' || buttonSize === 'full'
|
||||||
? 'h-6 max-h-6'
|
? 'h-6 max-h-6'
|
||||||
@ -472,8 +406,7 @@
|
|||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
on:click|preventDefault|stopPropagation={() => (needFocus = true)}
|
on:click|preventDefault|stopPropagation={() => (needFocus = true)}
|
||||||
>
|
>
|
||||||
{#if isFormatting}
|
<div class="formatPanel buttons-group xsmall-gap mb-4" class:withoutTopBorder bind:this={textEditorToolbar}>
|
||||||
<div class="formatPanel buttons-group xsmall-gap mb-4" class:withoutTopBorder>
|
|
||||||
<StyleButton
|
<StyleButton
|
||||||
icon={Header}
|
icon={Header}
|
||||||
size={formatButtonSize}
|
size={formatButtonSize}
|
||||||
@ -482,28 +415,28 @@
|
|||||||
on:click={toggleHeader}
|
on:click={toggleHeader}
|
||||||
/>
|
/>
|
||||||
<StyleButton
|
<StyleButton
|
||||||
icon={Bold}
|
icon={RIBold}
|
||||||
size={formatButtonSize}
|
size={formatButtonSize}
|
||||||
selected={activeModes.has('bold')}
|
selected={activeModes.has('bold')}
|
||||||
showTooltip={{ label: textEditorPlugin.string.Bold }}
|
showTooltip={{ label: textEditorPlugin.string.Bold }}
|
||||||
on:click={getToggler(textEditor.toggleBold)}
|
on:click={getToggler(textEditor.toggleBold)}
|
||||||
/>
|
/>
|
||||||
<StyleButton
|
<StyleButton
|
||||||
icon={Italic}
|
icon={RIItalic}
|
||||||
size={formatButtonSize}
|
size={formatButtonSize}
|
||||||
selected={activeModes.has('italic')}
|
selected={activeModes.has('italic')}
|
||||||
showTooltip={{ label: textEditorPlugin.string.Italic }}
|
showTooltip={{ label: textEditorPlugin.string.Italic }}
|
||||||
on:click={getToggler(textEditor.toggleItalic)}
|
on:click={getToggler(textEditor.toggleItalic)}
|
||||||
/>
|
/>
|
||||||
<StyleButton
|
<StyleButton
|
||||||
icon={Strikethrough}
|
icon={RIStrikethrough}
|
||||||
size={formatButtonSize}
|
size={formatButtonSize}
|
||||||
selected={activeModes.has('strike')}
|
selected={activeModes.has('strike')}
|
||||||
showTooltip={{ label: textEditorPlugin.string.Strikethrough }}
|
showTooltip={{ label: textEditorPlugin.string.Strikethrough }}
|
||||||
on:click={getToggler(textEditor.toggleStrike)}
|
on:click={getToggler(textEditor.toggleStrike)}
|
||||||
/>
|
/>
|
||||||
<StyleButton
|
<StyleButton
|
||||||
icon={Link}
|
icon={RILink}
|
||||||
size={formatButtonSize}
|
size={formatButtonSize}
|
||||||
selected={activeModes.has('link')}
|
selected={activeModes.has('link')}
|
||||||
disabled={isSelectionEmpty && !activeModes.has('link')}
|
disabled={isSelectionEmpty && !activeModes.has('link')}
|
||||||
@ -535,7 +468,7 @@
|
|||||||
/>
|
/>
|
||||||
<div class="buttons-divider" />
|
<div class="buttons-divider" />
|
||||||
<StyleButton
|
<StyleButton
|
||||||
icon={Code}
|
icon={RICode}
|
||||||
size={formatButtonSize}
|
size={formatButtonSize}
|
||||||
selected={activeModes.has('code')}
|
selected={activeModes.has('code')}
|
||||||
showTooltip={{ label: textEditorPlugin.string.Code }}
|
showTooltip={{ label: textEditorPlugin.string.Code }}
|
||||||
@ -566,13 +499,11 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
<div class="textInput" class:focusable>
|
<div class="textInput" class:focusable>
|
||||||
<div
|
<div
|
||||||
bind:clientHeight={contentHeight}
|
bind:clientHeight={contentHeight}
|
||||||
class="inputMsg"
|
class="inputMsg showScroll"
|
||||||
class:scrollable={isScrollable}
|
class:scrollable={isScrollable}
|
||||||
class:showScroll={contentHeight > 32}
|
|
||||||
style="--texteditor-maxheight: {varsStyle};"
|
style="--texteditor-maxheight: {varsStyle};"
|
||||||
>
|
>
|
||||||
{#if isScrollable}
|
{#if isScrollable}
|
||||||
@ -592,6 +523,7 @@
|
|||||||
on:blur
|
on:blur
|
||||||
on:focus
|
on:focus
|
||||||
supportSubmit={false}
|
supportSubmit={false}
|
||||||
|
{textEditorToolbar}
|
||||||
on:selection-update={updateFormattingState}
|
on:selection-update={updateFormattingState}
|
||||||
/>
|
/>
|
||||||
</Scroller>
|
</Scroller>
|
||||||
@ -611,6 +543,7 @@
|
|||||||
on:blur
|
on:blur
|
||||||
on:focus
|
on:focus
|
||||||
supportSubmit={false}
|
supportSubmit={false}
|
||||||
|
{textEditorToolbar}
|
||||||
on:selection-update={updateFormattingState}
|
on:selection-update={updateFormattingState}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@ -672,6 +605,16 @@
|
|||||||
}
|
}
|
||||||
&:not(.showScroll) {
|
&:not(.showScroll) {
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
/*
|
||||||
|
showScroll was set only when contentHeight > 32
|
||||||
|
But this gave a bad behaviour for editor toolbar
|
||||||
|
in the bubble when there is only one line of text.
|
||||||
|
|
||||||
|
I did the testing and figured out that now
|
||||||
|
we can use showScroll always.
|
||||||
|
|
||||||
|
Please refer UBER-555
|
||||||
|
*/
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@ -690,10 +633,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:focus-within .formatPanel {
|
|
||||||
position: sticky;
|
|
||||||
top: 1.25rem;
|
|
||||||
}
|
|
||||||
.formatPanel {
|
.formatPanel {
|
||||||
margin: -0.5rem -0.25rem 0.5rem;
|
margin: -0.5rem -0.25rem 0.5rem;
|
||||||
padding: 0.375rem;
|
padding: 0.375rem;
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
import { AnyExtension, Editor, Extension, HTMLContent } from '@tiptap/core'
|
import { AnyExtension, Editor, Extension, HTMLContent } from '@tiptap/core'
|
||||||
import { Level } from '@tiptap/extension-heading'
|
import { Level } from '@tiptap/extension-heading'
|
||||||
import Placeholder from '@tiptap/extension-placeholder'
|
import Placeholder from '@tiptap/extension-placeholder'
|
||||||
|
import BubbleMenu from '@tiptap/extension-bubble-menu'
|
||||||
|
|
||||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
||||||
import textEditorPlugin from '../plugin'
|
import textEditorPlugin from '../plugin'
|
||||||
import { FormatMode } from '../types'
|
import { FormatMode } from '../types'
|
||||||
@ -32,6 +34,7 @@
|
|||||||
export let extensions: AnyExtension[] = []
|
export let extensions: AnyExtension[] = []
|
||||||
export let supportSubmit = true
|
export let supportSubmit = true
|
||||||
export let isEmpty = true
|
export let isEmpty = true
|
||||||
|
export let textEditorToolbar: HTMLElement | null = null
|
||||||
|
|
||||||
let element: HTMLElement
|
let element: HTMLElement
|
||||||
let editor: Editor
|
let editor: Editor
|
||||||
@ -202,7 +205,10 @@
|
|||||||
...defaultExtensions,
|
...defaultExtensions,
|
||||||
...(supportSubmit ? [Handle] : []), // order important
|
...(supportSubmit ? [Handle] : []), // order important
|
||||||
Placeholder.configure({ placeholder: placeHolderStr }),
|
Placeholder.configure({ placeholder: placeHolderStr }),
|
||||||
...extensions
|
...extensions,
|
||||||
|
BubbleMenu.configure({
|
||||||
|
element: textEditorToolbar
|
||||||
|
})
|
||||||
],
|
],
|
||||||
parseOptions: {
|
parseOptions: {
|
||||||
preserveWhitespace: 'full'
|
preserveWhitespace: 'full'
|
||||||
|
@ -2,3 +2,9 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// need to override editor's bubble max-width
|
||||||
|
// due to https://github.com/atomiks/tippyjs/issues/451
|
||||||
|
.tippy-box {
|
||||||
|
max-width: 370px !important;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user