feat: refactor how frontend was structured
Some checks failed
Deploy to GitHub Pages / build_site (push) Failing after 1m16s
Some checks failed
Deploy to GitHub Pages / build_site (push) Failing after 1m16s
This commit is contained in:
39
app/src/lib/settings/Panel.svelte
Normal file
39
app/src/lib/settings/Panel.svelte
Normal file
@@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
import type { Readable } from "svelte/store";
|
||||
|
||||
export let id: string;
|
||||
export let icon: string = "";
|
||||
export let title = "";
|
||||
|
||||
const registerPanel =
|
||||
getContext<(id: string, icon: string) => Readable<boolean>>(
|
||||
"registerPanel",
|
||||
);
|
||||
|
||||
let visible = registerPanel(id, icon);
|
||||
</script>
|
||||
|
||||
{#if $visible}
|
||||
<div class="wrapper">
|
||||
{#if title}
|
||||
<header>
|
||||
<h3>{title}</h3>
|
||||
</header>
|
||||
{/if}
|
||||
<slot />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
header {
|
||||
border-bottom: solid thin var(--outline);
|
||||
height: 69px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 1em;
|
||||
}
|
||||
h3 {
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
@@ -1,33 +1,34 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import type { Writable } from "svelte/store";
|
||||
import localStore from "$lib/helpers/localStore";
|
||||
import type { SvelteComponent } from "svelte";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import { setContext } from "svelte";
|
||||
import { derived } from "svelte/store";
|
||||
|
||||
export let panels: Record<
|
||||
let panels: Record<
|
||||
string,
|
||||
{
|
||||
icon: string;
|
||||
id: string;
|
||||
hidden?: boolean;
|
||||
props?: Record<string, unknown>;
|
||||
component?: typeof SvelteComponent<{}, {}, {}>;
|
||||
definition: Record<string, NodeInput>;
|
||||
settings: Writable<Record<string, unknown>>;
|
||||
}
|
||||
>;
|
||||
> = {};
|
||||
|
||||
const activePanel = localStore<keyof typeof panels | false>(
|
||||
"nodes.settings.activePanel",
|
||||
false,
|
||||
);
|
||||
|
||||
$: keys = panels
|
||||
? (Object.keys(panels) as unknown as (keyof typeof panels)[]).filter(
|
||||
(key) => !!panels[key]?.id && panels[key]?.hidden !== true,
|
||||
(key) => !!panels[key]?.id,
|
||||
)
|
||||
: [];
|
||||
|
||||
setContext("registerPanel", (id: string, icon: string) => {
|
||||
panels[id] = { id, icon };
|
||||
return derived(activePanel, ($activePanel) => {
|
||||
return $activePanel === id;
|
||||
});
|
||||
});
|
||||
|
||||
function setActivePanel(panel: keyof typeof panels | false) {
|
||||
if (panel === $activePanel) {
|
||||
$activePanel = false;
|
||||
@@ -37,28 +38,6 @@
|
||||
$activePanel = false;
|
||||
}
|
||||
}
|
||||
|
||||
interface Nested {
|
||||
[key: string]: NodeInput | Nested;
|
||||
}
|
||||
|
||||
function constructNested(panel: (typeof panels)[keyof typeof panels]) {
|
||||
const nested: Nested = {};
|
||||
|
||||
for (const key in panel.definition) {
|
||||
const parts = key.split(".");
|
||||
let current = nested;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (i === parts.length - 1) {
|
||||
current[parts[i]] = panel.definition[key];
|
||||
} else {
|
||||
current[parts[i]] = current[parts[i]] || {};
|
||||
current = current[parts[i]] as Nested;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nested;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="wrapper" class:visible={$activePanel}>
|
||||
@@ -81,25 +60,7 @@
|
||||
{/each}
|
||||
</div>
|
||||
<div class="content">
|
||||
{#if $activePanel && panels[$activePanel] && panels[$activePanel].hidden !== true}
|
||||
<h1 class="m-0 p-4">{panels[$activePanel].id}</h1>
|
||||
{#key $activePanel}
|
||||
{#if panels[$activePanel]?.component}
|
||||
<svelte:component
|
||||
this={panels[$activePanel].component}
|
||||
{...panels[$activePanel]?.props}
|
||||
/>
|
||||
{:else}
|
||||
<div class="flex flex-col">
|
||||
<NestedSettings
|
||||
id={$activePanel}
|
||||
settings={constructNested(panels[$activePanel])}
|
||||
store={panels[$activePanel].settings}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/key}
|
||||
{/if}
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -10,6 +10,7 @@ export const AppSettings = localStore("node-settings", {
|
||||
showVertices: false,
|
||||
centerCamera: true,
|
||||
showStemLines: false,
|
||||
amount: 5
|
||||
});
|
||||
|
||||
const themes = ["dark", "light", "catppuccin", "solarized", "high-contrast", "nord", "dracula"];
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Node, NodeInput } from "@nodes/types";
|
||||
import NestedSettings from "../NestedSettings.svelte";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import { writable } from "svelte/store";
|
||||
import type { GraphManager } from "$lib/graph-interface/graph-manager";
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
export let manager: GraphManager;
|
||||
|
||||
export let node: Node;
|
||||
export let node: Node | undefined;
|
||||
let nodeDefinition: Record<string, NodeInput> | undefined;
|
||||
$: nodeDefinition = node?.tmp?.type
|
||||
? filterInputs(node.tmp.type.inputs)
|
40
app/src/lib/settings/panels/GraphSettings.svelte
Normal file
40
app/src/lib/settings/panels/GraphSettings.svelte
Normal file
@@ -0,0 +1,40 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import type { Writable } from "svelte/store";
|
||||
|
||||
interface Nested {
|
||||
[key: string]: NodeInput | Nested;
|
||||
}
|
||||
|
||||
export let type: Record<string, NodeInput>;
|
||||
|
||||
export let store: Writable<Record<string, any>>;
|
||||
|
||||
function constructNested(type: Record<string, NodeInput>) {
|
||||
const nested: Nested = {};
|
||||
|
||||
for (const key in type) {
|
||||
const parts = key.split(".");
|
||||
let current = nested;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (i === parts.length - 1) {
|
||||
current[parts[i]] = type[key];
|
||||
} else {
|
||||
current[parts[i]] = current[parts[i]] || {};
|
||||
current = current[parts[i]] as Nested;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nested;
|
||||
}
|
||||
|
||||
$: settings = constructNested({
|
||||
randomSeed: { type: "boolean", value: false },
|
||||
...type,
|
||||
});
|
||||
</script>
|
||||
|
||||
{#key settings}
|
||||
<NestedSettings id="graph-settings" {settings} {store} />
|
||||
{/key}
|
@@ -3,7 +3,7 @@
|
||||
import { ShortCut } from "@nodes/ui";
|
||||
|
||||
export let keymap: ReturnType<typeof createKeyMap>;
|
||||
const keys = keymap.keys;
|
||||
const keys = keymap?.keys;
|
||||
</script>
|
||||
|
||||
<div class="wrapper">
|
||||
@@ -13,7 +13,12 @@
|
||||
{#each $keys as key}
|
||||
{#if key.description}
|
||||
<div class="command-wrapper">
|
||||
<ShortCut {...key} />
|
||||
<ShortCut
|
||||
alt={key.alt}
|
||||
ctrl={key.ctrl}
|
||||
shift={key.shift}
|
||||
key={key.key}
|
||||
/>
|
||||
</div>
|
||||
<p>{key.description}</p>
|
||||
{/if}
|
||||
|
@@ -4,8 +4,12 @@
|
||||
import Input from "@nodes/ui";
|
||||
import type { Writable } from "svelte/store";
|
||||
|
||||
type Button = { type: "button"; label?: string; callback: () => void };
|
||||
|
||||
type Input = NodeInput | Button;
|
||||
|
||||
interface Nested {
|
||||
[key: string]: Nested | NodeInput;
|
||||
[key: string]: (Nested & { __title?: string }) | Input;
|
||||
}
|
||||
|
||||
export let id: string;
|
||||
@@ -20,22 +24,23 @@
|
||||
export let depth = 0;
|
||||
|
||||
const keys = Object.keys(settings).filter((key) => key !== "__title");
|
||||
function isNodeInput(v: NodeInput | Nested): v is NodeInput {
|
||||
function isNodeInput(v: Input | Nested): v is Input {
|
||||
return v && "type" in v;
|
||||
}
|
||||
console.log({ settings, store });
|
||||
</script>
|
||||
|
||||
{#if store}
|
||||
{#if $store}
|
||||
{#each keys as key}
|
||||
{@const value = settings[key]}
|
||||
<div class="wrapper" class:first-level={depth === 0}>
|
||||
{#if isNodeInput(value)}
|
||||
{#if value !== undefined && isNodeInput(value)}
|
||||
<div class="input input-{settings[key].type}">
|
||||
{#if settings[key].type === "button"}
|
||||
<button on:click={() => settings[key]?.callback?.()}
|
||||
>{settings[key].label || key}</button
|
||||
{#if value.type === "button"}
|
||||
<button on:click={() => value?.callback?.()}
|
||||
>{value.label || key}</button
|
||||
>
|
||||
{:else if "setting" in value}
|
||||
{: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}
|
Reference in New Issue
Block a user