[feat] new gui
This commit is contained in:
20
src/lib/UI/GUI/Button.svelte
Normal file
20
src/lib/UI/GUI/Button.svelte
Normal file
@@ -0,0 +1,20 @@
|
||||
<button
|
||||
on:click={onClick}
|
||||
class="{selected ? 'bg-borderc' : 'bg-gray-700'} border border-gray-600 text-white rounded-md shadow-sm hover:bg-borderc focus:outline-none focus:ring-2 focus:ring-borderc transition-colors duration-200{className ? (" " + className) : ""}"
|
||||
class:px-4 = {size == "md"}
|
||||
class:px-2 = {size == "sm"}
|
||||
class:px-6 = {size == "lg"}
|
||||
class:py-2 = {size == "md"}
|
||||
class:py-1 = {size == "sm"}
|
||||
class:py-3 = {size == "lg"}
|
||||
class:text-md = {size == "md"}
|
||||
class:text-sm = {size == "sm"}
|
||||
class:text-lg = {size == "lg"}>
|
||||
<slot></slot>
|
||||
</button>
|
||||
<script lang="ts">
|
||||
export let selected = false
|
||||
export let onClick = () => {}
|
||||
export let className = ""
|
||||
export let size: "sm" | "md" | "lg" = "md"
|
||||
</script>
|
||||
52
src/lib/UI/GUI/Check.svelte
Normal file
52
src/lib/UI/GUI/Check.svelte
Normal file
@@ -0,0 +1,52 @@
|
||||
<script lang="ts">
|
||||
import { CheckIcon } from "lucide-svelte";
|
||||
|
||||
export let check = false
|
||||
export let onChange = (check) => {}
|
||||
export let margin = true
|
||||
export let name = ''
|
||||
export let hiddenName = false
|
||||
</script>
|
||||
|
||||
<!-- <label title={name} class:mr-2={margin} class="flex relative">
|
||||
<input title={name} type="checkbox" class='absolute opacity-0 w-6 h-6' bind:checked={check} on:change={() => {
|
||||
onChange(check)
|
||||
}}/>
|
||||
{#if check}
|
||||
<div class="w-6 h-6 bg-green-500 flex justify-center items-center text-sm">
|
||||
<CheckIcon />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-6 h-6 bg-selected flex justify-center items-center text-sm"/>
|
||||
{/if}
|
||||
{#if name != '' && !hiddenName}
|
||||
<span class="text-neutral-200 ml-2">{name}</span>
|
||||
{/if}
|
||||
</label> -->
|
||||
|
||||
<label
|
||||
class="flex items-center space-x-2 cursor-pointer text-white"
|
||||
class:mr-2={margin}
|
||||
>
|
||||
<input
|
||||
class="hidden"
|
||||
type="checkbox"
|
||||
alt={name}
|
||||
bind:checked={check}
|
||||
on:change={() => {
|
||||
onChange(check)
|
||||
}}
|
||||
/>
|
||||
<span
|
||||
class="w-5 h-5 rounded-md border-2 border-gray-600 flex justify-center items-center {check ? 'bg-borderc' : 'bg-gray-700'} transition-colors duration-200"
|
||||
>
|
||||
{#if check}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="white" class="w-3 h-3">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
{/if}
|
||||
</span>
|
||||
{#if !hiddenName}
|
||||
<span>{name}</span>
|
||||
{/if}
|
||||
</label>
|
||||
@@ -1,4 +1,4 @@
|
||||
<input
|
||||
<!-- <input
|
||||
class="text-neutral-200 bg-transparent input-text focus:bg-selected"
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
@@ -13,8 +13,25 @@
|
||||
max={max}
|
||||
id={id}
|
||||
bind:value
|
||||
>
|
||||
> -->
|
||||
|
||||
<input
|
||||
class={"border border-gray-600 focus:border-borderc rounded-md shadow-sm text-white bg-transparent numinput focus:ring-borderc focus:ring-2 focus:outline-none transition-colors duration-200" + ((additionalClass) ? (' ' + additionalClass) : '')}
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:px-4={padding}
|
||||
class:py-2={padding}
|
||||
class:mb-4={marginBottom}
|
||||
class:w-full={fullwidth}
|
||||
class:h-full={fullh}
|
||||
type="number"
|
||||
min={min}
|
||||
max={max}
|
||||
id={id}
|
||||
bind:value
|
||||
on:change={onChange}
|
||||
/>
|
||||
|
||||
<script lang="ts">
|
||||
export let min:number = undefined
|
||||
@@ -27,5 +44,19 @@
|
||||
export let fullwidth = false
|
||||
export let fullh = false
|
||||
export let onChange = () => {}
|
||||
export let additionalClass = ''
|
||||
</script>
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.numinput::-webkit-outer-spin-button,
|
||||
.numinput::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
.numinput {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
</style>
|
||||
5
src/lib/UI/GUI/OptionInput.svelte
Normal file
5
src/lib/UI/GUI/OptionInput.svelte
Normal file
@@ -0,0 +1,5 @@
|
||||
<option value={value} selected={selected} class="bg-darkbg appearance-none"><slot></slot></option>
|
||||
<script lang="ts">
|
||||
export let value:string
|
||||
export let selected:boolean = false
|
||||
</script>
|
||||
22
src/lib/UI/GUI/SelectInput.svelte
Normal file
22
src/lib/UI/GUI/SelectInput.svelte
Normal file
@@ -0,0 +1,22 @@
|
||||
<select
|
||||
class={"border border-gray-600 focus:border-borderc rounded-md shadow-sm text-white bg-transparent focus:ring-borderc focus:ring-2 focus:outline-none transition-colors duration-200" + ((className) ? (' ' + className) : '')}
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:text-xl={size === 'xl'}
|
||||
class:px-4={size === 'md'}
|
||||
class:py-2={size === 'md'}
|
||||
class:px-2={size === 'sm'}
|
||||
class:py-1={size === 'sm'}
|
||||
class:px-6={size === 'lg'}
|
||||
class:py-3={size === 'lg'}
|
||||
bind:value
|
||||
>
|
||||
<slot></slot>
|
||||
</select>
|
||||
<script lang="ts">
|
||||
export let value:string
|
||||
export let className:string = ""
|
||||
export let size:'sm'|'md'|'lg'|'xl' = 'md'
|
||||
|
||||
</script>
|
||||
@@ -1,27 +1,44 @@
|
||||
<input
|
||||
class="text-neutral-200 bg-transparent input-text focus:bg-selected"
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:p-2={padding}
|
||||
class="text-neutral-200 bg-transparent input-text"
|
||||
class:mb-4={marginBottom}
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
id={id}
|
||||
step={step}
|
||||
bind:value
|
||||
>
|
||||
|
||||
<!-- <div class="p-6 max-w-sm mx-auto bg-gray-800 rounded-xl shadow-md flex items-center space-x-4 w-full" class:mb-4={marginBottom}>
|
||||
<div
|
||||
class="relative w-full h-2 bg-gray-700 rounded-full cursor-pointer"
|
||||
on:click={changeValue}
|
||||
>
|
||||
<div
|
||||
class="absolute top-0 left-0 h-2 rounded-full bg-indigo-500 transition-width duration-200"
|
||||
style="width: {(value - min) / (max - min) * 100}%;"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="absolute top-1/2 transform -translate-y-1/2 -translate-x-1/2 w-4 h-4 bg-white rounded-full shadow"
|
||||
style="left: {(value - min) / (max - min) * 100}%;"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
export let min:number = undefined
|
||||
export let max:number = undefined
|
||||
export let size: 'sm'|'md'|'lg' = 'sm'
|
||||
export let value:number
|
||||
export let id:string = undefined
|
||||
export let padding = true
|
||||
export let marginBottom = false
|
||||
export let step = 1
|
||||
|
||||
function changeValue(event) {
|
||||
const rect = event.target.getBoundingClientRect();
|
||||
const x = event.clientX - rect.left;
|
||||
let newValue = ((x / rect.width) * (max - min)) + min;
|
||||
newValue = Math.round(newValue / step) * step;
|
||||
value = Math.min(Math.max(newValue, min), max);
|
||||
}
|
||||
</script>
|
||||
64
src/lib/UI/GUI/TextAreaInput.svelte
Normal file
64
src/lib/UI/GUI/TextAreaInput.svelte
Normal file
@@ -0,0 +1,64 @@
|
||||
<!-- <textarea
|
||||
class={"bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none focus:bg-selected w-full" + ((additionalClass) ? (' ' + additionalClass) : '')}
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:text-xl={size === 'xl'}
|
||||
class:text-xs={size === 'xs'}
|
||||
class:p-2={padding}
|
||||
class:mb-4={margin === 'bottom'}
|
||||
class:mb-2={margin === 'both'}
|
||||
class:mt-4={margin === 'top'}
|
||||
class:mt-2={margin === 'both'}
|
||||
class:w-full={fullwidth}
|
||||
class:h-20={height === '20'}
|
||||
class:h-32={height === '32'}
|
||||
class:h-full={height === 'full'}
|
||||
class:min-h-20={height === '20'}
|
||||
class:min-h-32={height === '32'}
|
||||
|
||||
{autocomplete}
|
||||
{placeholder}
|
||||
id={id}
|
||||
bind:value
|
||||
on:input={onInput}
|
||||
/> -->
|
||||
|
||||
<textarea
|
||||
class={"border border-gray-600 focus:border-borderc resize-none rounded-md shadow-sm text-white bg-transparent focus:ring-borderc focus:ring-2 focus:outline-none transition-colors duration-200" + ((additionalClass) ? (' ' + additionalClass) : '')}
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:text-xl={size === 'xl'}
|
||||
class:text-xs={size === 'xs'}
|
||||
class:px-4={padding}
|
||||
class:py-2={padding}
|
||||
class:mb-4={margin === 'bottom'}
|
||||
class:mb-2={margin === 'both'}
|
||||
class:mt-4={margin === 'top'}
|
||||
class:mt-2={margin === 'both'}
|
||||
class:w-full={fullwidth}
|
||||
class:h-20={height === '20'}
|
||||
class:h-32={height === '32'}
|
||||
class:h-full={height === 'full'}
|
||||
class:min-h-20={height === '20'}
|
||||
class:min-h-32={height === '32'}
|
||||
{autocomplete}
|
||||
{placeholder}
|
||||
id={id}
|
||||
bind:value
|
||||
on:input={onInput}
|
||||
/>
|
||||
<script lang="ts">
|
||||
export let size: 'xs'|'sm'|'md'|'lg'|'xl' = 'xs'
|
||||
export let autocomplete: 'on'|'off' = 'off'
|
||||
export let placeholder: string = ''
|
||||
export let value:string
|
||||
export let id:string = undefined
|
||||
export let padding = true
|
||||
export let margin:"none"|"top"|"bottom"|"both" = "none"
|
||||
export let onInput = () => {}
|
||||
export let fullwidth = false
|
||||
export let height:'20'|'32'|'full' = '20'
|
||||
export let additionalClass = ''
|
||||
</script>
|
||||
45
src/lib/UI/GUI/TextAreaResizable.svelte
Normal file
45
src/lib/UI/GUI/TextAreaResizable.svelte
Normal file
@@ -0,0 +1,45 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { DataBase } from "../../../ts/storage/database";
|
||||
|
||||
let textarea;
|
||||
let previousScrollHeight = 0;
|
||||
export let value = ''
|
||||
|
||||
function resize() {
|
||||
textarea.style.height = '0px'; // Reset the textarea height
|
||||
textarea.style.height = `calc(${textarea.scrollHeight}px + 1rem)`; // Set the new height
|
||||
}
|
||||
|
||||
function handleInput() {
|
||||
if (textarea.scrollHeight !== previousScrollHeight) {
|
||||
previousScrollHeight = textarea.scrollHeight;
|
||||
resize();
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
resize();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
textarea {
|
||||
overflow: hidden;
|
||||
resize: none;
|
||||
box-sizing: border-box;
|
||||
background: transparent;
|
||||
color: white;
|
||||
border: 1px solid rgba(98, 114, 164, 0.5);
|
||||
max-width: calc(95% - 2rem);
|
||||
padding: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<textarea
|
||||
bind:this={textarea}
|
||||
on:input={handleInput}
|
||||
bind:value={value}
|
||||
style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
|
||||
style:line-height="{1.25 * ($DataBase.zoomsize / 100)}rem"
|
||||
/>
|
||||
@@ -1,4 +1,4 @@
|
||||
<input
|
||||
<!-- <input
|
||||
class={"text-neutral-200 bg-transparent input-text focus:bg-selected" + ((additionalClass) ? (' ' + additionalClass) : '')}
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
@@ -15,7 +15,27 @@
|
||||
type="text"
|
||||
bind:value
|
||||
on:input={onInput}
|
||||
>
|
||||
> -->
|
||||
|
||||
|
||||
<input
|
||||
class={"border border-gray-600 focus:border-borderc rounded-md shadow-sm text-white bg-transparent focus:ring-borderc focus:ring-2 focus:outline-none transition-colors duration-200" + ((additionalClass) ? (' ' + additionalClass) : '')}
|
||||
class:text-sm={size === 'sm'}
|
||||
class:text-md={size === 'md'}
|
||||
class:text-lg={size === 'lg'}
|
||||
class:text-xl={size === 'xl'}
|
||||
class:px-4={padding}
|
||||
class:py-2={padding}
|
||||
class:mb-4={marginBottom}
|
||||
class:w-full={fullwidth}
|
||||
class:h-full={fullh}
|
||||
{autocomplete}
|
||||
{placeholder}
|
||||
id={id}
|
||||
type="text"
|
||||
bind:value
|
||||
on:input={onInput}
|
||||
/>
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<span class="text-neutral-200">{language.creatorNotes}</span>
|
||||
<span class="text-gray-400 text-sm">A description that displays when you search and when you first open a bot.</span>
|
||||
<span class="text-gray-400 text-sm">More than 20 characters.</span>
|
||||
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 min-h-20 focus:bg-selected text-xs w-full" autocomplete="off" bind:value={char.creatorNotes}></textarea>
|
||||
<TextAreaInput autocomplete="off" bind:value={char.creatorNotes} height={"20"} />
|
||||
<span class="text-neutral-200">{language.tags}</span>
|
||||
<span class="text-gray-400 text-sm">Tags to search your character easily. latin alphabets only. seperate by comma.</span>
|
||||
<TextInput marginBottom placeholder="" bind:value={tags} on:input={() => {
|
||||
@@ -42,7 +42,7 @@
|
||||
{#if privateMode}
|
||||
<span class="text-gray-400 text-sm">Private characters can be removed from the server if there is only a few downloads.</span>
|
||||
{/if}
|
||||
<button on:click={async () => {
|
||||
<Button onClick={async () => {
|
||||
if(char.creatorNotes.length < 20){
|
||||
alertError("Creator Notes must be longer than 20 characters")
|
||||
}
|
||||
@@ -54,7 +54,7 @@
|
||||
})
|
||||
close()
|
||||
}
|
||||
}} class="text-neutral-200 mt-2 text-lg bg-transparent border-solid border-1 border-borderc p-4 hover:bg-green-800 transition-colors cursor-pointer">{language.shareCloud}</button>
|
||||
}} className="mt-2" size="lg">{language.shareCloud}</Button>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
@@ -68,6 +68,8 @@
|
||||
import { shareRisuHub } from "src/ts/characterCards";
|
||||
import { DataBase, type character } from "src/ts/storage/database";
|
||||
import TextInput from "./GUI/TextInput.svelte";
|
||||
import TextAreaInput from "./GUI/TextAreaInput.svelte";
|
||||
import Button from "./GUI/Button.svelte";
|
||||
export let close = () => {}
|
||||
export let char:character
|
||||
let tags=""
|
||||
|
||||
Reference in New Issue
Block a user