1
0
mirror of https://github.com/koloml/furbooru-tagging-assistant.git synced 2025-12-24 07:12:57 +00:00

Migration to Svelte 5 (using the migration script)

This commit is contained in:
2025-02-16 18:02:03 +04:00
parent 5975584905
commit 67d41ecf03
28 changed files with 287 additions and 160 deletions

View File

@@ -1,25 +1,33 @@
<script>
import { run } from 'svelte/legacy';
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { storagesCollection } from "$stores/debug";
import { goto } from "$app/navigation";
import { findDeepObject } from "$lib/utils";
/** @type {string} */
export let storage;
/** @type {string[]} */
export let path;
/**
* @typedef {Object} Props
* @property {string} storage
* @property {string[]} path
*/
/** @type {Props} */
let { storage, path } = $props();
/** @type {Object|null} */
let targetStorage = null;
let targetStorage = $state(null);
/** @type {[string, string][]} */
let breadcrumbs = [];
let breadcrumbs = $state([]);
/** @type {Object<string, any>|null} */
let targetObject = null;
let targetPathString = '';
let targetObject = $state(null);
let targetPathString = $state('');
$: {
run(() => {
/** @type {[string, string][]} */
const builtBreadcrumbs = [];
@@ -40,21 +48,21 @@
if (targetPathString.length) {
targetPathString += "/";
}
}
});
$: {
run(() => {
targetStorage = $storagesCollection[storage];
if (!targetStorage) {
goto("/preferences/debug/storage");
}
}
});
$: {
run(() => {
targetObject = targetStorage
? findDeepObject(targetStorage, path)
: null;
}
});
/**
* Helper function to resolve type, including the null.

View File

@@ -1,15 +1,19 @@
<script>
import TagsColorContainer from "$components/tags/TagsColorContainer.svelte";
/**
* @type {import('$entities/TagGroup').default}
* @typedef {Object} Props
* @property {import('$entities/TagGroup').default} group
*/
export let group;
let sortedTagsList, sortedPrefixes;
/** @type {Props} */
let { group } = $props();
$: sortedTagsList = group.settings.tags.sort((a, b) => a.localeCompare(b));
$: sortedPrefixes = group.settings.prefixes.sort((a, b) => a.localeCompare(b));
let sortedTagsList = $derived(group.settings.tags.sort((a, b) => a.localeCompare(b))), sortedPrefixes = $derived(group.settings.prefixes.sort((a, b) => a.localeCompare(b)));
</script>
<div class="block">

View File

@@ -1,6 +1,12 @@
<script>
/** @type {import('$entities/MaintenanceProfile').default} */
export let profile;
/**
* @typedef {Object} Props
* @property {import('$entities/MaintenanceProfile').default} profile
*/
/** @type {Props} */
let { profile } = $props();
const sortedTagsList = profile.settings.tags.sort((a, b) => a.localeCompare(b));
</script>

View File

@@ -1,61 +1,68 @@
<script>
/** @type {string} */
export let targetCategory = '';
/**
* @typedef {Object} Props
* @property {string} [targetCategory]
* @property {import('svelte').Snippet} [children]
*/
/** @type {Props} */
let { targetCategory = '', children } = $props();
</script>
<div class="tag-color-container tag-color-container--{targetCategory || 'default'}">
<slot></slot>
{@render children?.()}
</div>
<style lang="scss">
@use '$styles/colors';
.tag-color-container:is(.tag-color-container--rating) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--rating)) :global(.tag) {
background-color: colors.$tag-rating-background;
color: colors.$tag-rating-text;
}
.tag-color-container:is(.tag-color-container--spoiler) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--spoiler)) :global(.tag) {
background-color: colors.$tag-spoiler-background;
color: colors.$tag-spoiler-text;
}
.tag-color-container:is(.tag-color-container--origin) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--origin)) :global(.tag) {
background-color: colors.$tag-origin-background;
color: colors.$tag-origin-text;
}
.tag-color-container:is(.tag-color-container--oc) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--oc)) :global(.tag) {
background-color: colors.$tag-oc-background;
color: colors.$tag-oc-text;
}
.tag-color-container:is(.tag-color-container--error) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--error)) :global(.tag) {
background-color: colors.$tag-error-background;
color: colors.$tag-error-text;
}
.tag-color-container:is(.tag-color-container--character) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--character)) :global(.tag) {
background-color: colors.$tag-character-background;
color: colors.$tag-character-text;
}
.tag-color-container:is(.tag-color-container--content-official) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--content-official)) :global(.tag) {
background-color: colors.$tag-content-official-background;
color: colors.$tag-content-official-text;
}
.tag-color-container:is(.tag-color-container--content-fanmade) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--content-fanmade)) :global(.tag) {
background-color: colors.$tag-content-fanmade-background;
color: colors.$tag-content-fanmade-text;
}
.tag-color-container:is(.tag-color-container--species) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--species)) :global(.tag) {
background-color: colors.$tag-species-background;
color: colors.$tag-species-text;
}
.tag-color-container:is(.tag-color-container--body-type) :global(.tag) {
.tag-color-container:is(:global(.tag-color-container--body-type)) :global(.tag) {
background-color: colors.$tag-body-type-background;
color: colors.$tag-body-type-text;
}

View File

@@ -1,17 +1,24 @@
<script>
import { run } from 'svelte/legacy';
/**
* List of tags to edit. Any duplicated tags present in the array will be removed on the first edit.
* @type {string[]}
* @typedef {Object} Props
* @property {string[]} [tags] - List of tags to edit. Any duplicated tags present in the array will be removed on the first edit.
*/
export let tags = [];
/** @type {Props} */
let { tags = $bindable([]) } = $props();
/** @type {Set<string>} */
let uniqueTags = new Set();
let uniqueTags = $state(new Set());
$: uniqueTags = new Set(tags);
run(() => {
uniqueTags = new Set(tags);
});
/** @type {string} */
let addedTagName = '';
let addedTagName = $state('');
/**
* Create a callback function to pass into both mouse & keyboard events for tag removal.
@@ -81,14 +88,14 @@
{#each uniqueTags.values() as tagName}
<div class="tag">
{tagName}
<span class="remove" on:click={createTagRemoveHandler(tagName)}
on:keydown={createTagRemoveHandler(tagName)}
<span class="remove" onclick={createTagRemoveHandler(tagName)}
onkeydown={createTagRemoveHandler(tagName)}
role="button" tabindex="0">x</span>
</div>
{/each}
<input type="text"
bind:value={addedTagName}
on:keydown={handleKeyPresses}
onkeydown={handleKeyPresses}
autocomplete="off"
autocapitalize="none"/>
</div>

View File

@@ -1,12 +1,19 @@
<script>
/** @type {string|undefined} */
export let name = undefined;
/** @type {boolean} */
export let checked;
/**
* @typedef {Object} Props
* @property {string|undefined} [name]
* @property {boolean} checked
* @property {import('svelte').Snippet} [children]
*/
/** @type {Props} */
let { name = undefined, checked = $bindable(), children } = $props();
</script>
<input type="checkbox" {name} bind:checked={checked}>
<span>
<slot></slot>
{@render children?.()}
</span>

View File

@@ -1,5 +1,13 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<form>
<slot></slot>
{@render children?.()}
</form>
<style lang="scss">

View File

@@ -1,14 +1,21 @@
<script>
/** @type {string|undefined} */
export let label = undefined;
/**
* @typedef {Object} Props
* @property {string|undefined} [label]
* @property {import('svelte').Snippet} [children]
*/
/** @type {Props} */
let { label = undefined, children } = $props();
</script>
<label class="control">
{#if label}
<div class="label">{label}</div>
{/if}
<slot></slot>
{@render children?.()}
</label>
<style lang="scss">

View File

@@ -1,20 +1,29 @@
<script>
/**
* @type {string[]|Record<string, string>}
* @typedef {Object} Props
* @property {string[]|Record<string, string>} [options]
* @property {string|undefined} [name]
* @property {string|undefined} [id]
* @property {string|undefined} [value]
*/
export let options = [];
/** @type {string|undefined} */
export let name = undefined;
/** @type {string|undefined} */
export let id = undefined;
/** @type {string|undefined} */
export let value = undefined;
/** @type {Props} */
let {
options = [],
name = undefined,
id = undefined,
value = $bindable(undefined)
} = $props();
/** @type {Record<string, string>} */
const optionPairs = {};
const optionPairs = $state({});
if (Array.isArray(options)) {
for (let option of options) {

View File

@@ -2,13 +2,19 @@
import SelectField from "$components/ui/forms/SelectField.svelte";
import { categories } from "$lib/booru/tag-categories";
/** @type {string} */
export let value = '';
/**
* @typedef {Object} Props
* @property {string} [value]
*/
/** @type {Props} */
let { value = $bindable('') } = $props();
/** @type {Record<string, string>} */
let tagCategoriesOptions = {
let tagCategoriesOptions = $state({
'': 'Default'
};
});
tagCategoriesOptions = categories.reduce((options, category) => {
options[category] = category

View File

@@ -1,12 +1,18 @@
<script>
/** @type {string|undefined} */
export let name = undefined;
/** @type {string|undefined} */
export let placeholder = undefined;
/** @type {string} */
export let value = '';
/**
* @typedef {Object} Props
* @property {string|undefined} [name]
* @property {string|undefined} [placeholder]
* @property {string} [value]
*/
/** @type {Props} */
let { name = undefined, placeholder = undefined, value = $bindable('') } = $props();
</script>
<input type="text" {name} {placeholder} bind:value={value}>

View File

@@ -1,5 +1,13 @@
<script lang="ts">
interface Props {
children?: import('svelte').Snippet;
}
let { children }: Props = $props();
</script>
<nav>
<slot></slot>
{@render children?.()}
</nav>
<style lang="scss">

View File

@@ -1,30 +1,38 @@
<script>
import { createBubbler, stopPropagation } from 'svelte/legacy';
const bubble = createBubbler();
import MenuLink from "$components/ui/menu/MenuItem.svelte";
/**
* @type {boolean}
*/
export let checked;
/**
* @type {string|undefined}
*/
export let name = undefined;
/**
* @type {string|undefined}
*/
export let value = undefined;
/**
* @type {string|null}
* @typedef {Object} Props
* @property {boolean} checked
* @property {string|undefined} [name]
* @property {string|undefined} [value]
* @property {string|null} [href]
* @property {import('svelte').Snippet} [children]
*/
export let href = null;
/** @type {Props} */
let {
checked = $bindable(),
name = undefined,
value = undefined,
href = null,
children
} = $props();
</script>
<MenuLink {href}>
<input type="checkbox" {name} {value} bind:checked={checked} on:input on:click|stopPropagation>
<slot></slot>
<input type="checkbox" {name} {value} bind:checked={checked} oninput={bubble('input')} onclick={stopPropagation(bubble('click'))}>
{@render children?.()}
</MenuLink>
<style lang="scss">

View File

@@ -1,25 +1,34 @@
<script>
/**
* @type {string|null}
*/
export let href = null;
import { createBubbler } from 'svelte/legacy';
/**
* @type {App.IconName|null}
*/
export let icon = null;
const bubble = createBubbler();
/**
* @type {App.LinkTarget|undefined}
* @typedef {Object} Props
* @property {string|null} [href]
* @property {App.IconName|null} [icon]
* @property {App.LinkTarget|undefined} [target]
* @property {import('svelte').Snippet} [children]
*/
export let target = undefined;
/** @type {Props} */
let {
href = null,
icon = null,
target = undefined,
children
} = $props();
</script>
<svelte:element this="{href ? 'a': 'span'}" class="menu-item" {href} {target} on:click role="link" tabindex="0">
<svelte:element this="{href ? 'a': 'span'}" class="menu-item" {href} {target} onclick={bubble('click')} role="link" tabindex="0">
{#if icon}
<i class="icon icon-{icon}"></i>
{/if}
<slot></slot>
{@render children?.()}
</svelte:element>
<style lang="scss">

View File

@@ -1,30 +1,38 @@
<script>
import { createBubbler, stopPropagation } from 'svelte/legacy';
const bubble = createBubbler();
import MenuLink from "$components/ui/menu/MenuItem.svelte";
/**
* @type {boolean}
*/
export let checked;
/**
* @type {string}
*/
export let name;
/**
* @type {string}
*/
export let value;
/**
* @type {string|null}
* @typedef {Object} Props
* @property {boolean} checked
* @property {string} name
* @property {string} value
* @property {string|null} [href]
* @property {import('svelte').Snippet} [children]
*/
export let href = null;
/** @type {Props} */
let {
checked,
name,
value,
href = null,
children
} = $props();
</script>
<MenuLink {href}>
<input type="radio" {name} {value} {checked} on:input on:click|stopPropagation>
<slot></slot>
<input type="radio" {name} {value} {checked} oninput={bubble('input')} onclick={stopPropagation(bubble('click'))}>
{@render children?.()}
</MenuLink>
<style lang="scss">