1<script lang="ts">
2 import { highestZIndex, isMobile } from '$lib/window.ts';
3 import { draggable } from '@neodrag/svelte';
4
5 interface Props {
6 title?: string;
7 iconUri?: string;
8 id?: string;
9 sticky?: boolean;
10 entry?: boolean;
11 removePadding?: boolean;
12 center?: boolean;
13 layered?: boolean;
14 style?: string;
15 tooltip?: boolean;
16 children?: import('svelte').Snippet;
17 }
18
19 let {
20 title = undefined,
21 iconUri = '',
22 id = '',
23 sticky = false,
24 entry = false,
25 removePadding = false,
26 center = false,
27 layered = false,
28 style = '',
29 tooltip = false,
30 children
31 }: Props = $props();
32
33 const scaleKeyframes = [
34 'window-open',
35 'window-open-vertical',
36 'window-open-vertical',
37 'window-open-horizontal',
38 'window-open-horizontal',
39 'window-open-move-up',
40 'window-open-move-down',
41 'window-open-move-left',
42 'window-open-move-right'
43 ];
44 let chosenKeyframe = $derived(
45 scaleKeyframes.at(Math.floor(Math.random() * scaleKeyframes.length))
46 );
47
48 const isOnMobile = isMobile();
49 const _draggable = isOnMobile ? () => {} : draggable;
50
51 const focusWindow = (node: HTMLElement) => {
52 if (isOnMobile) return;
53 $highestZIndex += 1;
54 node.style.zIndex = $highestZIndex.toString();
55 };
56</script>
57
58<!-- svelte-ignore a11y_no_static_element_interactions -->
59<!-- svelte-ignore a11y_click_events_have_key_events -->
60<div
61 use:_draggable={{
62 disabled: isOnMobile,
63 applyUserSelectHack: true,
64 handle: '.window-titlebar',
65 onDragStart: (data) => {
66 focusWindow(data.currentNode);
67 }
68 }}
69 onclick={(data) => {
70 focusWindow(data.currentTarget);
71 }}
72 class="
73 relative flex flex-col w-full md:w-fit [height:fit-content]
74 {center ? 'mx-auto' : ''}
75 {layered ? 'col-[1] row-[1]' : ''}
76 {sticky ? 'md:sticky md:-top-9' : ''}
77 max-w-screen-sm lg:max-w-screen-md xl:max-w-screen-lg 2xl:max-w-screen-xl
78 {tooltip ? 'min-w-fit' : ''}
79 bg-ralsei-black border-ralsei-white border-ridge
80 {tooltip ? 'border-[6px] border-t-[9px]' : 'border-[7px] border-t-[12px]'}
81 {isOnMobile || tooltip ? '' : 'hover:-translate-x-1 hover:translate-y-1'}
82 animate-{chosenKeyframe} drop-shadow-[24px_24px_24px_rgba(1,1,1,0.8)]
83 {style}
84 "
85 {id}
86>
87 {#if title !== undefined}
88 <div
89 class="
90 window-titlebar p-1 border-ralsei-white border-8
91 bg-gradient-to-l from-ralsei-pink-neon to-ralsei-black to-75%
92 {!isOnMobile ? 'cursor-move' : ''}
93 "
94 style="border-style: hidden hidden ridge hidden;"
95 >
96 <div class="flex bg-opacity-100 pixelate-bg">
97 <h1
98 class="
99 font-monospace text-xl text-ralsei-pink-regular
100 grow justify-self-start self-center {entry ? 'p-name' : ''}
101 "
102 >
103 {title}
104 </h1>
105 {#if iconUri !== ''}
106 <img
107 class="justify-self-end self-center max-h-7"
108 style="image-rendering: pixelated;"
109 src={iconUri}
110 alt={iconUri}
111 />
112 {/if}
113 </div>
114 </div>
115 {/if}
116 <div
117 class="
118 {removePadding ? '' : tooltip ? 'p-1' : 'p-2'} bg-gradient-to-tl
119 to-ralsei-pink-neon/15 from-ralsei-pink-regular/20
120 "
121 >
122 {@render children?.()}
123 </div>
124</div>