feat: migrate some more stuff to svelte-5, mainly app settings
Some checks failed
Deploy to GitHub Pages / build_site (push) Failing after 4s
Some checks failed
Deploy to GitHub Pages / build_site (push) Failing after 4s
This commit is contained in:
@ -11,7 +11,7 @@
|
||||
function filterInputs(inputs: Record<string, NodeInput>) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(inputs)
|
||||
.filter(([key, value]) => {
|
||||
.filter(([_key, value]) => {
|
||||
return value.hidden === true;
|
||||
})
|
||||
.map(([key, value]) => {
|
||||
|
@ -3,6 +3,7 @@
|
||||
import type { OBJExporter } from "three/addons/exporters/OBJExporter.js";
|
||||
import type { GLTFExporter } from "three/addons/exporters/GLTFExporter.js";
|
||||
import FileSaver from "file-saver";
|
||||
import { appSettings } from "../app-settings.svelte";
|
||||
|
||||
// Download
|
||||
const download = (
|
||||
@ -51,6 +52,8 @@
|
||||
// download .obj file
|
||||
download(result, "plant", "text/plain", "obj");
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="p-2">
|
||||
|
@ -1,70 +1,100 @@
|
||||
<script lang="ts">
|
||||
import localStore from "$lib/helpers/localStore";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import {localState} from "$lib/helpers/localState.svelte";
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import Input from "@nodes/ui";
|
||||
import type { Writable } from "svelte/store";
|
||||
|
||||
type Button = { type: "button"; label?: string; callback: () => void };
|
||||
type Button = { type: "button"; label?: string };
|
||||
|
||||
type InputType = NodeInput | Button;
|
||||
|
||||
interface Nested {
|
||||
[key: string]: (Nested & { __title?: string }) | InputType;
|
||||
[key: string]: (Nested & { title?: string }) | InputType;
|
||||
}
|
||||
|
||||
export let id: string;
|
||||
type Props = {
|
||||
id: string;
|
||||
key?: string;
|
||||
value: Record<string, unknown> | string | number | boolean;
|
||||
type: Nested;
|
||||
depth?: number;
|
||||
};
|
||||
|
||||
$: expandedDetails = localStore<Record<string, boolean>>(
|
||||
`nodes.settings.expanded.${id}`,
|
||||
{},
|
||||
);
|
||||
let { id, key = "", value = $bindable(), type, depth = 0 }: Props = $props();
|
||||
|
||||
export let settings: Nested;
|
||||
export let store: Writable<Record<string, any>>;
|
||||
export let depth = 0;
|
||||
|
||||
const keys = Object.keys(settings).filter((key) => key !== "__title");
|
||||
function isNodeInput(v: InputType | Nested): v is InputType {
|
||||
return v && "type" in v;
|
||||
}
|
||||
|
||||
let internalValue = $state(Array.isArray(type?.[key]?.options) ? type[key]?.options?.indexOf(value?.[key]) : value?.[key]);
|
||||
|
||||
let openSections = localState("open-details", {});
|
||||
let open = $state(openSections[id]);
|
||||
if(depth > 0 && !isNodeInput(type[key])){
|
||||
$effect(() => {
|
||||
if(open !== undefined){}
|
||||
openSections[id] = open;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$effect(() => {
|
||||
if(key === "" || internalValue === undefined) return;
|
||||
if(isNodeInput(type[key]) && Array.isArray(type[key]?.options) && typeof internalValue === "number"){
|
||||
value[key] = type[key].options?.[internalValue];
|
||||
}else{
|
||||
value[key] = internalValue;
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if $store}
|
||||
{#each keys as key}
|
||||
{@const value = settings[key]}
|
||||
<div class="wrapper" class:first-level={depth === 0}>
|
||||
{#if value !== undefined && isNodeInput(value)}
|
||||
<div
|
||||
class="input input-{settings[key].type}"
|
||||
data-node-type={value?.__node_type || null}
|
||||
data-node-input={value?.__node_input || null}
|
||||
>
|
||||
{#if value.type === "button"}
|
||||
<button on:click={() => value?.callback?.()}
|
||||
>{value.label || key}</button
|
||||
>
|
||||
{:else if "setting" in value && value.setting !== undefined}
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input id={key} input={value} bind:value={$store[value?.setting]} />
|
||||
{:else}
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input id={key} input={value} bind:value={$store[key]} />
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
{#if depth > 0}
|
||||
<hr />
|
||||
{/if}
|
||||
{#if key && isNodeInput(type?.[key]) }
|
||||
<div class="input input-{type[key].type}">
|
||||
{#if type[key].type === "button"}
|
||||
<button onclick={() => console.log(type[key])}>
|
||||
{type[key].label || key}
|
||||
</button>
|
||||
{:else}
|
||||
<label for={id}>{type[key].label || key}</label>
|
||||
<Input id={id} input={type[key]} bind:value={internalValue} />
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
{#if depth === 0}
|
||||
{#each Object.keys(type).filter((key) => key !== "title") as childKey}
|
||||
<NestedSettings
|
||||
id={`${id}.${childKey}`}
|
||||
key={childKey}
|
||||
value={value as Record<string, unknown>}
|
||||
type={type as Nested}
|
||||
depth={depth + 1}
|
||||
/>
|
||||
{/each}
|
||||
{#if depth > 0}
|
||||
<hr />
|
||||
{/if}
|
||||
{:else if key && type?.[key]}
|
||||
{#if depth > 0}
|
||||
<hr />
|
||||
{/if}
|
||||
<details bind:open>
|
||||
<summary>{type[key]?.title||key}</summary>
|
||||
<div class="content">
|
||||
{#each Object.keys(type[key]).filter((key) => key !== "title") as childKey}
|
||||
<NestedSettings
|
||||
id={`${id}.${childKey}`}
|
||||
key={childKey}
|
||||
value={value[key] as Record<string, unknown>}
|
||||
type={type[key] as Nested}
|
||||
depth={depth + 1}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</details>
|
||||
|
||||
|
||||
{/if}
|
||||
|
||||
<details bind:open={$expandedDetails[key]}>
|
||||
<summary>{settings[key]?.__title || key}</summary>
|
||||
<div class="content">
|
||||
<svelte:self settings={settings[key]} {store} depth={depth + 1} />
|
||||
</div>
|
||||
</details>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
|
Reference in New Issue
Block a user