Vue init (#47)

This commit is contained in:
Geometrically
2023-02-27 09:11:34 -07:00
committed by GitHub
parent e591b7120a
commit c204caa350
58 changed files with 727 additions and 6666 deletions

9
theseus_gui/src/App.vue Normal file
View File

@@ -0,0 +1,9 @@
<script setup></script>
<template>
<div class="container">
<h1>Modrinth</h1>
</div>
</template>
<style scoped></style>

View File

@@ -1,13 +0,0 @@
/// <reference types="@sveltejs/kit" />
// See https://kit.svelte.dev/docs/typescript
// for information about these interfaces
declare namespace App {
interface Locals {}
interface Platform {}
interface Session {}
interface Stuff {}
}

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preload" href="/fonts/InterRegular.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/InterBold.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/InterSemiBold.woff2" as="font" type="font/woff2" crossorigin />
%sveltekit.head%
</head>
<body class="base theme-dark" style="background-color: hsl(220, 13%, 15%)">
%sveltekit.body%
</body>
</html>

View File

@@ -1,53 +0,0 @@
<script lang="ts">
export let title: string;
</script>
<div class="card-row">
<div class="card-row__title">{title}</div>
<div class="card-row__items">
<slot />
</div>
</div>
<style lang="postcss">
.card-row {
display: flex;
flex-direction: column;
padding: 1rem 0;
grid-gap: 1rem;
&__title {
padding: 0 1rem;
display: flex;
grid-gap: 1rem;
align-items: center;
&::after {
flex: 1 1;
content: ' ';
background-color: hsla(0, 0%, 100%, 0.2);
height: 0.2rem;
border-radius: var(--rounded-max);
}
}
&__items {
display: flex;
grid-gap: 1rem;
align-items: flex-start;
overflow-x: auto;
padding: 0 1rem;
/* Hide scrollbar */
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
&:nth-of-type(even) {
background-color: hsla(0, 0%, 0%, 0.2);
}
}
</style>

View File

@@ -1,59 +0,0 @@
<script lang="ts">
import { Field, Slider, TextInput, Button } from 'omorphia';
import TitledSection from '$components/TitledSection.svelte';
import WindowSettings from '$components/WindowSettings.svelte';
export let maxConcurrentDownloads: number = 20;
</script>
<div class="section">
<TitledSection title="Downloads">
<Field label="Max concurrent downloads">
<Slider min="1" max="64" bind:value={maxConcurrentDownloads} />
</Field>
</TitledSection>
<TitledSection title="Override game resolution" toggleable="true">
<WindowSettings />
</TitledSection>
<TitledSection title="Profile hooks">
<Field label="Pre-launch">
<TextInput />
</Field>
<Field label="Wrapper">
<TextInput />
</Field>
<Field label="Post-exit">
<TextInput />
</Field>
</TitledSection>
<TitledSection title="Java">
<Field label="Java 8 installation">
<TextInput placeholder="/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home" />
<div class="button-group">
<Button>Auto-detect</Button>
<Button>Browse installations</Button>
<Button>Test</Button>
</div>
</Field>
<Field label="Java 17 installation">
<TextInput placeholder="/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home" />
<div class="button-group">
<Button>Auto-detect</Button>
<Button>Browse installations</Button>
<Button>Test</Button>
</div>
</Field>
<Field label="Minimum memory allocatted (in MB)">
<TextInput />
</Field>
<Field label="Maximum memory allocatted (in MB)">
<TextInput value="2048" />
</Field>
<Field label="Arguments">
<TextInput />
</Field>
</TitledSection>
</div>
<style lang="postcss">
</style>

View File

@@ -1,90 +0,0 @@
<script lang="ts">
import IconPlayFilled from 'virtual:icons/carbon/play-filled-alt';
import IconBadgeCheck from 'virtual:icons/heroicons-solid/badge-check';
export let title: string;
export let id: string;
export let version: string;
export let modpack = false;
export let image: string;
</script>
<a
class="instance"
href="/library/instance/{id}/settings"
style:background-image="linear-gradient(5deg, hsla(0,0%,0%,0.8) 0%, hsla(0,0%,0%,0) 100%), url('{image}')"
>
<div class="instance__version">
{version}{#if modpack}<IconBadgeCheck />{/if}
</div>
<div class="instance__title">{title}</div>
<button class="play-button">
<IconPlayFilled />
</button>
</a>
<style lang="postcss">
.instance {
--size: 8rem;
min-width: var(--size);
min-height: var(--size);
border-radius: var(--rounded);
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding: 0.5rem;
box-shadow: var(--shadow-raised) var(--shadow-inset);
position: relative;
background-size: cover;
&__title {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
&__version {
color: var(--color-text);
font-size: var(--font-size-sm);
display: flex;
align-items: center;
grid-gap: 0.15rem;
:global(svg) {
margin-bottom: 0.05rem;
}
}
&:hover .play-button {
visibility: visible;
opacity: 1;
transform: none;
}
.play-button {
position: absolute;
bottom: 0.5rem;
right: 0.5rem;
background-color: var(--color-brand);
width: 2.5rem;
aspect-ratio: 1 / 1;
border-radius: var(--rounded-max);
display: flex;
align-items: center;
justify-content: center;
visibility: hidden;
opacity: 0;
transition-property: opacity, visibility, transform;
transition-duration: 0.2s;
transition-timing-function: ease-in-out;
transform: translateY(1rem);
:global(svg) {
width: 1.25rem;
height: auto;
color: black;
}
}
}
</style>

View File

@@ -1,130 +0,0 @@
<script lang="ts">
import { t } from 'svelte-intl-precompile';
import IconHeart from 'virtual:icons/lucide/heart';
import IconDownload from 'virtual:icons/heroicons-outline/download';
import IconCalendar from 'virtual:icons/lucide/calendar';
import { ago } from 'omorphia/utils';
import { simplify } from '$lib/number';
import { Avatar, Button } from 'omorphia';
import { tagIcons } from '$generated/tags.json';
export let project;
// @ts-ignore: Author is only available in the result
let author = project.author ?? '';
// @ts-ignore: ID is in different locations in the result and project
let id = project.id ?? project.project_id;
// @ts-ignore: Updated is in different locations in the result and project
let updated = project.date_modified ?? project.updated;
const href = `/${project.project_type}/${project.slug || id}`;
</script>
<div class="card project-card">
<a {href} tabindex="-1">
<Avatar src={project.icon_url} size="md" />
</a>
<div class="project-card__info">
<div class="project-card__info__top">
<div class="project-card__info__top__text">
<span
><a class="project-card__info__top__text__title" {href}>{project.title}</a>
{#if author}
<a href="/user/{author}" class="project-card__info__top__text__author"
>{@html $t('generic.byline', { values: { author } })}</a
>
{/if}
</span>
<p class="summary">
{project.description}
</p>
</div>
<div class="button-group">
<Button color="primary"><IconDownload />Install</Button>
</div>
</div>
<div class="tag-group">
{#each project.categories as category}
<div class="tag">
{@html tagIcons[category] || '?'}
{$t(`tags.${category}`)}
</div>
{/each}
<span class="stat">
<IconDownload />
<b>{simplify(project.downloads)}</b>
</span>
<span class="tag">
<IconCalendar />
{@html $t('stats.updated', { values: { ago: ago(updated) } })}
</span>
</div>
</div>
{#if !$$slots.actions}{:else}
<slot name="actions" />
{/if}
</div>
<style lang="postcss">
.project-card {
flex-direction: row;
flex-wrap: nowrap;
padding: 10px;
grid-gap: 1rem;
&__info {
display: flex;
flex-direction: column;
grid-gap: 0.25rem;
line-height: 100%;
margin-top: 0.2rem;
width: 100%;
&__top {
display: flex;
gap: 16px;
&__text {
display: flex;
flex-direction: column;
gap: 4px;
&__title {
font-weight: bold;
font-size: 16px;
}
&__author {
white-space: nowrap;
font-size: 12px;
}
.summary {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: calc(100vw - 224px - 24px - 16px - 64px - 130px);
}
}
:global(.button-group) {
margin-left: auto;
height: 33px;
}
}
.tag-group {
.stat {
margin-left: auto;
}
}
}
}
</style>

View File

@@ -1,49 +0,0 @@
<script lang="ts">
import { Checkbox } from 'omorphia';
export let title: string;
export let toggleable: boolean = false;
export let enabled: boolean = false;
</script>
<div class="section">
<div class="section__title">
{#if toggleable}<Checkbox bind:checked={enabled}>{title}</Checkbox>
{:else}{title}
{/if}
</div>
<div class="section__items">
{#if !toggleable || enabled}<slot />{/if}
</div>
</div>
<style lang="postcss">
.section {
display: flex;
flex-direction: column;
padding: 1rem;
grid-gap: 1rem;
&__title {
display: flex;
grid-gap: 1rem;
align-items: center;
&::after {
flex: 1 1;
content: ' ';
background-color: hsla(0, 0%, 100%, 0.2);
height: 0.2rem;
border-radius: var(--rounded-max);
}
}
&__items {
display: flex;
flex-direction: column;
grid-gap: 1rem;
padding: 0 8px;
}
}
</style>

View File

@@ -1,39 +0,0 @@
<script lang="ts">
import type { SvelteComponent } from 'svelte';
import { page } from '$app/stores';
export let items: {
label: string;
/** Page href, without slash prefix */
href: string;
icon: SvelteComponent;
}[];
/** Path level in URL, zero-indexed */
export let level = 0;
let path: string[];
$: path = $page.url.pathname.substring(1).split('/');
</script>
<div class="vertical-nav">
{#each items as item (item.href)}
<a
class="nav-item"
href="/{item.href}"
class:active={path[level] === item.href}
sveltekit:prefetch
>
<svelte:component this={item.icon} />
{item.label}
</a>
{/each}
</div>
<style lang="postcss">
.vertical-nav {
display: flex;
flex-direction: column;
grid-gap: 0.25rem;
}
</style>

View File

@@ -1,15 +0,0 @@
<script lang="ts">
import { Field, TextInput } from 'omorphia';
</script>
<div class="section">
<Field label="Window width">
<TextInput />
</Field>
<Field label="Window height">
<TextInput />
</Field>
</div>
<style lang="postcss">
</style>

View File

@@ -1,13 +0,0 @@
/// <reference types="@sveltejs/kit" />
/// <reference types="unplugin-icons/types/svelte" />
declare module '$assets/images/*' {
export { SvelteComponentDev as default } from 'svelte/internal';
}
declare module '$locales/*';
declare module '*.svg' {
import { SvelteComponent } from 'svelte';
const content: SvelteComponent;
export default content;
}

View File

@@ -1,6 +0,0 @@
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
return await resolve(event, {
ssr: false
});
}

View File

@@ -1,55 +0,0 @@
<script lang="ts">
import { Svrollbar } from 'svrollbar';
let viewport: Element;
let contents: Element;
</script>
<div class="page">
<div bind:this={viewport} class="viewport">
<div bind:this={contents} class="contents">
<slot />
</div>
</div>
<Svrollbar {viewport} {contents} />
</div>
<style lang="postcss">
.page {
position: relative;
width: 100%;
overflow: hidden;
--svrollbar-track-width: 20px;
--svrollbar-track-opacity: 0;
--svrollbar-thumb-width: 8px;
--svrollbar-thumb-background: hsla(216, 5%, 60%);
--svrollbar-thumb-opacity: 0.9;
}
.viewport {
position: relative;
width: 100%;
height: calc(100vh - 2.5rem);
overflow-y: scroll;
overflow-x: hidden;
/* hide scrollbar */
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
/* hide scrollbar */
display: none;
}
.contents {
height: 100%;
}
}
:global(.v-thumb) {
margin: 4px auto 4px auto !important;
}
</style>

View File

@@ -1,188 +0,0 @@
<script lang="ts">
import VerticalNav from '../components/VerticalNav.svelte';
import IconHome from 'virtual:icons/lucide/home';
import IconSearch from 'virtual:icons/heroicons-outline/search';
import IconPlus from 'virtual:icons/heroicons-outline/plus';
import IconLibrary from 'virtual:icons/lucide/library';
import IconSettings from 'virtual:icons/lucide/settings';
import { page } from '$app/stores';
import { Button } from 'omorphia';
</script>
<div class="sidebar">
<div class="account">
<div class="account__heads">
<img src="https://mc-heads.net/avatar/venashial" alt="Minecraft head" />
</div>
<a class="account__info" href="/settings/accounts">
<div>venashial</div>
<div class="account__info__manage">Manage accounts</div>
</a>
</div>
<VerticalNav
items={[
{
label: 'Home',
href: '',
icon: IconHome
},
{
label: 'Search',
href: 'search',
icon: IconSearch
},
{
label: 'Library',
href: 'library',
icon: IconLibrary
}
]}
/>
<div class="instance-list">
<div class="instance-list__title">Instances</div>
<div class="instance-list__container">
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
<a class="instance-list__container__item">Fabulously Optimized</a>
</div>
<div class="instance-list__create">
<Button color="primary"><IconPlus /></Button> Create instance
</div>
</div>
<a class="nav-item" href="/settings" class:active={$page.url.pathname.startsWith('/settings')}>
<IconSettings />
Settings
</a>
</div>
<style lang="postcss">
.sidebar {
display: flex;
flex-direction: column;
padding: 1rem;
height: 100%;
background-color: var(--sidebar-bg);
.account {
display: flex;
grid-gap: 0.75rem;
&__heads {
img {
width: 2.5rem;
border-radius: var(--rounded-sm);
}
}
&__info {
&__manage {
color: var(--color-text-light);
}
}
}
.instance-list {
padding: 0 8px;
display: flex;
flex-direction: column;
color: var(--color-text-light);
&__title {
text-transform: uppercase;
letter-spacing: 1px;
font-size: 11px;
line-height: 100%;
}
&__container {
max-height: calc(100vh - 400px);
overflow-y: auto;
mask-image: linear-gradient(to bottom, transparent, hsla(0, 0%, 0%, 1) 5% 95%, transparent);
scrollbar-width: none;
padding: 8px 0;
display: flex;
flex-direction: column;
gap: 4px;
&::-webkit-scrollbar {
display: none;
}
}
&__create {
margin-top: 16px;
display: flex;
align-items: center;
grid-gap: 8px;
&__title {
text-transform: uppercase;
letter-spacing: 1px;
font-size: 11px;
line-height: 100%;
}
}
&__container {
max-height: calc(100vh - 400px);
overflow-y: auto;
mask-image: linear-gradient(to bottom, transparent, hsla(0, 0%, 0%, 1) 5% 95%, transparent);
scrollbar-width: none;
padding: 8px 0;
display: flex;
flex-direction: column;
gap: 4px;
&::-webkit-scrollbar {
display: none;
}
}
&__create {
margin-top: 16px;
display: flex;
align-items: center;
grid-gap: 8px;
:global(button) {
width: 32px;
}
}
}
> :global(*) {
margin-bottom: 24px;
}
> *:last-child {
margin-top: auto;
margin-bottom: 0;
}
:global(button) {
width: 34px;
}
> :global(*) {
margin-bottom: 24px;
}
> *:last-child {
margin-top: auto;
margin-bottom: 0;
}
}
</style>

View File

@@ -1,91 +0,0 @@
<script lang="ts">
import IconChevronLeft from 'virtual:icons/lucide/chevron-left';
import IconChevronRight from 'virtual:icons/lucide/chevron-right';
import IconCaretRight from 'virtual:icons/carbon/caret-right';
import { page } from '$app/stores';
let path: string[];
$: path = $page.url.pathname.substring(1).split('/');
</script>
<div class="status-bar">
<div class="page-nav">
<button title="Back" on:click={() => window.history.back()}>
<IconChevronLeft />
</button>
<button title="Forward" on:click={() => window.history.forward()}>
<IconChevronRight />
</button>
</div>
<div class="breadcrumbs">
{#each path as crumb, index}
{#if index !== 0}
<IconCaretRight />
{/if}
<a class="breadcrumbs__crumb" href={crumb}>{crumb || 'home'}</a>
{/each}
</div>
<div class="statuses">
<div>Updating 12 mods...</div>
<div>236 mods installed</div>
</div>
</div>
<style lang="postcss">
.status-bar {
display: flex;
padding: 0.75rem;
grid-gap: 0.75rem;
background-color: var(--status-bg);
width: 100%;
height: 100%;
align-items: center;
box-shadow: var(--shadow-raised);
.page-nav {
display: flex;
gap: 2px;
button {
display: flex;
}
}
.breadcrumbs {
display: flex;
grid-gap: 0.25rem;
text-transform: capitalize;
align-items: center;
overflow-x: auto;
/* Hide scrollbar */
&::-webkit-scrollbar {
display: none; /* Chrome, Safari and Opera */
}
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
&__crumb:hover {
text-decoration: underline;
}
:global(.icon) {
color: var(--color-text-lightest);
}
}
.statuses {
margin-left: auto;
align-items: flex-end;
justify-content: flex-end;
display: flex;
grid-gap: 1rem;
color: var(--color-text-lightest);
font-size: 13px;
line-height: 1.2;
text-align: right;
}
}
</style>

View File

@@ -1,40 +0,0 @@
/**
* Convert large numbers to human readable strings
* @source https://github.com/rohmanhm/simplify-number
*/
export function simplify(num = 0): string {
let numberVar = num;
// 2 decimal places => 100, 3 => 1000, etc
const decPlaces = Math.pow(10, 1);
// Enumerate number abbreviations
const abbrev = ['K', 'M', 'B', 'T'];
// Go through the array backwards, so we do the largest first
for (let i = abbrev.length - 1; i >= 0; i--) {
// Convert array index to "1000", "1000000", etc
const size = Math.pow(10, (i + 1) * 3);
// If the number is bigger or equal do the abbreviation
if (size <= numberVar) {
// Here, we multiply by decPlaces, round, and then divide by decPlaces.
// This gives us nice rounding to a particular decimal place.
numberVar = Math.round((numberVar * decPlaces) / size) / decPlaces;
// Handle special case where we round up to the next abbreviation
if (numberVar === 1000 && i < abbrev.length - 1) {
numberVar = 1;
i++;
}
// Add the letter for the abbreviation
(numberVar as any) += abbrev[i];
// We are done... stop
break;
}
}
return String(numberVar);
}

5
theseus_gui/src/main.js Normal file
View File

@@ -0,0 +1,5 @@
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
createApp(App).mount("#app");

View File

@@ -1,58 +0,0 @@
<script context="module" lang="ts">
import { init, waitLocale, t, getLocaleFromAcceptLanguageHeader } from 'svelte-intl-precompile';
import { registerAll, availableLocales } from '$locales';
registerAll();
export const load: import('@sveltejs/kit').Load = async ({ session }) => {
init({
fallbackLocale: 'en',
initialLocale: getLocaleFromAcceptLanguageHeader(session.acceptLanguage, availableLocales)
});
await waitLocale();
return {};
};
</script>
<script lang="ts">
import '@fontsource/inter';
import 'omorphia/styles.postcss';
import '$styles/global.postcss';
import Sidebar from '$layout/Sidebar.svelte';
import StatusBar from '$layout/StatusBar.svelte';
import Page from '$layout/Page.svelte';
</script>
<div class="app base theme-dark">
<Sidebar />
<StatusBar />
<Page>
<slot />
</Page>
</div>
<style lang="postcss">
.app {
height: 100%;
width: 100%;
display: grid;
grid-template-areas:
'sidebar status-bar'
'sidebar page';
grid-template-rows: 2.5rem 1fr;
grid-template-columns: 14rem 1fr;
}
:global(.page) {
grid-area: page;
}
:global(.sidebar) {
grid-area: sidebar;
}
:global(.status-bar) {
grid-area: status-bar;
}
</style>

View File

@@ -1,41 +0,0 @@
<script lang="ts">
import Instance from '$components/Instance.svelte';
import CardRow from '$components/CardRow.svelte';
</script>
<CardRow title="Jump back in">
{#each Array(5) as _, i}
<Instance
title="New Caves"
id="234"
version="1.18"
image="https://i.ibb.co/8KDxBwq/patchnotes-cavesandcliffs.jpg"
/>
{/each}
</CardRow>
<CardRow title="Popular packs">
{#each Array(5) as _, i}
<Instance
title="All of Fabric 5"
id="567"
version="1.18.1"
image="https://media.forgecdn.net/avatars/458/829/637733746768258525.png"
modpack
/>
{/each}
</CardRow>
<CardRow title="New releases">
{#each Array(5) as _, i}
<Instance
title="New Caves"
id="234"
version="1.18.2"
image="https://i.ibb.co/8KDxBwq/patchnotes-cavesandcliffs.jpg"
/>
{/each}
</CardRow>
<style lang="postcss">
</style>

View File

@@ -1,8 +0,0 @@
<script context="module" lang="ts">
</script>
<script lang="ts">
</script>
<style lang="postcss">
</style>

View File

@@ -1,52 +0,0 @@
<script lang="ts">
import VerticalNav from '$components/VerticalNav.svelte';
import IconPackage from 'virtual:icons/lucide/package';
import IconAdjustments from 'virtual:icons/heroicons-outline/adjustments';
import IconFileText from 'virtual:icons/lucide/file-text';
</script>
<div class="layout-instance">
<div class="instance-sidebar">
<VerticalNav
level={3}
items={[
{
label: 'Mods',
href: 'mods',
icon: IconPackage
},
{
label: 'Settings',
href: 'settings',
icon: IconAdjustments
},
{
label: 'Logs',
href: 'logs',
icon: IconFileText
}
]}
/>
</div>
<div class="layout-instance__page">
<slot />
</div>
</div>
<style lang="postcss">
.layout-instance {
display: grid;
grid-template-columns: 224px 1fr;
height: 100%;
&__page {
height: 100%;
background-color: var(--sub-page-bg);
}
}
.instance-sidebar {
padding: 16px;
}
</style>

View File

@@ -1,45 +0,0 @@
<script context="module" lang="ts">
</script>
<script lang="ts">
import GlobalSettings from '$components/GlobalSettings.svelte';
import TitledSection from '$components/TitledSection.svelte';
export let overrideGlobalSettings = false;
</script>
<div class="section">
<TitledSection title="Override global settings" toggleable={true}>
<GlobalSettings />
</TitledSection>
</div>
<style lang="postcss">
.section {
display: flex;
flex-direction: column;
padding: 1rem;
grid-gap: 1rem;
&__title {
display: flex;
grid-gap: 1rem;
align-items: center;
&::after {
flex: 1 1;
content: ' ';
background-color: hsla(0, 0%, 100%, 0.2);
height: 0.2rem;
border-radius: var(--rounded-max);
}
}
&__items {
display: flex;
flex-direction: column;
grid-gap: 1rem;
padding: 0 8px;
}
}
</style>

View File

@@ -1,12 +0,0 @@
<div class="layout-search">
<slot />
</div>
<style lang="postcss">
.layout-search {
display: flex;
padding: 16px;
flex-direction: column;
gap: 16px;
}
</style>

View File

@@ -1,104 +0,0 @@
<script lang="ts" context="module">
/** @type {import('./index').Load} */
export async function load({ fetch }) {
const response = await fetch(`https://api.modrinth.com/v2/search?query=&limit=10&offset=0&index=relevance`);
return {
props: {
projects: response.ok && (await response.json()).hits
}
};
}
</script>
<script lang="ts">
import IconSearch from 'virtual:icons/heroicons-outline/search';
import IconSortDescending from 'virtual:icons/heroicons-outline/sort-descending';
import IconBox from 'virtual:icons/lucide/box';
import IconGlobe from 'virtual:icons/lucide/globe';
import IconCpu from 'virtual:icons/lucide/cpu';
import IconTruck from 'virtual:icons/lucide/truck';
import IconFileText from 'virtual:icons/lucide/file-text';
import { TextInput, Button } from 'omorphia';
import ProjectCard from '$components/ProjectCard.svelte';
export let projects;
export let searchQuery = "";
export const searchProjects = async (query) => {
const encodedQuery = encodeURI(query);
const response = await fetch(
`https://api.modrinth.com/v2/search?query=${encodedQuery}&limit=10&offset=0&index=relevance`
);
return response.ok && (await response.json()).hits;
};
export async function search(event) {
projects = await searchProjects(searchQuery);
};
</script>
<div class="controls">
<div class="controls__row">
<TextInput placeholder="Search..." icon={IconSearch} bind:value={searchQuery}/>
<Button on:click={search} color="tertiary"><IconSortDescending />Search</Button>
</div>
<div class="controls__row controls__row--overflow">
<Button color="secondary"><IconBox />Minecraft versions</Button>
<Button color="secondary"><IconGlobe />Categories</Button>
<Button color="secondary"><IconCpu />Environment</Button>
<Button color="secondary"><IconTruck />Mod loaders</Button>
<Button color="secondary"><IconFileText />License</Button>
</div>
</div>
<div class="results">
{#each projects as project}
<ProjectCard {project} />
{/each}
</div>
<style lang="postcss">
.controls {
display: flex;
flex-direction: column;
width: 100%;
gap: 10px;
&__row {
display: flex;
gap: 8px;
&--overflow {
overflow-x: auto;
margin: 0px -4px;
padding: 0 6px;
width: calc(100% + 3px);
mask-image: linear-gradient(to right, transparent, hsla(0, 0%, 0%, 1) 1% 99%, transparent);
/* Hide scrollbar */
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}
:global(.text-input) {
flex: 1 1;
}
:global(.text-input > input) {
width: auto;
}
}
}
.results {
display: flex;
flex-direction: column;
gap: 16px;
}
</style>

View File

@@ -1,13 +0,0 @@
<script context="module" lang="ts">
</script>
<script lang="ts">
import GlobalSettings from '$components/GlobalSettings.svelte';
</script>
<div class="section">
<GlobalSettings />
</div>
<style lang="postcss">
</style>

View File

@@ -1,3 +0,0 @@
import { writable } from 'svelte/store';
export const token = writable('');

15
theseus_gui/src/style.css Normal file
View File

@@ -0,0 +1,15 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}

View File

@@ -1,19 +0,0 @@
.nav-item {
display: flex;
align-items: center;
grid-gap: 0.5rem;
padding: 0.5rem 0.75rem;
border-radius: var(--rounded-sm);
box-shadow: var(--shadow-inset-sm) var(--shadow-raised);
transition: background-color 0.2s ease-in-out, color 0.1s ease-in-out;
color: var(--color-text-light);
&:hover,
&.active {
color: var(--color-text);
}
&.active {
background-color: var(--nav-active-bg);
}
}

View File

@@ -1,20 +0,0 @@
@import 'components.postcss';
.base {
font-size: 14px;
}
.avatar--size-md {
--size: 64px !important;
}
.theme-dark {
--status-bg: hsl(216, 5%, 29%);
--sidebar-bg: hsl(216, 10%, 3%);
--nav-active-bg: hsl(217, 9%, 25%);
--font-size-sm: 0.75rem;
--color-bg: hsl(217, 9%, 18%);
--color-brand: hsl(145, 75%, 45%);
--color-brand-contrast: black;
--sub-page-bg: hsl(220, 9%, 13%);
}