mirror of https://github.com/Budibase/budibase.git
11 changed files with 90 additions and 254 deletions
@ -0,0 +1,48 @@ |
|||
<script> |
|||
import "@spectrum-css/textfield/dist/index-vars.css" |
|||
import { createEventDispatcher } from "svelte" |
|||
|
|||
export let value = "" |
|||
export let placeholder = null |
|||
export let disabled = false |
|||
export let error = null |
|||
export let id = null |
|||
export let updateOnChange = true |
|||
|
|||
const dispatch = createEventDispatcher() |
|||
|
|||
const onChange = event => { |
|||
dispatch("change", event.target.value) |
|||
} |
|||
</script> |
|||
|
|||
<div |
|||
class="spectrum-Textfield spectrum-Textfield--multiline" |
|||
class:is-invalid={!!error} |
|||
class:is-disabled={disabled}> |
|||
{#if error} |
|||
<svg |
|||
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Textfield-validationIcon" |
|||
focusable="false" |
|||
aria-hidden="true"> |
|||
<use xlink:href="#spectrum-icon-18-Alert" /> |
|||
</svg> |
|||
{/if} |
|||
<textarea |
|||
placeholder={placeholder || ''} |
|||
class="spectrum-Textfield-input" |
|||
{disabled} |
|||
{id} |
|||
on:blur={onChange} |
|||
on:change={updateOnChange ? onChange : null}>{value || ''}</textarea> |
|||
</div> |
|||
|
|||
<style> |
|||
.spectrum-Textfield { |
|||
width: 100%; |
|||
} |
|||
textarea { |
|||
resize: vertical; |
|||
min-height: 80px !important; |
|||
} |
|||
</style> |
|||
@ -1,59 +0,0 @@ |
|||
<script> |
|||
import * as Quill from "quill" |
|||
import * as MarkdownIt from "markdown-it" |
|||
import TurndownService from "turndown" |
|||
import { onMount } from "svelte" |
|||
import "quill/dist/quill.snow.css" |
|||
|
|||
const convertMarkdown = new MarkdownIt() |
|||
convertMarkdown.set({ |
|||
html: true, |
|||
}) |
|||
const turndownService = new TurndownService() |
|||
|
|||
export let value = "" |
|||
export let options = null |
|||
export let width = 400 |
|||
|
|||
let quill |
|||
let container |
|||
let defaultOptions = { |
|||
modules: { |
|||
toolbar: [ |
|||
[{ header: [1, 2, 3, false] }], |
|||
["bold", "italic", "underline", "strike"], |
|||
], |
|||
}, |
|||
placeholder: "Type something...", |
|||
theme: "snow", // or 'bubble' |
|||
} |
|||
|
|||
let mergedOptions = { ...defaultOptions, ...options } |
|||
|
|||
const updateContent = () => { |
|||
value = turndownService.turndown(quill.container.firstChild.innerHTML) |
|||
} |
|||
|
|||
onMount(() => { |
|||
quill = new Quill(container, mergedOptions) |
|||
if (value) |
|||
quill.clipboard.dangerouslyPasteHTML(convertMarkdown.render(value + "\n")) |
|||
|
|||
quill.on("text-change", updateContent) |
|||
return () => { |
|||
quill.off("text-change", updateContent) |
|||
} |
|||
}) |
|||
</script> |
|||
|
|||
<svelte:head> |
|||
{#if mergedOptions.theme !== 'snow'} |
|||
<link |
|||
rel="stylesheet" |
|||
href="//cdn.quilljs.com/1.3.6/quill.{mergedOptions.theme}.css" /> |
|||
{/if} |
|||
</svelte:head> |
|||
|
|||
<div style="width: {width}px"> |
|||
<div bind:this={container} /> |
|||
</div> |
|||
@ -1,132 +1,29 @@ |
|||
<script> |
|||
import Field from "./Field.svelte" |
|||
import TextArea from "./Core/TextArea.svelte" |
|||
import { createEventDispatcher } from "svelte" |
|||
import Button from "../Button/Button.svelte" |
|||
import Label from "../Styleguide/Label.svelte" |
|||
import text_area_resize from "../Actions/autoresize_textarea.js" |
|||
|
|||
const dispatch = createEventDispatcher() |
|||
|
|||
export let name = false |
|||
export let label = false |
|||
export let thin = false |
|||
export let extraThin = false |
|||
export let edit = false |
|||
export let value = null |
|||
export let label = null |
|||
export let labelPosition = "above" |
|||
export let placeholder = null |
|||
export let disabled = false |
|||
export let placeholder |
|||
export let validator = () => {} |
|||
export let value = "" |
|||
export const getCaretPosition = () => { |
|||
return { start: textarea.selectionStart, end: textarea.selectionEnd } |
|||
} |
|||
|
|||
let textarea |
|||
|
|||
// This section handles the edit mode and dispatching of things to the parent when saved |
|||
let editMode = false |
|||
|
|||
const save = () => { |
|||
editMode = false |
|||
dispatch("save", value) |
|||
} |
|||
export let error = null |
|||
export let updateOnChange = true |
|||
|
|||
const enableEdit = () => { |
|||
editMode = true |
|||
const dispatch = createEventDispatcher() |
|||
const onChange = e => { |
|||
dispatch("change", e.detail) |
|||
value = e.detail |
|||
} |
|||
</script> |
|||
|
|||
<div class="container"> |
|||
{#if label || edit} |
|||
<div class="label-container"> |
|||
{#if label} |
|||
<Label extraSmall grey forAttr={name}>{label}</Label> |
|||
{/if} |
|||
{#if edit} |
|||
<div class="controls"> |
|||
<Button small secondary disabled={editMode} on:click={enableEdit}> |
|||
Edit |
|||
</Button> |
|||
<Button small blue disabled={!editMode} on:click={save}>Save</Button> |
|||
</div> |
|||
{/if} |
|||
</div> |
|||
{/if} |
|||
<textarea |
|||
class:thin |
|||
class:extraThin |
|||
bind:value |
|||
bind:this={textarea} |
|||
on:change |
|||
disabled={disabled || (edit && !editMode)} |
|||
<Field {label} {labelPosition} {disabled} {error}> |
|||
<TextArea |
|||
{error} |
|||
{disabled} |
|||
{value} |
|||
{placeholder} |
|||
{name} |
|||
use:text_area_resize /> |
|||
</div> |
|||
|
|||
<style> |
|||
.container { |
|||
min-width: 0; |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.label-container { |
|||
display: flex; |
|||
flex-direction: row; |
|||
justify-content: space-between; |
|||
align-items: flex-end; |
|||
margin-bottom: var(--spacing-s); |
|||
} |
|||
.label-container :global(label) { |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
.controls { |
|||
align-items: center; |
|||
display: grid; |
|||
grid-template-columns: auto auto; |
|||
grid-gap: 12px; |
|||
margin-left: auto; |
|||
padding-left: 12px; |
|||
} |
|||
.controls :global(button) { |
|||
min-width: 100px; |
|||
font-size: var(--font-size-s); |
|||
border-radius: var(--rounded-small); |
|||
} |
|||
|
|||
textarea { |
|||
min-width: 0; |
|||
color: var(--ink); |
|||
font-size: var(--font-size-s); |
|||
font-family: var(--font-sans); |
|||
border: none; |
|||
border-radius: var(--border-radius-s); |
|||
background-color: var(--grey-2); |
|||
padding: var(--spacing-m); |
|||
margin: 0; |
|||
border: var(--border-transparent); |
|||
outline: none; |
|||
} |
|||
textarea::placeholder { |
|||
color: var(--grey-6); |
|||
} |
|||
textarea.thin { |
|||
font-size: var(--font-size-xs); |
|||
} |
|||
textarea.extraThin { |
|||
font-size: var(--font-size-xs); |
|||
padding: var(--spacing-s) var(--spacing-m); |
|||
} |
|||
textarea:focus { |
|||
border: var(--border-blue); |
|||
} |
|||
textarea:disabled { |
|||
background: var(--grey-4); |
|||
} |
|||
textarea:disabled { |
|||
background: var(--grey-4); |
|||
} |
|||
textarea:disabled::placeholder { |
|||
color: var(--grey-6); |
|||
} |
|||
</style> |
|||
{updateOnChange} |
|||
on:change={onChange} /> |
|||
</Field> |
|||
|
|||
Loading…
Reference in new issue