mirror of
https://github.com/ivabus/gui
synced 2025-04-23 14:07:14 +03:00
change install buttons and other small fixes (#464)
* change install buttons and other small fixes * wtf is wrong with prettier * wtf is wrong with prettier * fix button vertical alignment on search results page
This commit is contained in:
parent
0163d30b28
commit
7af1e543f4
17 changed files with 236 additions and 207 deletions
2
modules/desktop/src/app.d.ts
vendored
2
modules/desktop/src/app.d.ts
vendored
|
@ -13,6 +13,6 @@ declare namespace svelte.JSX {
|
|||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface HTMLAttributes<T> {
|
||||
onclick_outside?: () => void;
|
||||
leave_delay?: () => void;
|
||||
onleave_delay?: () => void;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
import type { GUIPackage } from "$libs/types";
|
||||
import { packagesStore } from "$libs/stores";
|
||||
import { shellOpenExternal } from "@native";
|
||||
import InstallButton from "$components/install-button/install-button.svelte";
|
||||
import { findAvailableVersions } from "$libs/packages/pkg-utils";
|
||||
import { trimGithubSlug } from "$libs/github";
|
||||
import PackageVersionSelector from "$components/package-install-button/package-version-selector.svelte";
|
||||
|
||||
export let pkg: GUIPackage;
|
||||
let installing = false;
|
||||
|
@ -51,7 +51,7 @@
|
|||
{/if}
|
||||
<p class="mt-4 text-sm">{pkg.desc}</p>
|
||||
<menu class="mt-4 grid h-10 grid-cols-3 gap-4 text-xs">
|
||||
<InstallButton
|
||||
<PackageVersionSelector
|
||||
buttonSize="large"
|
||||
{pkg}
|
||||
availableVersions={findAvailableVersions(pkg)}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<script lang="ts">
|
||||
import "../../app.css";
|
||||
import ProgressCircle from "@tea/ui/progress-circle/progress-circle.svelte";
|
||||
import InstallButton from "../install-button/install-button.svelte";
|
||||
import type { GUIPackage } from "$libs/types";
|
||||
import { findRecentInstalledVersion } from "$libs/packages/pkg-utils";
|
||||
import PackageInstallButton from "$components/package-install-button/package-install-button.svelte";
|
||||
|
||||
export let pkg: GUIPackage;
|
||||
export let availableVersions: string[];
|
||||
export let link: string;
|
||||
export let progessLoading = 0;
|
||||
|
||||
|
@ -14,11 +13,7 @@
|
|||
? "https://tea.xyz/Images/package-thumb-nolabel4.jpg"
|
||||
: pkg.thumb_image_url;
|
||||
|
||||
export let onClickCTA = async (_version: string) => {
|
||||
console.log("do nothing");
|
||||
};
|
||||
|
||||
export let onUninstall = async () => {
|
||||
export let onClickCTA = async () => {
|
||||
console.log("do nothing");
|
||||
};
|
||||
|
||||
|
@ -53,7 +48,14 @@
|
|||
</article>
|
||||
<div class="relative mt-3.5 flex w-full">
|
||||
<div class="install-button" on:mousedown={preventPropagation}>
|
||||
<InstallButton {pkg} {availableVersions} onClick={onClickCTA} uninstall={onUninstall} />
|
||||
<PackageInstallButton
|
||||
{pkg}
|
||||
onClick={(evt) => {
|
||||
// prevent default to prevent the link that this button is inside of from being followed
|
||||
evt?.preventDefault();
|
||||
onClickCTA();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative mt-1.5 h-[10px] leading-[10px]">
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
[PackageStates.UNINSTALLED]: ""
|
||||
};
|
||||
|
||||
const hasVersionSelectorDropdown = !!$$slots.selector;
|
||||
|
||||
$: ctaLabel = $t(`package.cta-${pkg.state}`);
|
||||
</script>
|
||||
|
||||
|
@ -45,28 +47,24 @@
|
|||
>
|
||||
<div class="version-button h-full">
|
||||
<div class="flex h-full flex-col justify-center p-2">
|
||||
{#if pkg.state === PackageStates.AVAILABLE}
|
||||
{#if hasVersionSelectorDropdown}
|
||||
<div class="flex items-center justify-between gap-x-2">
|
||||
<div class="flex items-center gap-x-2">
|
||||
<div>{ctaLabel}</div>
|
||||
<div class="version-label install-badge">{pkg.version}</div>
|
||||
<div class="version-label {badgeClass[pkg.state]}">{pkg.version}</div>
|
||||
</div>
|
||||
<i class="icon-downward-arrow flex" />
|
||||
</div>
|
||||
{:else if pkg.state === PackageStates.NEEDS_UPDATE || pkg.state === PackageStates.INSTALLED}
|
||||
{:else}
|
||||
<div class="flex items-center justify-center gap-x-2">
|
||||
<div>{ctaLabel}</div>
|
||||
<div class="version-label {badgeClass[pkg.state]}">{pkg.version}</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex items-center justify-center">
|
||||
{ctaLabel}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<!-- This slot holds the drop down menu and it inside of the button so that the
|
||||
hover effect remain on the button while the user is hovering the dropdown items-->
|
||||
<slot />
|
||||
<slot name="selector" />
|
||||
</div>
|
||||
</Button>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { PackageStates, type GUIPackage } from "$libs/types";
|
||||
import clickOutside from "@tea/ui/lib/clickOutside";
|
||||
import PackageStateButton from "./package-state-button.svelte";
|
||||
import PackageStateButton from "./package-install-button.svelte";
|
||||
|
||||
export let buttonSize: "small" | "large" = "small";
|
||||
export let pkg: GUIPackage;
|
||||
|
@ -48,7 +48,7 @@
|
|||
|
||||
<div class="dropdown z-10" use:clickOutside on:click_outside={handleClickOutside}>
|
||||
<PackageStateButton {buttonSize} {pkg} onClick={toggleOpen}>
|
||||
<div class="pt-2">
|
||||
<div slot="selector" class="pt-2">
|
||||
<div class="version-list" class:visible={isOpened}>
|
||||
{#if (pkg?.installed_versions || []).length > 0}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
@ -112,7 +112,7 @@
|
|||
}
|
||||
|
||||
.installable-version:hover {
|
||||
border: 1px solid #949494;
|
||||
outline: 1px solid #949494;
|
||||
background-color: rgba(148, 148, 148, 0.35);
|
||||
}
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
<script lang="ts">
|
||||
import "$appcss";
|
||||
|
||||
import type { GUIPackage } from "$libs/types";
|
||||
import { PackageStates, type GUIPackage } from "$libs/types";
|
||||
import { packagesStore } from "$libs/stores";
|
||||
import { onMount } from "svelte";
|
||||
import PackageCard from "$components/package-card/package-card.svelte";
|
||||
import { findAvailableVersions } from "$libs/packages/pkg-utils";
|
||||
|
||||
export let tab = "all";
|
||||
export let pkg: GUIPackage;
|
||||
|
@ -17,11 +16,16 @@
|
|||
|
||||
<PackageCard
|
||||
{pkg}
|
||||
availableVersions={findAvailableVersions(pkg)}
|
||||
link="/packages/{pkg.slug}?tab={tab}"
|
||||
progessLoading={pkg.install_progress_percentage}
|
||||
onClickCTA={(version) => packagesStore.installPkg(pkg, version)}
|
||||
onUninstall={async () => {
|
||||
packagesStore.uninstallPkg(pkg);
|
||||
onClickCTA={async () => {
|
||||
if (
|
||||
[PackageStates.INSTALLED, PackageStates.INSTALLING, PackageStates.UPDATING].includes(
|
||||
pkg.state
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
packagesStore.installPkg(pkg);
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -1,83 +1,93 @@
|
|||
<script lang="ts">
|
||||
import { authStore, navStore } from '$libs/stores';
|
||||
import SelectLang from '$components/select-lang/select-lang.svelte';
|
||||
import { baseUrl } from '$libs/v1-client';
|
||||
import { shellOpenExternal, submitLogs } from '@native';
|
||||
import mouseLeaveDelay from "@tea/ui/lib/mouse-leave-delay";
|
||||
import { getSession } from '@native';
|
||||
import { authStore, navStore } from "$libs/stores";
|
||||
import SelectLang from "$components/select-lang/select-lang.svelte";
|
||||
import { baseUrl } from "$libs/v1-client";
|
||||
import { shellOpenExternal, submitLogs } from "@native";
|
||||
import mouseLeaveDelay from "@tea/ui/lib/mouse-leave-delay";
|
||||
import { getSession } from "@native";
|
||||
|
||||
const { user } = authStore;
|
||||
const { user } = authStore;
|
||||
|
||||
let authenticating = false;
|
||||
let authenticating = false;
|
||||
|
||||
const openGithub = async () => {
|
||||
authenticating = true;
|
||||
if (!authenticating) {
|
||||
try {
|
||||
const session = await getSession();
|
||||
if (session && session.device_id) {
|
||||
shellOpenExternal(`${baseUrl}/auth/user?device_id=${session.device_id}`);
|
||||
authStore.pollSession();
|
||||
} else {
|
||||
throw new Error("possible no internet connection");
|
||||
}
|
||||
} catch (error) {
|
||||
submittedMessage = (error as Error).message;
|
||||
console.error(error);
|
||||
} finally {
|
||||
authenticating = false;
|
||||
}
|
||||
}
|
||||
const openGithub = async () => {
|
||||
authenticating = true;
|
||||
if (!authenticating) {
|
||||
try {
|
||||
const session = await getSession();
|
||||
if (session && session.device_id) {
|
||||
shellOpenExternal(`${baseUrl}/auth/user?device_id=${session.device_id}`);
|
||||
authStore.pollSession();
|
||||
} else {
|
||||
throw new Error("possible no internet connection");
|
||||
}
|
||||
} catch (error) {
|
||||
submittedMessage = (error as Error).message;
|
||||
console.error(error);
|
||||
} finally {
|
||||
authenticating = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let submittedMessage = "";
|
||||
const onSubmitLogs = async () => {
|
||||
if (submittedMessage !== "syncing...") {
|
||||
submittedMessage = "syncing..."
|
||||
const msg = await submitLogs();
|
||||
submittedMessage = msg;
|
||||
}
|
||||
}
|
||||
let submittedMessage = "";
|
||||
const onSubmitLogs = async () => {
|
||||
if (submittedMessage !== "syncing...") {
|
||||
submittedMessage = "syncing...";
|
||||
const msg = await submitLogs();
|
||||
submittedMessage = msg;
|
||||
}
|
||||
};
|
||||
|
||||
const hidePopup = () => {
|
||||
navStore.sideNavOpen.set(false);
|
||||
}
|
||||
const hidePopup = () => {
|
||||
navStore.sideNavOpen.set(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<nav class="w-full p-2 text-sm" use:mouseLeaveDelay={2000} on:leave_delay={() => hidePopup()}>
|
||||
{#if $user}
|
||||
<section class="flex items-center justify-between p-1 hover:bg-gray hover:border hover:border-white rounded-sm hover:bg-opacity-90 hover:text-black">
|
||||
<div class="text-white">@{$user?.login}</div>
|
||||
<img id="avatar" class="rounded-sm" src={$user?.avatar_url || '/images/bored-ape.png'} alt="profile" />
|
||||
</section>
|
||||
{:else}
|
||||
<button
|
||||
class="mt-2 p-1 transition-all rounded-sm w-full h-8 text-left hover:bg-gray hover:border focus:bg-secondary bg-opacity-40"
|
||||
class:animate-pulse={authenticating}
|
||||
on:click={openGithub}>
|
||||
login
|
||||
</button>
|
||||
{/if}
|
||||
<hr class="mt-2 border border-gray border-b-0 border-t-0"/>
|
||||
<SelectLang/>
|
||||
<hr class="border border-gray border-b-0 border-t-0"/>
|
||||
<button
|
||||
class="mt-2 p-1 transition-all rounded-sm w-full h-8 text-left hover:bg-gray hover:border focus:bg-secondary"
|
||||
class:animate-pulse={submittedMessage === "syncing..."}
|
||||
on:click={onSubmitLogs}>
|
||||
submit logs
|
||||
</button>
|
||||
{#if submittedMessage}
|
||||
<p class="text-gray text-xs mt-2">{submittedMessage}</p>
|
||||
{/if}
|
||||
{#if $user}
|
||||
<section
|
||||
class="hover:bg-gray outline-gray flex items-center justify-between p-1 outline-1 hover:bg-opacity-25 hover:text-black hover:outline"
|
||||
>
|
||||
<div class="text-white">@{$user?.login}</div>
|
||||
<img
|
||||
id="avatar"
|
||||
class="rounded-sm"
|
||||
src={$user?.avatar_url || "/images/bored-ape.png"}
|
||||
alt="profile"
|
||||
/>
|
||||
</section>
|
||||
{:else}
|
||||
<button
|
||||
class="hover:bg-gray outline-gray focus:bg-secondary h-8 w-full p-1 text-left outline-1 transition-all hover:bg-opacity-25 hover:outline"
|
||||
class:animate-pulse={authenticating}
|
||||
on:click={openGithub}
|
||||
>
|
||||
login
|
||||
</button>
|
||||
{/if}
|
||||
<hr class="mt-1" />
|
||||
<SelectLang />
|
||||
<hr />
|
||||
<button
|
||||
class="hover:bg-gray outline-gray focus:bg-secondary h-8 w-full p-1 text-left outline-1 transition-all hover:bg-opacity-25 hover:outline"
|
||||
class:animate-pulse={submittedMessage === "syncing..."}
|
||||
on:click={onSubmitLogs}
|
||||
>
|
||||
submit logs
|
||||
</button>
|
||||
{#if submittedMessage}
|
||||
<p class="text-gray mt-2 text-xs">{submittedMessage}</p>
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
hr {
|
||||
border-width: 1px;
|
||||
}
|
||||
hr {
|
||||
border: 1px solid #272626;
|
||||
}
|
||||
|
||||
#avatar {
|
||||
height: 24px !important;
|
||||
width: 24px !important;
|
||||
}
|
||||
</style>
|
||||
#avatar {
|
||||
height: 24px !important;
|
||||
width: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<script lang="ts">
|
||||
import InstallButton from "$components/install-button/install-button.svelte";
|
||||
import type { GUIPackage } from "$libs/types";
|
||||
import { packagesStore } from "$libs/stores";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import ImgLoader from "@tea/ui/img-loader/img-loader.svelte";
|
||||
import { findAvailableVersions } from "$libs/packages/pkg-utils";
|
||||
import { goto } from "$app/navigation";
|
||||
import { goto } from "$app/navigation";
|
||||
import PackageInstallButton from "$components/package-install-button/package-install-button.svelte";
|
||||
export let pkg: GUIPackage;
|
||||
export let onClick: (_version: string) => Promise<void>;
|
||||
export let onClick: () => Promise<void>;
|
||||
export let onClose: () => void;
|
||||
|
||||
onMount(() => {
|
||||
|
@ -20,7 +20,7 @@
|
|||
const gotoPackagePage = () => {
|
||||
goto(`/packages/${pkg.slug}?tab=all`);
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
@ -38,8 +38,9 @@
|
|||
<p class="line-clamp-2 text-xs">{pkg.desc}</p>
|
||||
</header>
|
||||
<aside>
|
||||
<InstallButton {pkg} {availableVersions} {onClick} />
|
||||
<footer class="mt-2 text-center text-xs">v{pkg.version}</footer>
|
||||
<div>
|
||||
<PackageInstallButton {pkg} {onClick} />
|
||||
</div>
|
||||
</aside>
|
||||
</figure>
|
||||
|
||||
|
@ -47,4 +48,12 @@
|
|||
figure:hover {
|
||||
background-color: #252525;
|
||||
}
|
||||
</style>
|
||||
|
||||
aside {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: 140px;
|
||||
margin-right: 22px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
<script lang="ts">
|
||||
import { searchStore } from '$libs/stores';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
import SearchInput from '@tea/ui/search-input/search-input.svelte';
|
||||
import { t } from '$libs/translations';
|
||||
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
|
||||
import { packagesStore, searchStore } from "$libs/stores";
|
||||
import type { GUIPackage } from "$libs/types";
|
||||
import SearchInput from "@tea/ui/search-input/search-input.svelte";
|
||||
import { t } from "$libs/translations";
|
||||
import Preloader from "@tea/ui/Preloader/Preloader.svelte";
|
||||
import Package from "$components/packages/package.svelte";
|
||||
import { PackageStates } from '$libs/types';
|
||||
import { PackageStates } from "$libs/types";
|
||||
import PackageResult from "./package-search-result.svelte";
|
||||
import Mousetrap from 'mousetrap';
|
||||
import Mousetrap from "mousetrap";
|
||||
// import Posts from '@tea/ui/posts/posts.svelte';
|
||||
|
||||
import { installPackage } from '@native';
|
||||
import { onMount } from 'svelte';
|
||||
import { installPackage } from "@native";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
const { searching, packagesSearch } = searchStore;
|
||||
// import type { AirtablePost } from '@tea/ui/types';
|
||||
|
@ -42,30 +42,32 @@
|
|||
searchStore.searching.subscribe((v) => (loading = v));
|
||||
|
||||
const onClose = () => {
|
||||
term = '';
|
||||
term = "";
|
||||
searchStore.searching.set(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if $searching === true}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div id="bg-close" class="z-40" on:click={onClose}></div>
|
||||
<div id="bg-close" class="z-40" on:click={onClose} />
|
||||
<section class="z-50">
|
||||
<header class="flex border border-gray border-t-0 border-x-0 bg-black">
|
||||
<header class="border-gray flex border border-x-0 border-t-0 bg-black">
|
||||
<div class="relative w-full">
|
||||
<SearchInput
|
||||
class="w-full rounded-sm h-9"
|
||||
class="h-9 w-full rounded-sm"
|
||||
size="small"
|
||||
autofocus={true}
|
||||
placeholder="{$t("store-search-placeholder")}"
|
||||
placeholder={$t("store-search-placeholder")}
|
||||
onSearch={(search) => {
|
||||
term = search;
|
||||
searchStore.search(search);
|
||||
}}
|
||||
/>
|
||||
<div class="absolute top-2 right-3 opacity-50 flex items-center gap-1">
|
||||
<button class="text-xs mt-1">clear</button>
|
||||
<kbd class=" bg-gray text-white px-2 mt-1 rounded-sm flex items-center">
|
||||
<span class="text-xs">ctrl + shift + del</span>
|
||||
<div class="absolute top-2 right-3 flex items-center gap-1 pt-[1px] opacity-50">
|
||||
<span class="mr-1 text-xs">clear</span>
|
||||
<kbd class=" bg-gray flex items-center rounded-sm px-2 pt-[1px] text-white">
|
||||
<span class="mr-1.5 text-lg leading-4">⌘</span>
|
||||
<span class="text-xs">+ shift + del</span>
|
||||
</kbd>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -79,18 +81,21 @@
|
|||
<ul class="flex flex-col gap-2 p-2">
|
||||
{#if $packagesSearch.length > 0}
|
||||
{#each $packagesSearch as pkg}
|
||||
<div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}>
|
||||
<div class={pkg.state === PackageStates.INSTALLING ? "animate-pulse" : ""}>
|
||||
<PackageResult
|
||||
{pkg}
|
||||
{onClose}
|
||||
onClick={async () => {
|
||||
try {
|
||||
pkg.state = PackageStates.INSTALLING;
|
||||
await installPackage(pkg, pkg.version);
|
||||
pkg.state = PackageStates.INSTALLED;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
if (
|
||||
[
|
||||
PackageStates.INSTALLED,
|
||||
PackageStates.INSTALLING,
|
||||
PackageStates.UPDATING
|
||||
].includes(pkg.state)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
packagesStore.installPkg(pkg);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -119,7 +124,7 @@
|
|||
{/if} -->
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-full h-full flex flex-col justify-center bg-black">
|
||||
<div class="flex h-full w-full flex-col justify-center bg-black">
|
||||
<p class="text-gray text-center">start typing to search</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
@ -160,7 +165,6 @@
|
|||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<script lang="ts">
|
||||
import { t, locales, locale } from '$libs/translations';
|
||||
import SelectExpand from "@tea/ui/select-expand/select-expand.svelte";
|
||||
import { t, locales, locale } from "$libs/translations";
|
||||
import SelectExpand from "@tea/ui/select-expand/select-expand.svelte";
|
||||
|
||||
const label = "Language";
|
||||
const label = "language";
|
||||
</script>
|
||||
|
||||
<SelectExpand
|
||||
{label}
|
||||
bind:value={$locale}
|
||||
options={$locales.map((value) => ({
|
||||
label: $t(`lang.${value}`),
|
||||
value,
|
||||
selected: value === $locale,
|
||||
}))}
|
||||
/>
|
||||
{label}
|
||||
bind:value={$locale}
|
||||
options={$locales.map((value) => ({
|
||||
label: $t(`lang.${value}`),
|
||||
value,
|
||||
selected: value === $locale
|
||||
}))}
|
||||
/>
|
||||
|
|
|
@ -1,39 +1,40 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
export let icon:string;
|
||||
export let label:string;
|
||||
import "$appcss";
|
||||
export let icon: string;
|
||||
export let label: string;
|
||||
|
||||
export let active = false;
|
||||
export let active = false;
|
||||
|
||||
export let count = 0;
|
||||
export let count = 0;
|
||||
</script>
|
||||
|
||||
<button on:click
|
||||
class="text-xs w-full flex transition-all rounded-sm hover:bg-opacity-25 border-gray hover:border px-1 gap-2 items-center align-middle text-left hover:bg-gray box-border"
|
||||
class:active
|
||||
<button
|
||||
on:click
|
||||
class="outline-gray hover:bg-gray box-border flex w-full items-center gap-2 rounded-sm px-1 text-left align-middle text-xs outline-1 transition-all hover:bg-opacity-25 hover:outline"
|
||||
class:active
|
||||
>
|
||||
<i class="icon-{icon} mt-1"/>
|
||||
<div class="font-thin text-sm">
|
||||
{label}
|
||||
{#if count > 0}
|
||||
<span class="text-right rounded-sm">{count}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<i class="icon-{icon} mt-1" />
|
||||
<div class="text-sm font-thin">
|
||||
{label}
|
||||
{#if count > 0}
|
||||
<span class="rounded-sm text-right">{count}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<style>
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
height: 37px;
|
||||
}
|
||||
button.active {
|
||||
background: rgba(148, 148, 148, 0.5);
|
||||
border: rgba(148, 148, 148, 1) 1px solid;
|
||||
}
|
||||
span {
|
||||
color: white;
|
||||
background: #FF4100;
|
||||
padding: 2px;
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
height: 37px;
|
||||
}
|
||||
button.active {
|
||||
background: rgba(148, 148, 148, 0.5);
|
||||
border: rgba(148, 148, 148, 1) 1px solid;
|
||||
}
|
||||
span {
|
||||
color: white;
|
||||
background: #ff4100;
|
||||
padding: 2px;
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<script lang="ts">
|
||||
import '$appcss';
|
||||
import type { GUIPackage } from '$libs/types';
|
||||
import type { Package } from '@tea/ui/types';
|
||||
import { PackageStates } from '$libs/types';
|
||||
import Preloader from '@tea/ui/Preloader/Preloader.svelte';
|
||||
import "$appcss";
|
||||
import type { GUIPackage } from "$libs/types";
|
||||
import type { Package } from "@tea/ui/types";
|
||||
import { PackageStates } from "$libs/types";
|
||||
import Preloader from "@tea/ui/Preloader/Preloader.svelte";
|
||||
import PackageCard from "$components/packages/package.svelte";
|
||||
import { onMount } from 'svelte';
|
||||
import { installPackage } from '@native';
|
||||
import { packagesStore } from '$libs/stores';
|
||||
import { onMount } from "svelte";
|
||||
import { packagesStore } from "$libs/stores";
|
||||
|
||||
export let pkg: Package;
|
||||
|
||||
|
@ -27,19 +26,8 @@
|
|||
<ul class="grid grid-cols-3 bg-black">
|
||||
{#if packages.length > 0}
|
||||
{#each packages as pkg}
|
||||
<div class={pkg.state === PackageStates.INSTALLING ? 'animate-pulse' : ''}>
|
||||
<PackageCard
|
||||
{pkg}
|
||||
onClick={async () => {
|
||||
try {
|
||||
pkg.state = PackageStates.INSTALLING;
|
||||
await installPackage(pkg);
|
||||
pkg.state = PackageStates.INSTALLED;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div class={pkg.state === PackageStates.INSTALLING ? "animate-pulse" : ""}>
|
||||
<PackageCard {pkg} />
|
||||
</div>
|
||||
{/each}
|
||||
{:else}
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
</section>
|
||||
</div>
|
||||
{#if $sideNavOpen}
|
||||
<aside class="border-gray fixed z-50 rounded-md border bg-black transition-all">
|
||||
<aside class="border-gray fixed z-50 rounded-sm border bg-black transition-all">
|
||||
<PopoutMenu />
|
||||
</aside>
|
||||
{/if}
|
||||
|
|
2
modules/ui/src/app.d.ts
vendored
2
modules/ui/src/app.d.ts
vendored
|
@ -15,6 +15,6 @@ declare namespace svelte.JSX {
|
|||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface HTMLAttributes<T> {
|
||||
onclick_outside: () => void;
|
||||
leave_delay: () => void;
|
||||
onleave_delay: () => void;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
export default function mouseLeaveDelay(element: HTMLElement, timeout = 600) {
|
||||
let isOut = false;
|
||||
let timeoutId: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
const handleEnter = () => {
|
||||
isOut = false;
|
||||
};
|
||||
|
||||
const onDestroy = () => {
|
||||
element.removeEventListener("mouseenter", handleEnter, true);
|
||||
element.removeEventListener("mouseleave", handleLeave, true);
|
||||
element.removeEventListener("mouseenter", handleEnter);
|
||||
element.removeEventListener("mouseleave", handleLeave);
|
||||
};
|
||||
|
||||
const handleLeave = () => {
|
||||
isOut = true;
|
||||
setTimeout(() => {
|
||||
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
timeoutId = setTimeout(() => {
|
||||
if (isOut && element) {
|
||||
element.dispatchEvent(new CustomEvent("leave_delay"));
|
||||
onDestroy();
|
||||
|
@ -20,8 +26,8 @@ export default function mouseLeaveDelay(element: HTMLElement, timeout = 600) {
|
|||
}, timeout);
|
||||
};
|
||||
|
||||
element.addEventListener("mouseenter", handleEnter, true);
|
||||
element.addEventListener("mouseleave", handleLeave, true);
|
||||
element.addEventListener("mouseenter", handleEnter);
|
||||
element.addEventListener("mouseleave", handleLeave);
|
||||
|
||||
return {
|
||||
destroy: onDestroy
|
||||
|
|
|
@ -27,12 +27,17 @@
|
|||
}, 300);
|
||||
};
|
||||
|
||||
const clearInput = () => {
|
||||
searchInput.value = "";
|
||||
onSearch("");
|
||||
return false;
|
||||
};
|
||||
|
||||
onMount(() => {
|
||||
if (autofocus) searchInput.focus();
|
||||
Mousetrap.bind(["ctrl+shift+del"], function () {
|
||||
searchInput.value = "";
|
||||
return false;
|
||||
});
|
||||
|
||||
Mousetrap.bind(["command+shift+backspace"], clearInput);
|
||||
Mousetrap.bind(["command+shift+del"], clearInput);
|
||||
|
||||
Mousetrap.prototype.stopCallback = () => {
|
||||
return false;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
on:leave_delay={() => unexpand()}
|
||||
>
|
||||
<header
|
||||
class="mt-2 flex h-8 justify-between rounded-sm px-1 hover:border hover:bg-gray focus:bg-secondary"
|
||||
class="mt-1 flex h-8 items-center justify-between px-1 outline-1 outline-gray hover:bg-gray hover:bg-opacity-25 hover:outline focus:bg-secondary"
|
||||
>
|
||||
<span>{label || value}</span>
|
||||
<i class="icon-downward-arrow mt-1" />
|
||||
|
@ -29,7 +29,7 @@
|
|||
<div class="dropdown pr-2 transition-all">
|
||||
{#each options as option}
|
||||
<button
|
||||
class="flex h-6 w-full items-center justify-between gap-x-1 rounded-sm px-2 text-xs hover:bg-gray"
|
||||
class="m-[1px] flex h-6 w-full items-center justify-between gap-x-1 px-2 text-xs outline-1 outline-gray hover:bg-gray hover:bg-opacity-25 hover:outline"
|
||||
on:click={() => (value = option.value)}
|
||||
>
|
||||
<div>{option.label}</div>
|
||||
|
@ -62,7 +62,9 @@
|
|||
|
||||
section.expanded hr {
|
||||
display: block;
|
||||
border: 1px solid #272626;
|
||||
}
|
||||
|
||||
section.expanded .dropdown {
|
||||
max-height: 100px;
|
||||
overflow-y: scroll;
|
||||
|
|
Loading…
Reference in a new issue