fix(chore): prettier format

This commit is contained in:
Shahrad Elahi 2023-12-19 13:21:11 +03:30
parent 42bc3dc971
commit 8488858c46
66 changed files with 340 additions and 277 deletions

View File

@ -4,20 +4,14 @@
"singleQuote": true, "singleQuote": true,
"jsxSingleQuote": true, "jsxSingleQuote": true,
"trailingComma": "all", "trailingComma": "all",
"printWidth": 120, "printWidth": 100,
"jsxBracketSameLine": true,
"overrides": [ "overrides": [
{ {
"files": "*.svelte", "files": "*.svelte",
"options": { "options": {
"parser": "svelte", "parser": "svelte",
"plugins": [ "plugins": ["prettier-plugin-svelte"]
"prettier-plugin-svelte"
]
} }
} }
],
"pluginSearchDirs": [
"."
] ]
} }

View File

@ -10,4 +10,4 @@
"components": "$lib/components", "components": "$lib/components",
"utils": "$lib/utils" "utils": "$lib/utils"
} }
} }

View File

@ -9,8 +9,8 @@
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test": "mocha", "test": "mocha",
"lint": "prettier --plugin-search-dir . --check .", "lint": "prettier --check .",
"format": "prettier --plugin-search-dir . --write .", "format": "prettier --write .",
"start": "node ./build/index.js" "start": "node ./build/index.js"
}, },
"devDependencies": { "devDependencies": {
@ -55,4 +55,4 @@
"tailwind-merge": "^2.1.0", "tailwind-merge": "^2.1.0",
"tailwind-variants": "^0.1.18" "tailwind-variants": "^0.1.18"
} }
} }

View File

@ -6,8 +6,8 @@ const config = {
//Some plugins, like tailwindcss/nesting, need to run before Tailwind, //Some plugins, like tailwindcss/nesting, need to run before Tailwind,
tailwindcss(), tailwindcss(),
//But others, like autoprefixer, need to run after, //But others, like autoprefixer, need to run after,
autoprefixer autoprefixer,
] ],
}; };
module.exports = config; module.exports = config;

View File

@ -79,7 +79,6 @@
} }
@layer base { @layer base {
h1 { h1 {
@apply text-4xl font-bold; @apply text-4xl font-bold;
} }
@ -108,5 +107,4 @@
text-decoration: none; text-decoration: none;
transition: color 0.2s ease-in-out; transition: color 0.2s ease-in-out;
} }
}
}

View File

@ -1,12 +1,12 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.ico" /> <link rel="icon" href="%sveltekit.assets%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head% %sveltekit.head%
</head> </head>
<body data-sveltekit-preload-data="hover" class="min-h-screen"> <body data-sveltekit-preload-data="hover" class="min-h-screen">
<div style="display: contents" class="min-h-screen">%sveltekit.body%</div> <div style="display: contents" class="min-h-screen">%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@ -3,5 +3,5 @@ import Root from './EditableText.svelte';
export { export {
Root, Root,
// //
Root as EditableText Root as EditableText,
} };

View File

@ -21,7 +21,7 @@
viewBox="0 0 64 41" viewBox="0 0 64 41"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
{...$$restProps} {...$$restProps}
class={cn('max-w-full h-full m-auto',className)} class={cn('max-w-full h-full m-auto', className)}
> >
<g transform="translate(0 1)" fill="none" fill-rule="evenodd"> <g transform="translate(0 1)" fill="none" fill-rule="evenodd">
<ellipse fill={shadowColor} cx="32" cy="33" rx="32" ry="7" /> <ellipse fill={shadowColor} cx="32" cy="33" rx="32" ry="7" />

View File

@ -10,9 +10,9 @@
</script> </script>
<div class="w-full min-h-screen flex justify-center px-2 md:px-6 py-2"> <div class="w-full min-h-screen flex justify-center px-2 md:px-6 py-2">
<div class={cn("w-full mx-auto max-w-3xl space-y-3.5", rootClass)}> <div class={cn('w-full mx-auto max-w-3xl space-y-3.5', rootClass)}>
<PageHeader {showLogout} /> <PageHeader {showLogout} />
<main class={cn("py-2", className)}> <main class={cn('py-2', className)}>
<slot /> <slot />
</main> </main>
<PageFooter /> <PageFooter />

View File

@ -13,7 +13,11 @@
</div> </div>
<div class={'flex items-center gap-x-8'}> <div class={'flex items-center gap-x-8'}>
<a href={'https://github.com/shahradelahi/wireadmin'} title={'Giv me a star on Github'} class="hidden md:block"> <a
href={'https://github.com/shahradelahi/wireadmin'}
title={'Giv me a star on Github'}
class="hidden md:block"
>
<img <img
src={'https://img.shields.io/github/stars/shahradelahi/wireadmin.svg?style=social&label=Star'} src={'https://img.shields.io/github/stars/shahradelahi/wireadmin.svg?style=social&label=Star'}
alt={'Giv me a star on Github'} alt={'Giv me a star on Github'}
@ -21,8 +25,15 @@
</a> </a>
{#if showLogout} {#if showLogout}
<a href="/logout" rel="external" title="Logout" class="group text-sm/2 font-medium text-neutral-700 hover:text-neutral-800"> <a
<i class="far fa-arrow-right-from-arc text-sm text-neutral-500 group-hover:text-neutral-800 mr-0.5"></i> href="/logout"
rel="external"
title="Logout"
class="group text-sm/2 font-medium text-neutral-700 hover:text-neutral-800"
>
<i
class="far fa-arrow-right-from-arc text-sm text-neutral-500 group-hover:text-neutral-800 mr-0.5"
></i>
Logout Logout
</a> </a>
{/if} {/if}

View File

@ -8,6 +8,11 @@
export { className as class }; export { className as class };
</script> </script>
<svelte:element this={href ? 'a' : 'span'} {href} class={cn(badgeVariants({ variant, className }))} {...$$restProps}> <svelte:element
this={href ? 'a' : 'span'}
{href}
class={cn(badgeVariants({ variant, className }))}
{...$$restProps}
>
<slot /> <slot />
</svelte:element> </svelte:element>

View File

@ -8,7 +8,8 @@ export const badgeVariants = tv({
default: 'bg-primary hover:bg-primary/80 border-transparent text-primary-foreground', default: 'bg-primary hover:bg-primary/80 border-transparent text-primary-foreground',
secondary: 'bg-secondary hover:bg-secondary/80 border-transparent text-secondary-foreground', secondary: 'bg-secondary hover:bg-secondary/80 border-transparent text-secondary-foreground',
success: 'bg-green-500 hover:bg-green-500/80 border-transparent text-white', success: 'bg-green-500 hover:bg-green-500/80 border-transparent text-white',
destructive: 'bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground', destructive:
'bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground',
outline: 'text-foreground', outline: 'text-foreground',
}, },
}, },

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Button as ButtonPrimitive } from 'bits-ui'; import { Button as ButtonPrimitive } from 'bits-ui';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { buttonVariants, type Props, type Events } from '.'; import { buttonVariants, type Props, type Events } from '.';
@ -21,5 +21,5 @@
on:click on:click
on:keydown on:keydown
> >
<slot /> <slot />
</ButtonPrimitive.Root> </ButtonPrimitive.Root>

View File

@ -7,14 +7,10 @@ const buttonVariants = tv({
variants: { variants: {
variant: { variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90', default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
'bg-destructive text-destructive-foreground hover:bg-destructive/90', success: 'bg-green-500 text-white hover:bg-green-500/90 hover:text-gray-50',
success: outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
'bg-green-500 text-white hover:bg-green-500/90 hover:text-gray-50', secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
outline:
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground', ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline', link: 'text-primary underline-offset-4 hover:underline',
}, },

View File

@ -12,6 +12,10 @@
export { className as class }; export { className as class };
</script> </script>
<svelte:element this={tag} class={cn('text-lg font-semibold leading-none tracking-tight', className)} {...$$restProps}> <svelte:element
this={tag}
class={cn('text-lg font-semibold leading-none tracking-tight', className)}
{...$$restProps}
>
<slot /> <slot />
</svelte:element> </svelte:element>

View File

@ -8,6 +8,9 @@
export { className as class }; export { className as class };
</script> </script>
<div class={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)} {...$$restProps}> <div
class={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)}
{...$$restProps}
>
<slot /> <slot />
</div> </div>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Checkbox as CheckboxPrimitive } from 'bits-ui'; import { Checkbox as CheckboxPrimitive } from 'bits-ui';
import { Check, Minus } from 'lucide-svelte'; import { Check, Minus } from 'lucide-svelte';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
@ -13,22 +13,22 @@
<CheckboxPrimitive.Root <CheckboxPrimitive.Root
class={cn( class={cn(
"box-content peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50", 'box-content peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50',
className className,
)} )}
bind:checked bind:checked
{...$$restProps} {...$$restProps}
on:click on:click
> >
<CheckboxPrimitive.Indicator <CheckboxPrimitive.Indicator
class={cn("flex items-center justify-center text-current h-4 w-4")} class={cn('flex items-center justify-center text-current h-4 w-4')}
let:isChecked let:isChecked
let:isIndeterminate let:isIndeterminate
> >
{#if isChecked} {#if isChecked}
<Check class="h-3.5 w-3.5" /> <Check class="h-3.5 w-3.5" />
{:else if isIndeterminate} {:else if isIndeterminate}
<Minus class="h-3.5 w-3.5" /> <Minus class="h-3.5 w-3.5" />
{/if} {/if}
</CheckboxPrimitive.Indicator> </CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root> </CheckboxPrimitive.Root>

View File

@ -1,15 +1,15 @@
<script lang="ts"> <script lang="ts">
import { Collapsible as CollapsiblePrimitive } from "bits-ui"; import { Collapsible as CollapsiblePrimitive } from 'bits-ui';
import { slide } from "svelte/transition"; import { slide } from 'svelte/transition';
type $$Props = CollapsiblePrimitive.ContentProps; type $$Props = CollapsiblePrimitive.ContentProps;
export let transition: $$Props["transition"] = slide; export let transition: $$Props['transition'] = slide;
export let transitionConfig: $$Props["transitionConfig"] = { export let transitionConfig: $$Props['transitionConfig'] = {
duration: 150 duration: 150,
}; };
</script> </script>
<CollapsiblePrimitive.Content {transition} {transitionConfig} {...$$restProps}> <CollapsiblePrimitive.Content {transition} {transitionConfig} {...$$restProps}>
<slot /> <slot />
</CollapsiblePrimitive.Content> </CollapsiblePrimitive.Content>

View File

@ -1,15 +1,15 @@
import { Collapsible as CollapsiblePrimitive } from "bits-ui"; import { Collapsible as CollapsiblePrimitive } from 'bits-ui';
import Content from "./collapsible-content.svelte"; import Content from './collapsible-content.svelte';
const Root = CollapsiblePrimitive.Root; const Root = CollapsiblePrimitive.Root;
const Trigger = CollapsiblePrimitive.Trigger; const Trigger = CollapsiblePrimitive.Trigger;
export { export {
Root, Root,
Content, Content,
Trigger, Trigger,
// //
Root as Collapsible, Root as Collapsible,
Content as CollapsibleContent, Content as CollapsibleContent,
Trigger as CollapsibleTrigger Trigger as CollapsibleTrigger,
}; };

View File

@ -8,6 +8,9 @@
export { className as class }; export { className as class };
</script> </script>
<DialogPrimitive.Description class={cn('text-sm text-muted-foreground', className)} {...$$restProps}> <DialogPrimitive.Description
class={cn('text-sm text-muted-foreground', className)}
{...$$restProps}
>
<slot /> <slot />
</DialogPrimitive.Description> </DialogPrimitive.Description>

View File

@ -8,6 +8,9 @@
export { className as class }; export { className as class };
</script> </script>
<div class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...$$restProps}> <div
class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
{...$$restProps}
>
<slot /> <slot />
</div> </div>

View File

@ -8,6 +8,9 @@
export { className as class }; export { className as class };
</script> </script>
<DialogPrimitive.Title class={cn('text-lg font-semibold leading-none tracking-tight', className)} {...$$restProps}> <DialogPrimitive.Title
class={cn('text-lg font-semibold leading-none tracking-tight', className)}
{...$$restProps}
>
<slot /> <slot />
</DialogPrimitive.Title> </DialogPrimitive.Title>

View File

@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import * as Button from '$lib/components/ui/button'; import * as Button from '$lib/components/ui/button';
type $$Props = Button.Props; type $$Props = Button.Props;
type $$Events = Button.Events; type $$Events = Button.Events;
</script> </script>
<Button.Root type="submit" {...$$restProps} on:click on:keydown> <Button.Root type="submit" {...$$restProps} on:click on:keydown>
<slot /> <slot />
</Button.Root> </Button.Root>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import type { Checkbox as CheckboxPrimitive } from 'bits-ui'; import type { Checkbox as CheckboxPrimitive } from 'bits-ui';
import { Checkbox } from '$lib/components/ui/checkbox'; import { Checkbox } from '$lib/components/ui/checkbox';
@ -15,11 +15,11 @@
<Checkbox <Checkbox
{...rest} {...rest}
checked={typeof $value === "boolean" ? $value : false} checked={typeof $value === 'boolean' ? $value : false}
onCheckedChange={(v) => { onCheckedChange={(v) => {
onCheckedChange?.(v); onCheckedChange?.(v);
setValue(v); setValue(v);
}} }}
{...$$restProps} {...$$restProps}
on:click on:click
on:keydown on:keydown

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Form as FormPrimitive } from 'formsnap'; import { Form as FormPrimitive } from 'formsnap';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import type { HTMLAttributes } from 'svelte/elements'; import type { HTMLAttributes } from 'svelte/elements';
@ -8,9 +8,6 @@
export { className as class }; export { className as class };
</script> </script>
<FormPrimitive.Description <FormPrimitive.Description class={cn('text-sm text-muted-foreground', className)} {...$$restProps}>
class={cn("text-sm text-muted-foreground", className)} <slot />
{...$$restProps}
>
<slot />
</FormPrimitive.Description> </FormPrimitive.Description>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import type { HTMLInputAttributes } from 'svelte/elements'; import type { HTMLInputAttributes } from 'svelte/elements';
import { Input, type InputEvents } from '$lib/components/ui/input'; import { Input, type InputEvents } from '$lib/components/ui/input';

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import type { HTMLAttributes } from 'svelte/elements'; import type { HTMLAttributes } from 'svelte/elements';
type $$Props = HTMLAttributes<HTMLDivElement>; type $$Props = HTMLAttributes<HTMLDivElement>;
@ -7,6 +7,6 @@
export { className as class }; export { className as class };
</script> </script>
<div class={cn("space-y-2", className)} {...$$restProps}> <div class={cn('space-y-2', className)} {...$$restProps}>
<slot /> <slot />
</div> </div>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { Label as LabelPrimitive } from 'bits-ui'; import type { Label as LabelPrimitive } from 'bits-ui';
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { Label } from '$lib/components/ui/label'; import { Label } from '$lib/components/ui/label';
@ -12,10 +12,6 @@
const { errors, ids } = getFormField(); const { errors, ids } = getFormField();
</script> </script>
<Label <Label for={$ids.input} class={cn($errors && 'text-destructive', className)} {...$$restProps}>
for={$ids.input} <slot />
class={cn($errors && "text-destructive", className)}
{...$$restProps}
>
<slot />
</Label> </Label>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Form as FormPrimitive } from 'formsnap'; import { Form as FormPrimitive } from 'formsnap';
import { buttonVariants } from '$lib/components/ui/button'; import { buttonVariants } from '$lib/components/ui/button';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { ChevronDown } from 'lucide-svelte'; import { ChevronDown } from 'lucide-svelte';
@ -13,12 +13,12 @@
<FormPrimitive.Select <FormPrimitive.Select
class={cn( class={cn(
buttonVariants({ variant: "outline" }), buttonVariants({ variant: 'outline' }),
"appearance-none bg-transparent font-normal", 'appearance-none bg-transparent font-normal',
className className,
)} )}
{...$$restProps} {...$$restProps}
> >
<slot /> <slot />
</FormPrimitive.Select> </FormPrimitive.Select>
<ChevronDown class="absolute right-3 top-2.5 h-4 w-4 opacity-50" /> <ChevronDown class="absolute right-3 top-2.5 h-4 w-4 opacity-50" />

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import type { RadioGroup as RadioGroupPrimitive } from 'bits-ui'; import type { RadioGroup as RadioGroupPrimitive } from 'bits-ui';
import * as RadioGroup from '$lib/components/ui/radio-group'; import * as RadioGroup from '$lib/components/ui/radio-group';
@ -12,11 +12,11 @@
<RadioGroup.Root <RadioGroup.Root
{...$attrStore} {...$attrStore}
onValueChange={(v) => { onValueChange={(v) => {
onValueChange?.(v); onValueChange?.(v);
setValue(v); setValue(v);
}} }}
{...$$restProps} {...$$restProps}
> >
<slot /> <slot />
<input hidden {name} value={$value} /> <input hidden {name} value={$value} />
</RadioGroup.Root> </RadioGroup.Root>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import * as Select from '$lib/components/ui/select'; import * as Select from '$lib/components/ui/select';
import type { Select as SelectPrimitive } from 'bits-ui'; import type { Select as SelectPrimitive } from 'bits-ui';
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
@ -12,6 +12,6 @@
</script> </script>
<Select.Trigger {...$$restProps} {...$attrStore} on:click on:keydown> <Select.Trigger {...$$restProps} {...$attrStore} on:click on:keydown>
<Select.Value {placeholder} /> <Select.Value {placeholder} />
<slot /> <slot />
</Select.Trigger> </Select.Trigger>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import * as Select from '$lib/components/ui/select'; import * as Select from '$lib/components/ui/select';
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import type { Select as SelectPrimitive } from 'bits-ui'; import type { Select as SelectPrimitive } from 'bits-ui';
@ -10,11 +10,11 @@
<Select.Root <Select.Root
onSelectedChange={(v) => { onSelectedChange={(v) => {
onSelectedChange?.(v); onSelectedChange?.(v);
setValue(v ? v.value : undefined); setValue(v ? v.value : undefined);
}} }}
{...$$restProps} {...$$restProps}
> >
<slot /> <slot />
<input hidden {name} value={$value} /> <input hidden {name} value={$value} />
</Select.Root> </Select.Root>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import type { Switch as SwitchPrimitive } from 'bits-ui'; import type { Switch as SwitchPrimitive } from 'bits-ui';
import { Switch } from '$lib/components/ui/switch'; import { Switch } from '$lib/components/ui/switch';
@ -13,11 +13,11 @@
<Switch <Switch
{...$attrStore} {...$attrStore}
checked={typeof $value === "boolean" ? $value : false} checked={typeof $value === 'boolean' ? $value : false}
onCheckedChange={(v) => { onCheckedChange={(v) => {
onCheckedChange?.(v); onCheckedChange?.(v);
setValue(v); setValue(v);
}} }}
{...$$restProps} {...$$restProps}
on:click on:click
on:keydown on:keydown

View File

@ -1,11 +1,8 @@
<script lang="ts"> <script lang="ts">
import { getFormField } from 'formsnap'; import { getFormField } from 'formsnap';
import type { HTMLTextareaAttributes } from 'svelte/elements'; import type { HTMLTextareaAttributes } from 'svelte/elements';
import type { TextareaGetFormField } from '.'; import type { TextareaGetFormField } from '.';
import { import { Textarea, type TextareaEvents } from '$lib/components/ui/textarea';
Textarea,
type TextareaEvents,
} from '$lib/components/ui/textarea';
type $$Props = HTMLTextareaAttributes; type $$Props = HTMLTextareaAttributes;
type $$Events = TextareaEvents; type $$Events = TextareaEvents;

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Form as FormPrimitive } from 'formsnap'; import { Form as FormPrimitive } from 'formsnap';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import type { HTMLAttributes } from 'svelte/elements'; import type { HTMLAttributes } from 'svelte/elements';
@ -9,6 +9,6 @@
</script> </script>
<FormPrimitive.Validation <FormPrimitive.Validation
class={cn("text-sm font-medium text-destructive", className)} class={cn('text-sm font-medium text-destructive', className)}
{...$$restProps} {...$$restProps}
/> />

View File

@ -27,10 +27,7 @@ const SelectGroup = SelectComp.Group;
const SelectItem = SelectComp.Item; const SelectItem = SelectComp.Item;
const SelectSeparator = SelectComp.Separator; const SelectSeparator = SelectComp.Separator;
export type TextareaGetFormField = Omit< export type TextareaGetFormField = Omit<ReturnType<typeof getFormField>, 'value'> & {
ReturnType<typeof getFormField>,
'value'
> & {
value: Writable<string>; value: Writable<string>;
}; };

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { HTMLInputAttributes } from 'svelte/elements'; import type { HTMLInputAttributes } from 'svelte/elements';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import type { InputEvents } from '.'; import type { InputEvents } from '.';
@ -13,9 +13,9 @@
<input <input
class={cn( class={cn(
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-foreground 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", 'flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-foreground 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
on:blur on:blur
on:change on:change

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Label as LabelPrimitive } from 'bits-ui'; import { Label as LabelPrimitive } from 'bits-ui';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
type $$Props = LabelPrimitive.Props; type $$Props = LabelPrimitive.Props;
@ -11,11 +11,11 @@
<LabelPrimitive.Root <LabelPrimitive.Root
class={cn( class={cn(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
className className,
)} )}
{...$$restProps} {...$$restProps}
on:mousedown on:mousedown
> >
<slot /> <slot />
</LabelPrimitive.Root> </LabelPrimitive.Root>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { RadioGroup as RadioGroupPrimitive } from 'bits-ui'; import { RadioGroup as RadioGroupPrimitive } from 'bits-ui';
import { Circle } from 'lucide-svelte'; import { Circle } from 'lucide-svelte';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
@ -14,15 +14,15 @@
<RadioGroupPrimitive.Item <RadioGroupPrimitive.Item
{value} {value}
class={cn( class={cn(
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", 'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className className,
)} )}
{...$$restProps} {...$$restProps}
on:click on:click
> >
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
<RadioGroupPrimitive.ItemIndicator> <RadioGroupPrimitive.ItemIndicator>
<Circle class="h-2.5 w-2.5 fill-current text-current" /> <Circle class="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.ItemIndicator> </RadioGroupPrimitive.ItemIndicator>
</div> </div>
</RadioGroupPrimitive.Item> </RadioGroupPrimitive.Item>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { RadioGroup as RadioGroupPrimitive } from 'bits-ui'; import { RadioGroup as RadioGroupPrimitive } from 'bits-ui';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
type $$Props = RadioGroupPrimitive.Props; type $$Props = RadioGroupPrimitive.Props;
@ -9,10 +9,6 @@
export { className as class }; export { className as class };
</script> </script>
<RadioGroupPrimitive.Root <RadioGroupPrimitive.Root bind:value class={cn('grid gap-2', className)} {...$$restProps}>
bind:value <slot />
class={cn("grid gap-2", className)}
{...$$restProps}
>
<slot />
</RadioGroupPrimitive.Root> </RadioGroupPrimitive.Root>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui'; import { Select as SelectPrimitive } from 'bits-ui';
import { cn, flyAndScale } from '$lib/utils'; import { cn, flyAndScale } from '$lib/utils';
import { scale } from 'svelte/transition'; import { scale } from 'svelte/transition';
@ -24,13 +24,13 @@
{outTransition} {outTransition}
{outTransitionConfig} {outTransitionConfig}
class={cn( class={cn(
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md outline-none", 'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md outline-none',
className className,
)} )}
{...$$restProps} {...$$restProps}
on:keydown on:keydown
> >
<div class="w-full p-1"> <div class="w-full p-1">
<slot /> <slot />
</div> </div>
</SelectPrimitive.Content> </SelectPrimitive.Content>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { Select as SelectPrimitive } from 'bits-ui'; import { Select as SelectPrimitive } from 'bits-ui';
import { Check } from 'lucide-svelte'; import { Check } from 'lucide-svelte';
@ -18,9 +18,9 @@
{disabled} {disabled}
{label} {label}
class={cn( class={cn(
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
className className,
)} )}
{...$$restProps} {...$$restProps}
on:click on:click
on:keydown on:keydown
@ -29,10 +29,10 @@
on:pointerleave on:pointerleave
on:pointermove on:pointermove
> >
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator> <SelectPrimitive.ItemIndicator>
<Check class="h-4 w-4" /> <Check class="h-4 w-4" />
</SelectPrimitive.ItemIndicator> </SelectPrimitive.ItemIndicator>
</span> </span>
<slot /> <slot />
</SelectPrimitive.Item> </SelectPrimitive.Item>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui'; import { Select as SelectPrimitive } from 'bits-ui';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
type $$Props = SelectPrimitive.LabelProps; type $$Props = SelectPrimitive.LabelProps;
@ -9,8 +9,8 @@
</script> </script>
<SelectPrimitive.Label <SelectPrimitive.Label
class={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} class={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)}
{...$$restProps} {...$$restProps}
> >
<slot /> <slot />
</SelectPrimitive.Label> </SelectPrimitive.Label>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui'; import { Select as SelectPrimitive } from 'bits-ui';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
type $$Props = SelectPrimitive.SeparatorProps; type $$Props = SelectPrimitive.SeparatorProps;
@ -8,7 +8,4 @@
export { className as class }; export { className as class };
</script> </script>
<SelectPrimitive.Separator <SelectPrimitive.Separator class={cn('-mx-1 my-1 h-px bg-muted', className)} {...$$restProps} />
class={cn("-mx-1 my-1 h-px bg-muted", className)}
{...$$restProps}
/>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui'; import { Select as SelectPrimitive } from 'bits-ui';
import { ChevronDown } from 'lucide-svelte'; import { ChevronDown } from 'lucide-svelte';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
@ -12,16 +12,16 @@
<SelectPrimitive.Trigger <SelectPrimitive.Trigger
class={cn( class={cn(
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", 'flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
className className,
)} )}
{...$$restProps} {...$$restProps}
let:builder let:builder
on:click on:click
on:keydown on:keydown
> >
<slot {builder} /> <slot {builder} />
<div> <div>
<ChevronDown class="h-4 w-4 opacity-50" /> <ChevronDown class="h-4 w-4 opacity-50" />
</div> </div>
</SelectPrimitive.Trigger> </SelectPrimitive.Trigger>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui'; import { Select as SelectPrimitive } from 'bits-ui';
type $$Props = SelectPrimitive.Props; type $$Props = SelectPrimitive.Props;
@ -8,5 +8,5 @@
</script> </script>
<SelectPrimitive.Root bind:selected bind:open {...$$restProps}> <SelectPrimitive.Root bind:selected bind:open {...$$restProps}>
<slot /> <slot />
</SelectPrimitive.Root> </SelectPrimitive.Root>

View File

@ -1,7 +1,7 @@
import Root from "./skeleton.svelte"; import Root from './skeleton.svelte';
export { export {
Root, Root,
// //
Root as Skeleton Root as Skeleton,
}; };

View File

@ -1,14 +1,11 @@
<script lang="ts"> <script lang="ts">
import { cn } from "$lib/utils"; import { cn } from '$lib/utils';
import type { HTMLAttributes } from "svelte/elements"; import type { HTMLAttributes } from 'svelte/elements';
type $$Props = HTMLAttributes<HTMLDivElement>; type $$Props = HTMLAttributes<HTMLDivElement>;
let className: $$Props["class"] = undefined; let className: $$Props['class'] = undefined;
export { className as class }; export { className as class };
</script> </script>
<div <div class={cn('animate-pulse rounded-md bg-muted', className)} {...$$restProps} />
class={cn("animate-pulse rounded-md bg-muted", className)}
{...$$restProps}
/>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Switch as SwitchPrimitive } from 'bits-ui'; import { Switch as SwitchPrimitive } from 'bits-ui';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
type $$Props = SwitchPrimitive.Props; type $$Props = SwitchPrimitive.Props;
@ -12,14 +12,14 @@
<SwitchPrimitive.Root <SwitchPrimitive.Root
bind:checked bind:checked
class={cn( class={cn(
"peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", 'peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
className className,
)} )}
{...$$restProps} {...$$restProps}
> >
<SwitchPrimitive.Thumb <SwitchPrimitive.Thumb
class={cn( class={cn(
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0" 'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
)} )}
/> />
</SwitchPrimitive.Root> </SwitchPrimitive.Root>

View File

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { HTMLTextareaAttributes } from 'svelte/elements'; import type { HTMLTextareaAttributes } from 'svelte/elements';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
type $$Props = HTMLTextareaAttributes; type $$Props = HTMLTextareaAttributes;
@ -11,9 +11,9 @@
<textarea <textarea
class={cn( class={cn(
"flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background 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", 'flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background 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
on:blur on:blur
on:change on:change

View File

@ -35,7 +35,10 @@ export default class Network {
public static async getInUsePorts(): Promise<number[]> { public static async getInUsePorts(): Promise<number[]> {
const ports = []; const ports = [];
const output = await Shell.exec(`netstat -tulpn | grep LISTEN | awk '{print $4}' | awk -F ':' '{print $NF}'`, true); const output = await Shell.exec(
`netstat -tulpn | grep LISTEN | awk '{print $4}' | awk -F ':' '{print $NF}'`,
true,
);
for (const line of output.split('\n')) { for (const line of output.split('\n')) {
const clean = Number(line.trim()); const clean = Number(line.trim());
if (!isNaN(clean)) ports.push(clean); if (!isNaN(clean)) ports.push(clean);

View File

@ -2,7 +2,11 @@ import { exec } from 'child_process';
import logger from '$lib/logger'; import logger from '$lib/logger';
export default class Shell { export default class Shell {
public static async exec(command: string, safe: boolean = false, ...args: string[]): Promise<string> { public static async exec(
command: string,
safe: boolean = false,
...args: string[]
): Promise<string> {
if (process.platform !== 'linux') { if (process.platform !== 'linux') {
throw new Error('This program is not meant to run non UNIX systems'); throw new Error('This program is not meant to run non UNIX systems');
} }

View File

@ -77,9 +77,8 @@ export type APISuccessResponse<D> = {
}; };
export type SafeReturn<T, K = any> = LeastOne<{ export type SafeReturn<T, K = any> = LeastOne<{
data: T, data: T;
error: K error: K;
}> }>;
export type LeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U]; export type LeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];

View File

@ -531,7 +531,10 @@ export async function isIPReserved(ip: string): Promise<boolean> {
} }
export async function isPortReserved(port: number): Promise<boolean> { export async function isPortReserved(port: number): Promise<boolean> {
const inUsePorts = [await Network.getInUsePorts(), (await getServers()).map((s) => Number(s.listen))].flat(); const inUsePorts = [
await Network.getInUsePorts(),
(await getServers()).map((s) => Number(s.listen)),
].flat();
return inUsePorts.includes(port); return inUsePorts.includes(port);
} }
@ -594,7 +597,10 @@ export async function findServerIndex(id: string): Promise<number | undefined> {
return undefined; return undefined;
} }
export async function findServer(id: string | undefined, hash?: string): Promise<WgServer | undefined> { export async function findServer(
id: string | undefined,
hash?: string,
): Promise<WgServer | undefined> {
const servers = await getServers(); const servers = await getServers();
return id return id
? servers.find((s) => s.id === id) ? servers.find((s) => s.id === id)
@ -660,7 +666,9 @@ export async function genServerConf(server: WgServer): Promise<string> {
lines.push(`PublicKey = ${peer.publicKey}`); lines.push(`PublicKey = ${peer.publicKey}`);
lines.push(`${peer.preSharedKey ? `PresharedKey = ${peer.preSharedKey}` : 'OMIT'}`); lines.push(`${peer.preSharedKey ? `PresharedKey = ${peer.preSharedKey}` : 'OMIT'}`);
lines.push(`AllowedIPs = ${peer.allowedIps}/32`); lines.push(`AllowedIPs = ${peer.allowedIps}/32`);
lines.push(`${peer.persistentKeepalive ? `PersistentKeepalive = ${peer.persistentKeepalive}` : 'OMIT'}`); lines.push(
`${peer.persistentKeepalive ? `PersistentKeepalive = ${peer.persistentKeepalive}` : 'OMIT'}`,
);
}); });
return lines.filter((l) => l !== 'OMIT').join('\n'); return lines.filter((l) => l !== 'OMIT').join('\n');

View File

@ -32,9 +32,7 @@ export const PortSchema = z
}, },
); );
export const TorSchema = z export const TorSchema = z.boolean().default(false);
.boolean()
.default(false);
export const DnsSchema = z export const DnsSchema = z
.string() .string()

View File

@ -3,4 +3,4 @@
import '$lib/assets/fontawesome/index.css'; import '$lib/assets/fontawesome/index.css';
</script> </script>
<slot /> <slot />

View File

@ -1,6 +1,13 @@
import { type Actions, error } from '@sveltejs/kit'; import { type Actions, error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types'; import type { PageServerLoad } from './$types';
import { findServer, generateWgServer, getServers, isIPReserved, isPortReserved, WGServer } from '$lib/wireguard'; import {
findServer,
generateWgServer,
getServers,
isIPReserved,
isPortReserved,
WGServer,
} from '$lib/wireguard';
import { setError, superValidate } from 'sveltekit-superforms/server'; import { setError, superValidate } from 'sveltekit-superforms/server';
import { CreateServerSchema } from './schema'; import { CreateServerSchema } from './schema';
import { NameSchema } from '$lib/wireguard/schema'; import { NameSchema } from '$lib/wireguard/schema';

View File

@ -22,7 +22,11 @@
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { FormItem } from '$lib/components/ui/form/index.js'; import { FormItem } from '$lib/components/ui/form/index.js';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '$lib/components/ui/collapsible'; import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '$lib/components/ui/collapsible';
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
let loading: boolean = false; let loading: boolean = false;
@ -84,7 +88,9 @@
<FormItem> <FormItem>
<FormLabel>Port</FormLabel> <FormLabel>Port</FormLabel>
<FormInput placeholder={'e.g. 51820'} type={'text'} /> <FormInput placeholder={'e.g. 51820'} type={'text'} />
<FormDescription>This is the port that the WireGuard server will listen on.</FormDescription> <FormDescription
>This is the port that the WireGuard server will listen on.</FormDescription
>
<FormValidation /> <FormValidation />
</FormItem> </FormItem>
</FormField> </FormField>
@ -112,7 +118,9 @@
<FormItem> <FormItem>
<FormLabel>DNS</FormLabel> <FormLabel>DNS</FormLabel>
<FormInput placeholder={'e.g. 1.1.1.1'} type={'text'} /> <FormInput placeholder={'e.g. 1.1.1.1'} type={'text'} />
<FormDescription>Optional. This is the DNS server that will be pushed to clients.</FormDescription> <FormDescription
>Optional. This is the DNS server that will be pushed to clients.</FormDescription
>
<FormValidation /> <FormValidation />
</FormItem> </FormItem>
</FormField> </FormField>
@ -130,7 +138,8 @@
<DialogFooter> <DialogFooter>
<FormButton> <FormButton>
<i class={cn(loading ? 'far fa-arrow-rotate-right animate-spin' : 'far fa-plus', 'mr-2')}></i> <i class={cn(loading ? 'far fa-arrow-rotate-right animate-spin' : 'far fa-plus', 'mr-2')}
></i>
Create Create
</FormButton> </FormButton>
</DialogFooter> </DialogFooter>

View File

@ -17,9 +17,14 @@
<div class="flex items-center justify-between p-4 gap-x-4"> <div class="flex items-center justify-between p-4 gap-x-4">
<div class="w-full md:w-2/3 flex items-center gap-x-2"> <div class="w-full md:w-2/3 flex items-center gap-x-2">
<div class="flex grow"> <div class="flex grow">
<div class={'w-12 aspect-square flex items-center justify-center mr-4 rounded-full bg-gray-200 max-md:hidden'}> <div
class={'w-12 aspect-square flex items-center justify-center mr-4 rounded-full bg-gray-200 max-md:hidden'}
>
<i <i
class={cn(server.tor ? 'fa-solid fa-onion text-purple-700' : 'fa-solid fa-server text-gray-400', 'text-xl')} class={cn(
server.tor ? 'fa-solid fa-onion text-purple-700' : 'fa-solid fa-server text-gray-400',
'text-xl',
)}
/> />
</div> </div>
@ -36,7 +41,9 @@
asChild asChild
> >
<a href={`/${server.id}`} title="Manage the Server" class={cn({ hidden: editMode })}> <a href={`/${server.id}`} title="Manage the Server" class={cn({ hidden: editMode })}>
<span class="text-lg md:text-base hover:text-primary hover:font-medium"> {server.name} </span> <span class="text-lg md:text-base hover:text-primary hover:font-medium">
{server.name}
</span>
</a> </a>
</EditableText> </EditableText>
<CopiableText value={addressPort} class="text-sm" showInHover={true}> <CopiableText value={addressPort} class="text-sm" showInHover={true}>

View File

@ -9,7 +9,14 @@
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from '$lib/components/ui/dialog'; } from '$lib/components/ui/dialog';
import { Form, FormButton, FormField, FormInput, FormLabel, FormValidation } from '$lib/components/ui/form'; import {
Form,
FormButton,
FormField,
FormInput,
FormLabel,
FormValidation,
} from '$lib/components/ui/form';
import { FormItem } from '$lib/components/ui/form/index.js'; import { FormItem } from '$lib/components/ui/form/index.js';
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { invalidateAll } from '$app/navigation'; import { invalidateAll } from '$app/navigation';
@ -70,7 +77,8 @@
<DialogFooter> <DialogFooter>
<FormButton> <FormButton>
<i class={cn(loading ? 'far fa-arrow-rotate-right animate-spin' : 'far fa-plus', 'mr-2')}></i> <i class={cn(loading ? 'far fa-arrow-rotate-right animate-spin' : 'far fa-plus', 'mr-2')}
></i>
Create Create
</FormButton> </FormButton>
</DialogFooter> </DialogFooter>

View File

@ -35,7 +35,7 @@
return; return;
} }
// create a blob // create a blob
const blob = new Blob([ conf ], { type: 'text/plain' }); const blob = new Blob([conf], { type: 'text/plain' });
// create a link // create a link
const link = document.createElement('a'); const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
@ -55,9 +55,13 @@
}; };
</script> </script>
<div class="flex items-center justify-between p-4 border border-neutral-200/60 rounded-md hover:border-neutral-200"> <div
class="flex items-center justify-between p-4 border border-neutral-200/60 rounded-md hover:border-neutral-200"
>
<div class="flex items-center gap-x-2"> <div class="flex items-center gap-x-2">
<div class={'w-12 aspect-square flex items-center justify-center mr-4 rounded-full bg-gray-200 max-md:hidden'}> <div
class={'w-12 aspect-square flex items-center justify-center mr-4 rounded-full bg-gray-200 max-md:hidden'}
>
<i class={'fas fa-user text-gray-400 text-lg'} /> <i class={'fas fa-user text-gray-400 text-lg'} />
</div> </div>

View File

@ -2,7 +2,10 @@ import type { RequestHandler } from '@sveltejs/kit';
import QRCode from 'qrcode'; import QRCode from 'qrcode';
export const POST: RequestHandler = async ({ request }) => { export const POST: RequestHandler = async ({ request }) => {
if (!request.headers.has('Content-Type') || request.headers.get('Content-Type') !== 'text/plain') { if (
!request.headers.has('Content-Type') ||
request.headers.get('Content-Type') !== 'text/plain'
) {
return new Response(null, { status: 400, headers: { 'Content-Type': 'text/plain' } }); return new Response(null, { status: 400, headers: { 'Content-Type': 'text/plain' } });
} }

View File

@ -2,7 +2,15 @@
import { formSchema, type FormSchema } from './schema'; import { formSchema, type FormSchema } from './schema';
import type { SuperValidated } from 'sveltekit-superforms'; import type { SuperValidated } from 'sveltekit-superforms';
import { Card, CardContent } from '$lib/components/ui/card'; import { Card, CardContent } from '$lib/components/ui/card';
import { Form, FormButton, FormField, FormInput, FormItem, FormLabel, FormValidation } from '$lib/components/ui/form'; import {
Form,
FormButton,
FormField,
FormInput,
FormItem,
FormLabel,
FormValidation,
} from '$lib/components/ui/form';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import type { FormOptions } from 'formsnap'; import type { FormOptions } from 'formsnap';

View File

@ -1,5 +1,12 @@
import { z } from 'zod'; import { z } from 'zod';
import { AddressSchema, DnsSchema, MtuSchema, NameSchema, PortSchema, TorSchema } from '$lib/wireguard/schema'; import {
AddressSchema,
DnsSchema,
MtuSchema,
NameSchema,
PortSchema,
TorSchema,
} from '$lib/wireguard/schema';
export const CreateServerSchema = z.object({ export const CreateServerSchema = z.object({
name: NameSchema, name: NameSchema,

View File

@ -2,16 +2,16 @@ import { fontFamily } from 'tailwindcss/defaultTheme';
/** @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}'],
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: {
@ -22,43 +22,43 @@ const config = {
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>)',
} },
}, },
borderRadius: { borderRadius: {
lg: 'var(--radius)', lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)', md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)' sm: 'calc(var(--radius) - 4px)',
}, },
fontFamily: { fontFamily: {
sans: [ ...fontFamily.sans ] sans: [...fontFamily.sans],
} },
} },
} },
}; };
export default config; export default config;

View File

@ -1,8 +1,8 @@
import { sveltekit } from '@sveltejs/kit/vite'; import { sveltekit } from '@sveltejs/kit/vite';
export default { export default {
plugins: [ sveltekit() ], plugins: [sveltekit()],
test: { test: {
include: [ 'src/**/*.{test,spec}.{js,ts}' ] include: ['src/**/*.{test,spec}.{js,ts}'],
} },
}; };