mirror of https://github.com/Budibase/budibase.git
committed by
GitHub
19 changed files with 627 additions and 58 deletions
@ -0,0 +1,42 @@ |
|||
<script> |
|||
import MarkdownEditor from "../../Markdown/MarkdownEditor.svelte" |
|||
|
|||
export let value = "" |
|||
export let placeholder = null |
|||
export let disabled = false |
|||
export let error = null |
|||
export let height = null |
|||
export let id = null |
|||
export let fullScreenOffset = null |
|||
export let easyMDEOptions = null |
|||
</script> |
|||
|
|||
<div class:error> |
|||
<MarkdownEditor |
|||
{value} |
|||
{placeholder} |
|||
{height} |
|||
{id} |
|||
{fullScreenOffset} |
|||
{disabled} |
|||
{easyMDEOptions} |
|||
on:change |
|||
/> |
|||
</div> |
|||
|
|||
<style> |
|||
.error :global(.EasyMDEContainer .editor-toolbar) { |
|||
border-top-color: var(--spectrum-semantic-negative-color-default); |
|||
border-left-color: var(--spectrum-semantic-negative-color-default); |
|||
border-right-color: var(--spectrum-semantic-negative-color-default); |
|||
} |
|||
.error :global(.EasyMDEContainer .CodeMirror) { |
|||
border-bottom-color: var(--spectrum-semantic-negative-color-default); |
|||
border-left-color: var(--spectrum-semantic-negative-color-default); |
|||
border-right-color: var(--spectrum-semantic-negative-color-default); |
|||
} |
|||
.error :global(.EasyMDEContainer .editor-preview-side) { |
|||
border-bottom-color: var(--spectrum-semantic-negative-color-default); |
|||
border-right-color: var(--spectrum-semantic-negative-color-default); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,36 @@ |
|||
<script> |
|||
import Field from "./Field.svelte" |
|||
import RichTextField from "./Core/RichTextField.svelte" |
|||
import { createEventDispatcher } from "svelte" |
|||
|
|||
export let value = null |
|||
export let label = null |
|||
export let labelPosition = "above" |
|||
export let placeholder = null |
|||
export let disabled = false |
|||
export let error = null |
|||
export let height = null |
|||
export let id = null |
|||
export let fullScreenOffset = null |
|||
export let easyMDEOptions = null |
|||
|
|||
const dispatch = createEventDispatcher() |
|||
const onChange = e => { |
|||
value = e.detail |
|||
dispatch("change", e.detail) |
|||
} |
|||
</script> |
|||
|
|||
<Field {label} {labelPosition} {error}> |
|||
<RichTextField |
|||
{error} |
|||
{disabled} |
|||
{value} |
|||
{placeholder} |
|||
{height} |
|||
{id} |
|||
{fullScreenOffset} |
|||
{easyMDEOptions} |
|||
on:change={onChange} |
|||
/> |
|||
</Field> |
|||
@ -0,0 +1,60 @@ |
|||
<script> |
|||
import SpectrumMDE from "./SpectrumMDE.svelte" |
|||
import { createEventDispatcher } from "svelte" |
|||
|
|||
export let value = null |
|||
export let height = null |
|||
export let placeholder = null |
|||
export let id = null |
|||
export let fullScreenOffset = 0 |
|||
export let disabled = false |
|||
export let easyMDEOptions |
|||
|
|||
const dispatch = createEventDispatcher() |
|||
|
|||
let latestValue |
|||
let mde |
|||
|
|||
// Ensure the value is updated if the value prop changes outside the editor's |
|||
// control |
|||
$: checkValue(value) |
|||
$: mde?.codemirror.on("change", debouncedUpdate) |
|||
|
|||
const checkValue = val => { |
|||
if (mde && val !== latestValue) { |
|||
mde.value(val) |
|||
} |
|||
} |
|||
|
|||
const debounce = (fn, interval) => { |
|||
let timeout |
|||
return () => { |
|||
clearTimeout(timeout) |
|||
timeout = setTimeout(fn, interval) |
|||
} |
|||
} |
|||
|
|||
const update = () => { |
|||
latestValue = mde.value() |
|||
dispatch("change", latestValue) |
|||
} |
|||
|
|||
// Debounce the update function to avoid spamming it constantly |
|||
const debouncedUpdate = debounce(update, 250) |
|||
</script> |
|||
|
|||
{#key height} |
|||
<SpectrumMDE |
|||
bind:mde |
|||
scroll={true} |
|||
{height} |
|||
{id} |
|||
{fullScreenOffset} |
|||
{disabled} |
|||
easyMDEOptions={{ |
|||
initialValue: value, |
|||
placeholder, |
|||
...easyMDEOptions, |
|||
}} |
|||
/> |
|||
{/key} |
|||
@ -0,0 +1,70 @@ |
|||
<script> |
|||
import SpectrumMDE from "./SpectrumMDE.svelte" |
|||
|
|||
export let value |
|||
export let height |
|||
|
|||
let mde |
|||
|
|||
// Keep the value up to date |
|||
$: mde && mde.value(value || "") |
|||
$: { |
|||
if (mde && !mde.isPreviewActive()) { |
|||
mde.togglePreview() |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<div class="markdown-viewer" style="height:{height};"> |
|||
<SpectrumMDE |
|||
bind:mde |
|||
scroll={false} |
|||
easyMDEOptions={{ |
|||
initialValue: value, |
|||
toolbar: false, |
|||
}} |
|||
/> |
|||
</div> |
|||
|
|||
<style> |
|||
.markdown-viewer { |
|||
overflow: auto; |
|||
} |
|||
/* Remove padding, borders and background colors */ |
|||
.markdown-viewer :global(.editor-preview) { |
|||
padding: 0; |
|||
border: none; |
|||
background: transparent; |
|||
} |
|||
.markdown-viewer :global(.CodeMirror) { |
|||
border: none; |
|||
background: transparent; |
|||
padding: 0; |
|||
} |
|||
.markdown-viewer :global(.EasyMDEContainer) { |
|||
background: transparent; |
|||
} |
|||
/* Hide the actual code editor */ |
|||
.markdown-viewer :global(.CodeMirror-scroll) { |
|||
display: none; |
|||
} |
|||
/*Hide the scrollbar*/ |
|||
.markdown-viewer :global(.CodeMirror-vscrollbar) { |
|||
display: none !important; |
|||
} |
|||
/*Position relatively so we only consume whatever space we need */ |
|||
.markdown-viewer :global(.editor-preview-full) { |
|||
position: relative; |
|||
} |
|||
/* Remove margin on the first and last components to fully trim the preview */ |
|||
.markdown-viewer :global(.editor-preview-full > :first-child) { |
|||
margin-top: 0; |
|||
} |
|||
.markdown-viewer :global(.editor-preview-full > :last-child) { |
|||
margin-bottom: 0; |
|||
} |
|||
/* Code blocks in preview */ |
|||
.markdown-viewer :global(.editor-preview-full pre) { |
|||
background: var(--spectrum-global-color-gray-200); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,184 @@ |
|||
<script> |
|||
import EasyMDE from "easymde" |
|||
import "easymde/dist/easymde.min.css" |
|||
import { onMount } from "svelte" |
|||
|
|||
export let height = null |
|||
export let scroll = true |
|||
export let easyMDEOptions = null |
|||
export let mde = null |
|||
export let id = null |
|||
export let fullScreenOffset = null |
|||
export let disabled = false |
|||
|
|||
let element |
|||
|
|||
onMount(() => { |
|||
height = height || "200px" |
|||
mde = new EasyMDE({ |
|||
element, |
|||
spellChecker: false, |
|||
status: false, |
|||
unorderedListStyle: "-", |
|||
maxHeight: scroll ? height : undefined, |
|||
minHeight: scroll ? undefined : height, |
|||
...easyMDEOptions, |
|||
}) |
|||
|
|||
// Revert the editor when we unmount |
|||
return () => { |
|||
mde.toTextArea() |
|||
} |
|||
}) |
|||
|
|||
$: styleString = getStyleString(fullScreenOffset) |
|||
|
|||
const getStyleString = offset => { |
|||
let string = "" |
|||
string += `--fullscreen-offset-x:${offset?.x || "0px"};` |
|||
string += `--fullscreen-offset-y:${offset?.y || "0px"};` |
|||
return string |
|||
} |
|||
</script> |
|||
|
|||
<div class:disabled style={styleString}> |
|||
<textarea disabled {id} bind:this={element} /> |
|||
</div> |
|||
|
|||
<style> |
|||
/* Disabled styles */ |
|||
.disabled :global(textarea) { |
|||
display: none; |
|||
} |
|||
.disabled :global(.CodeMirror-cursor) { |
|||
display: none; |
|||
} |
|||
.disabled :global(.EasyMDEContainer) { |
|||
pointer-events: none; |
|||
} |
|||
.disabled :global(.editor-toolbar button i) { |
|||
color: var(--spectrum-global-color-gray-400); |
|||
} |
|||
.disabled :global(.CodeMirror) { |
|||
color: var(--spectrum-global-color-gray-600); |
|||
} |
|||
|
|||
/* Toolbar container */ |
|||
:global(.EasyMDEContainer .editor-toolbar) { |
|||
background: var(--spectrum-global-color-gray-50); |
|||
border-top: 1px solid var(--spectrum-alias-border-color); |
|||
border-left: 1px solid var(--spectrum-alias-border-color); |
|||
border-right: 1px solid var(--spectrum-alias-border-color); |
|||
} |
|||
/* Main code mirror instance and default color */ |
|||
:global(.EasyMDEContainer .CodeMirror) { |
|||
border: 1px solid var(--spectrum-alias-border-color); |
|||
background: var(--spectrum-global-color-gray-50); |
|||
color: var(--spectrum-alias-text-color); |
|||
} |
|||
/* Toolbar button active state */ |
|||
:global(.EasyMDEContainer .editor-toolbar button.active) { |
|||
background: var(--spectrum-global-color-gray-200); |
|||
border-color: var(--spectrum-global-color-gray-400); |
|||
} |
|||
/* Toolbar button hover state */ |
|||
:global(.EasyMDEContainer .editor-toolbar button:hover) { |
|||
background: var(--spectrum-global-color-gray-200); |
|||
border-color: var(--spectrum-global-color-gray-400); |
|||
} |
|||
/* Toolbar button color */ |
|||
:global(.EasyMDEContainer .editor-toolbar button i) { |
|||
color: var(--spectrum-global-color-gray-800); |
|||
} |
|||
/* Separator between toolbar buttons*/ |
|||
:global(.EasyMDEContainer .editor-toolbar i.separator) { |
|||
border-color: var(--spectrum-global-color-gray-300); |
|||
} |
|||
/* Cursor */ |
|||
:global(.EasyMDEContainer .CodeMirror-cursor) { |
|||
border-color: var(--spectrum-alias-text-color); |
|||
} |
|||
/* Text selections */ |
|||
:global(.EasyMDEContainer .CodeMirror-selectedtext) { |
|||
background: var(--spectrum-global-color-gray-400) !important; |
|||
} |
|||
/* Background of lines containing selected text */ |
|||
:global(.EasyMDEContainer .CodeMirror-selected) { |
|||
background: var(--spectrum-global-color-gray-400) !important; |
|||
} |
|||
/* Color of text for images and links */ |
|||
:global(.EasyMDEContainer .cm-s-easymde .cm-link) { |
|||
color: var(--spectrum-global-color-gray-600); |
|||
} |
|||
/* Color of URL for images and links */ |
|||
:global(.EasyMDEContainer .cm-s-easymde .cm-url) { |
|||
color: var(--spectrum-global-color-gray-500); |
|||
} |
|||
/* Full preview window */ |
|||
:global(.EasyMDEContainer .editor-preview) { |
|||
background: var(--spectrum-global-color-gray-50); |
|||
} |
|||
/* Side by side preview window */ |
|||
:global(.EasyMDEContainer .editor-preview) { |
|||
border: 1px solid var(--spectrum-alias-border-color); |
|||
} |
|||
/* Code blocks in editor */ |
|||
:global(.EasyMDEContainer .cm-s-easymde .cm-comment) { |
|||
background: var(--spectrum-global-color-gray-100); |
|||
} |
|||
/* Code blocks in preview */ |
|||
:global(.EasyMDEContainer pre) { |
|||
background: var(--spectrum-global-color-gray-100); |
|||
padding: 4px; |
|||
border-radius: 4px; |
|||
} |
|||
:global(.EasyMDEContainer code) { |
|||
color: #e83e8c; |
|||
} |
|||
:global(.EasyMDEContainer pre code) { |
|||
color: var(--spectrum-alias-text-color); |
|||
} |
|||
/* Block quotes */ |
|||
:global(.EasyMDEContainer blockquote) { |
|||
border-left: 4px solid var(--spectrum-global-color-gray-400); |
|||
color: var(--spectrum-global-color-gray-700); |
|||
margin-left: 0; |
|||
padding-left: 20px; |
|||
} |
|||
/* HR's */ |
|||
:global(.EasyMDEContainer hr) { |
|||
background-color: var(--spectrum-global-color-gray-300); |
|||
border: none; |
|||
height: 2px; |
|||
} |
|||
/* Tables */ |
|||
:global(.EasyMDEContainer td, .EasyMDEContainer th) { |
|||
border-color: var(--spectrum-alias-border-color) !important; |
|||
} |
|||
/* Links */ |
|||
:global(.EasyMDEContainer a) { |
|||
color: var(--primaryColor); |
|||
} |
|||
:global(.EasyMDEContainer a:hover) { |
|||
color: var(--primaryColorHover); |
|||
} |
|||
/* Allow full screen offset */ |
|||
:global(.EasyMDEContainer .editor-toolbar.fullscreen) { |
|||
left: var(--fullscreen-offset-x); |
|||
top: var(--fullscreen-offset-y); |
|||
} |
|||
:global(.EasyMDEContainer .CodeMirror-fullscreen) { |
|||
left: var(--fullscreen-offset-x); |
|||
top: calc(50px + var(--fullscreen-offset-y)); |
|||
} |
|||
|
|||
:global(.EasyMDEContainer .CodeMirror-fullscreen.CodeMirror-sided) { |
|||
width: calc((100% - var(--fullscreen-offset-x)) / 2) !important; |
|||
} |
|||
|
|||
:global(.EasyMDEContainer .editor-preview-side) { |
|||
left: calc(50% + (var(--fullscreen-offset-x) / 2)); |
|||
top: calc(50px + var(--fullscreen-offset-y)); |
|||
width: calc((100% - var(--fullscreen-offset-x)) / 2) !important; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,19 @@ |
|||
<script> |
|||
import { MarkdownViewer } from "@budibase/bbui" |
|||
import { getContext } from "svelte" |
|||
import Placeholder from "./Placeholder.svelte" |
|||
|
|||
export let value |
|||
|
|||
const component = getContext("component") |
|||
const { builderStore, styleable } = getContext("sdk") |
|||
const height = $component.styles?.normal?.height |
|||
</script> |
|||
|
|||
<div use:styleable={$component.styles}> |
|||
{#if value} |
|||
<MarkdownViewer {value} {height} /> |
|||
{:else if $builderStore.inBuilder} |
|||
<Placeholder /> |
|||
{/if} |
|||
</div> |
|||
Loading…
Reference in new issue