Merge pull request #4309 from Budibase/feature/real-rich-text
Rich text field + markdown viewer component
This commit is contained in:
commit
171905fd13
|
@ -79,6 +79,7 @@
|
||||||
"@spectrum-css/underlay": "^2.0.9",
|
"@spectrum-css/underlay": "^2.0.9",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
|
"easymde": "^2.16.1",
|
||||||
"svelte-flatpickr": "^3.2.3",
|
"svelte-flatpickr": "^3.2.3",
|
||||||
"svelte-portal": "^1.0.0"
|
"svelte-portal": "^1.0.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -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>
|
|
@ -22,11 +22,23 @@
|
||||||
dispatch("change", event.target.value)
|
dispatch("change", event.target.value)
|
||||||
focus = false
|
focus = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStyleString = (attribute, value) => {
|
||||||
|
if (!attribute || value == null) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if (isNaN(value)) {
|
||||||
|
return `${attribute}:${value};`
|
||||||
|
}
|
||||||
|
return `${attribute}:${value}px;`
|
||||||
|
}
|
||||||
|
|
||||||
|
$: heightString = getStyleString("height", height)
|
||||||
|
$: minHeightString = getStyleString("min-height", minHeight)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={(height ? `height: ${height}px;` : "") +
|
style={`${heightString}${minHeightString}`}
|
||||||
(minHeight ? `min-height: ${minHeight}px` : "")}
|
|
||||||
class="spectrum-Textfield spectrum-Textfield--multiline"
|
class="spectrum-Textfield spectrum-Textfield--multiline"
|
||||||
class:is-invalid={!!error}
|
class:is-invalid={!!error}
|
||||||
class:is-disabled={disabled}
|
class:is-disabled={disabled}
|
||||||
|
|
|
@ -10,3 +10,4 @@ export { default as CoreSearch } from "./Search.svelte"
|
||||||
export { default as CoreDatePicker } from "./DatePicker.svelte"
|
export { default as CoreDatePicker } from "./DatePicker.svelte"
|
||||||
export { default as CoreDropzone } from "./Dropzone.svelte"
|
export { default as CoreDropzone } from "./Dropzone.svelte"
|
||||||
export { default as CoreStepper } from "./Stepper.svelte"
|
export { default as CoreStepper } from "./Stepper.svelte"
|
||||||
|
export { default as CoreRichTextField } from "./RichTextField.svelte"
|
||||||
|
|
|
@ -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>
|
|
@ -60,6 +60,9 @@ export { default as StatusLight } from "./StatusLight/StatusLight.svelte"
|
||||||
export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
|
export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
|
||||||
export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte"
|
export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte"
|
||||||
export { default as Banner } from "./Banner/Banner.svelte"
|
export { default as Banner } from "./Banner/Banner.svelte"
|
||||||
|
export { default as MarkdownEditor } from "./Markdown/MarkdownEditor.svelte"
|
||||||
|
export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte"
|
||||||
|
export { default as RichTextField } from "./Form/RichTextField.svelte"
|
||||||
|
|
||||||
// Renderers
|
// Renderers
|
||||||
export { default as BoldRenderer } from "./Table/BoldRenderer.svelte"
|
export { default as BoldRenderer } from "./Table/BoldRenderer.svelte"
|
||||||
|
|
|
@ -271,6 +271,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.2.tgz#ea9062c3c98dfc6ba59e5df14a03025ad8969999"
|
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.2.tgz#ea9062c3c98dfc6ba59e5df14a03025ad8969999"
|
||||||
integrity sha512-vzS9KqYXot4J3AEER/u618MXWAS+IoMvYMNrOoscKiLLKYQWenaueakUWulFonToPd/9vIpqtdbwxznqrK5qDw==
|
integrity sha512-vzS9KqYXot4J3AEER/u618MXWAS+IoMvYMNrOoscKiLLKYQWenaueakUWulFonToPd/9vIpqtdbwxznqrK5qDw==
|
||||||
|
|
||||||
|
"@types/codemirror@^5.60.4":
|
||||||
|
version "5.60.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.5.tgz#5b989a3b4bbe657458cf372c92b6bfda6061a2b7"
|
||||||
|
integrity sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==
|
||||||
|
dependencies:
|
||||||
|
"@types/tern" "*"
|
||||||
|
|
||||||
"@types/estree@*":
|
"@types/estree@*":
|
||||||
version "0.0.47"
|
version "0.0.47"
|
||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
|
||||||
|
@ -281,6 +288,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
||||||
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
|
||||||
|
|
||||||
|
"@types/marked@^4.0.1":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.2.tgz#cb2dbf10da2f41cf20bd91fb5f89b67540c282f7"
|
||||||
|
integrity sha512-auNrZ/c0w6wsM9DccwVxWHssrMDezHUAXNesdp2RQrCVCyrQbOiSq7yqdJKrUQQpw9VTm7CGYJH2A/YG7jjrjQ==
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "14.14.41"
|
version "14.14.41"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615"
|
||||||
|
@ -303,6 +315,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/tern@*":
|
||||||
|
version "0.23.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb"
|
||||||
|
integrity sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "*"
|
||||||
|
|
||||||
accepts@~1.3.7:
|
accepts@~1.3.7:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
||||||
|
@ -525,6 +544,18 @@ coa@^2.0.2:
|
||||||
chalk "^2.4.1"
|
chalk "^2.4.1"
|
||||||
q "^1.1.2"
|
q "^1.1.2"
|
||||||
|
|
||||||
|
codemirror-spell-checker@1.1.2:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz#1c660f9089483ccb5113b9ba9ca19c3f4993371e"
|
||||||
|
integrity sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=
|
||||||
|
dependencies:
|
||||||
|
typo-js "*"
|
||||||
|
|
||||||
|
codemirror@^5.63.1:
|
||||||
|
version "5.65.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.1.tgz#5988a812c974c467f964bcc1a00c944e373de502"
|
||||||
|
integrity sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA==
|
||||||
|
|
||||||
color-convert@^1.9.0, color-convert@^1.9.1:
|
color-convert@^1.9.0, color-convert@^1.9.1:
|
||||||
version "1.9.3"
|
version "1.9.3"
|
||||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
|
@ -861,6 +892,17 @@ dot-prop@^5.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-obj "^2.0.0"
|
is-obj "^2.0.0"
|
||||||
|
|
||||||
|
easymde@^2.16.1:
|
||||||
|
version "2.16.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/easymde/-/easymde-2.16.1.tgz#f4c2380312615cb33826f1a1fecfaa4022ff551a"
|
||||||
|
integrity sha512-FihYgjRsKfhGNk89SHSqxKLC4aJ1kfybPWW6iAmtb5GnXu+tnFPSzSaGBmk1RRlCuhFSjhF0SnIMGVPjEzkr6g==
|
||||||
|
dependencies:
|
||||||
|
"@types/codemirror" "^5.60.4"
|
||||||
|
"@types/marked" "^4.0.1"
|
||||||
|
codemirror "^5.63.1"
|
||||||
|
codemirror-spell-checker "1.1.2"
|
||||||
|
marked "^4.0.10"
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||||
|
@ -1472,6 +1514,11 @@ magic-string@^0.25.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
sourcemap-codec "^1.4.4"
|
sourcemap-codec "^1.4.4"
|
||||||
|
|
||||||
|
marked@^4.0.10:
|
||||||
|
version "4.0.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
|
||||||
|
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
|
||||||
|
|
||||||
mdn-data@2.0.14:
|
mdn-data@2.0.14:
|
||||||
version "2.0.14"
|
version "2.0.14"
|
||||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
|
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
|
||||||
|
@ -2490,6 +2537,11 @@ type-is@~1.6.17, type-is@~1.6.18:
|
||||||
media-typer "0.3.0"
|
media-typer "0.3.0"
|
||||||
mime-types "~2.1.24"
|
mime-types "~2.1.24"
|
||||||
|
|
||||||
|
typo-js@*:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.2.1.tgz#334a0d8c3f6c56f2f1e15fdf6c31677793cbbe9b"
|
||||||
|
integrity sha512-bTGLjbD3WqZDR3CgEFkyi9Q/SS2oM29ipXrWfDb4M74ea69QwKAECVceYpaBu0GfdnASMg9Qfl67ttB23nePHg==
|
||||||
|
|
||||||
unbox-primitive@^1.0.0:
|
unbox-primitive@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
|
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
|
||||||
|
|
|
@ -169,6 +169,11 @@ export function makeDatasourceFormComponents(datasource) {
|
||||||
optionsSource: "schema",
|
optionsSource: "schema",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (fieldType === "longform") {
|
||||||
|
component.customProps({
|
||||||
|
format: "auto",
|
||||||
|
})
|
||||||
|
}
|
||||||
if (fieldType === "array") {
|
if (fieldType === "array") {
|
||||||
component.customProps({
|
component.customProps({
|
||||||
placeholder: "Choose an option",
|
placeholder: "Choose an option",
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
Select,
|
Select,
|
||||||
DatePicker,
|
DatePicker,
|
||||||
Toggle,
|
Toggle,
|
||||||
TextArea,
|
|
||||||
Multiselect,
|
Multiselect,
|
||||||
Label,
|
Label,
|
||||||
|
RichTextField,
|
||||||
|
TextArea,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import Dropzone from "components/common/Dropzone.svelte"
|
import Dropzone from "components/common/Dropzone.svelte"
|
||||||
import { capitalise } from "helpers"
|
import { capitalise } from "helpers"
|
||||||
|
@ -43,7 +44,11 @@
|
||||||
{:else if type === "link"}
|
{:else if type === "link"}
|
||||||
<LinkedRowSelector bind:linkedRows={value} schema={meta} />
|
<LinkedRowSelector bind:linkedRows={value} schema={meta} />
|
||||||
{:else if type === "longform"}
|
{:else if type === "longform"}
|
||||||
<TextArea {label} bind:value />
|
{#if meta.useRichText}
|
||||||
|
<RichTextField {label} height="150px" bind:value />
|
||||||
|
{:else}
|
||||||
|
<TextArea {label} height="150px" bind:value />
|
||||||
|
{/if}
|
||||||
{:else if type === "json"}
|
{:else if type === "json"}
|
||||||
<Label>{label}</Label>
|
<Label>{label}</Label>
|
||||||
<Editor
|
<Editor
|
||||||
|
|
|
@ -367,7 +367,7 @@
|
||||||
|
|
||||||
{#if canBeSearched && !external}
|
{#if canBeSearched && !external}
|
||||||
<div>
|
<div>
|
||||||
<Label grey small>Search Indexes</Label>
|
<Label>Search Indexes</Label>
|
||||||
<Toggle
|
<Toggle
|
||||||
value={indexes[0] === field.name}
|
value={indexes[0] === field.name}
|
||||||
disabled={indexes[1] === field.name}
|
disabled={indexes[1] === field.name}
|
||||||
|
@ -394,6 +394,19 @@
|
||||||
label="Options (one per line)"
|
label="Options (one per line)"
|
||||||
bind:values={field.constraints.inclusion}
|
bind:values={field.constraints.inclusion}
|
||||||
/>
|
/>
|
||||||
|
{:else if field.type === "longform"}
|
||||||
|
<div>
|
||||||
|
<Label
|
||||||
|
size="M"
|
||||||
|
tooltip="Rich text includes support for images, links, tables, lists and more"
|
||||||
|
>
|
||||||
|
Formatting
|
||||||
|
</Label>
|
||||||
|
<Toggle
|
||||||
|
bind:value={field.useRichText}
|
||||||
|
text="Enable rich text support (markdown)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{:else if field.type === "array"}
|
{:else if field.type === "array"}
|
||||||
<ValuesList
|
<ValuesList
|
||||||
label="Options (one per line)"
|
label="Options (one per line)"
|
||||||
|
|
|
@ -81,7 +81,8 @@
|
||||||
"backgroundimage",
|
"backgroundimage",
|
||||||
"link",
|
"link",
|
||||||
"icon",
|
"icon",
|
||||||
"embed"
|
"embed",
|
||||||
|
"markdownviewer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -2365,11 +2365,10 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"longformfield": {
|
"longformfield": {
|
||||||
"name": "Rich Text",
|
"name": "Long Form Field",
|
||||||
"icon": "TextParagraph",
|
"icon": "TextParagraph",
|
||||||
"styles": ["size"],
|
"styles": ["size"],
|
||||||
"editable": true,
|
"editable": true,
|
||||||
"illegalChildren": ["section"],
|
|
||||||
"settings": [
|
"settings": [
|
||||||
{
|
{
|
||||||
"type": "field/longform",
|
"type": "field/longform",
|
||||||
|
@ -2392,6 +2391,27 @@
|
||||||
"label": "Default value",
|
"label": "Default value",
|
||||||
"key": "defaultValue"
|
"key": "defaultValue"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "select",
|
||||||
|
"label": "Formatting",
|
||||||
|
"key": "format",
|
||||||
|
"placeholder": null,
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "Auto",
|
||||||
|
"value": "auto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Plain text",
|
||||||
|
"value": "plain"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Rich text (markdown)",
|
||||||
|
"value": "rich"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"defaultValue": "auto"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"label": "Disabled",
|
"label": "Disabled",
|
||||||
|
@ -2402,35 +2422,6 @@
|
||||||
"type": "validation/string",
|
"type": "validation/string",
|
||||||
"label": "Validation",
|
"label": "Validation",
|
||||||
"key": "validation"
|
"key": "validation"
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "select",
|
|
||||||
"label": "Alignment",
|
|
||||||
"key": "align",
|
|
||||||
"defaultValue": "left",
|
|
||||||
"showInBar": true,
|
|
||||||
"barStyle": "buttons",
|
|
||||||
"options": [{
|
|
||||||
"label": "Left",
|
|
||||||
"value": "left",
|
|
||||||
"barIcon": "TextAlignLeft",
|
|
||||||
"barTitle": "Align left"
|
|
||||||
}, {
|
|
||||||
"label": "Center",
|
|
||||||
"value": "center",
|
|
||||||
"barIcon": "TextAlignCenter",
|
|
||||||
"barTitle": "Align center"
|
|
||||||
}, {
|
|
||||||
"label": "Right",
|
|
||||||
"value": "right",
|
|
||||||
"barIcon": "TextAlignRight",
|
|
||||||
"barTitle": "Align right"
|
|
||||||
}, {
|
|
||||||
"label": "Justify",
|
|
||||||
"value": "justify",
|
|
||||||
"barIcon": "TextAlignJustify",
|
|
||||||
"barTitle": "Justify text"
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -3448,5 +3439,18 @@
|
||||||
"key": "validation"
|
"key": "validation"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"markdownviewer": {
|
||||||
|
"name": "Markdown Viewer",
|
||||||
|
"icon": "TaskList",
|
||||||
|
"styles": ["size"],
|
||||||
|
"editable": true,
|
||||||
|
"settings": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"label": "Markdown",
|
||||||
|
"key": "value"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext, setContext } from "svelte"
|
||||||
|
import { writable } from "svelte/store"
|
||||||
import { Heading, Icon } from "@budibase/bbui"
|
import { Heading, Icon } from "@budibase/bbui"
|
||||||
import { FieldTypes } from "../../constants"
|
import { FieldTypes } from "../../constants"
|
||||||
import active from "svelte-spa-router/active"
|
import active from "svelte-spa-router/active"
|
||||||
|
@ -29,6 +30,16 @@
|
||||||
Small: "s",
|
Small: "s",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set some layout context. This isn't used in bindings but can be used
|
||||||
|
// determine things about the current app layout.
|
||||||
|
$: mobile = $context.device.mobile
|
||||||
|
const store = writable({ headerHeight: 0 })
|
||||||
|
$: store.set({
|
||||||
|
screenXOffset: getScreenXOffset(navigation, mobile),
|
||||||
|
screenYOffset: getScreenYOffset(navigation, mobile),
|
||||||
|
})
|
||||||
|
setContext("layout", store)
|
||||||
|
|
||||||
// Permanently go into peek mode if we ever get the peek flag
|
// Permanently go into peek mode if we ever get the peek flag
|
||||||
let isPeeking = false
|
let isPeeking = false
|
||||||
$: {
|
$: {
|
||||||
|
@ -58,13 +69,27 @@
|
||||||
if ($builderStore.inBuilder) return
|
if ($builderStore.inBuilder) return
|
||||||
window.location.href = "/builder/apps"
|
window.location.href = "/builder/apps"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getScreenXOffset = (navigation, mobile) => {
|
||||||
|
if (navigation !== "Left") {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return mobile ? "0px" : "250px"
|
||||||
|
}
|
||||||
|
const getScreenYOffset = (navigation, mobile) => {
|
||||||
|
if (mobile) {
|
||||||
|
return !navigation || navigation === "None" ? 0 : "61px"
|
||||||
|
} else {
|
||||||
|
return navigation === "Top" ? "137px" : "0px"
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="layout layout--{typeClass}"
|
class="layout layout--{typeClass}"
|
||||||
use:styleable={$component.styles}
|
use:styleable={$component.styles}
|
||||||
class:desktop={!$context.device.mobile}
|
class:desktop={!mobile}
|
||||||
class:mobile={!!$context.device.mobile}
|
class:mobile={!!mobile}
|
||||||
>
|
>
|
||||||
{#if typeClass !== "none"}
|
{#if typeClass !== "none"}
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -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>
|
|
@ -1,7 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import { CoreTextArea } from "@budibase/bbui"
|
import { getContext, setContext } from "svelte"
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import { CoreRichTextField, CoreTextArea } from "@budibase/bbui"
|
||||||
import Field from "./Field.svelte"
|
import Field from "./Field.svelte"
|
||||||
import { getContext } from "svelte"
|
|
||||||
|
|
||||||
export let field
|
export let field
|
||||||
export let label
|
export let label
|
||||||
|
@ -9,13 +10,40 @@
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let validation
|
export let validation
|
||||||
export let defaultValue = ""
|
export let defaultValue = ""
|
||||||
export let align
|
export let format = "auto"
|
||||||
|
|
||||||
let fieldState
|
let fieldState
|
||||||
let fieldApi
|
let fieldApi
|
||||||
|
let fieldSchema
|
||||||
|
|
||||||
|
const context = getContext("context")
|
||||||
const component = getContext("component")
|
const component = getContext("component")
|
||||||
$: height = $component.styles?.normal?.height || "124px"
|
const layout = getContext("layout")
|
||||||
|
const newContext = writable($component)
|
||||||
|
setContext("component", newContext)
|
||||||
|
|
||||||
|
// Determine whether we should use a rich or plain text component.
|
||||||
|
// We treat undefined as "auto".
|
||||||
|
$: useRichText =
|
||||||
|
format === "rich" || (format !== "plain" && fieldSchema?.useRichText)
|
||||||
|
|
||||||
|
// Extract the settings height so we can pass it on to the rich text field.
|
||||||
|
// We then wipe the height style so that the field will automatically size
|
||||||
|
// itself based on the height of the rich text field.
|
||||||
|
let height
|
||||||
|
$: {
|
||||||
|
height = $component.styles?.normal?.height || "150px"
|
||||||
|
newContext.set({
|
||||||
|
...$component,
|
||||||
|
styles: {
|
||||||
|
...$component.styles,
|
||||||
|
normal: {
|
||||||
|
...$component.styles.normal,
|
||||||
|
height: undefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Field
|
<Field
|
||||||
|
@ -27,29 +55,36 @@
|
||||||
type="longform"
|
type="longform"
|
||||||
bind:fieldState
|
bind:fieldState
|
||||||
bind:fieldApi
|
bind:fieldApi
|
||||||
|
bind:fieldSchema
|
||||||
>
|
>
|
||||||
{#if fieldState}
|
{#if fieldState}
|
||||||
<div style="--height: {height};">
|
{#if useRichText}
|
||||||
|
<CoreRichTextField
|
||||||
|
value={fieldState.value}
|
||||||
|
on:change={e => fieldApi.setValue(e.detail)}
|
||||||
|
disabled={fieldState.disabled}
|
||||||
|
error={fieldState.error}
|
||||||
|
id={fieldState.fieldId}
|
||||||
|
{placeholder}
|
||||||
|
{height}
|
||||||
|
fullScreenOffset={{
|
||||||
|
x: $layout.screenXOffset,
|
||||||
|
y: $layout.screenYOffset,
|
||||||
|
}}
|
||||||
|
easyMDEOptions={{
|
||||||
|
hideIcons: $context.device.mobile ? ["side-by-side", "guide"] : [],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
<CoreTextArea
|
<CoreTextArea
|
||||||
value={fieldState.value}
|
value={fieldState.value}
|
||||||
on:change={e => fieldApi.setValue(e.detail)}
|
on:change={e => fieldApi.setValue(e.detail)}
|
||||||
disabled={fieldState.disabled}
|
disabled={fieldState.disabled}
|
||||||
error={fieldState.error}
|
error={fieldState.error}
|
||||||
id={fieldState.fieldId}
|
id={fieldState.fieldId}
|
||||||
{align}
|
|
||||||
{placeholder}
|
{placeholder}
|
||||||
|
minHeight={height}
|
||||||
/>
|
/>
|
||||||
</div>
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<style>
|
|
||||||
:global(.spectrum-Form-itemField .spectrum-Textfield--multiline) {
|
|
||||||
min-height: calc(var(--height) - 24px);
|
|
||||||
}
|
|
||||||
:global(.spectrum-Form--labelsAbove
|
|
||||||
.spectrum-Form-itemField
|
|
||||||
.spectrum-Textfield--multiline) {
|
|
||||||
min-height: calc(var(--height) - 24px);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ export { default as daterangepicker } from "./DateRangePicker.svelte"
|
||||||
export { default as cardstat } from "./CardStat.svelte"
|
export { default as cardstat } from "./CardStat.svelte"
|
||||||
export { default as spectrumcard } from "./SpectrumCard.svelte"
|
export { default as spectrumcard } from "./SpectrumCard.svelte"
|
||||||
export { default as tag } from "./Tag.svelte"
|
export { default as tag } from "./Tag.svelte"
|
||||||
|
export { default as markdownviewer } from "./MarkdownViewer.svelte"
|
||||||
export * from "./charts"
|
export * from "./charts"
|
||||||
export * from "./forms"
|
export * from "./forms"
|
||||||
export * from "./table"
|
export * from "./table"
|
||||||
|
|
Loading…
Reference in New Issue