mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-14 05:15:18 +00:00
enh: formatting toolbar for chat
This commit is contained in:
parent
0acd78049d
commit
bfa42c6277
5 changed files with 256 additions and 211 deletions
|
|
@ -60,7 +60,7 @@
|
||||||
export let scrollToBottom: Function = () => {};
|
export let scrollToBottom: Function = () => {};
|
||||||
|
|
||||||
export let acceptFiles = true;
|
export let acceptFiles = true;
|
||||||
export let showFormattingButtons = true;
|
export let showFormattingToolbar = true;
|
||||||
|
|
||||||
let showInputVariablesModal = false;
|
let showInputVariablesModal = false;
|
||||||
let inputVariables: Record<string, any> = {};
|
let inputVariables: Record<string, any> = {};
|
||||||
|
|
@ -700,7 +700,7 @@
|
||||||
bind:this={chatInputElement}
|
bind:this={chatInputElement}
|
||||||
json={true}
|
json={true}
|
||||||
messageInput={true}
|
messageInput={true}
|
||||||
{showFormattingButtons}
|
{showFormattingToolbar}
|
||||||
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
|
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
|
||||||
(!$mobile ||
|
(!$mobile ||
|
||||||
!(
|
!(
|
||||||
|
|
|
||||||
|
|
@ -1086,232 +1086,247 @@
|
||||||
class="scrollbar-hidden rtl:text-right ltr:text-left bg-transparent dark:text-gray-100 outline-hidden w-full pt-2.5 pb-[5px] px-1 resize-none h-fit max-h-80 overflow-auto"
|
class="scrollbar-hidden rtl:text-right ltr:text-left bg-transparent dark:text-gray-100 outline-hidden w-full pt-2.5 pb-[5px] px-1 resize-none h-fit max-h-80 overflow-auto"
|
||||||
id="chat-input-container"
|
id="chat-input-container"
|
||||||
>
|
>
|
||||||
<RichTextInput
|
{#key $settings?.showFormattingToolbar ?? false}
|
||||||
bind:this={chatInputElement}
|
<RichTextInput
|
||||||
id="chat-input"
|
bind:this={chatInputElement}
|
||||||
onChange={(e) => {
|
id="chat-input"
|
||||||
prompt = e.md;
|
onChange={(e) => {
|
||||||
command = getCommand();
|
prompt = e.md;
|
||||||
}}
|
command = getCommand();
|
||||||
json={true}
|
}}
|
||||||
messageInput={true}
|
json={true}
|
||||||
showFormattingButtons={false}
|
messageInput={true}
|
||||||
insertPromptAsRichText={$settings?.insertPromptAsRichText ?? false}
|
showFormattingToolbar={$settings?.showFormattingToolbar ?? false}
|
||||||
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
|
floatingMenuPlacement={'top-start'}
|
||||||
(!$mobile ||
|
insertPromptAsRichText={$settings?.insertPromptAsRichText ?? false}
|
||||||
!(
|
shiftEnter={!($settings?.ctrlEnterToSend ?? false) &&
|
||||||
'ontouchstart' in window ||
|
(!$mobile ||
|
||||||
navigator.maxTouchPoints > 0 ||
|
|
||||||
navigator.msMaxTouchPoints > 0
|
|
||||||
))}
|
|
||||||
placeholder={placeholder ? placeholder : $i18n.t('Send a Message')}
|
|
||||||
largeTextAsFile={($settings?.largeTextAsFile ?? false) && !shiftKey}
|
|
||||||
autocomplete={$config?.features?.enable_autocomplete_generation &&
|
|
||||||
($settings?.promptAutocomplete ?? false)}
|
|
||||||
generateAutoCompletion={async (text) => {
|
|
||||||
if (selectedModelIds.length === 0 || !selectedModelIds.at(0)) {
|
|
||||||
toast.error($i18n.t('Please select a model first.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await generateAutoCompletion(
|
|
||||||
localStorage.token,
|
|
||||||
selectedModelIds.at(0),
|
|
||||||
text,
|
|
||||||
history?.currentId
|
|
||||||
? createMessagesList(history, history.currentId)
|
|
||||||
: null
|
|
||||||
).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(res);
|
|
||||||
return res;
|
|
||||||
}}
|
|
||||||
oncompositionstart={() => (isComposing = true)}
|
|
||||||
oncompositionend={() => (isComposing = false)}
|
|
||||||
on:keydown={async (e) => {
|
|
||||||
e = e.detail.event;
|
|
||||||
|
|
||||||
const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac
|
|
||||||
const commandsContainerElement =
|
|
||||||
document.getElementById('commands-container');
|
|
||||||
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
stopResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command/Ctrl + Shift + Enter to submit a message pair
|
|
||||||
if (isCtrlPressed && e.key === 'Enter' && e.shiftKey) {
|
|
||||||
e.preventDefault();
|
|
||||||
createMessagePair(prompt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if Ctrl + R is pressed
|
|
||||||
if (prompt === '' && isCtrlPressed && e.key.toLowerCase() === 'r') {
|
|
||||||
e.preventDefault();
|
|
||||||
console.log('regenerate');
|
|
||||||
|
|
||||||
const regenerateButton = [
|
|
||||||
...document.getElementsByClassName('regenerate-response-button')
|
|
||||||
]?.at(-1);
|
|
||||||
|
|
||||||
regenerateButton?.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prompt === '' && e.key == 'ArrowUp') {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const userMessageElement = [
|
|
||||||
...document.getElementsByClassName('user-message')
|
|
||||||
]?.at(-1);
|
|
||||||
|
|
||||||
if (userMessageElement) {
|
|
||||||
userMessageElement.scrollIntoView({ block: 'center' });
|
|
||||||
const editButton = [
|
|
||||||
...document.getElementsByClassName('edit-user-message-button')
|
|
||||||
]?.at(-1);
|
|
||||||
|
|
||||||
editButton?.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandsContainerElement) {
|
|
||||||
if (commandsContainerElement && e.key === 'ArrowUp') {
|
|
||||||
e.preventDefault();
|
|
||||||
commandsElement.selectUp();
|
|
||||||
|
|
||||||
const commandOptionButton = [
|
|
||||||
...document.getElementsByClassName('selected-command-option-button')
|
|
||||||
]?.at(-1);
|
|
||||||
commandOptionButton.scrollIntoView({ block: 'center' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandsContainerElement && e.key === 'ArrowDown') {
|
|
||||||
e.preventDefault();
|
|
||||||
commandsElement.selectDown();
|
|
||||||
|
|
||||||
const commandOptionButton = [
|
|
||||||
...document.getElementsByClassName('selected-command-option-button')
|
|
||||||
]?.at(-1);
|
|
||||||
commandOptionButton.scrollIntoView({ block: 'center' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandsContainerElement && e.key === 'Tab') {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const commandOptionButton = [
|
|
||||||
...document.getElementsByClassName('selected-command-option-button')
|
|
||||||
]?.at(-1);
|
|
||||||
|
|
||||||
commandOptionButton?.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandsContainerElement && e.key === 'Enter') {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const commandOptionButton = [
|
|
||||||
...document.getElementsByClassName('selected-command-option-button')
|
|
||||||
]?.at(-1);
|
|
||||||
|
|
||||||
if (commandOptionButton) {
|
|
||||||
commandOptionButton?.click();
|
|
||||||
} else {
|
|
||||||
document.getElementById('send-message-button')?.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
!$mobile ||
|
|
||||||
!(
|
!(
|
||||||
'ontouchstart' in window ||
|
'ontouchstart' in window ||
|
||||||
navigator.maxTouchPoints > 0 ||
|
navigator.maxTouchPoints > 0 ||
|
||||||
navigator.msMaxTouchPoints > 0
|
navigator.msMaxTouchPoints > 0
|
||||||
)
|
))}
|
||||||
) {
|
placeholder={placeholder ? placeholder : $i18n.t('Send a Message')}
|
||||||
if (isComposing) {
|
largeTextAsFile={($settings?.largeTextAsFile ?? false) && !shiftKey}
|
||||||
return;
|
autocomplete={$config?.features?.enable_autocomplete_generation &&
|
||||||
}
|
($settings?.promptAutocomplete ?? false)}
|
||||||
|
generateAutoCompletion={async (text) => {
|
||||||
|
if (selectedModelIds.length === 0 || !selectedModelIds.at(0)) {
|
||||||
|
toast.error($i18n.t('Please select a model first.'));
|
||||||
|
}
|
||||||
|
|
||||||
// Uses keyCode '13' for Enter key for chinese/japanese keyboards.
|
const res = await generateAutoCompletion(
|
||||||
//
|
localStorage.token,
|
||||||
// Depending on the user's settings, it will send the message
|
selectedModelIds.at(0),
|
||||||
// either when Enter is pressed or when Ctrl+Enter is pressed.
|
text,
|
||||||
const enterPressed =
|
history?.currentId
|
||||||
($settings?.ctrlEnterToSend ?? false)
|
? createMessagesList(history, history.currentId)
|
||||||
? (e.key === 'Enter' || e.keyCode === 13) && isCtrlPressed
|
: null
|
||||||
: (e.key === 'Enter' || e.keyCode === 13) && !e.shiftKey;
|
).catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
if (enterPressed) {
|
return null;
|
||||||
e.preventDefault();
|
});
|
||||||
if (prompt !== '' || files.length > 0) {
|
|
||||||
dispatch('submit', prompt);
|
console.log(res);
|
||||||
}
|
return res;
|
||||||
|
}}
|
||||||
|
oncompositionstart={() => (isComposing = true)}
|
||||||
|
oncompositionend={() => (isComposing = false)}
|
||||||
|
on:keydown={async (e) => {
|
||||||
|
e = e.detail.event;
|
||||||
|
|
||||||
|
const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac
|
||||||
|
const commandsContainerElement =
|
||||||
|
document.getElementById('commands-container');
|
||||||
|
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
stopResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command/Ctrl + Shift + Enter to submit a message pair
|
||||||
|
if (isCtrlPressed && e.key === 'Enter' && e.shiftKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
createMessagePair(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if Ctrl + R is pressed
|
||||||
|
if (prompt === '' && isCtrlPressed && e.key.toLowerCase() === 'r') {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log('regenerate');
|
||||||
|
|
||||||
|
const regenerateButton = [
|
||||||
|
...document.getElementsByClassName('regenerate-response-button')
|
||||||
|
]?.at(-1);
|
||||||
|
|
||||||
|
regenerateButton?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prompt === '' && e.key == 'ArrowUp') {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const userMessageElement = [
|
||||||
|
...document.getElementsByClassName('user-message')
|
||||||
|
]?.at(-1);
|
||||||
|
|
||||||
|
if (userMessageElement) {
|
||||||
|
userMessageElement.scrollIntoView({ block: 'center' });
|
||||||
|
const editButton = [
|
||||||
|
...document.getElementsByClassName('edit-user-message-button')
|
||||||
|
]?.at(-1);
|
||||||
|
|
||||||
|
editButton?.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'Escape') {
|
if (commandsContainerElement) {
|
||||||
console.log('Escape');
|
if (commandsContainerElement && e.key === 'ArrowUp') {
|
||||||
atSelectedModel = undefined;
|
e.preventDefault();
|
||||||
selectedToolIds = [];
|
commandsElement.selectUp();
|
||||||
selectedFilterIds = [];
|
|
||||||
|
|
||||||
webSearchEnabled = false;
|
const commandOptionButton = [
|
||||||
imageGenerationEnabled = false;
|
...document.getElementsByClassName(
|
||||||
codeInterpreterEnabled = false;
|
'selected-command-option-button'
|
||||||
}
|
)
|
||||||
}}
|
]?.at(-1);
|
||||||
on:paste={async (e) => {
|
commandOptionButton.scrollIntoView({ block: 'center' });
|
||||||
e = e.detail.event;
|
}
|
||||||
console.log(e);
|
|
||||||
|
|
||||||
const clipboardData = e.clipboardData || window.clipboardData;
|
if (commandsContainerElement && e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault();
|
||||||
|
commandsElement.selectDown();
|
||||||
|
|
||||||
if (clipboardData && clipboardData.items) {
|
const commandOptionButton = [
|
||||||
for (const item of clipboardData.items) {
|
...document.getElementsByClassName(
|
||||||
if (item.type.indexOf('image') !== -1) {
|
'selected-command-option-button'
|
||||||
const blob = item.getAsFile();
|
)
|
||||||
const reader = new FileReader();
|
]?.at(-1);
|
||||||
|
commandOptionButton.scrollIntoView({ block: 'center' });
|
||||||
|
}
|
||||||
|
|
||||||
reader.onload = function (e) {
|
if (commandsContainerElement && e.key === 'Tab') {
|
||||||
files = [
|
e.preventDefault();
|
||||||
...files,
|
|
||||||
{
|
|
||||||
type: 'image',
|
|
||||||
url: `${e.target.result}`
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
reader.readAsDataURL(blob);
|
const commandOptionButton = [
|
||||||
} else if (item?.kind === 'file') {
|
...document.getElementsByClassName(
|
||||||
const file = item.getAsFile();
|
'selected-command-option-button'
|
||||||
if (file) {
|
)
|
||||||
const _files = [file];
|
]?.at(-1);
|
||||||
await inputFilesHandler(_files);
|
|
||||||
e.preventDefault();
|
commandOptionButton?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commandsContainerElement && e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const commandOptionButton = [
|
||||||
|
...document.getElementsByClassName(
|
||||||
|
'selected-command-option-button'
|
||||||
|
)
|
||||||
|
]?.at(-1);
|
||||||
|
|
||||||
|
if (commandOptionButton) {
|
||||||
|
commandOptionButton?.click();
|
||||||
|
} else {
|
||||||
|
document.getElementById('send-message-button')?.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
!$mobile ||
|
||||||
|
!(
|
||||||
|
'ontouchstart' in window ||
|
||||||
|
navigator.maxTouchPoints > 0 ||
|
||||||
|
navigator.msMaxTouchPoints > 0
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (isComposing) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} else if (item.type === 'text/plain') {
|
|
||||||
if (($settings?.largeTextAsFile ?? false) && !shiftKey) {
|
|
||||||
const text = clipboardData.getData('text/plain');
|
|
||||||
|
|
||||||
if (text.length > PASTED_TEXT_CHARACTER_LIMIT) {
|
// Uses keyCode '13' for Enter key for chinese/japanese keyboards.
|
||||||
e.preventDefault();
|
//
|
||||||
const blob = new Blob([text], { type: 'text/plain' });
|
// Depending on the user's settings, it will send the message
|
||||||
const file = new File([blob], `Pasted_Text_${Date.now()}.txt`, {
|
// either when Enter is pressed or when Ctrl+Enter is pressed.
|
||||||
type: 'text/plain'
|
const enterPressed =
|
||||||
});
|
($settings?.ctrlEnterToSend ?? false)
|
||||||
|
? (e.key === 'Enter' || e.keyCode === 13) && isCtrlPressed
|
||||||
|
: (e.key === 'Enter' || e.keyCode === 13) && !e.shiftKey;
|
||||||
|
|
||||||
await uploadFileHandler(file, true);
|
if (enterPressed) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (prompt !== '' || files.length > 0) {
|
||||||
|
dispatch('submit', prompt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}}
|
if (e.key === 'Escape') {
|
||||||
/>
|
console.log('Escape');
|
||||||
|
atSelectedModel = undefined;
|
||||||
|
selectedToolIds = [];
|
||||||
|
selectedFilterIds = [];
|
||||||
|
|
||||||
|
webSearchEnabled = false;
|
||||||
|
imageGenerationEnabled = false;
|
||||||
|
codeInterpreterEnabled = false;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:paste={async (e) => {
|
||||||
|
e = e.detail.event;
|
||||||
|
console.log(e);
|
||||||
|
|
||||||
|
const clipboardData = e.clipboardData || window.clipboardData;
|
||||||
|
|
||||||
|
if (clipboardData && clipboardData.items) {
|
||||||
|
for (const item of clipboardData.items) {
|
||||||
|
if (item.type.indexOf('image') !== -1) {
|
||||||
|
const blob = item.getAsFile();
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = function (e) {
|
||||||
|
files = [
|
||||||
|
...files,
|
||||||
|
{
|
||||||
|
type: 'image',
|
||||||
|
url: `${e.target.result}`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
} else if (item?.kind === 'file') {
|
||||||
|
const file = item.getAsFile();
|
||||||
|
if (file) {
|
||||||
|
const _files = [file];
|
||||||
|
await inputFilesHandler(_files);
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
} else if (item.type === 'text/plain') {
|
||||||
|
if (($settings?.largeTextAsFile ?? false) && !shiftKey) {
|
||||||
|
const text = clipboardData.getData('text/plain');
|
||||||
|
|
||||||
|
if (text.length > PASTED_TEXT_CHARACTER_LIMIT) {
|
||||||
|
e.preventDefault();
|
||||||
|
const blob = new Blob([text], { type: 'text/plain' });
|
||||||
|
const file = new File(
|
||||||
|
[blob],
|
||||||
|
`Pasted_Text_${Date.now()}.txt`,
|
||||||
|
{
|
||||||
|
type: 'text/plain'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
await uploadFileHandler(file, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<textarea
|
<textarea
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
let detectArtifacts = true;
|
let detectArtifacts = true;
|
||||||
|
|
||||||
let richTextInput = true;
|
let richTextInput = true;
|
||||||
|
let showFormattingToolbar = false;
|
||||||
let insertPromptAsRichText = false;
|
let insertPromptAsRichText = false;
|
||||||
let promptAutocomplete = false;
|
let promptAutocomplete = false;
|
||||||
|
|
||||||
|
|
@ -228,6 +229,11 @@
|
||||||
saveSettings({ richTextInput });
|
saveSettings({ richTextInput });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleShowFormattingToolbar = async () => {
|
||||||
|
showFormattingToolbar = !showFormattingToolbar;
|
||||||
|
saveSettings({ showFormattingToolbar });
|
||||||
|
};
|
||||||
|
|
||||||
const toggleInsertPromptAsRichText = async () => {
|
const toggleInsertPromptAsRichText = async () => {
|
||||||
insertPromptAsRichText = !insertPromptAsRichText;
|
insertPromptAsRichText = !insertPromptAsRichText;
|
||||||
saveSettings({ insertPromptAsRichText });
|
saveSettings({ insertPromptAsRichText });
|
||||||
|
|
@ -335,6 +341,7 @@
|
||||||
chatFadeStreamingText = $settings?.chatFadeStreamingText ?? true;
|
chatFadeStreamingText = $settings?.chatFadeStreamingText ?? true;
|
||||||
|
|
||||||
richTextInput = $settings?.richTextInput ?? true;
|
richTextInput = $settings?.richTextInput ?? true;
|
||||||
|
showFormattingToolbar = $settings?.showFormattingToolbar ?? false;
|
||||||
insertPromptAsRichText = $settings?.insertPromptAsRichText ?? false;
|
insertPromptAsRichText = $settings?.insertPromptAsRichText ?? false;
|
||||||
promptAutocomplete = $settings?.promptAutocomplete ?? false;
|
promptAutocomplete = $settings?.promptAutocomplete ?? false;
|
||||||
|
|
||||||
|
|
@ -863,6 +870,29 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if richTextInput}
|
{#if richTextInput}
|
||||||
|
<div>
|
||||||
|
<div class=" py-0.5 flex w-full justify-between">
|
||||||
|
<div id="rich-input-label" class=" self-center text-xs">
|
||||||
|
{$i18n.t('Show Formatting Toolbar')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
aria-labelledby="rich-input-label"
|
||||||
|
class="p-1 px-3 text-xs flex rounded-sm transition"
|
||||||
|
on:click={() => {
|
||||||
|
toggleShowFormattingToolbar();
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
{#if showFormattingToolbar === true}
|
||||||
|
<span class="ml-2 self-center">{$i18n.t('On')}</span>
|
||||||
|
{:else}
|
||||||
|
<span class="ml-2 self-center">{$i18n.t('Off')}</span>
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class=" py-0.5 flex w-full justify-between">
|
<div class=" py-0.5 flex w-full justify-between">
|
||||||
<div id="rich-input-label" class=" self-center text-xs">
|
<div id="rich-input-label" class=" self-center text-xs">
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@
|
||||||
export let editable = true;
|
export let editable = true;
|
||||||
export let collaboration = false;
|
export let collaboration = false;
|
||||||
|
|
||||||
export let showFormattingButtons = true;
|
export let showFormattingToolbar = true;
|
||||||
|
|
||||||
export let preserveBreaks = false;
|
export let preserveBreaks = false;
|
||||||
export let generateAutoCompletion: Function = async () => null;
|
export let generateAutoCompletion: Function = async () => null;
|
||||||
|
|
@ -1003,7 +1003,7 @@
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
|
|
||||||
...(showFormattingButtons
|
...(showFormattingToolbar
|
||||||
? [
|
? [
|
||||||
BubbleMenu.configure({
|
BubbleMenu.configure({
|
||||||
element: bubbleMenuElement,
|
element: bubbleMenuElement,
|
||||||
|
|
@ -1316,7 +1316,7 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if showFormattingButtons}
|
{#if showFormattingToolbar}
|
||||||
<div bind:this={bubbleMenuElement} id="bubble-menu" class="p-0">
|
<div bind:this={bubbleMenuElement} id="bubble-menu" class="p-0">
|
||||||
<FormattingButtons {editor} />
|
<FormattingButtons {editor} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ Based on the user's instruction, update and enhance the existing notes or select
|
||||||
bind:chatInputElement
|
bind:chatInputElement
|
||||||
acceptFiles={false}
|
acceptFiles={false}
|
||||||
inputLoading={loading}
|
inputLoading={loading}
|
||||||
showFormattingButtons={false}
|
showFormattingToolbar={false}
|
||||||
onSubmit={submitHandler}
|
onSubmit={submitHandler}
|
||||||
{onStop}
|
{onStop}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue