Migrate to svelte 5

This commit is contained in:
kwaroran
2024-10-23 02:31:37 +09:00
parent e434c7ab96
commit c7330719ad
120 changed files with 2398 additions and 2033 deletions

View File

@@ -1,5 +1,5 @@
<button
on:click
onclick={onclick}
class="{
styled === 'primary' ? ((selected ? 'bg-bg-selected' : 'bg-darkbutton') + " hover:bg-selected focus:ring-selected border-darkborderc")
: styled === 'outlined' ? 'bg-transparent hover:bg-darkbg focus:ring-selected border-darkborderc text-textcolor2'
@@ -14,11 +14,27 @@
class:text-md = {size == "md"}
class:text-sm = {size == "sm"}
class:text-lg = {size == "lg"}>
<slot></slot>
{@render children?.()}
</button>
<script lang="ts">
export let selected = false
export let styled:'primary'|'danger'|'outlined' = 'primary'
export let className = ""
export let size: "sm" | "md" | "lg" = "md"
interface Props {
selected?: boolean;
styled?: 'primary'|'danger'|'outlined';
className?: string;
size?: "sm" | "md" | "lg";
children?: import('svelte').Snippet;
onclick?: (event: MouseEvent & {
currentTarget: EventTarget & HTMLButtonElement;
}) => any
}
let {
selected = false,
styled = 'primary',
className = "",
size = "md",
children,
onclick
}: Props = $props();
</script>

View File

@@ -1,14 +1,29 @@
<script lang="ts">
import { CheckIcon } from "lucide-svelte";
export let check = false
export let onChange = (check:boolean) => {}
export let margin = true
export let name = ''
export let hiddenName = false
export let reverse = false
export let className = ""
export let grayText = false
interface Props {
check?: boolean;
onChange?: any;
margin?: boolean;
name?: string;
hiddenName?: boolean;
reverse?: boolean;
className?: string;
grayText?: boolean;
children?: import('svelte').Snippet;
}
let {
check = $bindable(),
onChange = (check:boolean) => {},
margin = true,
name = '',
hiddenName = false,
reverse = false,
className = "",
grayText = false,
children
}: Props = $props();
</script>
<label
@@ -18,14 +33,14 @@
aria-labelledby="{name} {check ? 'abled' : 'disabled'}"
>
{#if reverse}
<span>{name}<slot /></span>
<span>{name}{@render children?.()}</span>
{/if}
<input
class="hidden"
type="checkbox"
alt={name}
bind:checked={check}
on:change={() => {
onchange={() => {
onChange(check)
}}
aria-describedby="{name} {check ? 'abled' : 'disabled'}"
@@ -44,6 +59,6 @@
{/if}
</span>
{#if !hiddenName && !reverse}
<span>{name}<slot /></span>
<span>{name}{@render children?.()}</span>
{/if}
</label>

View File

@@ -1,12 +1,24 @@
<script lang="ts">
import ColorPicker from 'svelte-awesome-color-picker';
export let value = '#000000';
export let nullable = false;
interface Props {
value?: string;
nullable?: boolean;
oninput?: () => void;
}
let { value = $bindable('#000000'), nullable = false, oninput }: Props = $props();
$effect(() => {
//this is for updating
value
oninput?.()
});
</script>
<div class="cl rounded-full bg-white">
<ColorPicker
label="" bind:hex={value} on:input
label="" bind:hex={value}
nullable={nullable}
/>
</div>

View File

@@ -1,25 +1,33 @@
<script lang="ts">
import { run, stopPropagation } from 'svelte/legacy';
import { ColorSchemeTypeStore } from "src/ts/gui/colorscheme";
import { ParseMarkdown } from "src/ts/parser";
import { parseMultilangString, toLangName } from "src/ts/util";
export let value: string
export let markdown: boolean = false
let valueObject: {[code:string]:string} = parseMultilangString(value)
let selectedLang = "en"
interface Props {
value: string;
markdown?: boolean;
}
let { value, markdown = false }: Props = $props();
let valueObject: {[code:string]:string} = $state(parseMultilangString(value))
let selectedLang = $state("en")
if(valueObject["en"] === undefined){
selectedLang = "xx"
}
$: valueObject = parseMultilangString(value)
run(() => {
valueObject = parseMultilangString(value)
});
</script>
<div class="flex flex-col">
<div class="flex flex-wrap max-w-fit p-1 gap-2">
{#each Object.keys(valueObject) as lang}
{#if lang !== 'xx' || Object.keys(valueObject).length === 1}
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} on:click|stopPropagation={() => {
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} onclick={stopPropagation(() => {
selectedLang = lang
}}>{toLangName(lang)}</button>
})}>{toLangName(lang)}</button>
{/if}
{/each}
</div>

View File

@@ -1,12 +1,18 @@
<script lang="ts">
import { run } from 'svelte/legacy';
import { encodeMultilangString, languageCodes, parseMultilangString, toLangName } from "src/ts/util";
import TextAreaInput from "./TextAreaInput.svelte";
export let value: string
let addingLang = false
let valueObject: {[code:string]:string} = parseMultilangString(value)
let selectedLang = "en"
export let className = ""
export let onInput = () => {}
let addingLang = $state(false)
let selectedLang = $state("en")
interface Props {
value: string;
className?: string;
onInput?: any;
}
let { value = $bindable(), className = "", onInput = () => {} }: Props = $props();
let valueObject: {[code:string]:string} = $state(parseMultilangString(value))
const updateValue = () => {
for(let lang in valueObject){
if(valueObject[lang] === "" && lang !== selectedLang && lang!=="en" ){
@@ -27,25 +33,27 @@
delete valueObject["xx"]
updateValue()
}
$: valueObject = parseMultilangString(value)
run(() => {
valueObject = parseMultilangString(value)
});
</script>
<div class="flex flex-wrap max-w-fit p-1 gap-2">
{#each Object.keys(valueObject) as lang}
{#if lang !== 'xx'}
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} on:click={() => {
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} onclick={() => {
selectedLang = lang
updateValue()
}}>{toLangName(lang)}</button>
{/if}
{/each}
<button class="text-nowrap bg-bgcolor py-2 rounded-lg px-4" class:ring-1={addingLang} on:click={() => {addingLang = !addingLang}}>+</button>
<button class="text-nowrap bg-bgcolor py-2 rounded-lg px-4" class:ring-1={addingLang} onclick={() => {addingLang = !addingLang}}>+</button>
</div>
{#if addingLang}
<div class="m-1 p-1 g-2 flex max-w-fit rounded-md border-t-bgcolor flex-wrap gap-1">
{#each languageCodes as lang}
{#if toLangName(lang).length !== 2}
<button class="bg-bgcolor py-2 rounded-lg px-4 text-nowrap" on:click={() => {
<button class="bg-bgcolor py-2 rounded-lg px-4 text-nowrap" onclick={() => {
valueObject[lang] = ""
selectedLang = lang
addingLang = false

View File

@@ -20,23 +20,41 @@
id={id}
disabled={disabled}
bind:value
on:change={onChange}
onchange={onChange}
/>
<script lang="ts">
import type { ChangeEventHandler } from "svelte/elements";
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 fullwidth = false
export let fullh = false
export let onChange:ChangeEventHandler<HTMLInputElement> = () => {}
export let className = ''
export let disabled = false
interface Props {
min?: number;
max?: number;
size?: 'sm'|'md'|'lg';
value: number;
id?: string;
padding?: boolean;
marginBottom?: boolean;
fullwidth?: boolean;
fullh?: boolean;
onChange?: (event: Event & {
currentTarget: EventTarget & HTMLInputElement;
}) => any;
className?: string;
disabled?: boolean;
}
let {
min = undefined,
max = undefined,
size = 'sm',
value = $bindable(),
id = undefined,
padding = true,
marginBottom = false,
fullwidth = false,
fullh = false,
onChange = () => {},
className = '',
disabled = false
}: Props = $props();
</script>
<style>

View File

@@ -1,5 +1,10 @@
<option value={value} selected={selected} class="bg-darkbg appearance-none"><slot></slot></option>
<option value={value} selected={selected} class="bg-darkbg appearance-none">{@render children?.()}</option>
<script lang="ts">
export let value:string
export let selected:boolean = false
interface Props {
value: string;
selected?: boolean;
children?: import('svelte').Snippet;
}
let { value, selected = false, children }: Props = $props();
</script>

View File

@@ -2,10 +2,19 @@
import CheckInput from "./CheckInput.svelte";
import NumberInput from "./NumberInput.svelte";
import TextInput from "./TextInput.svelte";
export let value:string|number|boolean
export let numberMode = false
export let boolMode = false
export let marginBottom = false
interface Props {
value: string|number|boolean;
numberMode?: boolean;
boolMode?: boolean;
marginBottom?: boolean;
}
let {
value = $bindable(),
numberMode = false,
boolMode = false,
marginBottom = false
}: Props = $props();
const valToggle = () => {
value = !value
}
@@ -38,8 +47,8 @@
{:else if typeof(value) === 'number'}
<NumberInput bind:value={value} className="flex-1"/>
{:else if typeof(value) === 'boolean'}
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={!value} on:click={valToggle}>True</button>
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={value} on:click={valToggle}>False</button>
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={!value} onclick={valToggle}>True</button>
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={value} onclick={valToggle}>False</button>
{:else}
<TextInput value={"Using default"} className="flex-1" disabled/>
{/if}

View File

@@ -11,13 +11,27 @@
class:px-6={size === 'lg'}
class:py-3={size === 'lg'}
bind:value
on:change
onchange={onchange}
>
<slot></slot>
{@render children?.()}
</select>
<script lang="ts">
export let value:string
export let className:string = ""
export let size:'sm'|'md'|'lg'|'xl' = 'md'
interface Props {
value: string;
className?: string;
size?: 'sm'|'md'|'lg'|'xl';
children?: import('svelte').Snippet;
onchange?: (event: Event & {
currentTarget: EventTarget & HTMLSelectElement;
}) => any;
}
let {
value = $bindable(),
className = "",
size = 'md',
children,
onchange
}: Props = $props();
</script>

View File

@@ -6,14 +6,13 @@
{#if !$MobileGUI}
{#if $sideBarStore && !$DynamicGUI}
<button on:click={() => {sideBarClosing.set(true)}} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-transparent rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor z-20">
<button onclick={() => {sideBarClosing.set(true)}} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-transparent rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor z-20">
<ArrowLeft />
</button>
{:else}
<button on:click={() => {
<button onclick={() => {
sideBarClosing.set(false);
sideBarStore.set(true)}
} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-borderc rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor opacity-50 hover:opacity-90 z-20">
sideBarStore.set(true)}} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-borderc rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor opacity-50 hover:opacity-90 z-20">
<ArrowRight />
</button>
{/if}

View File

@@ -6,7 +6,7 @@
max={max}
step={step}
bind:value
on:change
onchange
> -->
<div class="w-full flex" class:mb-4={marginBottom}>
@@ -14,6 +14,7 @@
<div class="relative h-8 border-darkborderc border rounded-full cursor-pointer rounded-r-none border-r-0 flex justify-center items-center">
<CheckInput check={value !== -1000} margin={false} onChange={(c) => {
onchange?.()
if(c) {
value = min;
} else {
@@ -28,23 +29,23 @@
style:background={
`linear-gradient(to right, var(--risu-theme-darkbutton) 0%, var(--risu-theme-darkbutton) ${(value - min) / (max - min) * 100}%, var(--risu-theme-darkbg) ${(value - min) / (max - min) * 100}%, var(--risu-theme-darkbg) 100%)`
}
on:pointerdown={(event) => {
onpointerdown={(event) => {
mouseDown = true;
changeValue(event);
}}
on:pointermove={(event) => {
onpointermove={(event) => {
if (mouseDown) {
changeValue(event);
}
}}
on:pointerup={() => {
onpointerup={() => {
mouseDown = false;
}}
on:pointerleave={() => {
onpointerleave={() => {
mouseDown = false;
}}
bind:this={slider}
@@ -67,17 +68,33 @@
import { language } from "src/lang";
import CheckInput from "./CheckInput.svelte";
export let min:number = undefined
export let max:number = undefined
export let value:number
export let marginBottom = false
export let step = 1
export let fixed = 0
export let multiple = 1
let slider: HTMLDivElement
let mouseDown = false
export let disableable = false
export let customText: string|undefined = undefined
let slider: HTMLDivElement = $state()
let mouseDown = $state(false)
interface Props {
min?: number;
max?: number;
value: number;
marginBottom?: boolean;
step?: number;
fixed?: number;
multiple?: number;
disableable?: boolean;
customText?: string|undefined;
onchange?: Function;
}
let {
min = undefined,
max = undefined,
value = $bindable(),
marginBottom = false,
step = 1,
fixed = 0,
multiple = 1,
disableable = false,
customText = undefined,
onchange
}: Props = $props();
function changeValue(event) {
const rect = slider.getBoundingClientRect();

View File

@@ -34,7 +34,7 @@
class:mt-4={margin === 'top'}
class:mt-2={margin === 'both'}
bind:this={highlightDom}
on:focusout={() => {
onfocusout={() => {
hideAutoComplete()
}}
>
@@ -47,7 +47,7 @@
{placeholder}
id={id}
bind:value={value}
on:input={(e) => {
oninput={(e) => {
if(optimaizedInput){
if(inpa++ > 10){
value = e.currentTarget.value
@@ -60,26 +60,26 @@
onInput()
}
}}
on:change={(e) => {
onchange={(e) => {
if(optimaizedInput){
value = e.currentTarget.value
onInput()
}
}}
/>
></textarea>
{:else if isFirefox}
<div
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-50 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap"
contenteditable="true"
bind:textContent={value}
on:keydown={(e) => {
onkeydown={(e) => {
handleKeyDown(e)
onInput()
}}
on:input={(e) => {
oninput={(e) => {
autoComplete()
}}
on:paste={(e) => {
onpaste={(e) => {
e.preventDefault()
const text = e.clipboardData.getData('text/plain')
if(text){
@@ -94,11 +94,11 @@
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-50 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap"
contenteditable="plaintext-only"
bind:innerText={value}
on:keydown={(e) => {
onkeydown={(e) => {
handleKeyDown(e)
onInput()
}}
on:input={(e) => {
oninput={(e) => {
autoComplete()
}}
bind:this={inputDom}
@@ -107,39 +107,59 @@
{/if}
<div class="hidden absolute z-100 bg-bgcolor border border-darkborderc p-2 flex-col" bind:this={autoCompleteDom}>
{#each autocompleteContents as content, i}
<button class="w-full text-left py-1 px-2 bg-bgcolor" class:text-blue-500={selectingAutoComplete === i} on:click={() => {
<button class="w-full text-left py-1 px-2 bg-bgcolor" class:text-blue-500={selectingAutoComplete === i} onclick={() => {
insertContent(content)
}}>{content}</button>
{/each}
</div>
</div>
<script lang="ts">
import { run } from 'svelte/legacy';
import { textAreaSize, textAreaTextSize } from 'src/ts/gui/guisize'
import { highlighter, getNewHighlightId, removeHighlight, AllCBS } from 'src/ts/gui/highlight'
import { isMobile } from 'src/ts/storage/globalApi';
import { isFirefox, sleep } from 'src/ts/util';
import { onDestroy, onMount } from 'svelte';
export let size: 'xs'|'sm'|'md'|'lg'|'xl'|'default' = 'default'
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'|'24'|'28'|'32'|'36'|'full'|'default' = 'default'
export let className = ''
export let optimaizedInput = true
export let highlight = false
let selectingAutoComplete = 0
interface Props {
size?: 'xs'|'sm'|'md'|'lg'|'xl'|'default';
autocomplete?: 'on'|'off';
placeholder?: string;
value: string;
id?: string;
padding?: boolean;
margin?: "none"|"top"|"bottom"|"both";
onInput?: any;
fullwidth?: boolean;
height?: '20'|'24'|'28'|'32'|'36'|'full'|'default';
className?: string;
optimaizedInput?: boolean;
highlight?: boolean;
}
let {
size = 'default',
autocomplete = 'off',
placeholder = '',
value = $bindable(),
id = undefined,
padding = true,
margin = "none",
onInput = () => {},
fullwidth = false,
height = 'default',
className = '',
optimaizedInput = true,
highlight = false
}: Props = $props();
let selectingAutoComplete = $state(0)
let highlightId = highlight ? getNewHighlightId() : 0
let inpa = 0
let highlightDom: HTMLDivElement
let optiValue = value
let autoCompleteDom: HTMLDivElement
let autocompleteContents:string[] = []
let inputDom: HTMLDivElement
let inpa = $state(0)
let highlightDom: HTMLDivElement = $state()
let optiValue = $state(value)
let autoCompleteDom: HTMLDivElement = $state()
let autocompleteContents:string[] = $state([])
let inputDom: HTMLDivElement = $state()
const autoComplete = () => {
if(isMobile){
@@ -291,7 +311,11 @@
} catch (error) {}
}
$: optiValue = value
$: highlightChange(value, highlightId)
run(() => {
optiValue = value
});
run(() => {
highlightChange(value, highlightId)
});
</script>

View File

@@ -3,10 +3,14 @@
import { DataBase } from "../../../ts/storage/database";
import { longpress } from 'src/ts/gui/longtouch';
let textarea;
let textarea:HTMLElement = $state();
let previousScrollHeight = 0;
export let value = ''
export let handleLongPress = (e:MouseEvent) => {};
interface Props {
value?: string;
handleLongPress?: any;
}
let { value = $bindable(''), handleLongPress = (e:MouseEvent) => {} }: Props = $props();
function resize() {
textarea.style.height = '0px'; // Reset the textarea height
@@ -27,10 +31,10 @@
<textarea
bind:this={textarea}
on:input={handleInput}
oninput={handleInput}
use:longpress={handleLongPress}
bind:value={value}
class="rounded-md p-2 text-textcolor bg-transparent resize-none overflow-y-hidden border border-darkborderc"
style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
style:line-height="{($DataBase.lineHeight ?? 1.25) * ($DataBase.zoomsize / 100)}rem"
/>
></textarea>

View File

@@ -29,7 +29,8 @@
type="password"
bind:value
disabled={disabled}
on:input={onInput}
oninput={oninput}
onchange={onchange}
/>
{:else}
@@ -60,29 +61,52 @@
type="text"
bind:value
disabled={disabled}
on:input={(e) => {
onInput(e)
}}
oninput={oninput}
onchange={onchange}
/>
{/if}
<script lang="ts">
export let size: 'sm'|'md'|'lg'|'xl' = 'md'
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 marginBottom = false
export let marginTop = false
export let onInput = (e:Event & {
currentTarget: EventTarget & HTMLInputElement;
}) => {}
export let fullwidth = false
export let fullh = false
export let className = ''
export let disabled = false
export let hideText = false
type FormEventHandler<T extends EventTarget> = (event: Event & {
currentTarget: EventTarget & T;
}) => any
interface Props {
size?: 'sm'|'md'|'lg'|'xl';
autocomplete?: 'on'|'off';
placeholder?: string;
value: string;
id?: string;
padding?: boolean;
marginBottom?: boolean;
marginTop?: boolean;
oninput?: FormEventHandler<HTMLInputElement>
onchange?: FormEventHandler<HTMLInputElement>;
fullwidth?: boolean;
fullh?: boolean;
className?: string;
disabled?: boolean;
hideText?: boolean;
}
let {
size = 'md',
autocomplete = 'off',
placeholder = '',
value = $bindable(),
id = undefined,
padding = true,
marginBottom = false,
marginTop = false,
oninput,
onchange,
fullwidth = false,
fullh = false,
className = '',
disabled = false,
hideText = false,
}: Props = $props();
</script>
<style>