feat: add outline to themes
This commit is contained in:
parent
d8ada83db3
commit
c62cfbf75e
@ -1,164 +1,163 @@
|
||||
<script lang="ts">
|
||||
import type { GraphManager } from './graph-manager.js';
|
||||
import { HTML } from '@threlte/extras';
|
||||
import { onMount } from 'svelte';
|
||||
import type { GraphManager } from "./graph-manager.js";
|
||||
import { HTML } from "@threlte/extras";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
export let position: [x: number, y: number] | null;
|
||||
export let position: [x: number, y: number] | null;
|
||||
|
||||
export let graph: GraphManager;
|
||||
export let graph: GraphManager;
|
||||
|
||||
let input: HTMLInputElement;
|
||||
let value: string = '';
|
||||
let activeNodeId: string = '';
|
||||
let input: HTMLInputElement;
|
||||
let value: string = "";
|
||||
let activeNodeId: string = "";
|
||||
|
||||
const allNodes = graph.getNodeTypes();
|
||||
const allNodes = graph.getNodeTypes();
|
||||
|
||||
function filterNodes() {
|
||||
return allNodes.filter((node) => node.id.includes(value));
|
||||
}
|
||||
function filterNodes() {
|
||||
return allNodes.filter((node) => node.id.includes(value));
|
||||
}
|
||||
|
||||
$: nodes = value === '' ? allNodes : filterNodes();
|
||||
$: if (nodes) {
|
||||
if (activeNodeId === '') {
|
||||
activeNodeId = nodes[0].id;
|
||||
} else if (nodes.length) {
|
||||
const node = nodes.find((node) => node.id === activeNodeId);
|
||||
if (!node) {
|
||||
activeNodeId = nodes[0].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
$: nodes = value === "" ? allNodes : filterNodes();
|
||||
$: if (nodes) {
|
||||
if (activeNodeId === "") {
|
||||
activeNodeId = nodes[0].id;
|
||||
} else if (nodes.length) {
|
||||
const node = nodes.find((node) => node.id === activeNodeId);
|
||||
if (!node) {
|
||||
activeNodeId = nodes[0].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
event.stopImmediatePropagation();
|
||||
const value = (event.target as HTMLInputElement).value;
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
if (event.key === 'Escape') {
|
||||
position = null;
|
||||
return;
|
||||
}
|
||||
if (event.key === "Escape") {
|
||||
position = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowDown') {
|
||||
const index = nodes.findIndex((node) => node.id === activeNodeId);
|
||||
activeNodeId = nodes[(index + 1) % nodes.length].id;
|
||||
return;
|
||||
}
|
||||
if (event.key === "ArrowDown") {
|
||||
const index = nodes.findIndex((node) => node.id === activeNodeId);
|
||||
activeNodeId = nodes[(index + 1) % nodes.length].id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowUp') {
|
||||
const index = nodes.findIndex((node) => node.id === activeNodeId);
|
||||
activeNodeId = nodes[(index - 1 + nodes.length) % nodes.length].id;
|
||||
return;
|
||||
}
|
||||
if (event.key === "ArrowUp") {
|
||||
const index = nodes.findIndex((node) => node.id === activeNodeId);
|
||||
activeNodeId = nodes[(index - 1 + nodes.length) % nodes.length].id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === 'Enter') {
|
||||
if (activeNodeId && position) {
|
||||
graph.createNode({ type: activeNodeId, position });
|
||||
position = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (event.key === "Enter") {
|
||||
if (activeNodeId && position) {
|
||||
graph.createNode({ type: activeNodeId, position });
|
||||
position = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
input.disabled = false;
|
||||
setTimeout(() => input.focus(), 50);
|
||||
});
|
||||
onMount(() => {
|
||||
input.disabled = false;
|
||||
setTimeout(() => input.focus(), 50);
|
||||
});
|
||||
</script>
|
||||
|
||||
<HTML position.x={position?.[0]} position.z={position?.[1]} transform={false}>
|
||||
<div class="add-menu-wrapper">
|
||||
<div class="header">
|
||||
<input
|
||||
id="add-menu"
|
||||
type="text"
|
||||
aria-label="Search for a node type"
|
||||
role="searchbox"
|
||||
placeholder="Search..."
|
||||
disabled={false}
|
||||
on:keydown={handleKeyDown}
|
||||
bind:value
|
||||
bind:this={input}
|
||||
/>
|
||||
</div>
|
||||
<div class="add-menu-wrapper">
|
||||
<div class="header">
|
||||
<input
|
||||
id="add-menu"
|
||||
type="text"
|
||||
aria-label="Search for a node type"
|
||||
role="searchbox"
|
||||
placeholder="Search..."
|
||||
disabled={false}
|
||||
on:keydown={handleKeyDown}
|
||||
bind:value
|
||||
bind:this={input}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
{#each nodes as node}
|
||||
<div
|
||||
class="result"
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
aria-selected={node.id === activeNodeId}
|
||||
on:keydown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
if (position) {
|
||||
graph.createNode({ type: node.id, position });
|
||||
position = null;
|
||||
}
|
||||
}
|
||||
}}
|
||||
on:mousedown={() => {
|
||||
if (position) {
|
||||
graph.createNode({ type: node.id, position });
|
||||
position = null;
|
||||
}
|
||||
}}
|
||||
on:focus={() => {
|
||||
activeNodeId = node.id;
|
||||
}}
|
||||
class:selected={node.id === activeNodeId}
|
||||
on:mouseover={() => {
|
||||
activeNodeId = node.id;
|
||||
}}
|
||||
>
|
||||
{node.id}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
{#each nodes as node}
|
||||
<div
|
||||
class="result"
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
aria-selected={node.id === activeNodeId}
|
||||
on:keydown={(event) => {
|
||||
if (event.key === "Enter") {
|
||||
if (position) {
|
||||
graph.createNode({ type: node.id, position, props: {} });
|
||||
position = null;
|
||||
}
|
||||
}
|
||||
}}
|
||||
on:mousedown={() => {
|
||||
if (position) {
|
||||
graph.createNode({ type: node.id, position, props: {} });
|
||||
position = null;
|
||||
}
|
||||
}}
|
||||
on:focus={() => {
|
||||
activeNodeId = node.id;
|
||||
}}
|
||||
class:selected={node.id === activeNodeId}
|
||||
on:mouseover={() => {
|
||||
activeNodeId = node.id;
|
||||
}}
|
||||
>
|
||||
{node.id}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</HTML>
|
||||
|
||||
<style>
|
||||
input {
|
||||
background: var(--background-color-lighter);
|
||||
font-family: var(--font-family);
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
padding: 0.8em;
|
||||
width: calc(100% - 2px);
|
||||
box-sizing: border-box;
|
||||
font-size: 1em;
|
||||
margin-left: 1px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
input {
|
||||
background: var(--layer-0);
|
||||
font-family: var(--font-family);
|
||||
border: none;
|
||||
color: var(--text-color);
|
||||
padding: 0.8em;
|
||||
width: calc(100% - 2px);
|
||||
box-sizing: border-box;
|
||||
font-size: 1em;
|
||||
margin-left: 1px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: solid 2px rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
input:focus {
|
||||
outline: solid 2px rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.add-menu-wrapper {
|
||||
position: absolute;
|
||||
background: var(--background-color);
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
border: solid 2px var(--background-color-lighter);
|
||||
width: 150px;
|
||||
}
|
||||
.content {
|
||||
min-height: none;
|
||||
width: 100%;
|
||||
color: var(--text-color);
|
||||
}
|
||||
.add-menu-wrapper {
|
||||
position: absolute;
|
||||
background: var(--layer-1);
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
border: solid 2px var(--layer-2);
|
||||
width: 150px;
|
||||
}
|
||||
.content {
|
||||
min-height: none;
|
||||
width: 100%;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.result {
|
||||
padding: 1em 0.9em;
|
||||
border-bottom: solid 1px var(--background-color-lighter);
|
||||
opacity: 0.7;
|
||||
font-size: 0.9em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.result {
|
||||
padding: 1em 0.9em;
|
||||
border-bottom: solid 1px var(--layer-2);
|
||||
opacity: 0.7;
|
||||
font-size: 0.9em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.result[aria-selected='true'] {
|
||||
background: var(--background-color-lighter);
|
||||
opacity: 1;
|
||||
}
|
||||
.result[aria-selected="true"] {
|
||||
background: var(--layer-2);
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,28 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { HTML } from '@threlte/extras';
|
||||
import { HTML } from "@threlte/extras";
|
||||
|
||||
export let p1 = { x: 0, y: 0 };
|
||||
export let p2 = { x: 0, y: 0 };
|
||||
export let p1 = { x: 0, y: 0 };
|
||||
export let p2 = { x: 0, y: 0 };
|
||||
|
||||
export let cameraPosition = [0, 1, 0];
|
||||
export let cameraPosition = [0, 1, 0];
|
||||
|
||||
$: width = Math.abs(p1.x - p2.x) * cameraPosition[2];
|
||||
$: height = Math.abs(p1.y - p2.y) * cameraPosition[2];
|
||||
$: width = Math.abs(p1.x - p2.x) * cameraPosition[2];
|
||||
$: height = Math.abs(p1.y - p2.y) * cameraPosition[2];
|
||||
|
||||
$: x = Math.max(p1.x, p2.x) - width / cameraPosition[2];
|
||||
$: y = Math.max(p1.y, p2.y) - height / cameraPosition[2];
|
||||
$: x = Math.max(p1.x, p2.x) - width / cameraPosition[2];
|
||||
$: y = Math.max(p1.y, p2.y) - height / cameraPosition[2];
|
||||
</script>
|
||||
|
||||
<HTML position.x={x} position.z={y} transform={false}>
|
||||
<div class="box-selection" style={`width: ${width}px; height: ${height}px;`}></div>
|
||||
<div
|
||||
class="box-selection"
|
||||
style={`width: ${width}px; height: ${height}px;`}
|
||||
></div>
|
||||
</HTML>
|
||||
|
||||
<style>
|
||||
.box-selection {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
border: solid 0.2px rgba(200, 200, 200, 0.8);
|
||||
border-style: dashed;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.box-selection {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
border: solid 0.2px var(--outline);
|
||||
border-style: dashed;
|
||||
border-radius: 2px;
|
||||
}
|
||||
</style>
|
||||
|
@ -746,7 +746,7 @@
|
||||
<div
|
||||
on:wheel={handleMouseScroll}
|
||||
bind:this={wrapper}
|
||||
class="wrapper"
|
||||
class="graph-wrapper"
|
||||
aria-label="Graph"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@ -794,8 +794,9 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
.graph-wrapper {
|
||||
position: relative;
|
||||
transition: opacity 0.3s ease;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
const manager = new GraphManager(registry);
|
||||
|
||||
export const status = manager.status;
|
||||
|
||||
const updateSettings = debounce((s) => {
|
||||
manager.setSettings(s);
|
||||
}, 200);
|
||||
|
@ -16,6 +16,8 @@ export const colors = writable({
|
||||
layer2: new Color().setStyle("#2D2D2D"),
|
||||
layer3: new Color().setStyle("#A6A6A6"),
|
||||
outline: new Color().setStyle("#000000"),
|
||||
active: new Color().setStyle("#c65a19"),
|
||||
selected: new Color().setStyle("#ffffff"),
|
||||
});
|
||||
|
||||
if ("getComputedStyle" in globalThis) {
|
||||
@ -30,6 +32,8 @@ if ("getComputedStyle" in globalThis) {
|
||||
const layer2 = style.getPropertyValue("--layer-2");
|
||||
const layer3 = style.getPropertyValue("--layer-3");
|
||||
const outline = style.getPropertyValue("--outline");
|
||||
const active = style.getPropertyValue("--active");
|
||||
const selected = style.getPropertyValue("--selected");
|
||||
|
||||
colors.update(col => {
|
||||
col.layer0.setStyle(layer0);
|
||||
@ -42,6 +46,10 @@ if ("getComputedStyle" in globalThis) {
|
||||
col.layer3.convertLinearToSRGB();
|
||||
col.outline.setStyle(outline);
|
||||
col.outline.convertLinearToSRGB();
|
||||
col.active.setStyle(active);
|
||||
col.active.convertLinearToSRGB();
|
||||
col.selected.setStyle(selected);
|
||||
col.selected.convertLinearToSRGB();
|
||||
return col;
|
||||
});
|
||||
|
||||
|
@ -6,12 +6,8 @@ uniform float uHeight;
|
||||
|
||||
uniform vec3 uColorDark;
|
||||
uniform vec3 uColorBright;
|
||||
uniform vec3 uSelectedColor;
|
||||
uniform vec3 uActiveColor;
|
||||
|
||||
uniform bool uSelected;
|
||||
uniform bool uActive;
|
||||
|
||||
uniform vec3 uStrokeColor;
|
||||
uniform float uStrokeWidth;
|
||||
|
||||
float msign(in float x) { return (x < 0.0) ? -1.0 : 1.0; }
|
||||
@ -47,16 +43,9 @@ void main(){
|
||||
// outside
|
||||
gl_FragColor = vec4(0.0,0.0,0.0, 0.0);
|
||||
}else{
|
||||
|
||||
if (distance.w > -uStrokeWidth || mod(y+5.0, 10.0) < uStrokeWidth/2.0) {
|
||||
// draw the outer stroke
|
||||
if (uSelected) {
|
||||
gl_FragColor = vec4(uSelectedColor, 1.0);
|
||||
} else if (uActive) {
|
||||
gl_FragColor = vec4(uActiveColor, 1.0);
|
||||
} else {
|
||||
gl_FragColor = vec4(uColorBright, 1.0);
|
||||
}
|
||||
gl_FragColor = vec4(uStrokeColor, 1.0);
|
||||
}else if (y<5.0){
|
||||
// draw the header
|
||||
gl_FragColor = vec4(uColorBright, 1.0);
|
||||
|
@ -67,18 +67,18 @@
|
||||
uniforms={{
|
||||
uColorBright: { value: new Color("#171717") },
|
||||
uColorDark: { value: new Color("#151515") },
|
||||
uSelectedColor: { value: new Color("#9d5f28") },
|
||||
uActiveColor: { value: new Color("white") },
|
||||
uSelected: { value: false },
|
||||
uActive: { value: false },
|
||||
uStrokeColor: { value: new Color("#9d5f28") },
|
||||
uStrokeWidth: { value: 1.0 },
|
||||
uWidth: { value: 20 },
|
||||
uHeight: { value: height },
|
||||
}}
|
||||
uniforms.uSelected.value={isSelected}
|
||||
uniforms.uActive.value={isActive}
|
||||
uniforms.uColorBright.value={$colors.layer2}
|
||||
uniforms.uColorDark.value={$colors.layer1}
|
||||
uniforms.uStrokeColor.value={isSelected
|
||||
? $colors.selected
|
||||
: isActive
|
||||
? $colors.active
|
||||
: $colors.outline}
|
||||
uniforms.uStrokeWidth.value={(7 - z) / 3}
|
||||
/>
|
||||
</T.Mesh>
|
||||
@ -122,12 +122,12 @@
|
||||
}
|
||||
|
||||
.node.active {
|
||||
--stroke: white;
|
||||
--stroke-width: 1px;
|
||||
--stroke: var(--active);
|
||||
--stroke-width: 2px;
|
||||
}
|
||||
|
||||
.node.selected {
|
||||
--stroke: #9d5f28;
|
||||
--stroke-width: 1px;
|
||||
--stroke: var(--selected);
|
||||
--stroke-width: 2px;
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,4 @@
|
||||
<script lang="ts">
|
||||
</script>
|
||||
|
||||
duuude
|
@ -11,7 +11,6 @@
|
||||
export let store: Writable<Record<string, any>>;
|
||||
export let depth = 0;
|
||||
|
||||
console.log(settings);
|
||||
const keys = Object.keys(settings);
|
||||
function isNodeInput(v: NodeInput | Nested): v is NodeInput {
|
||||
return "type" in v;
|
||||
@ -23,12 +22,18 @@
|
||||
<div class="wrapper" class:first-level={depth === 0}>
|
||||
{#if isNodeInput(value)}
|
||||
<div class="input input-{settings[key].type}">
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input
|
||||
id={key}
|
||||
input={value}
|
||||
bind:value={$store[value?.setting || key]}
|
||||
/>
|
||||
{#if settings[key].type === "button"}
|
||||
<button on:click={() => settings[key]?.callback?.()}
|
||||
>{key || settings[key].label}</button
|
||||
>
|
||||
{:else}
|
||||
<label for={key}>{settings[key].label || key}</label>
|
||||
<Input
|
||||
id={key}
|
||||
input={value}
|
||||
bind:value={$store[value?.setting || key]}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<details>
|
||||
|
@ -1,49 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import type { Writable } from "svelte/store";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
|
||||
export let setting: {
|
||||
icon: string;
|
||||
id: string;
|
||||
definition: Record<string, NodeInput>;
|
||||
settings: Writable<Record<string, unknown>>;
|
||||
};
|
||||
|
||||
const store = setting.settings;
|
||||
|
||||
interface Nested {
|
||||
[key: string]: NodeInput | Nested;
|
||||
}
|
||||
|
||||
$: nestedSettings = constructNested();
|
||||
|
||||
function constructNested() {
|
||||
const nested: Nested = {};
|
||||
|
||||
for (const key in setting.definition) {
|
||||
const parts = key.split(".");
|
||||
let current = nested;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (i === parts.length - 1) {
|
||||
current[parts[i]] = setting.definition[key];
|
||||
} else {
|
||||
current[parts[i]] = current[parts[i]] || {};
|
||||
current = current[parts[i]] as Nested;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nested;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<h1 class="m-0 p-4">{setting.id}</h1>
|
||||
<NestedSettings settings={nestedSettings} {store} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
border-bottom: solid thin var(--outline);
|
||||
}
|
||||
</style>
|
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import type { Writable } from "svelte/store";
|
||||
import SettingsComponent from "./Panel.svelte";
|
||||
import localStore from "$lib/helpers/localStore";
|
||||
import type { SvelteComponent } from "svelte";
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
|
||||
export let settings: Record<
|
||||
export let panels: Record<
|
||||
string,
|
||||
{
|
||||
icon: string;
|
||||
@ -16,13 +16,15 @@
|
||||
}
|
||||
>;
|
||||
|
||||
const activePanel = localStore<keyof typeof settings | false>(
|
||||
const activePanel = localStore<keyof typeof panels | false>(
|
||||
"nodes.settings.activePanel",
|
||||
false,
|
||||
);
|
||||
$: keys = Object.keys(settings) as unknown as (keyof typeof settings)[];
|
||||
$: keys = panels
|
||||
? (Object.keys(panels) as unknown as (keyof typeof panels)[])
|
||||
: [];
|
||||
|
||||
function setActivePanel(panel: keyof typeof settings | false) {
|
||||
function setActivePanel(panel: keyof typeof panels | false) {
|
||||
if (panel === $activePanel) {
|
||||
$activePanel = false;
|
||||
} else if (panel) {
|
||||
@ -31,6 +33,28 @@
|
||||
$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}>
|
||||
@ -42,26 +66,32 @@
|
||||
>
|
||||
<span class="absolute i-tabler-chevron-left w-6 h-6 block"></span>
|
||||
</button>
|
||||
{#each keys as panel (settings[panel].id)}
|
||||
{#each keys as panel (panels[panel].id)}
|
||||
<button
|
||||
class="tab"
|
||||
class:active={panel === $activePanel}
|
||||
on:click={() => setActivePanel(panel)}
|
||||
>
|
||||
<i class={`block w-6 h-6 ${settings[panel].icon}`} />
|
||||
<i class={`block w-6 h-6 ${panels[panel].icon}`} />
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
<div class="content">
|
||||
{#if $activePanel && settings[$activePanel]}
|
||||
{#if $activePanel && panels[$activePanel]}
|
||||
<h1 class="m-0 p-4">{panels[$activePanel].id}</h1>
|
||||
{#key $activePanel}
|
||||
{#if settings[$activePanel].component}
|
||||
{#if panels[$activePanel]?.component}
|
||||
<svelte:component
|
||||
this={settings[$activePanel].component}
|
||||
{...settings[$activePanel]}
|
||||
this={panels[$activePanel].component}
|
||||
{...panels[$activePanel]}
|
||||
/>
|
||||
{:else}
|
||||
<SettingsComponent setting={settings[$activePanel]} />
|
||||
<div class="flex flex-col">
|
||||
<NestedSettings
|
||||
settings={constructNested(panels[$activePanel])}
|
||||
store={panels[$activePanel].settings}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/key}
|
||||
{/if}
|
||||
@ -84,6 +114,10 @@
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: solid thin var(--outline);
|
||||
}
|
||||
|
||||
.content {
|
||||
background: var(--layer-1);
|
||||
}
|
||||
@ -97,6 +131,7 @@
|
||||
.tabs > button {
|
||||
height: 30px;
|
||||
padding: 5px;
|
||||
border-radius: 0px;
|
||||
background: none;
|
||||
color: var(--outline);
|
||||
border: none;
|
||||
|
@ -33,6 +33,19 @@ export const AppSettingTypes = {
|
||||
label: "Show Grid",
|
||||
value: true,
|
||||
},
|
||||
stressTest: {
|
||||
amount: {
|
||||
type: "integer",
|
||||
min: 2,
|
||||
max: 15
|
||||
},
|
||||
loadGrid: {
|
||||
type: "button"
|
||||
},
|
||||
loadTree: {
|
||||
type: "button"
|
||||
},
|
||||
},
|
||||
debug: {
|
||||
wireframe: {
|
||||
type: "boolean",
|
||||
|
@ -8,7 +8,8 @@
|
||||
import Viewer from "$lib/viewer/Viewer.svelte";
|
||||
import Settings from "$lib/settings/Settings.svelte";
|
||||
import { AppSettings, AppSettingTypes } from "$lib/settings/app-settings";
|
||||
import { get, writable } from "svelte/store";
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import Keymap from "$lib/settings/Keymap.svelte";
|
||||
|
||||
const nodeRegistry = new RemoteNodeRegistry("http://localhost:3001");
|
||||
const runtimeExecutor = new MemoryRuntimeExecutor(nodeRegistry);
|
||||
@ -19,6 +20,8 @@
|
||||
? JSON.parse(localStorage.getItem("graph")!)
|
||||
: templates.grid(3, 3);
|
||||
|
||||
let managerStatus: Writable<"loading" | "error" | "idle">;
|
||||
|
||||
function handleResult(event: CustomEvent<Graph>) {
|
||||
res = runtimeExecutor.execute(event.detail, get(settings?.graph?.settings));
|
||||
}
|
||||
@ -34,6 +37,12 @@
|
||||
settings: AppSettings,
|
||||
definition: AppSettingTypes,
|
||||
},
|
||||
graph: {},
|
||||
shortcuts: {
|
||||
id: "shortcuts",
|
||||
icon: "i-tabler-keyboard",
|
||||
component: Keymap,
|
||||
},
|
||||
};
|
||||
|
||||
function handleSettings(
|
||||
@ -42,27 +51,28 @@
|
||||
types: Record<string, unknown>;
|
||||
}>,
|
||||
) {
|
||||
settings = {
|
||||
...settings,
|
||||
graph: {
|
||||
icon: "i-tabler-chart-bar",
|
||||
id: "graph",
|
||||
settings: writable(ev.detail.values),
|
||||
definition: ev.detail.types,
|
||||
},
|
||||
settings.general.definition.stressTest.loadGrid.callback = function () {
|
||||
const store = get(settings.general.settings);
|
||||
graph = templates.grid(store.amount, store.amount);
|
||||
};
|
||||
|
||||
settings.general.definition.stressTest.loadTree.callback = function () {
|
||||
const store = get(settings.general.settings);
|
||||
graph = templates.tree(store.amount);
|
||||
};
|
||||
|
||||
settings.graph = {
|
||||
icon: "i-tabler-chart-bar",
|
||||
id: "graph",
|
||||
settings: writable(ev.detail.values),
|
||||
definition: ev.detail.types,
|
||||
};
|
||||
settings = settings;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="wrapper">
|
||||
<header>
|
||||
header
|
||||
<button
|
||||
on:click={() => {
|
||||
graph = templates.grid(15, 15);
|
||||
}}>grid stress-test</button
|
||||
>
|
||||
</header>
|
||||
<div class="wrapper manager-{$managerStatus}">
|
||||
<header></header>
|
||||
<Grid.Row>
|
||||
<Grid.Cell>
|
||||
<Viewer result={res} />
|
||||
@ -72,12 +82,13 @@
|
||||
<GraphInterface
|
||||
registry={nodeRegistry}
|
||||
{graph}
|
||||
bind:status={managerStatus}
|
||||
settings={settings?.graph?.settings}
|
||||
on:settings={handleSettings}
|
||||
on:result={handleResult}
|
||||
on:save={handleSave}
|
||||
/>
|
||||
<Settings {settings}></Settings>
|
||||
<Settings panels={settings}></Settings>
|
||||
{/key}
|
||||
</Grid.Cell>
|
||||
</Grid.Row>
|
||||
@ -97,6 +108,17 @@
|
||||
grid-template-rows: 50px 1fr;
|
||||
}
|
||||
|
||||
.wrapper :global(canvas) {
|
||||
transition: opacity 0.3s ease;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.manager-loading :global(.graph-wrapper),
|
||||
.manager-loading :global(canvas) {
|
||||
opacity: 0.2;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:global(html) {
|
||||
background: rgb(13, 19, 32);
|
||||
background: linear-gradient(
|
||||
|
0
packages/ui/src/lib/ShortCut.svelte
Normal file
0
packages/ui/src/lib/ShortCut.svelte
Normal file
@ -57,6 +57,9 @@ body {
|
||||
--layer-2: var(--neutral-400);
|
||||
--layer-3: var(--neutral-200);
|
||||
|
||||
--active: #ffffff;
|
||||
--selected: #c65a19;
|
||||
|
||||
--outline: var(--neutral-400);
|
||||
|
||||
--text-color: var(--neutral-200);
|
||||
@ -76,6 +79,8 @@ body.theme-light {
|
||||
--layer-1: var(--neutral-100);
|
||||
--layer-2: var(--neutral-100);
|
||||
--layer-3: var(--neutral-500);
|
||||
--active: #000000;
|
||||
--selected: #c65a19;
|
||||
}
|
||||
|
||||
body.theme-solarized {
|
||||
@ -83,8 +88,10 @@ body.theme-solarized {
|
||||
--outline: #93a1a1;
|
||||
--layer-0: #fdf6e3;
|
||||
--layer-1: #eee8d5;
|
||||
--layer-2: #93a1a1;
|
||||
--layer-2: #c4c0b4;
|
||||
--layer-3: #586e75;
|
||||
--active: #000000;
|
||||
--selected: #268bd2;
|
||||
}
|
||||
|
||||
body.theme-catppuccin {
|
||||
@ -107,17 +114,13 @@ body.theme-high-contrast {
|
||||
|
||||
body.theme-nord {
|
||||
--text-color: #D8DEE9;
|
||||
/* Nord snow */
|
||||
--outline: #4C566A;
|
||||
/* Nord frost */
|
||||
--layer-0: #2E3440;
|
||||
/* Nord polar night */
|
||||
--layer-1: #3B4252;
|
||||
/* Nord polar night */
|
||||
--layer-2: #434C5E;
|
||||
/* Nord polar night */
|
||||
--layer-3: #5E81AC;
|
||||
/* Nord frost */
|
||||
--active: #8999bd;
|
||||
--selected: #b76c3f
|
||||
}
|
||||
|
||||
body.theme-dracula {
|
||||
@ -133,6 +136,9 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* canvas { */
|
||||
/* display: none !important; */
|
||||
/* } */
|
||||
button {
|
||||
background-color: var(--layer-2);
|
||||
border: 1px solid var(--outline);
|
||||
padding: 8px 9px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user