Compare commits
4 Commits
feat/drop-
...
aea2cbceba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aea2cbceba
|
||
|
|
cb89b16dd8
|
||
|
|
4217621574
|
||
|
|
22f285eaff
|
@@ -13,34 +13,34 @@
|
|||||||
"@nodarium/registry": "link:../packages/registry",
|
"@nodarium/registry": "link:../packages/registry",
|
||||||
"@nodarium/ui": "link:../packages/ui",
|
"@nodarium/ui": "link:../packages/ui",
|
||||||
"@nodarium/utils": "link:../packages/utils",
|
"@nodarium/utils": "link:../packages/utils",
|
||||||
"@sveltejs/kit": "^2.49.0",
|
"@sveltejs/kit": "^2.50.0",
|
||||||
"@threlte/core": "8.3.0",
|
"@threlte/core": "8.3.1",
|
||||||
"@threlte/extras": "9.7.0",
|
"@threlte/extras": "9.7.1",
|
||||||
"@types/three": "^0.181.0",
|
"@types/three": "^0.182.0",
|
||||||
"@unocss/reset": "^66.5.9",
|
"@unocss/reset": "^66.6.0",
|
||||||
"comlink": "^4.4.2",
|
"comlink": "^4.4.2",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"idb": "^8.0.3",
|
"idb": "^8.0.3",
|
||||||
"jsondiffpatch": "^0.7.3",
|
"jsondiffpatch": "^0.7.3",
|
||||||
"three": "^0.181.2"
|
"three": "^0.182.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify-json/tabler": "^1.2.23",
|
"@iconify-json/tabler": "^1.2.26",
|
||||||
"@nodarium/types": "link:../packages/types",
|
"@nodarium/types": "link:../packages/types",
|
||||||
"@sveltejs/adapter-static": "^3.0.10",
|
"@sveltejs/adapter-static": "^3.0.10",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||||
"@tsconfig/svelte": "^5.0.6",
|
"@tsconfig/svelte": "^5.0.6",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@unocss/preset-icons": "^66.5.9",
|
"@unocss/preset-icons": "^66.6.0",
|
||||||
"svelte": "^5.43.14",
|
"svelte": "^5.46.4",
|
||||||
"svelte-check": "^4.3.4",
|
"svelte-check": "^4.3.5",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"unocss": "^66.5.9",
|
"unocss": "^66.6.0",
|
||||||
"vite": "^7.2.4",
|
"vite": "^7.3.1",
|
||||||
"vite-plugin-comlink": "^5.3.0",
|
"vite-plugin-comlink": "^5.3.0",
|
||||||
"vite-plugin-glsl": "^1.5.4",
|
"vite-plugin-glsl": "^1.5.5",
|
||||||
"vite-plugin-wasm": "^3.5.0",
|
"vite-plugin-wasm": "^3.5.0",
|
||||||
"vitest": "^4.0.13"
|
"vitest": "^4.0.17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,11 +177,9 @@
|
|||||||
<EdgeEl z={graphState.cameraPosition[2]} {x1} {y1} {x2} {y2} />
|
<EdgeEl z={graphState.cameraPosition[2]} {x1} {y1} {x2} {y2} />
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
<HTML transform={false}>
|
<HTML>
|
||||||
<div
|
<div
|
||||||
role="tree"
|
|
||||||
id="graph"
|
id="graph"
|
||||||
tabindex="0"
|
|
||||||
class="wrapper"
|
class="wrapper"
|
||||||
style:transform={`scale(${graphState.cameraPosition[2] * 0.1})`}
|
style:transform={`scale(${graphState.cameraPosition[2] * 0.1})`}
|
||||||
class:hovering-sockets={graphState.activeSocket}
|
class:hovering-sockets={graphState.activeSocket}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect x="17" y="8" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
|
<rect x="17" y="8" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
|
||||||
<rect x="2" y="3" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
|
<rect x="2" y="3" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
|
||||||
<rect x="2" y="14" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
|
<rect x="2" y="14" width="5" height="7" rx="1" stroke="currentColor" stroke-width="2"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 496 B |
@@ -2,7 +2,7 @@
|
|||||||
import NestedSettings from "./NestedSettings.svelte";
|
import NestedSettings from "./NestedSettings.svelte";
|
||||||
import { localState } from "$lib/helpers/localState.svelte";
|
import { localState } from "$lib/helpers/localState.svelte";
|
||||||
import type { NodeInput } from "@nodarium/types";
|
import type { NodeInput } from "@nodarium/types";
|
||||||
import Input from "@nodarium/ui";
|
import { Input } from "@nodarium/ui";
|
||||||
|
|
||||||
type Button = { type: "button"; callback: () => void; label?: string };
|
type Button = { type: "button"; callback: () => void; label?: string };
|
||||||
|
|
||||||
|
|||||||
25
app/src/routes/dev/+page.svelte
Normal file
25
app/src/routes/dev/+page.svelte
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Grid from "$lib/grid";
|
||||||
|
import Panel from "$lib/sidebar/Panel.svelte";
|
||||||
|
import Sidebar from "$lib/sidebar/Sidebar.svelte";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Cell></Grid.Cell>
|
||||||
|
<Grid.Cell>
|
||||||
|
<Sidebar>
|
||||||
|
<Panel
|
||||||
|
id="node-store"
|
||||||
|
classes="text-green-400"
|
||||||
|
title="Node Store"
|
||||||
|
icon="i-tabler-database"
|
||||||
|
></Panel>
|
||||||
|
</Sidebar>
|
||||||
|
</Grid.Cell>
|
||||||
|
</Grid.Row>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global body {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -14,9 +14,6 @@ export const entries: EntryGenerator = async () => {
|
|||||||
|
|
||||||
|
|
||||||
export const GET: RequestHandler = async function GET({ params }) {
|
export const GET: RequestHandler = async function GET({ params }) {
|
||||||
|
|
||||||
const namespaces = await registry.getUser(params.user)
|
const namespaces = await registry.getUser(params.user)
|
||||||
|
|
||||||
return json(namespaces);
|
return json(namespaces);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,6 @@ export const entries: EntryGenerator = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const GET: RequestHandler = async function GET({ params }) {
|
export const GET: RequestHandler = async function GET({ params }) {
|
||||||
|
|
||||||
const namespaces = await registry.getCollection(`${params.user}/${params.collection}`);
|
const namespaces = await registry.getCollection(`${params.user}/${params.collection}`);
|
||||||
|
|
||||||
return json(namespaces);
|
return json(namespaces);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import * as registry from "$lib/node-registry";
|
|||||||
|
|
||||||
export const prerender = true;
|
export const prerender = true;
|
||||||
|
|
||||||
|
|
||||||
export const entries: EntryGenerator = async () => {
|
export const entries: EntryGenerator = async () => {
|
||||||
const users = await registry.getUsers();
|
const users = await registry.getUsers();
|
||||||
return users.map(user => {
|
return users.map(user => {
|
||||||
@@ -18,9 +17,7 @@ export const entries: EntryGenerator = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const GET: RequestHandler = async function GET({ params }) {
|
export const GET: RequestHandler = async function GET({ params }) {
|
||||||
|
|
||||||
const nodeId = `${params.user}/${params.collection}/${params.node}` as const;
|
const nodeId = `${params.user}/${params.collection}/${params.node}` as const;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const node = await getNode(nodeId);
|
const node = await getNode(nodeId);
|
||||||
return json(node);
|
return json(node);
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ import * as registry from "$lib/node-registry";
|
|||||||
export const prerender = true;
|
export const prerender = true;
|
||||||
|
|
||||||
export const GET: RequestHandler = async function GET() {
|
export const GET: RequestHandler = async function GET() {
|
||||||
|
|
||||||
const users = await registry.getUsers();
|
const users = await registry.getUsers();
|
||||||
|
|
||||||
return json(users);
|
return json(users);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// uno.config.ts
|
// uno.config.ts
|
||||||
import { defineConfig } from 'unocss'
|
import { defineConfig } from 'unocss'
|
||||||
import presetIcons from '@unocss/preset-icons'
|
import presetIcons from '@unocss/preset-icons'
|
||||||
import { presetUno } from 'unocss'
|
import fs from 'node:fs'
|
||||||
import fs from 'fs'
|
|
||||||
|
|
||||||
const icons = Object.fromEntries(fs.readdirSync('./src/lib/icons')
|
const icons = Object.fromEntries(fs.readdirSync('./src/lib/icons')
|
||||||
.map(name => [name.replace(".svg", ""), fs.readFileSync(`./src/lib/icons/${name}`, 'utf-8')]))
|
.map(name => [name.replace(".svg", ""), fs.readFileSync(`./src/lib/icons/${name}`, 'utf-8')]))
|
||||||
@@ -10,7 +9,6 @@ const icons = Object.fromEntries(fs.readdirSync('./src/lib/icons')
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
presets: [
|
presets: [
|
||||||
presetUno(),
|
|
||||||
presetIcons({
|
presetIcons({
|
||||||
collections: {
|
collections: {
|
||||||
custom: icons
|
custom: icons
|
||||||
|
|||||||
@@ -10,10 +10,8 @@
|
|||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {},
|
||||||
"@hey-api/client-fetch": "^0.13.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@hey-api/openapi-ts": "^0.88.0"
|
"@hey-api/openapi-ts": "^0.90.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,6 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"zod": "^4.1.12"
|
"zod": "^4.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { StorybookConfig } from '@storybook/sveltekit';
|
|
||||||
|
|
||||||
const config: StorybookConfig = {
|
|
||||||
"stories": [
|
|
||||||
"../src/**/*.stories.@(js|ts|svelte)"
|
|
||||||
],
|
|
||||||
|
|
||||||
"addons": [
|
|
||||||
"@storybook/addon-svelte-csf",
|
|
||||||
"@storybook/addon-essentials",
|
|
||||||
"@storybook/addon-themes",
|
|
||||||
],
|
|
||||||
|
|
||||||
"framework": {
|
|
||||||
"name": "@storybook/sveltekit",
|
|
||||||
"options": {}
|
|
||||||
},
|
|
||||||
|
|
||||||
docs: {}
|
|
||||||
};
|
|
||||||
export default config;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<style>
|
|
||||||
.sidebar-header {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
#downshift-0-label {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downshift-0-label ~ div {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { withThemeByClassName } from "@storybook/addon-themes";
|
|
||||||
import type { Preview } from '@storybook/svelte';
|
|
||||||
|
|
||||||
import "../src/lib/app.css";
|
|
||||||
|
|
||||||
const preview: Preview = {
|
|
||||||
parameters: {
|
|
||||||
controls: {
|
|
||||||
matchers: {
|
|
||||||
color: /(background|color)$/i,
|
|
||||||
date: /Date$/i,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
decorators: [withThemeByClassName({
|
|
||||||
themes: {
|
|
||||||
dark: 'theme-dark',
|
|
||||||
light: 'theme-light',
|
|
||||||
catppuccin: 'theme-catppuccin',
|
|
||||||
solarized: 'theme-solarized',
|
|
||||||
high: 'theme-high-contrast',
|
|
||||||
nord: 'theme-nord',
|
|
||||||
dracula: 'theme-dracula',
|
|
||||||
},
|
|
||||||
defaultTheme: 'light',
|
|
||||||
})],
|
|
||||||
};
|
|
||||||
|
|
||||||
export default preview;
|
|
||||||
@@ -10,9 +10,7 @@
|
|||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
"lint": "eslint .",
|
"lint": "eslint ."
|
||||||
"story:dev": "storybook dev -p 6006",
|
|
||||||
"story:build": "storybook build"
|
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
@@ -30,36 +28,32 @@
|
|||||||
"svelte": "^4.0.0"
|
"svelte": "^4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@storybook/addon-essentials": "^8.6.14",
|
"@nodarium/types": "link:../types",
|
||||||
"@storybook/addon-svelte-csf": "5.0.10",
|
|
||||||
"@storybook/addon-themes": "^10.0.8",
|
|
||||||
"@storybook/svelte": "^10.0.8",
|
|
||||||
"@storybook/sveltekit": "^10.0.8",
|
|
||||||
"@sveltejs/adapter-static": "^3.0.10",
|
"@sveltejs/adapter-static": "^3.0.10",
|
||||||
"@sveltejs/kit": "^2.49.0",
|
"@sveltejs/kit": "^2.50.0",
|
||||||
"@sveltejs/package": "^2.5.6",
|
"@sveltejs/package": "^2.5.7",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
"@types/three": "^0.182.0",
|
||||||
"@typescript-eslint/parser": "^8.47.0",
|
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
||||||
"eslint": "^9.39.1",
|
"@typescript-eslint/parser": "^8.53.0",
|
||||||
"eslint-plugin-storybook": "^10.0.8",
|
"eslint": "^9.39.2",
|
||||||
"eslint-plugin-svelte": "^3.13.0",
|
"eslint-plugin-svelte": "^3.14.0",
|
||||||
"publint": "^0.3.15",
|
"publint": "^0.3.16",
|
||||||
"storybook": "^10.0.8",
|
"svelte": "^5.46.4",
|
||||||
"svelte": "^5.43.14",
|
"svelte-check": "^4.3.5",
|
||||||
"svelte-check": "^4.3.4",
|
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.9.3",
|
"typescript": "^5.9.3",
|
||||||
"vite": "^7.2.4",
|
"vite": "^7.3.1",
|
||||||
"vitest": "^4.0.13",
|
"vitest": "^4.0.17"
|
||||||
"@nodarium/types": "link:../types"
|
|
||||||
},
|
},
|
||||||
"svelte": "./dist/index.js",
|
"svelte": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@threlte/core": "^8.3.0",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
"@threlte/extras": "^9.7.0"
|
"@threlte/core": "^8.3.1",
|
||||||
|
"@threlte/extras": "^9.7.1",
|
||||||
|
"tailwindcss": "^4.1.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
45
packages/ui/src/lib/Checkbox.svelte
Normal file
45
packages/ui/src/lib/Checkbox.svelte
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
interface Props {
|
||||||
|
value: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { value = $bindable(false) }: Props = $props();
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
value = value === 'true';
|
||||||
|
} else if (typeof value === 'number') {
|
||||||
|
value = value === 1;
|
||||||
|
} else if (!(typeof value === 'boolean')) {
|
||||||
|
value = !!value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<label
|
||||||
|
class="relative inline-flex h-[22px] w-[22px] cursor-pointer items-center justify-center bg-[var(--layer-2)] rounded-[5px]"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={value}
|
||||||
|
class="peer absolute h-px w-px overflow-hidden whitespace-nowrap border-0 p-0 [clip:rect(0,0,0,0)]"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="absolute opacity-0 peer-checked:opacity-100 transition-opacity duration-100 flex w-full h-full items-center justify-center"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 19 14"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-[10px] w-[12px] text-[var(--text-color)]"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M2 7L7 12L17 2"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="3"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
@@ -6,7 +6,12 @@
|
|||||||
open?: boolean;
|
open?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { title = "Details", transparent = false, children, open = $bindable(false) }: Props = $props();
|
let {
|
||||||
|
title = 'Details',
|
||||||
|
transparent = false,
|
||||||
|
children,
|
||||||
|
open = $bindable(false)
|
||||||
|
}: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<details class:transparent bind:open>
|
<details class:transparent bind:open>
|
||||||
@@ -33,5 +38,4 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,15 +4,13 @@
|
|||||||
step?: number;
|
step?: number;
|
||||||
min?: number;
|
min?: number;
|
||||||
max?: number;
|
max?: number;
|
||||||
id?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
value = $bindable(0.5),
|
value = $bindable(0.5),
|
||||||
step = 0.01,
|
step = 0.01,
|
||||||
min = $bindable(0),
|
min = $bindable(0),
|
||||||
max = $bindable(1),
|
max = $bindable(1)
|
||||||
id = ''
|
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
if (min > max) {
|
if (min > max) {
|
||||||
@@ -55,6 +53,7 @@
|
|||||||
window.addEventListener('mousemove', handleMouseMove);
|
window.addEventListener('mousemove', handleMouseMove);
|
||||||
window.addEventListener('mouseup', handleMouseUp);
|
window.addEventListener('mouseup', handleMouseUp);
|
||||||
document.body.style.cursor = 'ew-resize';
|
document.body.style.cursor = 'ew-resize';
|
||||||
|
(ev.target as HTMLElement)?.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseUp() {
|
function handleMouseUp() {
|
||||||
@@ -93,6 +92,7 @@
|
|||||||
} else {
|
} else {
|
||||||
value = Math.max(Math.min(min + (max - min) * vx, max), min);
|
value = Math.max(Math.min(min + (max - min) * vx, max), min);
|
||||||
}
|
}
|
||||||
|
(ev.target as HTMLElement)?.blur();
|
||||||
}
|
}
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if ((value || 0).toString().length > 5) {
|
if ((value || 0).toString().length > 5) {
|
||||||
@@ -110,7 +110,6 @@
|
|||||||
<input
|
<input
|
||||||
bind:value
|
bind:value
|
||||||
bind:this={inputEl}
|
bind:this={inputEl}
|
||||||
{id}
|
|
||||||
{step}
|
{step}
|
||||||
{max}
|
{max}
|
||||||
{min}
|
{min}
|
||||||
@@ -1,29 +1,28 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Checkbox from './elements/Checkbox.svelte';
|
import Checkbox from './Checkbox.svelte';
|
||||||
import Float from './elements/Float.svelte';
|
import Float from './Float.svelte';
|
||||||
import Integer from './elements/Integer.svelte';
|
import Integer from './Integer.svelte';
|
||||||
import Select from './elements/Select.svelte';
|
import Select from './Select.svelte';
|
||||||
|
import Vec3 from './Vec3.svelte';
|
||||||
|
|
||||||
import type { NodeInput } from '@nodarium/types';
|
import type { NodeInput } from '@nodarium/types';
|
||||||
import Vec3 from './elements/Vec3.svelte';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
input: NodeInput;
|
input: NodeInput;
|
||||||
value: any;
|
value: any;
|
||||||
id: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let { input, value = $bindable(), id }: Props = $props();
|
let { input, value = $bindable() }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if input.type === 'float'}
|
{#if input.type === 'float'}
|
||||||
<Float {id} bind:value min={input?.min} max={input?.max} />
|
<Float bind:value min={input?.min} max={input?.max} />
|
||||||
{:else if input.type === 'integer'}
|
{:else if input.type === 'integer'}
|
||||||
<Integer {id} bind:value min={input?.min} max={input?.max} />
|
<Integer bind:value min={input?.min} max={input?.max} />
|
||||||
{:else if input.type === 'boolean'}
|
{:else if input.type === 'boolean'}
|
||||||
<Checkbox {id} bind:value />
|
<Checkbox bind:value />
|
||||||
{:else if input.type === 'select'}
|
{:else if input.type === 'select'}
|
||||||
<Select {id} bind:value options={input.options} />
|
<Select bind:value options={input.options} />
|
||||||
{:else if input.type === 'vec3'}
|
{:else if input.type === 'vec3'}
|
||||||
<Vec3 {id} bind:value />
|
<Vec3 bind:value />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte';
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
min?: number | undefined;
|
min?: number | undefined;
|
||||||
max?: number | undefined;
|
max?: number | undefined;
|
||||||
step?: number;
|
step?: number;
|
||||||
value?: number;
|
value?: number;
|
||||||
id?: string;
|
onchange?: (value: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
@@ -15,21 +12,21 @@
|
|||||||
max = undefined,
|
max = undefined,
|
||||||
step = 1,
|
step = 1,
|
||||||
value = $bindable(0),
|
value = $bindable(0),
|
||||||
id = ''
|
onchange
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputEl: HTMLInputElement | undefined = $state();
|
let inputEl = $state<HTMLInputElement>();
|
||||||
let wrapper: HTMLDivElement | undefined = $state();
|
let wrapper = $state<HTMLDivElement>();
|
||||||
|
|
||||||
let prev = -1;
|
let prev = -1;
|
||||||
function update() {
|
function update() {
|
||||||
if (prev === value) return;
|
if (prev === value) return;
|
||||||
prev = value;
|
prev = value;
|
||||||
dispatch('change', parseFloat(value + ''));
|
onchange?.(parseFloat(value + ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleChange(change: number) {
|
function handleChange(change: number) {
|
||||||
@@ -45,7 +42,7 @@
|
|||||||
|
|
||||||
downV = value;
|
downV = value;
|
||||||
downX = ev.clientX;
|
downX = ev.clientX;
|
||||||
rect = wrapper.getBoundingClientRect();
|
rect = wrapper?.getBoundingClientRect()!;
|
||||||
|
|
||||||
window.removeEventListener('mousemove', handleMouseMove);
|
window.removeEventListener('mousemove', handleMouseMove);
|
||||||
window.addEventListener('mousemove', handleMouseMove);
|
window.addEventListener('mousemove', handleMouseMove);
|
||||||
@@ -55,9 +52,9 @@
|
|||||||
|
|
||||||
function handleMouseUp() {
|
function handleMouseUp() {
|
||||||
if (downV === value) {
|
if (downV === value) {
|
||||||
inputEl.focus();
|
inputEl?.focus();
|
||||||
} else {
|
} else {
|
||||||
inputEl.blur();
|
inputEl?.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.style.cursor = 'unset';
|
document.body.style.cursor = 'unset';
|
||||||
@@ -100,7 +97,6 @@
|
|||||||
<input
|
<input
|
||||||
bind:value
|
bind:value
|
||||||
bind:this={inputEl}
|
bind:this={inputEl}
|
||||||
{id}
|
|
||||||
{step}
|
{step}
|
||||||
{max}
|
{max}
|
||||||
{min}
|
{min}
|
||||||
@@ -2,13 +2,12 @@
|
|||||||
interface Props {
|
interface Props {
|
||||||
options?: string[];
|
options?: string[];
|
||||||
value?: number;
|
value?: number;
|
||||||
id?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let { options = [], value = $bindable(0), id = '' }: Props = $props();
|
let { options = [], value = $bindable(0) }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<select {id} bind:value>
|
<select bind:value>
|
||||||
{#each options as label, i}
|
{#each options as label, i}
|
||||||
<option value={i}>{label}</option>
|
<option value={i}>{label}</option>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -3,16 +3,15 @@
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
value?: any;
|
value?: any;
|
||||||
id?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let { value = $bindable([0, 0, 0]), id = '' }: Props = $props();
|
let { value = $bindable([0, 0, 0]) }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Float id={`${id}-x`} bind:value={value[0]} />
|
<Float bind:value={value[0]} />
|
||||||
<Float id={`${id}-y`} bind:value={value[1]} />
|
<Float bind:value={value[1]} />
|
||||||
<Float id={`${id}-z`} bind:value={value[2]} />
|
<Float bind:value={value[2]} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
/* fira-code-300 - latin */
|
/* fira-code-300 - latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
@@ -63,9 +65,6 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
|
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
background-color: var(--layer-0);
|
background-color: var(--layer-0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
interface Props {
|
|
||||||
value: boolean;
|
|
||||||
id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
let { value = $bindable(false), id = '' }: Props = $props();
|
|
||||||
$effect(() => {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
value = value === 'true';
|
|
||||||
} else if (typeof value === 'number') {
|
|
||||||
value = value === 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<input {id} type="checkbox" bind:checked={value} />
|
|
||||||
<label for={id}>
|
|
||||||
<svg viewBox="0 0 19 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
d="M2 7L7 12L17 2"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="3"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
input[type='checkbox'] {
|
|
||||||
position: absolute;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0 0 0 0);
|
|
||||||
height: 1px;
|
|
||||||
width: 1px;
|
|
||||||
margin: -1px;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
#inputPreview {
|
|
||||||
display: flex;
|
|
||||||
gap: 20px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
input + label {
|
|
||||||
position: relative;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 22px;
|
|
||||||
color: rgb(0, 0, 0);
|
|
||||||
}
|
|
||||||
input + label::before {
|
|
||||||
content: ' ';
|
|
||||||
display: inline;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 3px;
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
background-color: var(--layer-2);
|
|
||||||
border-radius: 5px;
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
input:checked + label::after {
|
|
||||||
content: ' ';
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 12px 12px;
|
|
||||||
background-position: center center;
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: 0px;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
text-align: center;
|
|
||||||
background-color: transparent;
|
|
||||||
color: red;
|
|
||||||
font-size: 10px;
|
|
||||||
height: 22px;
|
|
||||||
width: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input + label > svg {
|
|
||||||
position: absolute;
|
|
||||||
display: none;
|
|
||||||
width: 12px;
|
|
||||||
height: 10px;
|
|
||||||
left: 5px;
|
|
||||||
color: var(--text-color);
|
|
||||||
top: 5.9px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input:checked + label > svg {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<script module>
|
|
||||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
||||||
import FloatComp from './Float.svelte';
|
|
||||||
|
|
||||||
const { Story } = defineMeta({
|
|
||||||
title: 'Inputs/Float',
|
|
||||||
component: FloatComp
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Story name="Float" />
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<script module>
|
|
||||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
||||||
import IntegerComp from './Integer.svelte';
|
|
||||||
|
|
||||||
const { Story } = defineMeta({
|
|
||||||
title: 'Inputs/Integer',
|
|
||||||
component: IntegerComp
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Story name="Integer" />
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<script module>
|
|
||||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
||||||
import SelectComp from '$lib/elements/Select.svelte';
|
|
||||||
const { Story } = defineMeta({
|
|
||||||
title: 'Inputs/Select',
|
|
||||||
component: SelectComp,
|
|
||||||
|
|
||||||
argTypes: {
|
|
||||||
options: {
|
|
||||||
control: {
|
|
||||||
type: 'select'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
parameters: {
|
|
||||||
actions: {
|
|
||||||
handles: ['change']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Story name="Select" args={{ options: ['strawberry', 'raspberry', 'chickpeas'] }} />
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<script module>
|
|
||||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
||||||
import Vec3Comp from './Vec3.svelte';
|
|
||||||
const { Story } = defineMeta({
|
|
||||||
title: 'Inputs/Vec3',
|
|
||||||
component: Vec3Comp
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Story name="Vec3" />
|
|
||||||
@@ -1,16 +1,8 @@
|
|||||||
// Reexport your entry components here
|
export { default as Input } from './Input.svelte';
|
||||||
import Input from './Input.svelte';
|
export { default as Float } from "./Float.svelte";
|
||||||
|
export { default as Integer } from "./Integer.svelte";
|
||||||
import Float from "./elements/Float.svelte";
|
export { default as Vec3 } from "./Vec3.svelte";
|
||||||
import Integer from "./elements/Integer.svelte";
|
export { default as Select } from "./Select.svelte";
|
||||||
import Select from "./elements/Select.svelte";
|
export { default as Checkbox } from "./Checkbox.svelte";
|
||||||
import Checkbox from "./elements/Checkbox.svelte";
|
export { default as Details } from "./Details.svelte";
|
||||||
import Details from "./Details.svelte";
|
|
||||||
|
|
||||||
export const icons = import.meta.glob('./icons/*.svg?raw', { eager: true })
|
|
||||||
|
|
||||||
export { Float, Integer, Select, Checkbox, Input, Details };
|
|
||||||
|
|
||||||
export default Input;
|
|
||||||
|
|
||||||
export { default as ShortCut } from "./ShortCut.svelte";
|
export { default as ShortCut } from "./ShortCut.svelte";
|
||||||
|
|||||||
@@ -1,29 +1,51 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import '$lib/app.css';
|
import '$lib/app.css';
|
||||||
import Float from '$lib/elements/Float.svelte';
|
import { Checkbox, Details, Float, Integer, Select, ShortCut, Vec3 } from '$lib/index.js';
|
||||||
import Integer from '$lib/elements/Integer.svelte';
|
import Section from './Section.svelte';
|
||||||
import Vec3 from '$lib/elements/Vec3.svelte';
|
|
||||||
|
|
||||||
let intValue = $state(0);
|
let intValue = $state(0);
|
||||||
let floatValue = $state(0.2);
|
let floatValue = $state(0.2);
|
||||||
let vecValue = $state([0.2, 0.3, 0.4]);
|
let vecValue = $state([0.2, 0.3, 0.4]);
|
||||||
|
const options = ['strawberry', 'raspberry', 'chickpeas'];
|
||||||
|
let selectValue = $state(0);
|
||||||
|
const d = $derived(options[selectValue]);
|
||||||
|
|
||||||
|
let checked = $state(false);
|
||||||
|
let detailsOpen = $state(false);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main>
|
<main class="flex flex-col gap-8 py-8">
|
||||||
<section>
|
<h1 class="text-4xl">@nodarium/ui</h1>
|
||||||
<h3>Integer {intValue}</h3>
|
|
||||||
|
<Section title="Integer" value={intValue}>
|
||||||
<Integer bind:value={intValue} />
|
<Integer bind:value={intValue} />
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
<section>
|
<Section title="Float" value={floatValue}>
|
||||||
<h3>Float {floatValue}</h3>
|
|
||||||
<Float bind:value={floatValue} />
|
<Float bind:value={floatValue} />
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
<section>
|
<Section title="Vec3" value={JSON.stringify(vecValue)}>
|
||||||
<h3>Vec3 {JSON.stringify(vecValue)}</h3>
|
|
||||||
<Vec3 bind:value={vecValue} />
|
<Vec3 bind:value={vecValue} />
|
||||||
</section>
|
</Section>
|
||||||
|
|
||||||
|
<Section title="Select" value={d}>
|
||||||
|
<Select bind:value={selectValue} {options} />
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section title="Checkbox" value={checked}>
|
||||||
|
<Checkbox bind:value={checked} />
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section title="Details" value={detailsOpen}>
|
||||||
|
<Details title="More Information" bind:open={detailsOpen}>
|
||||||
|
<p>Here is some more information that was previously hidden.</p>
|
||||||
|
</Details>
|
||||||
|
</Section>
|
||||||
|
|
||||||
|
<Section title="Shortcut">
|
||||||
|
<ShortCut ctrl key="S" />
|
||||||
|
</Section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
18
packages/ui/src/routes/Section.svelte
Normal file
18
packages/ui/src/routes/Section.svelte
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { type Snippet } from 'svelte';
|
||||||
|
let { title, value, children } = $props<{
|
||||||
|
title?: string;
|
||||||
|
value?: unknown;
|
||||||
|
children?: Snippet;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="border border-1/2 mb-4 p-4 flex flex-col gap-4">
|
||||||
|
<h3 class="flex gap-2 font-bold">
|
||||||
|
{title}
|
||||||
|
<p class="font-normal! opacity-50!">{value}</p>
|
||||||
|
</h3>
|
||||||
|
<div>
|
||||||
|
{@render children()}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { sveltekit } from '@sveltejs/kit/vite';
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vitest/config';
|
||||||
|
import tailwindcss from '@tailwindcss/vite'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [sveltekit()],
|
plugins: [tailwindcss(), sveltekit()],
|
||||||
test: {
|
test: {
|
||||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
"@nodarium/types": "link:../types"
|
"@nodarium/types": "link:../types"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "^7.2.4",
|
"vite": "^7.3.1",
|
||||||
"vitest": "^4.0.13"
|
"vitest": "^4.0.17"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3331
pnpm-lock.yaml
generated
3331
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user