Use textbox components in settings page

This commit is contained in:
Mattias Granlund 2023-12-05 23:49:31 +01:00
parent 1e66a6eec8
commit 4ffad7a466
4 changed files with 66 additions and 60 deletions

View File

@ -1,21 +1,24 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
export let value: string;
export let placeholder: string;
export let value: string | undefined;
export let placeholder: string | undefined = undefined;
export let required = false;
export let rows = 4;
export let id: string | undefined = undefined;
const dispatch = createEventDispatcher<{ input: string }>();
const dispatch = createEventDispatcher<{ input: string; change: string }>();
</script>
<textarea
class="text-box text-base-13"
bind:value
{id}
{placeholder}
{required}
{rows}
on:input={(e) => dispatch('input', e.currentTarget.value)}
on:change={(e) => dispatch('change', e.currentTarget.value)}
/>
<style lang="postcss">

View File

@ -3,19 +3,24 @@
import Icon from '$lib/icons/Icon.svelte';
import { createEventDispatcher } from 'svelte';
export let id: string | undefined = undefined;
export let icon: keyof typeof iconsJson | undefined = undefined;
export let iconPosition: 'left' | 'right' = 'left';
export let value: string | undefined = undefined;
export let placeholder: string | undefined = undefined;
export let iconPosition: 'left' | 'right' = 'left';
export let disabled = false;
export let readonly = false;
export let required = false;
export let password = false;
const dispatch = createEventDispatcher<{ input: string }>();
const dispatch = createEventDispatcher<{ input: string; change: string }>();
</script>
<div class="textbox">
<div
class="textbox__input-wrap"
class:textbox_left-orient={iconPosition === 'left'}
class:textbox_right-orient={iconPosition === 'right'}
class:textbox__left-orient={icon && iconPosition == 'left'}
class:textbox__right-orient={icon && iconPosition == 'right'}
class:disabled
>
{#if icon}
@ -23,12 +28,30 @@
<Icon name={icon} />
</div>
{/if}
<input
type="text"
class="textbox__input text-base-13"
{placeholder}
on:input={(e) => dispatch('input', e.currentTarget.value)}
/>
{#if password}
<input
{id}
type="password"
class="textbox__input text-base-13"
{placeholder}
{readonly}
{required}
bind:value
on:input={(e) => dispatch('input', e.currentTarget.value)}
on:change={(e) => dispatch('change', e.currentTarget.value)}
/>
{:else}
<input
{id}
class="textbox__input text-base-13"
{placeholder}
{readonly}
{required}
bind:value
on:input={(e) => dispatch('input', e.currentTarget.value)}
on:change={(e) => dispatch('change', e.currentTarget.value)}
/>
{/if}
</div>
</div>
@ -87,7 +110,7 @@
/* Modifiers */
.textbox_left-orient {
.textbox__left-orient {
& .textbox__input {
padding-left: calc(var(--space-32) + var(--space-2));
}
@ -96,7 +119,7 @@
}
}
.textbox_right-orient {
.textbox__right-orient {
& .textbox__input {
padding-right: calc(var(--space-32) + var(--space-2));
}

View File

@ -1,6 +1,7 @@
<script lang="ts">
import type { Project } from '$lib/backend/projects';
import { debounce } from '$lib/utils/random';
import TextArea from '$lib/components/TextArea.svelte';
import TextBox from '$lib/components/TextBox.svelte';
import { createEventDispatcher } from 'svelte';
export let project: Project;
@ -8,16 +9,6 @@
let title = project?.title;
let description = project?.description;
const onTitleInput = debounce((e: InputEvent) => {
project.title = (e.target as HTMLInputElement).value;
dispatch('updated', project);
}, 300);
const onDescriptionInput = debounce((e: InputEvent) => {
project.description = (e.target as HTMLTextAreaElement).value;
dispatch('updated', project);
}, 300);
const dispatch = createEventDispatcher<{
updated: Project;
}>();
@ -27,40 +18,31 @@
<fieldset class="flex flex-col gap-3">
<div class="flex flex-col gap-1">
<label for="path">Path</label>
<input
disabled
id="path"
name="path"
type="text"
class="input w-full"
value={project?.path}
/>
<TextBox readonly id="path" value={project?.path} />
</div>
<div class="flex flex-col gap-1">
<label for="name">Project Name</label>
<input
<TextBox
id="name"
name="name"
type="text"
class="input w-full"
placeholder="Project name can't be empty"
bind:value={title}
required
on:input={onTitleInput}
on:change={(e) => {
project.title = e.detail;
dispatch('updated', project);
}}
/>
</div>
<div class="flex flex-col gap-1">
<label for="description">Project Description</label>
<textarea
autocomplete="off"
autocorrect="off"
spellcheck="false"
<TextArea
id="description"
name="description"
rows="3"
class="input w-full"
value={description}
on:input={onDescriptionInput}
rows={3}
bind:value={description}
on:change={(e) => {
project.description = e.detail;
dispatch('updated', project);
}}
/>
</div>
</fieldset>

View File

@ -5,6 +5,7 @@
import { createEventDispatcher } from 'svelte';
import Button from '$lib/components/Button.svelte';
import Link from '$lib/components/Link.svelte';
import TextBox from '$lib/components/TextBox.svelte';
export let project: Project;
@ -102,7 +103,7 @@
{/if}
</div>
<input type="radio" bind:group={selectedOption} value="local" on:input={setLocalKey} />
<input type="radio" bind:group={selectedOption} value="local" on:input={() => setLocalKey} />
<div class="flex flex-col space-y-2">
<div>Use existing SSH key</div>
@ -113,23 +114,20 @@
</div>
</div>
<div class="grid grid-cols-2 gap-2" style="grid-template-columns: max-content 1fr;">
<div
class="grid grid-cols-2 items-center gap-2"
style="grid-template-columns: max-content 1fr;"
>
<label for="path">Path to private key</label>
<input
name="path"
type="text"
<TextBox
placeholder="~/.ssh/id_rsa"
bind:value={privateKeyPath}
on:input={setLocalKey}
on:change={setLocalKey}
/>
<label for="passphrase">Passphrase</label>
<input
name="passphrase"
type="password"
bind:value={privateKeyPassphrase}
on:input={setLocalKey}
/>
<TextBox password bind:value={privateKeyPassphrase} on:change={setLocalKey} />
</div>
{/if}
</div>