too many changes, forgot to commit smh
This commit is contained in:
35
src/lib/components/ui/checkbox/checkbox.svelte
Normal file
35
src/lib/components/ui/checkbox/checkbox.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { Checkbox as CheckboxPrimitive, type WithoutChildrenOrChild } from "bits-ui";
|
||||
import Check from "@lucide/svelte/icons/check";
|
||||
import Minus from "@lucide/svelte/icons/minus";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
checked = $bindable(false),
|
||||
indeterminate = $bindable(false),
|
||||
class: className,
|
||||
...restProps
|
||||
}: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
|
||||
</script>
|
||||
|
||||
<CheckboxPrimitive.Root
|
||||
bind:ref
|
||||
class={cn(
|
||||
"border-primary ring-offset-background focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer box-content size-4 shrink-0 rounded-sm border focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50",
|
||||
className
|
||||
)}
|
||||
bind:checked
|
||||
bind:indeterminate
|
||||
{...restProps}
|
||||
>
|
||||
{#snippet children({ checked, indeterminate })}
|
||||
<div class="flex size-4 items-center justify-center text-current">
|
||||
{#if indeterminate}
|
||||
<Minus class="size-3.5" />
|
||||
{:else}
|
||||
<Check class={cn("size-3.5", !checked && "text-transparent")} />
|
||||
{/if}
|
||||
</div>
|
||||
{/snippet}
|
||||
</CheckboxPrimitive.Root>
|
6
src/lib/components/ui/checkbox/index.ts
Normal file
6
src/lib/components/ui/checkbox/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import Root from "./checkbox.svelte";
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Checkbox,
|
||||
};
|
7
src/lib/components/ui/label/index.ts
Normal file
7
src/lib/components/ui/label/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import Root from "./label.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Label,
|
||||
};
|
19
src/lib/components/ui/label/label.svelte
Normal file
19
src/lib/components/ui/label/label.svelte
Normal file
@@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { Label as LabelPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
...restProps
|
||||
}: LabelPrimitive.RootProps = $props();
|
||||
</script>
|
||||
|
||||
<LabelPrimitive.Root
|
||||
bind:ref
|
||||
class={cn(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
||||
className
|
||||
)}
|
||||
{...restProps}
|
||||
/>
|
176
src/lib/components/ui/osu-cursor/OsuCursor.svelte
Normal file
176
src/lib/components/ui/osu-cursor/OsuCursor.svelte
Normal file
@@ -0,0 +1,176 @@
|
||||
<script lang="ts">
|
||||
import cursor_default from '$assets/cursor.png';
|
||||
import cursor_additive from '$assets/cursor-additive.png';
|
||||
import { animate } from 'animejs';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let mouseX = $state(0);
|
||||
let mouseY = $state(0);
|
||||
let rotation = $state(0);
|
||||
let isMouseDown = $state(false);
|
||||
let isHoveringInteractive = $state(false);
|
||||
|
||||
let dragStartX = $state(0);
|
||||
let dragStartY = $state(0);
|
||||
let degrees = $state(0);
|
||||
let applyRotation = $state(false);
|
||||
|
||||
function isInteractive(el: Element | null): boolean {
|
||||
while (el) {
|
||||
const tag = el.tagName.toLowerCase();
|
||||
const role = el.getAttribute('role');
|
||||
const computed = getComputedStyle(el);
|
||||
if (
|
||||
['button', 'a', 'input', 'select', 'textarea', 'label', 'option'].includes(tag) ||
|
||||
(role && ['button', 'link', 'checkbox', 'combobox'].includes(role)) ||
|
||||
computed.cursor === 'pointer'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
el = el.parentElement;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const handleMouseMove = (e: MouseEvent) => {
|
||||
mouseX = e.clientX;
|
||||
mouseY = e.clientY;
|
||||
|
||||
const deltaX = e.pageX - window.pageXOffset - dragStartX;
|
||||
const deltaY = e.pageY - window.pageYOffset - dragStartY;
|
||||
|
||||
if (!applyRotation && isMouseDown && deltaX * deltaX + deltaY * deltaY > 30 * 100) {
|
||||
applyRotation = true;
|
||||
}
|
||||
|
||||
let newDegrees = (Math.atan2(-deltaX, deltaY) * 180) / Math.PI + 24.3;
|
||||
|
||||
let diff = (newDegrees - degrees) % 360;
|
||||
if (diff < -180) diff += 360;
|
||||
if (diff > 180) diff -= 360;
|
||||
if (isMouseDown && applyRotation) {
|
||||
degrees += diff;
|
||||
} else {
|
||||
degrees = 0;
|
||||
}
|
||||
|
||||
const el = document.elementFromPoint(mouseX, mouseY);
|
||||
isHoveringInteractive = isInteractive(el);
|
||||
|
||||
if (!isMouseDown) {
|
||||
if (isHoveringInteractive) {
|
||||
animate(cursorAdditive, {
|
||||
opacity: 1,
|
||||
duration: 800,
|
||||
ease: (t: number) => (t - 1) ** 5 + 1,
|
||||
});
|
||||
} else {
|
||||
animate(cursorAdditive, {
|
||||
opacity: 0,
|
||||
duration: 800,
|
||||
ease: (t: number) => (t - 1) ** 5 + 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
animate(cursor, {
|
||||
duration: 180,
|
||||
translateX: mouseX,
|
||||
translateY: mouseY - 50,
|
||||
ease: (t: number) => (t - 1) ** 3 + 1,
|
||||
});
|
||||
|
||||
animate(cursor, {
|
||||
duration: 1500,
|
||||
rotate: degrees,
|
||||
transformOrigin: '0px 0px 0',
|
||||
ease: (t: number) => Math.pow(2, -10 * t) * Math.sin((t - 0.075) * 20.94) + 1 - 0.0005 * t,
|
||||
});
|
||||
};
|
||||
|
||||
const handleMouseDown = (event: MouseEvent) => {
|
||||
dragStartX = event.clientX;
|
||||
dragStartY = event.clientY;
|
||||
|
||||
isMouseDown = true;
|
||||
animate(cursorInner, {
|
||||
scale: 0.9,
|
||||
duration: 800,
|
||||
ease: (t: number) => (t - 1) ** 3 + 1,
|
||||
});
|
||||
animate(cursorAdditive, {
|
||||
opacity: 1,
|
||||
scale: 0.9,
|
||||
duration: 800,
|
||||
ease: (t: number) => (t - 1) ** 5 + 1,
|
||||
});
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
rotation = 0;
|
||||
isMouseDown = false;
|
||||
applyRotation = false;
|
||||
animate(cursorInner, {
|
||||
scale: 1,
|
||||
duration: 500,
|
||||
ease: (t: number) => Math.pow(2, -10 * t) * Math.sin((t - 0.075) * 20.94) + 1 - 0.0005 * t,
|
||||
});
|
||||
animate(cursorAdditive, {
|
||||
opacity: 0,
|
||||
duration: 500,
|
||||
scale: 1,
|
||||
ease: (t: number) => (t - 1) ** 5 + 1,
|
||||
});
|
||||
};
|
||||
|
||||
let cursor: HTMLElement;
|
||||
let cursorInner: HTMLDivElement;
|
||||
let cursorAdditive: HTMLImageElement;
|
||||
|
||||
/* onMount(() => {
|
||||
const processMouseMove = (e: MouseEvent) =>
|
||||
handleMouseMove(e.clientX, e.clientY, e.pageX, e.pageY);
|
||||
document.addEventListener('pointermove', processMouseMove);
|
||||
document.addEventListener('pointerdown', handleMouseDown);
|
||||
document.addEventListener('pointerup', handleMouseUp);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('pointermove', processMouseMove);
|
||||
document.removeEventListener('pointerdown', handleMouseDown);
|
||||
document.removeEventListener('pointerup', handleMouseUp);
|
||||
};
|
||||
}); */
|
||||
</script>
|
||||
|
||||
<svelte:window
|
||||
onmousemove={handleMouseMove}
|
||||
onmousedown={handleMouseDown}
|
||||
onmouseup={handleMouseUp}
|
||||
/>
|
||||
|
||||
<div class="h-7 w-7 fixed pointer-events-none z-[99999]" bind:this={cursor}>
|
||||
<div class="relative">
|
||||
<img class="absolute top-0 left-0" src={cursor_default} bind:this={cursorInner} alt="cursor" />
|
||||
<img
|
||||
class="absolute top-0 left-0 opacity-0"
|
||||
src={cursor_additive}
|
||||
bind:this={cursorAdditive}
|
||||
alt="cursor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(html),
|
||||
:global(body),
|
||||
:global(*),
|
||||
:global(*:hover),
|
||||
:global(button),
|
||||
:global(a),
|
||||
:global(input),
|
||||
:global(select),
|
||||
:global(textarea) {
|
||||
cursor: none !important;
|
||||
}
|
||||
</style>
|
@@ -19,7 +19,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div data-tauri-drag-region class="titlebar z-[99999] border-b border-theme-800/90">
|
||||
<div data-tauri-drag-region class="titlebar z-[60] border-b border-theme-800/90">
|
||||
<div class="mr-auto ms-2 flex flex-row gap-2 items-center text-[1.05rem] font-semibold">
|
||||
<img src={Logo} alt="EZPP Launcher Logo" class="h-11 w-11 inline-block" />
|
||||
<span>EZPPLauncher</span>
|
||||
|
Reference in New Issue
Block a user