Add TextAreaEditor (#1694)

* Add TextAreaEditor

Signed-off-by: Anna No <anna.no@xored.com>

* fix formatting

Signed-off-by: Anna No <anna.no@xored.com>

* fix formatting

Signed-off-by: Anna No <anna.no@xored.com>
This commit is contained in:
Anna No 2022-05-11 13:18:03 +07:00 committed by GitHub
parent 5b7c4132b2
commit 6706486aff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 64 deletions

View File

@ -3,6 +3,7 @@
"EditBoxPlaceholder": "Type text...",
"Ok": "Ok",
"Cancel": "Cancel",
"Save": "Save",
"Minutes": "{minutes, plural, =0 {less than a minute ago} =1 {a minute ago} other {# minutes ago}}",
"Hours": "{hours, plural, =0 {less than an hour ago} =1 {an hour ago} other {# hours ago}}",
"Days": "{days, plural, =0 {today} =1 {yesterday} other {# days ago}}",

View File

@ -3,6 +3,7 @@
"EditBoxPlaceholder": "Введите текст здесь",
"Ok": "Ок",
"Cancel": "Отменить",
"Save": "Сохранить",
"Minutes": "{minutes, plural, =0 {меньше минуты назад} =1 {минуту назад} other {# минут назад}}",
"Hours": "{hours, plural, =0 {меньше часа назад} =1 {час назад} other {# часов назад}}",
"Days": "{days, plural, =0 {сегода} =1 {вчера} other {# дней назад}}",

View File

@ -0,0 +1,72 @@
<script lang="ts">
import type { IntlString } from '@anticrm/platform'
import { createEventDispatcher } from 'svelte'
import ui from '../plugin'
import IconClose from './icons/Close.svelte'
import ActionIcon from './ActionIcon.svelte'
import Button from './Button.svelte'
import TextArea from './TextArea.svelte'
export let inputRef: TextArea | undefined = undefined
export let value: string = ''
export let width: string | undefined = undefined
export let height: string | undefined = undefined
export let submitLabel: IntlString = ui.string.Save
export let placeholder: IntlString | undefined
const dispatch = createEventDispatcher()
let isEditing = false
let openedContainerRef: HTMLDivElement
async function onClickOutside (e: any) {
if (openedContainerRef && !openedContainerRef.contains(e.target) && !e.defaultPrevented && isEditing) {
if (value) {
submit()
}
}
}
const submit = () => {
dispatch('submit', value)
}
const cancel = () => {
dispatch('cancel')
}
const onKeydown = (e: any) => {
if (e.detail.key !== 'Enter') {
return
}
e.detail.preventDefault()
submit()
}
$: if (inputRef && !value) {
isEditing = true
inputRef.focus()
}
</script>
<svelte:window on:click={onClickOutside} />
<div bind:this={openedContainerRef}>
<div
class="flex-col background-bg-accent border-bg-accent border-radius-1 pt-1 pb-1 pr-2 pl-2"
style:user-select="none"
>
<TextArea
{placeholder}
{height}
{width}
bind:this={inputRef}
bind:value
on:keydown={onKeydown}
noFocusBorder={true}
/>
</div>
<div class="flex-row-center mt-3">
<Button label={submitLabel} kind="no-border" size="medium" on:click={submit} />
<div class="ml-2" on:click={cancel}>
<ActionIcon icon={IconClose} size="medium" action={cancel} />
</div>
</div>
</div>

View File

@ -57,6 +57,7 @@ export { default as PopupMenu } from './components/PopupMenu.svelte'
export { default as SelectPopup } from './components/SelectPopup.svelte'
export { default as ColorPopup } from './components/ColorPopup.svelte'
export { default as TextArea } from './components/TextArea.svelte'
export { default as TextAreaEditor } from './components/TextAriaEditor.svelte'
export { default as Section } from './components/Section.svelte'
export { default as DatePickerPopup } from './components/calendar/DatePickerPopup.svelte'
export { default as DatePicker } from './components/calendar/DatePicker.svelte'

View File

@ -28,6 +28,7 @@ export default plugin(uiId, {
EditBoxPlaceholder: '' as IntlString,
Ok: '' as IntlString,
Cancel: '' as IntlString,
Save: '' as IntlString,
Minutes: '' as IntlString,
Hours: '' as IntlString,
Days: '' as IntlString,

View File

@ -1,78 +1,26 @@
<script lang="ts">
import { Button, TextArea, ActionIcon, IconClose } from '@anticrm/ui'
import { TextAreaEditor } from '@anticrm/ui'
import board from '../../plugin'
export let onClose: () => void
export let onAdd: (title: string, checkNewLine?: boolean) => Promise<any>
let isEditing = false
let title = ''
let inputRef: TextArea
let openedContainerRef: HTMLDivElement
let value = ''
async function addCard () {
async function addCard (event: CustomEvent) {
const title = event.detail
if (!title) {
inputRef.focus()
return
}
isEditing = false
await onAdd(title, true)
title = ''
}
async function onClickOutside (e: any) {
if (openedContainerRef && !openedContainerRef.contains(e.target) && !e.defaultPrevented && isEditing) {
if (title) {
await onAdd(title)
}
onClose()
}
}
const onKeydown = (e: any) => {
if (e.detail.key !== 'Enter') {
return
}
e.detail.preventDefault()
addCard()
}
$: if (inputRef && !title) {
isEditing = true
inputRef.focus()
value = ''
}
</script>
<svelte:window on:click={onClickOutside} />
<div bind:this={openedContainerRef}>
<div class="card-container">
<TextArea
placeholder={board.string.CardTitlePlaceholder}
bind:this={inputRef}
bind:value={title}
on:keydown={onKeydown}
noFocusBorder={true}
/>
</div>
<div class="flex-row-center mt-3">
<Button label={board.string.AddCard} kind="no-border" on:click={addCard} />
<div class="ml-2" on:click={onClose}>
<ActionIcon icon={IconClose} size={'large'} action={onClose} />
</div>
</div>
</div>
<style lang="scss">
.card-container {
display: flex;
flex-direction: column;
padding: 0.5rem 1rem;
background-color: var(--board-card-bg-color);
border: 1px solid var(--board-card-bg-color);
border-radius: 0.25rem;
user-select: none;
}
</style>
<TextAreaEditor
bind:value
placeholder={board.string.CardTitlePlaceholder}
submitLabel={board.string.AddCard}
on:submit={addCard}
on:cancel={onClose}
/>