Compare commits
9 Commits
config-set
...
ce9ed1f950
| Author | SHA1 | Date | |
|---|---|---|---|
|
ce9ed1f950
|
|||
| f314b960e1 | |||
|
4f97e26295
|
|||
|
a2fe2780cf
|
|||
|
3c16148bb7
|
|||
|
9a8e97885c
|
|||
|
46feef3a48
|
|||
| 6e7dd7a560 | |||
| 7a347ed246 |
@@ -257,6 +257,8 @@ async def handle_add_tracker(request):
|
|||||||
return web.Response(text="Tracker already exists", status=400)
|
return web.Response(text="Tracker already exists", status=400)
|
||||||
|
|
||||||
trackers[tracker_id] = TrackerData(tracker_id, *START_POSITION_INTERNAL)
|
trackers[tracker_id] = TrackerData(tracker_id, *START_POSITION_INTERNAL)
|
||||||
|
await update_all_clients(request.app)
|
||||||
|
|
||||||
return web.Response(text="OK", status=200)
|
return web.Response(text="OK", status=200)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return web.Response(text=f"Error: {e}", status=400)
|
return web.Response(text=f"Error: {e}", status=400)
|
||||||
@@ -273,6 +275,8 @@ async def handler_delete_tracker(request):
|
|||||||
return web.Response(text="Tracker does not exist", status=400)
|
return web.Response(text="Tracker does not exist", status=400)
|
||||||
|
|
||||||
del trackers[tracker_id]
|
del trackers[tracker_id]
|
||||||
|
await update_all_clients(request.app)
|
||||||
|
|
||||||
return web.Response(text="OK", status=200)
|
return web.Response(text="OK", status=200)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return web.Response(text=f"Error: {e}", status=400)
|
return web.Response(text=f"Error: {e}", status=400)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ services:
|
|||||||
PSN_DEFAULT_UDP_MCAST_ADDRESS: "236.10.10.10"
|
PSN_DEFAULT_UDP_MCAST_ADDRESS: "236.10.10.10"
|
||||||
WEB_SERVER_PORT: 8000
|
WEB_SERVER_PORT: 8000
|
||||||
OSC_SERVER_PORT: 9000
|
OSC_SERVER_PORT: 9000
|
||||||
NUM_TRACKERS: 3
|
NUM_TRACKERS: 0
|
||||||
volumes:
|
volumes:
|
||||||
- spot-data:/data
|
- spot-data:/data
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
"$schema": "https://next.shadcn-svelte.com/schema.json",
|
||||||
"style": "default",
|
"style": "default",
|
||||||
"tailwind": {
|
"tailwind": {
|
||||||
"config": "tailwind.config.mjs",
|
"config": "tailwind.config.mjs",
|
||||||
"css": "src/styles/app.css",
|
"css": "src/styles/app.css",
|
||||||
"baseColor": "slate"
|
"baseColor": "slate"
|
||||||
},
|
},
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"components": "$lib/components",
|
"components": "$lib/components",
|
||||||
"utils": "$lib/utils"
|
"utils": "$lib/utils",
|
||||||
},
|
"ui": "$lib/components/ui",
|
||||||
"typescript": true
|
"hooks": "$lib/hooks"
|
||||||
}
|
},
|
||||||
|
"typescript": true,
|
||||||
|
"registry": "https://next.shadcn-svelte.com/registry"
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwind-variants": "^1.0.0",
|
"tailwind-variants": "^1.0.0",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"vaul-svelte": "^0.3.2"
|
"vaul-svelte": "^0.3.2"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
|||||||
12
frontend/pnpm-lock.yaml
generated
12
frontend/pnpm-lock.yaml
generated
@@ -54,6 +54,9 @@ importers:
|
|||||||
tailwind-variants:
|
tailwind-variants:
|
||||||
specifier: ^1.0.0
|
specifier: ^1.0.0
|
||||||
version: 1.0.0(tailwindcss@3.4.17)
|
version: 1.0.0(tailwindcss@3.4.17)
|
||||||
|
tailwindcss-animate:
|
||||||
|
specifier: ^1.0.7
|
||||||
|
version: 1.0.7(tailwindcss@3.4.17)
|
||||||
vaul-svelte:
|
vaul-svelte:
|
||||||
specifier: ^0.3.2
|
specifier: ^0.3.2
|
||||||
version: 0.3.2(svelte@5.22.6)
|
version: 0.3.2(svelte@5.22.6)
|
||||||
@@ -1879,6 +1882,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
tailwindcss: '*'
|
tailwindcss: '*'
|
||||||
|
|
||||||
|
tailwindcss-animate@1.0.7:
|
||||||
|
resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
|
||||||
|
peerDependencies:
|
||||||
|
tailwindcss: '>=3.0.0 || insiders'
|
||||||
|
|
||||||
tailwindcss@3.4.17:
|
tailwindcss@3.4.17:
|
||||||
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
|
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
|
||||||
engines: {node: '>=14.0.0'}
|
engines: {node: '>=14.0.0'}
|
||||||
@@ -4425,6 +4433,10 @@ snapshots:
|
|||||||
tailwind-merge: 3.0.2
|
tailwind-merge: 3.0.2
|
||||||
tailwindcss: 3.4.17
|
tailwindcss: 3.4.17
|
||||||
|
|
||||||
|
tailwindcss-animate@1.0.7(tailwindcss@3.4.17):
|
||||||
|
dependencies:
|
||||||
|
tailwindcss: 3.4.17
|
||||||
|
|
||||||
tailwindcss@3.4.17:
|
tailwindcss@3.4.17:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@alloc/quick-lru': 5.2.0
|
'@alloc/quick-lru': 5.2.0
|
||||||
|
|||||||
@@ -8,10 +8,7 @@
|
|||||||
let ws: WebSocket | null = $state(null);
|
let ws: WebSocket | null = $state(null);
|
||||||
let image: HTMLImageElement | null = $state(null);
|
let image: HTMLImageElement | null = $state(null);
|
||||||
|
|
||||||
let trackers: TrackerData[] = $state([
|
let trackers: TrackerData[] = $state([]);
|
||||||
{ id: 1, x: 0, y: 0, z: 0 },
|
|
||||||
{ id: 2, x: 0, y: 0, z: 0 },
|
|
||||||
]);
|
|
||||||
|
|
||||||
let width = $state(0);
|
let width = $state(0);
|
||||||
let height = $state(0);
|
let height = $state(0);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
onpointermove={onPointerMove}
|
onpointermove={onPointerMove}
|
||||||
style={`transform: translate(${vis_x}px, ${vis_y}px)`}
|
style={`transform: translate(${vis_x}px, ${vis_y}px)`}
|
||||||
class={`absolute flex h-24 w-24 touch-none select-none items-center justify-center rounded-full
|
class={`absolute flex h-24 w-24 touch-none select-none items-center justify-center rounded-full
|
||||||
${selected === id ? "border-green-400 bg-green-400" : "border-red-400 bg-red-400"}`}
|
${selected === id ? "border-green-400 bg-green-400 z-50" : "border-red-400 bg-red-400"}`}
|
||||||
>
|
>
|
||||||
Tracker {id}
|
Tracker {id}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
class="absolute left-0 top-0 z-50 m-0 h-full max-h-full w-full max-w-full p-0 open:bg-black/80"
|
class="absolute left-0 top-0 z-50 m-0 h-full max-h-full w-full max-w-full p-0 open:bg-black/80"
|
||||||
>
|
>
|
||||||
<div class="flex h-full w-full flex-col items-center justify-center">
|
<div class="flex h-full w-full flex-col items-center justify-center">
|
||||||
<h1 class="text-8xl text-red-600">THIS GONNA FUCK THINGS UP</h1>
|
<h1 class="text-8xl text-red-600 text-center">THIS GONNA FUCK THINGS UP</h1>
|
||||||
<div class="flex items-center justify-center gap-6">
|
<div class="flex items-center justify-center gap-6">
|
||||||
<button class="rounded-md bg-gray-400 p-4" onclick={() => dialog.close()}
|
<button class="rounded-md bg-gray-400 p-4" onclick={() => dialog.close()}
|
||||||
>Close</button
|
>Close</button
|
||||||
|
|||||||
@@ -3,32 +3,34 @@
|
|||||||
import { Button } from "$lib/components/ui/button/index.js";
|
import { Button } from "$lib/components/ui/button/index.js";
|
||||||
import TrackerSetting from "./TrackerSetting.svelte";
|
import TrackerSetting from "./TrackerSetting.svelte";
|
||||||
|
|
||||||
const addTracker = async () => {
|
const addTracker = async (arg: number) => {
|
||||||
const response = await fetch("/tracker", {
|
const response = await fetch("/tracker", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
id: 4,
|
id: Number(arg),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(response);
|
console.log(response);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteTracker = async () => {
|
const deleteTracker = async (arg: number) => {
|
||||||
const response = await fetch("/tracker", {
|
const response = await fetch("/tracker", {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
id: 4,
|
id: Number(arg),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
console.log(response);
|
console.log(response);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let id = $state(0);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Drawer.Root>
|
<Drawer.Root>
|
||||||
@@ -41,8 +43,12 @@
|
|||||||
<Drawer.Description>This action cannot be undone.</Drawer.Description>
|
<Drawer.Description>This action cannot be undone.</Drawer.Description>
|
||||||
</Drawer.Header>
|
</Drawer.Header>
|
||||||
<div class="flex items-center justify-evenly">
|
<div class="flex items-center justify-evenly">
|
||||||
<TrackerSetting action={addTracker} text="Add Tracker" />
|
<TrackerSetting bind:value={id} action={addTracker} text="Add Tracker" />
|
||||||
<TrackerSetting action={deleteTracker} text="Delete Tracker" />
|
<TrackerSetting
|
||||||
|
bind:value={id}
|
||||||
|
action={deleteTracker}
|
||||||
|
text="Delete Tracker"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Drawer.Content>
|
</Drawer.Content>
|
||||||
</Drawer.Root>
|
</Drawer.Root>
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
|
|
||||||
let arena_state: "full_arena" | "scene_only" = $state("scene_only");
|
let arena_state: "full_arena" | "scene_only" = $state("scene_only");
|
||||||
|
|
||||||
let tracker = trackers.find((ball) => {
|
let tracker = $state<TrackerData | undefined>(undefined);
|
||||||
ball.id === selected;
|
|
||||||
|
$effect(() => {
|
||||||
|
tracker = trackers.find((ball) => ball.id === selected);
|
||||||
});
|
});
|
||||||
|
|
||||||
const onchange = () => {
|
const onchange = () => {
|
||||||
@@ -61,15 +63,18 @@
|
|||||||
|
|
||||||
<div class="slider-container ml-auto">
|
<div class="slider-container ml-auto">
|
||||||
<Modal action={buttonAction} />
|
<Modal action={buttonAction} />
|
||||||
<input
|
{#if tracker}
|
||||||
type="range"
|
<input
|
||||||
id="z"
|
type="range"
|
||||||
min="0"
|
id="z"
|
||||||
max="4"
|
min="0"
|
||||||
step="0.01"
|
max="4"
|
||||||
oninput={onchange}
|
step="0.01"
|
||||||
/>
|
oninput={onchange}
|
||||||
<output for="z">{z_viz} m</output>
|
bind:value={tracker.z}
|
||||||
|
/>
|
||||||
|
<output for="z">{z_viz} m</output>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -4,14 +4,15 @@
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
text: string;
|
text: string;
|
||||||
action: () => void;
|
action: (arg: number) => void;
|
||||||
|
value: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
let { action, text }: Props = $props();
|
let { action, text, value = $bindable() }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h2>{text}</h2>
|
<h2>{text}</h2>
|
||||||
<Input placeholder={"1"} type="tel" />
|
<Input placeholder={"1"} bind:value required />
|
||||||
<Button onclick={action}>Submit</Button>
|
<Button onclick={() => action(value)}>Submit</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,42 +1,43 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLInputAttributes } from "svelte/elements";
|
import type { HTMLInputAttributes } from "svelte/elements";
|
||||||
import type { InputEvents } from "./index.js";
|
import type { InputEvents } from "./index.js";
|
||||||
import { cn } from "$lib/utils.js";
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
type $$Props = HTMLInputAttributes;
|
type $$Props = HTMLInputAttributes;
|
||||||
type $$Events = InputEvents;
|
type $$Events = InputEvents;
|
||||||
|
|
||||||
let className: $$Props["class"] = undefined;
|
let className: $$Props["class"] = undefined;
|
||||||
export let value: $$Props["value"] = undefined;
|
export let value: $$Props["value"] = undefined;
|
||||||
export { className as class };
|
export { className as class };
|
||||||
|
|
||||||
// Workaround for https://github.com/sveltejs/svelte/issues/9305
|
// Workaround for https://github.com/sveltejs/svelte/issues/9305
|
||||||
// Fixed in Svelte 5, but not backported to 4.x.
|
// Fixed in Svelte 5, but not backported to 4.x.
|
||||||
export let readonly: $$Props["readonly"] = undefined;
|
export let readonly: $$Props["readonly"] = undefined;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
class={cn(
|
class={cn(
|
||||||
"border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className
|
className,
|
||||||
)}
|
)}
|
||||||
bind:value
|
bind:value
|
||||||
{readonly}
|
{readonly}
|
||||||
on:blur
|
type="tel"
|
||||||
on:change
|
on:blur
|
||||||
on:click
|
on:change
|
||||||
on:focus
|
on:click
|
||||||
on:focusin
|
on:focus
|
||||||
on:focusout
|
on:focusin
|
||||||
on:keydown
|
on:focusout
|
||||||
on:keypress
|
on:keydown
|
||||||
on:keyup
|
on:keypress
|
||||||
on:mouseover
|
on:keyup
|
||||||
on:mouseenter
|
on:mouseover
|
||||||
on:mouseleave
|
on:mouseenter
|
||||||
on:mousemove
|
on:mouseleave
|
||||||
on:paste
|
on:mousemove
|
||||||
on:input
|
on:paste
|
||||||
on:wheel|passive
|
on:input
|
||||||
{...$$restProps}
|
on:wheel|passive
|
||||||
|
{...$$restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,73 +1,70 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 222.2 84% 4.9%;
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
--muted: 210 40% 96.1%;
|
--muted: 210 40% 96.1%;
|
||||||
--muted-foreground: 215.4 16.3% 46.9%;
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
--popover: 0 0% 100%;
|
--popover: 0 0% 100%;
|
||||||
--popover-foreground: 222.2 84% 4.9%;
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
--card: 0 0% 100%;
|
--card: 0 0% 100%;
|
||||||
--card-foreground: 222.2 84% 4.9%;
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
--border: 214.3 31.8% 91.4%;
|
--border: 214.3 31.8% 91.4%;
|
||||||
--input: 214.3 31.8% 91.4%;
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
|
||||||
--primary: 222.2 47.4% 11.2%;
|
--primary: 222.2 47.4% 11.2%;
|
||||||
--primary-foreground: 210 40% 98%;
|
--primary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--secondary: 210 40% 96.1%;
|
--secondary: 210 40% 96.1%;
|
||||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
--accent: 210 40% 96.1%;
|
--accent: 210 40% 96.1%;
|
||||||
--accent-foreground: 222.2 47.4% 11.2%;
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
--destructive: 0 72.2% 50.6%;
|
--destructive: 0 72.2% 50.6%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--ring: 222.2 84% 4.9%;
|
--ring: 222.2 84% 4.9%;
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
|
--sidebar-background: 0 0% 98%;
|
||||||
|
--sidebar-foreground: 240 5.3% 26.1%;
|
||||||
|
--sidebar-primary: 240 5.9% 10%;
|
||||||
|
--sidebar-primary-foreground: 0 0% 98%;
|
||||||
|
--sidebar-accent: 240 4.8% 95.9%;
|
||||||
|
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||||
|
--sidebar-border: 220 13% 91%;
|
||||||
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: 222.2 84% 4.9%;
|
--background: 222.2 84% 4.9%;
|
||||||
--foreground: 210 40% 98%;
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
--muted: 217.2 32.6% 17.5%;
|
--muted: 217.2 32.6% 17.5%;
|
||||||
--muted-foreground: 215 20.2% 65.1%;
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
--popover: 222.2 84% 4.9%;
|
--popover: 222.2 84% 4.9%;
|
||||||
--popover-foreground: 210 40% 98%;
|
--popover-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--card: 222.2 84% 4.9%;
|
--card: 222.2 84% 4.9%;
|
||||||
--card-foreground: 210 40% 98%;
|
--card-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--border: 217.2 32.6% 17.5%;
|
--border: 217.2 32.6% 17.5%;
|
||||||
--input: 217.2 32.6% 17.5%;
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
|
||||||
--primary: 210 40% 98%;
|
--primary: 210 40% 98%;
|
||||||
--primary-foreground: 222.2 47.4% 11.2%;
|
--primary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
--secondary: 217.2 32.6% 17.5%;
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
--secondary-foreground: 210 40% 98%;
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--accent: 217.2 32.6% 17.5%;
|
--accent: 217.2 32.6% 17.5%;
|
||||||
--accent-foreground: 210 40% 98%;
|
--accent-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--destructive: 0 62.8% 30.6%;
|
--destructive: 0 62.8% 30.6%;
|
||||||
--destructive-foreground: 210 40% 98%;
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
--ring: 212.7 26.8% 83.9%;
|
--ring: 212.7 26.8% 83.9%;
|
||||||
|
--sidebar-background: 240 5.9% 10%;
|
||||||
|
--sidebar-foreground: 240 4.8% 95.9%;
|
||||||
|
--sidebar-primary: 224.3 76.3% 48%;
|
||||||
|
--sidebar-primary-foreground: 0 0% 100%;
|
||||||
|
--sidebar-accent: 240 3.7% 15.9%;
|
||||||
|
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||||
|
--sidebar-border: 240 3.7% 15.9%;
|
||||||
|
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
@@ -75,4 +72,5 @@
|
|||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +1,6 @@
|
|||||||
import { type ClassValue, clsx } from "clsx";
|
import { type ClassValue, clsx } from "clsx";
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
import { cubicOut } from "svelte/easing";
|
|
||||||
import type { TransitionConfig } from "svelte/transition";
|
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
type FlyAndScaleParams = {
|
|
||||||
y?: number;
|
|
||||||
x?: number;
|
|
||||||
start?: number;
|
|
||||||
duration?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const flyAndScale = (
|
|
||||||
node: Element,
|
|
||||||
params: FlyAndScaleParams = { y: -8, x: 0, start: 0.95, duration: 150 }
|
|
||||||
): TransitionConfig => {
|
|
||||||
const style = getComputedStyle(node);
|
|
||||||
const transform = style.transform === "none" ? "" : style.transform;
|
|
||||||
|
|
||||||
const scaleConversion = (
|
|
||||||
valueA: number,
|
|
||||||
scaleA: [number, number],
|
|
||||||
scaleB: [number, number]
|
|
||||||
) => {
|
|
||||||
const [minA, maxA] = scaleA;
|
|
||||||
const [minB, maxB] = scaleB;
|
|
||||||
|
|
||||||
const percentage = (valueA - minA) / (maxA - minA);
|
|
||||||
const valueB = percentage * (maxB - minB) + minB;
|
|
||||||
|
|
||||||
return valueB;
|
|
||||||
};
|
|
||||||
|
|
||||||
const styleToString = (
|
|
||||||
style: Record<string, number | string | undefined>
|
|
||||||
): string => {
|
|
||||||
return Object.keys(style).reduce((str, key) => {
|
|
||||||
if (style[key] === undefined) return str;
|
|
||||||
return str + `${key}:${style[key]};`;
|
|
||||||
}, "");
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
duration: params.duration ?? 200,
|
|
||||||
delay: 0,
|
|
||||||
css: (t) => {
|
|
||||||
const y = scaleConversion(t, [0, 1], [params.y ?? 5, 0]);
|
|
||||||
const x = scaleConversion(t, [0, 1], [params.x ?? 0, 0]);
|
|
||||||
const scale = scaleConversion(t, [0, 1], [params.start ?? 0.95, 1]);
|
|
||||||
|
|
||||||
return styleToString({
|
|
||||||
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
|
|
||||||
opacity: t
|
|
||||||
});
|
|
||||||
},
|
|
||||||
easing: cubicOut
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,64 +1,96 @@
|
|||||||
import { fontFamily } from "tailwindcss/defaultTheme";
|
import { fontFamily } from "tailwindcss/defaultTheme";
|
||||||
|
import tailwindcssAnimate from "tailwindcss-animate";
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
content: ["./src/**/*.{html,js,svelte,ts}"],
|
content: ["./src/**/*.{html,js,svelte,ts,astro}"],
|
||||||
safelist: ["dark"],
|
safelist: ["dark"],
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
center: true,
|
center: true,
|
||||||
padding: "2rem",
|
padding: "2rem",
|
||||||
screens: {
|
screens: {
|
||||||
"2xl": "1400px"
|
"2xl": "1400px",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
border: "hsl(var(--border) / <alpha-value>)",
|
border: "hsl(var(--border) / <alpha-value>)",
|
||||||
input: "hsl(var(--input) / <alpha-value>)",
|
input: "hsl(var(--input) / <alpha-value>)",
|
||||||
ring: "hsl(var(--ring) / <alpha-value>)",
|
ring: "hsl(var(--ring) / <alpha-value>)",
|
||||||
background: "hsl(var(--background) / <alpha-value>)",
|
background: "hsl(var(--background) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--foreground) / <alpha-value>)",
|
foreground: "hsl(var(--foreground) / <alpha-value>)",
|
||||||
primary: {
|
primary: {
|
||||||
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
|
DEFAULT: "hsl(var(--primary) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--primary-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--primary-foreground) / <alpha-value>)",
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
|
DEFAULT: "hsl(var(--secondary) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--secondary-foreground) / <alpha-value>)",
|
||||||
},
|
},
|
||||||
destructive: {
|
destructive: {
|
||||||
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
|
DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--destructive-foreground) / <alpha-value>)",
|
||||||
},
|
},
|
||||||
muted: {
|
muted: {
|
||||||
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
|
DEFAULT: "hsl(var(--muted) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--muted-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--muted-foreground) / <alpha-value>)",
|
||||||
},
|
},
|
||||||
accent: {
|
accent: {
|
||||||
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
|
DEFAULT: "hsl(var(--accent) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--accent-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--accent-foreground) / <alpha-value>)",
|
||||||
},
|
},
|
||||||
popover: {
|
popover: {
|
||||||
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
|
DEFAULT: "hsl(var(--popover) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--popover-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--popover-foreground) / <alpha-value>)",
|
||||||
},
|
},
|
||||||
card: {
|
card: {
|
||||||
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
DEFAULT: "hsl(var(--card) / <alpha-value>)",
|
||||||
foreground: "hsl(var(--card-foreground) / <alpha-value>)"
|
foreground: "hsl(var(--card-foreground) / <alpha-value>)",
|
||||||
}
|
},
|
||||||
},
|
sidebar: {
|
||||||
borderRadius: {
|
DEFAULT: "hsl(var(--sidebar-background))",
|
||||||
lg: "var(--radius)",
|
foreground: "hsl(var(--sidebar-foreground))",
|
||||||
md: "calc(var(--radius) - 2px)",
|
primary: "hsl(var(--sidebar-primary))",
|
||||||
sm: "calc(var(--radius) - 4px)"
|
"primary-foreground": "hsl(var(--sidebar-primary-foreground))",
|
||||||
},
|
accent: "hsl(var(--sidebar-accent))",
|
||||||
fontFamily: {
|
"accent-foreground": "hsl(var(--sidebar-accent-foreground))",
|
||||||
sans: [...fontFamily.sans]
|
border: "hsl(var(--sidebar-border))",
|
||||||
}
|
ring: "hsl(var(--sidebar-ring))",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
borderRadius: {
|
||||||
|
xl: "calc(var(--radius) + 4px)",
|
||||||
|
lg: "var(--radius)",
|
||||||
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: [...fontFamily.sans],
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
"accordion-down": {
|
||||||
|
from: { height: "0" },
|
||||||
|
to: { height: "var(--bits-accordion-content-height)" },
|
||||||
|
},
|
||||||
|
"accordion-up": {
|
||||||
|
from: { height: "var(--bits-accordion-content-height)" },
|
||||||
|
to: { height: "0" },
|
||||||
|
},
|
||||||
|
"caret-blink": {
|
||||||
|
"0%,70%,100%": { opacity: "1" },
|
||||||
|
"20%,50%": { opacity: "0" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
|
"caret-blink": "caret-blink 1.25s ease-out infinite",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [tailwindcssAnimate],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|||||||
Reference in New Issue
Block a user