Compare commits
4 Commits
d068828b68
...
aea2cbceba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aea2cbceba
|
||
|
|
cb89b16dd8
|
||
|
|
4217621574
|
||
|
|
22f285eaff
|
@@ -13,34 +13,34 @@
|
||||
"@nodarium/registry": "link:../packages/registry",
|
||||
"@nodarium/ui": "link:../packages/ui",
|
||||
"@nodarium/utils": "link:../packages/utils",
|
||||
"@sveltejs/kit": "^2.49.0",
|
||||
"@threlte/core": "8.3.0",
|
||||
"@threlte/extras": "9.7.0",
|
||||
"@types/three": "^0.181.0",
|
||||
"@unocss/reset": "^66.5.9",
|
||||
"@sveltejs/kit": "^2.50.0",
|
||||
"@threlte/core": "8.3.1",
|
||||
"@threlte/extras": "9.7.1",
|
||||
"@types/three": "^0.182.0",
|
||||
"@unocss/reset": "^66.6.0",
|
||||
"comlink": "^4.4.2",
|
||||
"file-saver": "^2.0.5",
|
||||
"idb": "^8.0.3",
|
||||
"jsondiffpatch": "^0.7.3",
|
||||
"three": "^0.181.2"
|
||||
"three": "^0.182.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/tabler": "^1.2.23",
|
||||
"@iconify-json/tabler": "^1.2.26",
|
||||
"@nodarium/types": "link:../packages/types",
|
||||
"@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",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@unocss/preset-icons": "^66.5.9",
|
||||
"svelte": "^5.43.14",
|
||||
"svelte-check": "^4.3.4",
|
||||
"@unocss/preset-icons": "^66.6.0",
|
||||
"svelte": "^5.46.4",
|
||||
"svelte-check": "^4.3.5",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.9.3",
|
||||
"unocss": "^66.5.9",
|
||||
"vite": "^7.2.4",
|
||||
"unocss": "^66.6.0",
|
||||
"vite": "^7.3.1",
|
||||
"vite-plugin-comlink": "^5.3.0",
|
||||
"vite-plugin-glsl": "^1.5.4",
|
||||
"vite-plugin-glsl": "^1.5.5",
|
||||
"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} />
|
||||
{/each}
|
||||
|
||||
<HTML transform={false}>
|
||||
<HTML>
|
||||
<div
|
||||
role="tree"
|
||||
id="graph"
|
||||
tabindex="0"
|
||||
class="wrapper"
|
||||
style:transform={`scale(${graphState.cameraPosition[2] * 0.1})`}
|
||||
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="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"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 519 B After Width: | Height: | Size: 496 B |
@@ -2,7 +2,7 @@
|
||||
import NestedSettings from "./NestedSettings.svelte";
|
||||
import { localState } from "$lib/helpers/localState.svelte";
|
||||
import type { NodeInput } from "@nodarium/types";
|
||||
import Input from "@nodarium/ui";
|
||||
import { Input } from "@nodarium/ui";
|
||||
|
||||
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 }) {
|
||||
|
||||
const namespaces = await registry.getUser(params.user)
|
||||
|
||||
return json(namespaces);
|
||||
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ export const entries: EntryGenerator = async () => {
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async function GET({ params }) {
|
||||
|
||||
const namespaces = await registry.getCollection(`${params.user}/${params.collection}`);
|
||||
|
||||
return json(namespaces);
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import * as registry from "$lib/node-registry";
|
||||
|
||||
export const prerender = true;
|
||||
|
||||
|
||||
export const entries: EntryGenerator = async () => {
|
||||
const users = await registry.getUsers();
|
||||
return users.map(user => {
|
||||
@@ -18,9 +17,7 @@ export const entries: EntryGenerator = async () => {
|
||||
}
|
||||
|
||||
export const GET: RequestHandler = async function GET({ params }) {
|
||||
|
||||
const nodeId = `${params.user}/${params.collection}/${params.node}` as const;
|
||||
|
||||
try {
|
||||
const node = await getNode(nodeId);
|
||||
return json(node);
|
||||
|
||||
@@ -6,9 +6,6 @@ import * as registry from "$lib/node-registry";
|
||||
export const prerender = true;
|
||||
|
||||
export const GET: RequestHandler = async function GET() {
|
||||
|
||||
const users = await registry.getUsers();
|
||||
|
||||
return json(users);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// uno.config.ts
|
||||
import { defineConfig } from 'unocss'
|
||||
import presetIcons from '@unocss/preset-icons'
|
||||
import { presetUno } from 'unocss'
|
||||
import fs from 'fs'
|
||||
import fs from 'node:fs'
|
||||
|
||||
const icons = Object.fromEntries(fs.readdirSync('./src/lib/icons')
|
||||
.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({
|
||||
presets: [
|
||||
presetUno(),
|
||||
presetIcons({
|
||||
collections: {
|
||||
custom: icons
|
||||
|
||||
@@ -10,10 +10,8 @@
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@hey-api/client-fetch": "^0.13.1"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@hey-api/openapi-ts": "^0.88.0"
|
||||
"@hey-api/openapi-ts": "^0.90.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"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:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"test": "vitest",
|
||||
"lint": "eslint .",
|
||||
"story:dev": "storybook dev -p 6006",
|
||||
"story:build": "storybook build"
|
||||
"lint": "eslint ."
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
@@ -30,36 +28,32 @@
|
||||
"svelte": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-essentials": "^8.6.14",
|
||||
"@storybook/addon-svelte-csf": "5.0.10",
|
||||
"@storybook/addon-themes": "^10.0.8",
|
||||
"@storybook/svelte": "^10.0.8",
|
||||
"@storybook/sveltekit": "^10.0.8",
|
||||
"@nodarium/types": "link:../types",
|
||||
"@sveltejs/adapter-static": "^3.0.10",
|
||||
"@sveltejs/kit": "^2.49.0",
|
||||
"@sveltejs/package": "^2.5.6",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||
"@sveltejs/kit": "^2.50.0",
|
||||
"@sveltejs/package": "^2.5.7",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.47.0",
|
||||
"@typescript-eslint/parser": "^8.47.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-storybook": "^10.0.8",
|
||||
"eslint-plugin-svelte": "^3.13.0",
|
||||
"publint": "^0.3.15",
|
||||
"storybook": "^10.0.8",
|
||||
"svelte": "^5.43.14",
|
||||
"svelte-check": "^4.3.4",
|
||||
"@types/three": "^0.182.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
||||
"@typescript-eslint/parser": "^8.53.0",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-svelte": "^3.14.0",
|
||||
"publint": "^0.3.16",
|
||||
"svelte": "^5.46.4",
|
||||
"svelte-check": "^4.3.5",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^7.2.4",
|
||||
"vitest": "^4.0.13",
|
||||
"@nodarium/types": "link:../types"
|
||||
"vite": "^7.3.1",
|
||||
"vitest": "^4.0.17"
|
||||
},
|
||||
"svelte": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@threlte/core": "^8.3.0",
|
||||
"@threlte/extras": "^9.7.0"
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@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>
|
||||
@@ -1,37 +1,41 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
title?: string;
|
||||
transparent?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
open?: boolean;
|
||||
}
|
||||
interface Props {
|
||||
title?: string;
|
||||
transparent?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
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>
|
||||
|
||||
<details class:transparent bind:open>
|
||||
<summary>{title}</summary>
|
||||
<div class="content">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<summary>{title}</summary>
|
||||
<div class="content">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<style>
|
||||
details {
|
||||
padding: 1em;
|
||||
color: var(--text-color);
|
||||
padding-left: 20px;
|
||||
background-color: #202020;
|
||||
outline: solid 0.1px white;
|
||||
border-radius: 2px;
|
||||
font-weight: 300;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
details.transparent {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
}
|
||||
details {
|
||||
padding: 1em;
|
||||
color: var(--text-color);
|
||||
padding-left: 20px;
|
||||
background-color: #202020;
|
||||
outline: solid 0.1px white;
|
||||
border-radius: 2px;
|
||||
font-weight: 300;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
details.transparent {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,15 +4,13 @@
|
||||
step?: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
value = $bindable(0.5),
|
||||
step = 0.01,
|
||||
min = $bindable(0),
|
||||
max = $bindable(1),
|
||||
id = ''
|
||||
max = $bindable(1)
|
||||
}: Props = $props();
|
||||
|
||||
if (min > max) {
|
||||
@@ -55,6 +53,7 @@
|
||||
window.addEventListener('mousemove', handleMouseMove);
|
||||
window.addEventListener('mouseup', handleMouseUp);
|
||||
document.body.style.cursor = 'ew-resize';
|
||||
(ev.target as HTMLElement)?.blur();
|
||||
}
|
||||
|
||||
function handleMouseUp() {
|
||||
@@ -93,6 +92,7 @@
|
||||
} else {
|
||||
value = Math.max(Math.min(min + (max - min) * vx, max), min);
|
||||
}
|
||||
(ev.target as HTMLElement)?.blur();
|
||||
}
|
||||
$effect(() => {
|
||||
if ((value || 0).toString().length > 5) {
|
||||
@@ -110,7 +110,6 @@
|
||||
<input
|
||||
bind:value
|
||||
bind:this={inputEl}
|
||||
{id}
|
||||
{step}
|
||||
{max}
|
||||
{min}
|
||||
@@ -1,29 +1,28 @@
|
||||
<script lang="ts">
|
||||
import Checkbox from './elements/Checkbox.svelte';
|
||||
import Float from './elements/Float.svelte';
|
||||
import Integer from './elements/Integer.svelte';
|
||||
import Select from './elements/Select.svelte';
|
||||
import Checkbox from './Checkbox.svelte';
|
||||
import Float from './Float.svelte';
|
||||
import Integer from './Integer.svelte';
|
||||
import Select from './Select.svelte';
|
||||
import Vec3 from './Vec3.svelte';
|
||||
|
||||
import type { NodeInput } from '@nodarium/types';
|
||||
import Vec3 from './elements/Vec3.svelte';
|
||||
|
||||
interface Props {
|
||||
input: NodeInput;
|
||||
value: any;
|
||||
id: string;
|
||||
}
|
||||
|
||||
let { input, value = $bindable(), id }: Props = $props();
|
||||
let { input, value = $bindable() }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#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'}
|
||||
<Integer {id} bind:value min={input?.min} max={input?.max} />
|
||||
<Integer bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === 'boolean'}
|
||||
<Checkbox {id} bind:value />
|
||||
<Checkbox bind:value />
|
||||
{:else if input.type === 'select'}
|
||||
<Select {id} bind:value options={input.options} />
|
||||
<Select bind:value options={input.options} />
|
||||
{:else if input.type === 'vec3'}
|
||||
<Vec3 {id} bind:value />
|
||||
<Vec3 bind:value />
|
||||
{/if}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
interface Props {
|
||||
min?: number | undefined;
|
||||
max?: number | undefined;
|
||||
step?: number;
|
||||
value?: number;
|
||||
id?: string;
|
||||
onchange?: (value: number) => void;
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -15,21 +12,21 @@
|
||||
max = undefined,
|
||||
step = 1,
|
||||
value = $bindable(0),
|
||||
id = ''
|
||||
onchange
|
||||
}: Props = $props();
|
||||
|
||||
if (!value) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
let inputEl: HTMLInputElement | undefined = $state();
|
||||
let wrapper: HTMLDivElement | undefined = $state();
|
||||
let inputEl = $state<HTMLInputElement>();
|
||||
let wrapper = $state<HTMLDivElement>();
|
||||
|
||||
let prev = -1;
|
||||
function update() {
|
||||
if (prev === value) return;
|
||||
prev = value;
|
||||
dispatch('change', parseFloat(value + ''));
|
||||
onchange?.(parseFloat(value + ''));
|
||||
}
|
||||
|
||||
function handleChange(change: number) {
|
||||
@@ -45,7 +42,7 @@
|
||||
|
||||
downV = value;
|
||||
downX = ev.clientX;
|
||||
rect = wrapper.getBoundingClientRect();
|
||||
rect = wrapper?.getBoundingClientRect()!;
|
||||
|
||||
window.removeEventListener('mousemove', handleMouseMove);
|
||||
window.addEventListener('mousemove', handleMouseMove);
|
||||
@@ -55,9 +52,9 @@
|
||||
|
||||
function handleMouseUp() {
|
||||
if (downV === value) {
|
||||
inputEl.focus();
|
||||
inputEl?.focus();
|
||||
} else {
|
||||
inputEl.blur();
|
||||
inputEl?.blur();
|
||||
}
|
||||
|
||||
document.body.style.cursor = 'unset';
|
||||
@@ -100,7 +97,6 @@
|
||||
<input
|
||||
bind:value
|
||||
bind:this={inputEl}
|
||||
{id}
|
||||
{step}
|
||||
{max}
|
||||
{min}
|
||||
@@ -2,13 +2,12 @@
|
||||
interface Props {
|
||||
options?: string[];
|
||||
value?: number;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
let { options = [], value = $bindable(0), id = '' }: Props = $props();
|
||||
let { options = [], value = $bindable(0) }: Props = $props();
|
||||
</script>
|
||||
|
||||
<select {id} bind:value>
|
||||
<select bind:value>
|
||||
{#each options as label, i}
|
||||
<option value={i}>{label}</option>
|
||||
{/each}
|
||||
@@ -3,16 +3,15 @@
|
||||
|
||||
interface Props {
|
||||
value?: any;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
let { value = $bindable([0, 0, 0]), id = '' }: Props = $props();
|
||||
let { value = $bindable([0, 0, 0]) }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Float id={`${id}-x`} bind:value={value[0]} />
|
||||
<Float id={`${id}-y`} bind:value={value[1]} />
|
||||
<Float id={`${id}-z`} bind:value={value[2]} />
|
||||
<Float bind:value={value[0]} />
|
||||
<Float bind:value={value[1]} />
|
||||
<Float bind:value={value[2]} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -1,3 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
/* fira-code-300 - latin */
|
||||
@font-face {
|
||||
font-display: swap;
|
||||
@@ -63,9 +65,6 @@ html {
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
color: var(--text-color);
|
||||
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
|
||||
import Input from './Input.svelte';
|
||||
|
||||
import Float from "./elements/Float.svelte";
|
||||
import Integer from "./elements/Integer.svelte";
|
||||
import Select from "./elements/Select.svelte";
|
||||
import Checkbox from "./elements/Checkbox.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 Input } from './Input.svelte';
|
||||
export { default as Float } from "./Float.svelte";
|
||||
export { default as Integer } from "./Integer.svelte";
|
||||
export { default as Vec3 } from "./Vec3.svelte";
|
||||
export { default as Select } from "./Select.svelte";
|
||||
export { default as Checkbox } from "./Checkbox.svelte";
|
||||
export { default as Details } from "./Details.svelte";
|
||||
export { default as ShortCut } from "./ShortCut.svelte";
|
||||
|
||||
@@ -1,29 +1,51 @@
|
||||
<script lang="ts">
|
||||
import '$lib/app.css';
|
||||
import Float from '$lib/elements/Float.svelte';
|
||||
import Integer from '$lib/elements/Integer.svelte';
|
||||
import Vec3 from '$lib/elements/Vec3.svelte';
|
||||
import { Checkbox, Details, Float, Integer, Select, ShortCut, Vec3 } from '$lib/index.js';
|
||||
import Section from './Section.svelte';
|
||||
|
||||
let intValue = $state(0);
|
||||
let floatValue = $state(0.2);
|
||||
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>
|
||||
|
||||
<main>
|
||||
<section>
|
||||
<h3>Integer {intValue}</h3>
|
||||
<main class="flex flex-col gap-8 py-8">
|
||||
<h1 class="text-4xl">@nodarium/ui</h1>
|
||||
|
||||
<Section title="Integer" value={intValue}>
|
||||
<Integer bind:value={intValue} />
|
||||
</section>
|
||||
</Section>
|
||||
|
||||
<section>
|
||||
<h3>Float {floatValue}</h3>
|
||||
<Section title="Float" value={floatValue}>
|
||||
<Float bind:value={floatValue} />
|
||||
</section>
|
||||
</Section>
|
||||
|
||||
<section>
|
||||
<h3>Vec3 {JSON.stringify(vecValue)}</h3>
|
||||
<Section title="Vec3" value={JSON.stringify(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>
|
||||
|
||||
<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 { defineConfig } from 'vitest/config';
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [sveltekit()],
|
||||
plugins: [tailwindcss(), sveltekit()],
|
||||
test: {
|
||||
include: ['src/**/*.{test,spec}.{js,ts}']
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"@nodarium/types": "link:../types"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^7.2.4",
|
||||
"vitest": "^4.0.13"
|
||||
"vite": "^7.3.1",
|
||||
"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