File size: 2,336 Bytes
41a5ab2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<script lang="ts">
	import { Dialog as DialogPrimitive } from 'bits-ui';
	import XIcon from '@lucide/svelte/icons/x';

	interface Props {
		open: boolean;
		code: string;
		language: string;
		onOpenChange?: (open: boolean) => void;
	}

	let { open = $bindable(), code, language, onOpenChange }: Props = $props();

	let iframeRef = $state<HTMLIFrameElement | null>(null);

	$effect(() => {
		if (!iframeRef) return;

		if (open) {
			iframeRef.srcdoc = code;
		} else {
			iframeRef.srcdoc = '';
		}
	});

	function handleOpenChange(nextOpen: boolean) {
		open = nextOpen;
		onOpenChange?.(nextOpen);
	}
</script>

<DialogPrimitive.Root {open} onOpenChange={handleOpenChange}>

	<DialogPrimitive.Portal>

		<DialogPrimitive.Overlay class="code-preview-overlay" />



		<DialogPrimitive.Content class="code-preview-content">

			<iframe

				bind:this={iframeRef}

				title="Preview {language}"

				sandbox="allow-scripts allow-same-origin"

				class="code-preview-iframe"

			></iframe>



			<DialogPrimitive.Close

				class="code-preview-close absolute top-4 right-4 border-none bg-transparent text-white opacity-70 mix-blend-difference transition-opacity hover:opacity-100 focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-8"

				aria-label="Close preview"

			>

				<XIcon />

				<span class="sr-only">Close preview</span>

			</DialogPrimitive.Close>

		</DialogPrimitive.Content>

	</DialogPrimitive.Portal>

</DialogPrimitive.Root>

<style lang="postcss">

	:global(.code-preview-overlay) {

		position: fixed;

		inset: 0;

		background-color: transparent;

		z-index: 100000;

	}



	:global(.code-preview-content) {

		position: fixed;

		inset: 0;

		top: 0 !important;

		left: 0 !important;

		width: 100dvw;

		height: 100dvh;

		margin: 0;

		padding: 0;

		border: none;

		border-radius: 0;

		background-color: transparent;

		box-shadow: none;

		display: block;

		overflow: hidden;

		transform: none !important;

		z-index: 100001;

	}



	:global(.code-preview-iframe) {

		display: block;

		width: 100dvw;

		height: 100dvh;

		border: 0;

	}



	:global(.code-preview-close) {

		position: absolute;

		z-index: 100002;

	}

</style>