feat(frontend): App builder password and date input (#1022)

* feat: Add password input to app builder
This commit is contained in:
Ádám Kovács
2022-12-20 15:34:36 +01:00
committed by GitHub
parent b7afe5ecfc
commit 4651c9d8cd
10 changed files with 165 additions and 33 deletions
@@ -0,0 +1,49 @@
<script lang="ts">
import { getContext } from 'svelte'
import type { AppInput } from '../../inputType'
import type { Output } from '../../rx'
import type { AppEditorContext } from '../../types'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
import InputValue from '../helpers/InputValue.svelte'
export let id: string
export let configuration: Record<string, AppInput>
export let inputType: 'date' | 'time' | 'datetime-local'
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export const staticOutputs: string[] = ['result']
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
let input: HTMLInputElement
let labelValue: string = 'Title'
let minValue: string = ''
let maxValue: string = ''
$: outputs = $worldStore?.outputsById[id] as {
result: Output<string>
}
function handleInput() {
outputs?.result.set(input.value)
}
</script>
<InputValue input={configuration.label} bind:value={labelValue} />
<InputValue input={configuration.minDate} bind:value={minValue} />
<InputValue input={configuration.maxDate} bind:value={maxValue} />
<AlignWrapper {verticalAlignment}>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="w-full">
<div>
{labelValue}
</div>
<input
type={inputType}
bind:this={input}
on:input={handleInput}
min={minValue}
max={maxValue}
placeholder="Type..."
/>
</label>
</AlignWrapper>
@@ -14,7 +14,6 @@
export let recomputeIds: string[] | undefined = undefined
export let extraQueryParams: Record<string, any> = {}
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export const staticOutputs: string[] = ['loading', 'result']
@@ -38,7 +37,7 @@
autoRefresh={false}
forceSchemaDisplay={true}
>
<AlignWrapper {horizontalAlignment} {verticalAlignment} disableVerticalAlignment={true}>
<AlignWrapper {horizontalAlignment}>
<Button
on:click={() => {
runnableComponent?.runComponent()
@@ -1,9 +1,8 @@
<script lang="ts">
import { classNames } from '$lib/utils'
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined
export let disableVerticalAlignment: boolean = false
export let horizontalAlignment: 'left' | 'center' | 'right' | undefined = undefined
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
function tailwindHorizontalAlignment(horizontalAlignment) {
switch (horizontalAlignment) {
@@ -31,7 +30,7 @@
'flex w-full',
tailwindHorizontalAlignment(horizontalAlignment),
tailwindVerticalAlignment(verticalAlignment),
disableVerticalAlignment ? '' : 'h-full'
verticalAlignment ? 'h-full' : ''
)
</script>
@@ -4,10 +4,12 @@
import type { Output } from '../../rx'
import type { AppEditorContext } from '../../types'
import DebouncedInput from '../helpers/DebouncedInput.svelte'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
import InputValue from '../helpers/InputValue.svelte'
export let id: string
export let configuration: Record<string, AppInput>
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export const staticOutputs: string[] = ['result']
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
@@ -29,17 +31,19 @@
<InputValue input={configuration.label} bind:value={labelValue} />
<!-- svelte-ignore a11y-label-has-associated-control -->
<label>
<div>
{labelValue}
</div>
<DebouncedInput
bind:value={value}
debounceDelay={300}
type="number"
inputmode="numeric"
pattern="\d*"
placeholder="Type..."
/>
</label>
<AlignWrapper {verticalAlignment}>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="w-full">
<div>
{labelValue}
</div>
<DebouncedInput
bind:value={value}
debounceDelay={300}
type="number"
inputmode="numeric"
pattern="\d*"
placeholder="Type..."
/>
</label>
</AlignWrapper>
@@ -3,28 +3,41 @@
import type { AppInput } from '../../inputType'
import type { Output } from '../../rx'
import type { AppEditorContext } from '../../types'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
import InputValue from '../helpers/InputValue.svelte'
export let id: string
export let configuration: Record<string, AppInput>
export let inputType = 'text'
export let verticalAlignment: 'top' | 'center' | 'bottom' | undefined = undefined
export const staticOutputs: string[] = ['result']
const { worldStore } = getContext<AppEditorContext>('AppEditorContext')
let value: string
let input: HTMLInputElement
let labelValue: string = 'Title'
$: outputs = $worldStore?.outputsById[id] as {
result: Output<string>
}
$: (value || !value) && outputs?.result.set(value || '')
function handleInput() {
outputs?.result.set(input.value)
}
</script>
<InputValue input={configuration.label} bind:value={labelValue} />
<!-- svelte-ignore a11y-label-has-associated-control -->
<label>
<div>
{labelValue}
</div>
<input type="text" bind:value placeholder="Type..." />
</label>
<AlignWrapper {verticalAlignment}>
<!-- svelte-ignore a11y-label-has-associated-control -->
<label class="w-full">
<div>
{labelValue}
</div>
<input
type={inputType}
bind:this={input}
on:input={handleInput}
placeholder="Type..."
/>
</label>
</AlignWrapper>
@@ -12,6 +12,7 @@
import CheckboxComponent from '../components/selectInputs/AppCheckbox.svelte'
import TextInputComponent from '../components/textInputs/AppTextInput.svelte'
import NumberInputComponent from '../components/numberInputs/AppNumberInput.svelte'
import DateInputComponent from '../components/dateInputs/AppDateInput.svelte'
import ComponentHeader from './ComponentHeader.svelte'
import AppForm from '../components/form/AppForm.svelte'
@@ -90,6 +91,10 @@
<CheckboxComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
{:else if component.type === 'textinputcomponent'}
<TextInputComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
{:else if component.type === 'passwordinputcomponent'}
<TextInputComponent inputType='password' {...component} bind:staticOutputs={$staticOutputs[component.id]} />
{:else if component.type === 'dateinputcomponent'}
<DateInputComponent inputType='date' {...component} bind:staticOutputs={$staticOutputs[component.id]} />
{:else if component.type === 'numberinputcomponent'}
<NumberInputComponent {...component} bind:staticOutputs={$staticOutputs[component.id]} />
{/if}
@@ -43,7 +43,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="bg-white h-full relative"
on:click|preventDefault={() => ($selectedComponent = undefined)}
on:click|preventDefault={() => $selectedComponent = undefined}
>
<RecomputeAllComponents />
@@ -64,7 +64,7 @@
'h-full w-full flex justify-center align-center',
gridComponent.data.card ? 'border border-gray-100' : ''
)}
on:click|preventDefault|stopPropagation={() => {
on:click|stopPropagation={() => {
if (!$connectingInput.opened) {
$selectedComponent = dataItem.data.id
}
@@ -5,6 +5,7 @@ const inputs: ComponentSet = {
title: 'Inputs',
components: [
{
verticalAlignment: 'center',
id: 'textinputcomponent',
type: 'textinputcomponent',
componentInput: undefined,
@@ -20,6 +21,23 @@ const inputs: ComponentSet = {
card: false
},
{
verticalAlignment: 'center',
id: 'passwordinputcomponent',
type: 'passwordinputcomponent',
componentInput: undefined,
configuration: {
label: {
type: 'static',
visible: false,
value: 'Label',
fieldType: 'textarea',
defaultValue: 'Label'
}
},
card: false
},
{
verticalAlignment: 'center',
id: 'numberinputcomponent',
type: 'numberinputcomponent',
componentInput: undefined,
@@ -34,6 +52,37 @@ const inputs: ComponentSet = {
},
card: false
},
{
verticalAlignment: 'center',
id: 'dateinputcomponent',
type: 'dateinputcomponent',
componentInput: undefined,
configuration: {
label: {
type: 'static',
visible: false,
value: 'Title',
fieldType: 'textarea',
defaultValue: 'Title'
},
minDate: {
type: 'static',
visible: false,
value: '',
fieldType: 'date',
defaultValue: ''
},
maxDate: {
type: 'static',
visible: false,
value: '',
fieldType: 'date',
defaultValue: ''
},
},
card: false,
softWrap: true
},
{
...defaultAlignement,
id: 'checkboxcomponent',
@@ -51,7 +100,7 @@ const inputs: ComponentSet = {
card: false
},
{
...defaultAlignement,
verticalAlignment: 'center',
id: 'selectcomponent',
type: 'selectcomponent',
componentInput: undefined,
@@ -133,7 +182,7 @@ const buttons: ComponentSet = {
card: false
},
{
...defaultAlignement,
horizontalAlignment: 'center',
id: 'formcomponent',
type: 'formcomponent',
componentInput: {
@@ -17,6 +17,8 @@ type BaseComponent<T extends string> = {
export type TextComponent = BaseComponent<'textcomponent'>
export type TextInputComponent = BaseComponent<'textinputcomponent'>
export type PasswordInputComponent = BaseComponent<'passwordinputcomponent'>
export type DateInputComponent = BaseComponent<'dateinputcomponent'>
export type NumberInputComponent = BaseComponent<'numberinputcomponent'>
export type ButtonComponent = BaseComponent<'buttoncomponent'> & {
recomputeIds: string[] | undefined
@@ -67,6 +69,8 @@ export type AppComponent = BaseAppComponent &
| RunFormComponent
| DisplayComponent
| TextInputComponent
| PasswordInputComponent
| DateInputComponent
| NumberInputComponent
| BarChartComponent
| TableComponent
+10
View File
@@ -13,6 +13,8 @@ import {
Table2,
TextCursorInput,
Type,
Lock,
Calendar,
ToggleLeft
} from 'lucide-svelte'
import type { AppInput, AppInputs, InputType } from './inputType'
@@ -121,6 +123,14 @@ export const displayData: Record<AppComponent['type'], { name: string; icon: any
numberinputcomponent: {
name: 'Number input',
icon: Binary
},
passwordinputcomponent: {
name: 'Password input',
icon: Lock
},
dateinputcomponent: {
name: 'Date input',
icon: Calendar
}
}