mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Update/marketplace (#2575)
* make category link generic * fix ai category display and svg icons * fix markdown display and ansi module; cleanup * convert tailwindcss to scss in marketplace menu component * convert tailwindcss to scss in marketplace categories component * convert tailwindcss to scss in marketplace item component * update launch icon to taiga icon * convert tailwindcss to scss in marketplace search component + cleanup * convert tailwindcss to scss in marketplace release notes component + cleanup * convert tailwindcss to scss in marketplace about component + cleanup * convert tailwindcss to scss in marketplace additional component * convert tailwindcss to scss in marketplace dependencies component + misc style fixes * convert tailwindcss to scss in marketplace hero component + misc style fixes * convert tailwindcss to scss in marketplace screenshots component * convert tailwindcss to scss in portal marketplace components * remove the rest of tailwindscss and fix reset styles * bump shared and marketplace package versions * misc style + build fixes * sync package lock * fix markdown + cleanup * fix markdown margins and git hash size * fix mobile zindex for hero and mobile changing categories routing link
This commit is contained in:
720
web/package-lock.json
generated
720
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -78,7 +78,6 @@
|
||||
"pbkdf2": "^3.1.2",
|
||||
"rxjs": "^7.5.6",
|
||||
"swiper": "^8.2.4",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"ts-matches": "^5.2.1",
|
||||
"tslib": "^2.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
{
|
||||
"name": "@start9labs/marketplace",
|
||||
"version": "0.3.16",
|
||||
"version": "0.3.19",
|
||||
"peerDependencies": {
|
||||
"@angular/common": ">=13.2.0",
|
||||
"@angular/core": ">=13.2.0",
|
||||
"@start9labs/shared": ">=0.3.2",
|
||||
"@taiga-ui/cdk": ">=3.0.0",
|
||||
"@tinkoff/ng-dompurify": ">=4.0.0",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"fuse.js": "^6.4.6"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,34 +1,24 @@
|
||||
<header
|
||||
class="header overflow-hidden w-full fixed sm:w-[34vw] md:w-[28vw] lg:w-[22vw] 2xl:w-[280px] sm:bg-zinc-700/90 sm:backdrop-blur-2xl sm:min-h-screen overflow-y-auto flex flex-col sm:py-6 sm:after:block sm:after:absolute sm:after:top-0 sm:after:bottom-0 sm:after:right-0 sm:after:w-0.5 after:h-[calc(100vh - 20px)] sm:after:bg-gradient-to-b from-zinc-700 to-zinc-400"
|
||||
>
|
||||
<header>
|
||||
<ng-container *tuiLet="store$ | async as store">
|
||||
<div class="hidden sm:flex flex-col mx-6 pb-3 items-center">
|
||||
<div
|
||||
class="mb-3 rounded-full"
|
||||
<div class="title">
|
||||
<store-icon
|
||||
[class.tui-skeleton]="!store"
|
||||
[class.tui-skeleton_rounded]="!store"
|
||||
>
|
||||
<store-icon
|
||||
size="64px"
|
||||
[url]="store?.url || ''"
|
||||
[marketplace]="iconConfig"
|
||||
></store-icon>
|
||||
</div>
|
||||
<h1
|
||||
class="font-semibold text-2xl text-zinc-100 text-center mb-3"
|
||||
[class.tui-skeleton]="!store"
|
||||
>
|
||||
size="64px"
|
||||
[url]="store?.url || ''"
|
||||
[marketplace]="iconConfig"
|
||||
></store-icon>
|
||||
<h1 [class.tui-skeleton]="!store">
|
||||
{{ store?.info?.name || 'Loading store' }}
|
||||
</h1>
|
||||
<!-- change registry modal -->
|
||||
<ng-content select="[slot=desktop]"></ng-content>
|
||||
</div>
|
||||
<!-- mobile nav -->
|
||||
<div class="sm:hidden bg-zinc-700/90 backdrop-blur-3xl">
|
||||
<div class="flex justify-between items-center py-4 px-4 w-[100vw]">
|
||||
<div class="nav-mobile">
|
||||
<div class="nav-mobile-bar">
|
||||
<!-- mobile search -->
|
||||
<marketplace-search
|
||||
class="max-w-fit"
|
||||
[(query)]="query"
|
||||
(queryChange)="onQueryChange($event)"
|
||||
></marketplace-search>
|
||||
@@ -43,101 +33,78 @@
|
||||
>
|
||||
<store-icon
|
||||
size="48px"
|
||||
[style.height]="'48px'"
|
||||
[style.border-radius]="'100%'"
|
||||
[url]="store?.url || ''"
|
||||
[marketplace]="iconConfig"
|
||||
class="rounded-full"
|
||||
[class.tui-skeleton]="!store"
|
||||
[class.tui-skeleton_rounded]="!store"
|
||||
></store-icon>
|
||||
<nav
|
||||
*tuiSidebar="open; direction: 'right'; autoWidth: true"
|
||||
class="bg-zinc-700/90 h-screen w-[70vw]"
|
||||
class="nav-mobile-sidebar divide-bar"
|
||||
>
|
||||
<div class="flex flex-col divide-y divide-zinc-500 h-full">
|
||||
<div class="flex items-center p-4">
|
||||
<h1
|
||||
class="font-semibold text-xl text-zinc-200 flex-grow"
|
||||
[class.tui-skeleton]="!store"
|
||||
>
|
||||
{{ store?.info?.name }}
|
||||
</h1>
|
||||
<button
|
||||
[style.--tui-padding]="0"
|
||||
class="place-self-end"
|
||||
tuiButton
|
||||
type="button"
|
||||
appearance="icon"
|
||||
icon="tuiIconClose"
|
||||
(tuiActiveZoneChange)="toggleMenu($event)"
|
||||
(click)="toggleMenu(false)"
|
||||
></button>
|
||||
</div>
|
||||
<!-- change registry modal -->
|
||||
<ng-content select="[slot=mobile]"></ng-content>
|
||||
<div
|
||||
class="flex flex-col justify-between divide-y divide-zinc-500 h-full"
|
||||
<div class="nav-mobile-sidebar-top">
|
||||
<h1 [class.tui-skeleton]="!store">
|
||||
{{ store?.info?.name }}
|
||||
</h1>
|
||||
<button
|
||||
[style.--tui-padding]="0"
|
||||
tuiButton
|
||||
type="button"
|
||||
appearance="icon"
|
||||
icon="tuiIconClose"
|
||||
(tuiActiveZoneChange)="toggleMenu($event)"
|
||||
(click)="toggleMenu(false)"
|
||||
></button>
|
||||
</div>
|
||||
<!-- change registry modal -->
|
||||
<ng-content select="[slot=mobile]"></ng-content>
|
||||
<div class="nav-mobile-sidebar-bottom divide-bar">
|
||||
<marketplace-categories
|
||||
[categories]="store?.info?.categories"
|
||||
[category]="query ? '' : category"
|
||||
(categoryChange)="onCategoryChange($event); toggleMenu(false)"
|
||||
></marketplace-categories>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/Start9Labs/service-pipeline#readme"
|
||||
>
|
||||
<marketplace-categories
|
||||
[categories]="store?.info?.categories"
|
||||
[category]="query ? '' : category"
|
||||
(categoryChange)="onCategoryChange($event); toggleMenu(false)"
|
||||
class="grow pt-5 pl-5 pr-5"
|
||||
></marketplace-categories>
|
||||
<a
|
||||
class="flex relative gap-2 hover:no-underline p-5"
|
||||
target="_blank"
|
||||
href="https://github.com/Start9Labs/service-pipeline#readme"
|
||||
>
|
||||
<img
|
||||
alt="Launch icon"
|
||||
width="24"
|
||||
height="24"
|
||||
class="opacity-70 invert"
|
||||
src="svg/rocket-outline.svg"
|
||||
/>
|
||||
<span
|
||||
class="text-base text-zinc-50 text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
>
|
||||
Launch your project
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<!-- @TODO need rocket icon -->
|
||||
<tui-icon
|
||||
tuiAppearance="icon"
|
||||
icon="tuiIconExternalLinkLarge"
|
||||
></tui-icon>
|
||||
<span>Launch your project</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- desktop nav -->
|
||||
<nav class="hidden sm:flex grow flex-col py-3 px-4">
|
||||
<nav class="nav-desktop">
|
||||
<!-- desktop search -->
|
||||
<marketplace-search
|
||||
class="place-self-center md:pb-8"
|
||||
[query]="query"
|
||||
(queryChange)="onQueryChange($event)"
|
||||
></marketplace-search>
|
||||
<div class="flex grow flex-col justify-between">
|
||||
<div class="nav-desktop-container">
|
||||
<marketplace-categories
|
||||
[categories]="store?.info?.categories"
|
||||
[category]="query ? '' : category"
|
||||
(categoryChange)="onCategoryChange($event)"
|
||||
></marketplace-categories>
|
||||
<a
|
||||
class="flex gap-2 p-2 hover:no-underline sm:hover:bg-[#222428] hover:cursor-pointer sm:w-[120%] z-50 rounded-l-lg ease-in-out delay-75 duration-300"
|
||||
target="_blank"
|
||||
href="https://github.com/Start9Labs/service-pipeline#readme"
|
||||
>
|
||||
<img
|
||||
alt="Rocket Icon"
|
||||
width="24"
|
||||
height="24"
|
||||
class="opacity-70 invert"
|
||||
src="svg/rocket-outline.svg"
|
||||
/>
|
||||
<span
|
||||
class="text-base text-zinc-50 text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
>
|
||||
Launch your project
|
||||
</span>
|
||||
<!-- @TODO need rocket icon -->
|
||||
<tui-icon
|
||||
tuiAppearance="icon"
|
||||
icon="tuiIconExternalLinkLarge"
|
||||
></tui-icon>
|
||||
<span>Launch your project</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { TuiSidebarModule } from '@taiga-ui/addon-mobile'
|
||||
import { SearchModule } from '../../pages/list/search/search.module'
|
||||
import { CategoriesModule } from '../../pages/list/categories/categories.module'
|
||||
import { StoreIconComponentModule } from '../store-icon/store-icon.component.module'
|
||||
import { TuiAppearanceModule, TuiIconModule } from '@taiga-ui/experimental'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -23,6 +24,8 @@ import { StoreIconComponentModule } from '../store-icon/store-icon.component.mod
|
||||
CategoriesModule,
|
||||
StoreIconComponentModule,
|
||||
TuiLetModule,
|
||||
TuiAppearanceModule,
|
||||
TuiIconModule,
|
||||
],
|
||||
declarations: [MenuComponent],
|
||||
exports: [MenuComponent],
|
||||
|
||||
@@ -1,13 +1,229 @@
|
||||
@import '@taiga-ui/core/styles/taiga-ui-local';
|
||||
|
||||
.header {
|
||||
header {
|
||||
@include scrollbar-hidden();
|
||||
|
||||
max-height: 100%;
|
||||
// TODO: Theme
|
||||
background: #373a3f;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 10;
|
||||
|
||||
@media screen and (min-width: 640px) {
|
||||
width: 15rem;
|
||||
background-color: rgb(var(--tw-color-zinc-700) / 0.9);
|
||||
backdrop-filter: blur(40px);
|
||||
min-height: calc(100vh - var(--portal-header-height));
|
||||
padding: 1.5rem 0;
|
||||
|
||||
&::after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
width: 0.125rem;
|
||||
content: '';
|
||||
background-image: linear-gradient(
|
||||
to bottom,
|
||||
rgb(var(--tw-color-zinc-700)),
|
||||
rgb(var(--tw-color-zinc-400))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
display: none;
|
||||
|
||||
@media (min-width: 640px) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-left: 1.5rem;
|
||||
margin-right: 1.5rem;
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
store-icon {
|
||||
margin-bottom: 0.75rem;
|
||||
border-radius: 100%;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
color: rgb(244 244 245);
|
||||
text-align: center;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.nav {
|
||||
&-desktop {
|
||||
display: none;
|
||||
padding: 0.75rem 1rem;
|
||||
|
||||
marketplace-search {
|
||||
place-self: center;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-container {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
z-index: 50;
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-delay: 75ms;
|
||||
transition-duration: 300ms;
|
||||
|
||||
&:hover {
|
||||
text-decoration-line: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
img {
|
||||
opacity: 0.7;
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
color: rgb(250 250 250);
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
width: 120%;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(34 36 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-mobile {
|
||||
@media (min-width: 640px) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
width: 100vw;
|
||||
|
||||
marketplace-search {
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
&-sidebar {
|
||||
background-color: rgb(var(--tw-color-zinc-700) / 0.9);
|
||||
height: calc(100vh - var(--portal-header-height));
|
||||
width: 70vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
&-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid rgb(113 113 122);
|
||||
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
color: rgb(228 228 231);
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
button {
|
||||
place-self: end;
|
||||
}
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border-top: 1px solid rgb(113 113 122);
|
||||
height: 100%;
|
||||
|
||||
marketplace-categories {
|
||||
flex-grow: 1;
|
||||
padding: 1.25rem 1.25rem 0px 1.25rem;
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
position: relative;
|
||||
gap: 0.5rem;
|
||||
padding: 1.25rem;
|
||||
|
||||
&:hover {
|
||||
text-decoration-line: none;
|
||||
}
|
||||
|
||||
img {
|
||||
opacity: 0.7;
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
color: rgb(250 250 250);
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.divide-bar > * + * {
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 0px;
|
||||
border-color: rgb(113 113 122);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: rgb(var(--tw-color-gray-200) / 1);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,25 @@
|
||||
<button
|
||||
*ngFor="let cat of categories || ['', '', '', '', '', '']"
|
||||
class="flex relative gap-2 hover:no-underline hover:cursor-pointer sm:hover:bg-[#222428] sm:hover:opacity-90 sm:w-[120%] rounded-l-lg ease-in-out delay-75 duration-300 mb-5 sm:p-2 sm:mb-3 z-50"
|
||||
routerLink="/marketplace"
|
||||
routerLink="../"
|
||||
(click)="switchCategory(cat)"
|
||||
[class.category_selected]="cat === category"
|
||||
>
|
||||
<div
|
||||
class="relative flex"
|
||||
class="category-wrapper"
|
||||
[class.tui-skeleton]="!categories"
|
||||
[class.tui-skeleton_rounded]="!categories"
|
||||
>
|
||||
<img
|
||||
alt="Category Icon"
|
||||
width="24"
|
||||
height="24"
|
||||
class="opacity-70 invert"
|
||||
src="/svg/{{ determineIcon(cat) }}.svg"
|
||||
/>
|
||||
<tui-icon tuiAppearance="icon" icon="{{ determineIcon(cat) }}"></tui-icon>
|
||||
</div>
|
||||
<span
|
||||
class="text-base text-zinc-50 text-ellipsis overflow-hidden whitespace-nowrap"
|
||||
class="category-title"
|
||||
[class.tui-skeleton]="!categories"
|
||||
[class.tui-skeleton_rounded]="!categories"
|
||||
>
|
||||
{{ (cat | titlecase) || 'loading category...' }}
|
||||
{{
|
||||
cat === 'ai'
|
||||
? (cat | uppercase)
|
||||
: (cat | titlecase) || 'loading category...'
|
||||
}}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -9,4 +9,49 @@
|
||||
background-color: #222428;
|
||||
opacity: 90;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
position: relative;
|
||||
gap: 0.5rem;
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-delay: 75ms;
|
||||
transition-duration: 300ms;
|
||||
margin-bottom: 1.25rem;
|
||||
z-index: 50;
|
||||
|
||||
&:hover {
|
||||
text-decoration-line: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
width: 120%;
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(34 36 40);
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.category {
|
||||
&-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
color: rgb(250 250 250);
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,27 +30,31 @@ export class CategoriesComponent {
|
||||
determineIcon(category: string): string {
|
||||
switch (category.toLowerCase()) {
|
||||
case 'all':
|
||||
return 'apps-outline'
|
||||
return 'tuiIconGridLarge'
|
||||
case 'bitcoin':
|
||||
return 'logo-bitcoin'
|
||||
// @TODO need bitcoin icon
|
||||
return 'tuiIconBoldLarge'
|
||||
case 'messaging':
|
||||
case 'communications':
|
||||
return 'chatbubbles-outline'
|
||||
return 'tuiIconMessageCircleLarge'
|
||||
case 'data':
|
||||
return 'document-outline'
|
||||
return 'tuiIconFileTextLarge'
|
||||
case 'developer tools':
|
||||
return 'code-slash-outline'
|
||||
return 'tuiIconTableSplitLarge'
|
||||
case 'featured':
|
||||
return 'star-outline'
|
||||
return 'tuiIconStarLarge'
|
||||
case 'lightning':
|
||||
return 'flash-outline'
|
||||
return 'tuiIconZapLarge'
|
||||
case 'media':
|
||||
return 'play-outline'
|
||||
return 'tuiIconPlayCircleLarge'
|
||||
case 'networking':
|
||||
return 'globe-outline'
|
||||
return 'tuiIconGlobeLarge'
|
||||
case 'social':
|
||||
return 'people-outline'
|
||||
return 'tuiIconUsersLarge'
|
||||
case 'ai':
|
||||
return 'tuiIconCpuLarge'
|
||||
default:
|
||||
return 'cube-outline'
|
||||
return 'tuiIconBoxLarge'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ import { CommonModule } from '@angular/common'
|
||||
import { NgModule } from '@angular/core'
|
||||
|
||||
import { CategoriesComponent } from './categories.component'
|
||||
import { TuiAppearanceModule, TuiIconModule } from '@taiga-ui/experimental'
|
||||
import { RouterModule } from '@angular/router'
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
imports: [RouterModule, CommonModule, TuiAppearanceModule, TuiIconModule],
|
||||
declarations: [CategoriesComponent],
|
||||
exports: [CategoriesComponent],
|
||||
})
|
||||
|
||||
@@ -1,32 +1,24 @@
|
||||
<div
|
||||
class="h-full relative rounded-3xl pt-20 pb-10 px-8 gap-4 shadow-lg hover:scale-90 transition duration-500 ease-in-out min-w-[300px]"
|
||||
>
|
||||
<div class="item-container box-shadow-lg">
|
||||
<!-- color background -->
|
||||
<div
|
||||
class="overflow-hidden absolute w-full h-full top-0 left-0 -z-50 rounded-3xl bg-zinc-800"
|
||||
>
|
||||
<div class="background">
|
||||
<img
|
||||
[src]="'data:image/png;base64,' + pkg.icon | trustUrl"
|
||||
class="absolute object-cover pointer-events-none w-[150%] h-[150%] max-w-[200%] blur-[100px]"
|
||||
[src]="pkg | mimeType | trustUrl"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
/>
|
||||
</div>
|
||||
<!-- darkening overlay -->
|
||||
<div
|
||||
class="overflow-hidden absolute w-full h-full top-0 left-0 -z-50 rounded-3xl bg-zinc-800 opacity-40"
|
||||
></div>
|
||||
<div class="overlay"></div>
|
||||
<!-- icon -->
|
||||
<img
|
||||
[src]="'data:image/png;base64,' + pkg.icon | trustUrl"
|
||||
class="w-[5.5rem] h-[5.5rem] pointer-events-none absolute -top-10 rounded-full object-cover shadow-lg z-10"
|
||||
[src]="pkg | mimeType | trustUrl"
|
||||
class="icon box-shadow-lg"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
style="transform: none"
|
||||
/>
|
||||
<div class="mt-3 text-zinc-5 mix-blend-plus-lighter">
|
||||
<span class="block text-2xl font-medium line-clamp-1 mb-1">
|
||||
<div class="detail">
|
||||
<span class="detail-title">
|
||||
{{ pkg.manifest.title }}
|
||||
</span>
|
||||
<span class="block text-base h-12 line-clamp-2">
|
||||
<span class="detail-description">
|
||||
{{ pkg.manifest.description.short }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
.item-container {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
min-width: 300px;
|
||||
border-radius: 1.5rem;
|
||||
padding: 5rem 2rem 2rem 2.5rem;
|
||||
gap: 1rem;
|
||||
transition-property: transform;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 500ms;
|
||||
|
||||
&:hover {
|
||||
transform: scaleX(0.9) scaleY(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.background {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: -50;
|
||||
border-radius: 1.5rem;
|
||||
background-color: rgb(39 39 42);
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
object-fit: cover;
|
||||
pointer-events: none;
|
||||
width: 150%;
|
||||
height: 150%;
|
||||
max-width: 200%;
|
||||
filter: blur(100px);
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-radius: 1.5rem;
|
||||
background-color: rgb(39 39 42);
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 5.5rem;
|
||||
height: 5.5rem;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: -2.5rem;
|
||||
border-radius: 9999px;
|
||||
object-fit: cover;
|
||||
z-index: 10;
|
||||
backdrop-filter: blur(24px);
|
||||
background-color: rgb(0 0 0 / 0.5);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.detail {
|
||||
margin-top: 0.75rem;
|
||||
mix-blend-mode: plus-lighter;
|
||||
|
||||
&-title {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
margin-bottom: 0.25rem;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
|
||||
&-description {
|
||||
display: block;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
height: 3rem;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { MarketplacePkg } from '../../../types'
|
||||
@Component({
|
||||
selector: 'marketplace-item',
|
||||
templateUrl: 'item.component.html',
|
||||
styleUrls: ['item.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ItemComponent {
|
||||
|
||||
@@ -3,10 +3,11 @@ import { NgModule } from '@angular/core'
|
||||
import { RouterModule } from '@angular/router'
|
||||
import { SharedPipesModule } from '@start9labs/shared'
|
||||
import { ItemComponent } from './item.component'
|
||||
import { MimeTypePipeModule } from '../../../pipes/mime-type.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [ItemComponent],
|
||||
exports: [ItemComponent],
|
||||
imports: [CommonModule, RouterModule, SharedPipesModule],
|
||||
imports: [CommonModule, RouterModule, SharedPipesModule, MimeTypePipeModule],
|
||||
})
|
||||
export class ItemModule {}
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
<div class="text-zinc-100 bg-zinc-500 px-3 rounded-full">
|
||||
<div class="relative flex items-center">
|
||||
<img
|
||||
alt="Search icon"
|
||||
width="24"
|
||||
height="24"
|
||||
class="invert"
|
||||
src="svg/search.svg"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
class="mt-1 bg-transparent placeholder-zinc-300 focus:outline-none px-3 py-2"
|
||||
placeholder="Search..."
|
||||
autocomplete="off"
|
||||
[ngModel]="query"
|
||||
(ngModelChange)="onModelChange($event)"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-box">
|
||||
<tui-svg src="tuiIconSearchLarge"></tui-svg>
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
placeholder="Search..."
|
||||
autocomplete="off"
|
||||
[ngModel]="query"
|
||||
(ngModelChange)="onModelChange($event)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
.search-box {
|
||||
color: rgb(244 244 245);
|
||||
background-color: rgb(113 113 122);
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
border-radius: 9999px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
margin-top: 0.25rem;
|
||||
background-color: transparent;
|
||||
padding: 0.5rem 0.75rem;
|
||||
&::placeholder {
|
||||
color: rgb(212 212 216);
|
||||
}
|
||||
&:focus {
|
||||
outline: 2px solid transparent;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: rgb(var(--tw-color-gray-200) / 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@ import { CommonModule } from '@angular/common'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { SearchComponent } from './search.component'
|
||||
import { TuiSvgModule } from '@taiga-ui/core'
|
||||
|
||||
@NgModule({
|
||||
imports: [FormsModule, CommonModule],
|
||||
imports: [FormsModule, CommonModule, TuiSvgModule],
|
||||
declarations: [SearchComponent],
|
||||
exports: [SearchComponent],
|
||||
})
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
<div
|
||||
class="rounded-xl bg-gradient-to-bl from-zinc-400/75 to-zinc-600 p-px shadow-lg shadow-zinc-400/10 mt-6"
|
||||
>
|
||||
<div class="bg-zinc-800 rounded-xl p-7 grid grid-flow-row items-center gap-6">
|
||||
<div class="block">
|
||||
<h3 class="text-lg font-bold small-caps">What's new</h3>
|
||||
<p
|
||||
*ngIf="pkg['published-at'] as published"
|
||||
class="text-base font-light mb-1 text-zinc-300"
|
||||
>
|
||||
<div class="background-border box-shadow-lg shadow-color-light">
|
||||
<div class="box-container">
|
||||
<div class="box-container-title">
|
||||
<h3 class="small-caps">What's new</h3>
|
||||
<p *ngIf="pkg['published-at'] as published">
|
||||
<span class="small-caps">Latest Release</span>
|
||||
-
|
||||
<span class="text-sm">{{ published | date: 'medium' }}</span>
|
||||
<span class="box-container-title-date">
|
||||
{{ published | date: 'medium' }}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap justify-between gap-6">
|
||||
<div class="text-base">
|
||||
<div class="box-container-details">
|
||||
<div class="box-container-details-version">
|
||||
<p>Version {{ pkg.manifest.version }}</p>
|
||||
<p
|
||||
safeLinks
|
||||
class="flex-wrap mt-1"
|
||||
class="box-container-details-notes"
|
||||
[innerHTML]="pkg.manifest['release-notes'] | markdown | dompurify"
|
||||
></p>
|
||||
</div>
|
||||
@@ -27,7 +24,6 @@
|
||||
type="button"
|
||||
appearance="secondary"
|
||||
size="m"
|
||||
class="mt-3 place-self-end sm:place-self-start md:place-self-start lg:place-self-end"
|
||||
(click)="showReleaseNotes(template)"
|
||||
>
|
||||
Previous releases
|
||||
@@ -39,11 +35,12 @@
|
||||
<ng-template #template let-observer>
|
||||
<ng-container *ngIf="notes$ | async as notes; else loading">
|
||||
<tui-accordion
|
||||
class="max-w-lg"
|
||||
class="max-width-lg"
|
||||
style="max-width: 32rem"
|
||||
[closeOthers]="false"
|
||||
*ngFor="let note of notes | keyvalue: asIsOrder"
|
||||
>
|
||||
<tui-accordion-item class="my-1">
|
||||
<tui-accordion-item style="margin: 0.25rem 0">
|
||||
{{ note.key | displayEmver }}
|
||||
<ng-template tuiAccordionItemContent>
|
||||
<p safeLinks [innerHTML]="note.value | markdown | dompurify"></p>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
.box-container {
|
||||
background-color: rgb(39 39 42);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.75rem;
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
|
||||
&-title {
|
||||
display: block;
|
||||
|
||||
h3 {
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
font-weight: 300;
|
||||
margin-bottom: 0.25rem;
|
||||
color: rgb(212 212 216);
|
||||
}
|
||||
|
||||
&-date {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-details {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 1.5rem;
|
||||
|
||||
&-version {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
&-notes {
|
||||
flex-wrap: wrap;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 0.75rem;
|
||||
place-self: end;
|
||||
|
||||
// @media (min-width: 640px) {
|
||||
// place-self: start;
|
||||
// }
|
||||
|
||||
@media (min-width: 768px) {
|
||||
place-self: start;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
place-self: end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
<div
|
||||
class="rounded-xl bg-gradient-to-bl from-zinc-400/75 to-zinc-600 p-px shadow-lg shadow-zinc-400/10"
|
||||
>
|
||||
<div class="lg:col-span-5 xl:col-span-4 bg-zinc-800 rounded-xl p-7">
|
||||
<h2 class="text-lg font-bold small-caps pb-3">Description</h2>
|
||||
<p class="text-base mb-3">
|
||||
<div class="background-border box-shadow-lg shadow-color-light">
|
||||
<div class="box-container">
|
||||
<h2 class="additional-detail-title">Description</h2>
|
||||
<p>
|
||||
{{ pkg.manifest.description.long }}
|
||||
</p>
|
||||
<ng-container *ngIf="pkg.manifest.replaces as replaces">
|
||||
<div *ngIf="replaces.length">
|
||||
<h2 class="text-lg font-bold small-caps pb-3">Intended to replace</h2>
|
||||
<h2 class="replaces">Intended to replace</h2>
|
||||
<tui-tag
|
||||
*ngFor="let app; index as i; of: replaces"
|
||||
size="l"
|
||||
[class]="i > 0 ? 'ml-1.5 mt-2' : 'mt-2'"
|
||||
[class]="i > 0 ? 'tag-margin-full' : 'tag-margin-empty'"
|
||||
[value]="app"
|
||||
></tui-tag>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
.box-container {
|
||||
background-color: rgb(39 39 42);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.75rem;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
grid-column: span 5 / span 5;
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
grid-column: span 4 / span 4;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-margin-full {
|
||||
margin-left: 0.375rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.tag-margin-empty {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.replaces {
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -1,12 +1,8 @@
|
||||
<a [href]="url" target="_blank" rel="noreferrer">
|
||||
<div class="flex justify-between items-center">
|
||||
<label [tuiLabel]="label" class="hover:cursor-pointer">
|
||||
<div class="link-container">
|
||||
<label [tuiLabel]="label">
|
||||
<tui-line-clamp [content]="url" [linesLimit]="1"></tui-line-clamp>
|
||||
</label>
|
||||
<img
|
||||
alt="Open Icon"
|
||||
class="block opacity-70 invert w-4"
|
||||
src="svg/open-outline.svg"
|
||||
/>
|
||||
<tui-svg src="tuiIconExternalLinkLarge"></tui-svg>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { NgModule } from '@angular/core'
|
||||
import { AdditionalLinkComponent } from './additional-link.component'
|
||||
import { TuiLabelModule } from '@taiga-ui/core'
|
||||
import { TuiLabelModule, TuiSvgModule } from '@taiga-ui/core'
|
||||
import { TuiLineClampModule } from '@taiga-ui/kit'
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, TuiLabelModule, TuiLineClampModule],
|
||||
imports: [CommonModule, TuiLabelModule, TuiLineClampModule, TuiSvgModule],
|
||||
declarations: [AdditionalLinkComponent],
|
||||
exports: [AdditionalLinkComponent],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
.link-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
label:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tui-svg {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,127 +1,93 @@
|
||||
<div
|
||||
class="rounded-xl bg-gradient-to-bl from-zinc-400/75 to-zinc-600 p-px shadow-lg shadow-zinc-400/10"
|
||||
>
|
||||
<div class="bg-zinc-800 rounded-xl p-7">
|
||||
<h2 class="text-lg font-bold small-caps pb-3">Information</h2>
|
||||
<div class="grid grid-flow-row divide-y divide-zinc-500">
|
||||
<div class="background-border shadow-color-light box-shadow-lg">
|
||||
<div class="box-container">
|
||||
<h2 class="additional-detail-title">Information</h2>
|
||||
<div class="detail-container">
|
||||
<!-- git hash -->
|
||||
<div
|
||||
*ngIf="pkg.manifest['git-hash'] as gitHash; else noHash"
|
||||
button
|
||||
detail="false"
|
||||
class="py-3 px-1 flex flex-wrap justify-between items-center"
|
||||
class="detail-container-item item-padding item-copy"
|
||||
(click)="copyService.copy(gitHash)"
|
||||
>
|
||||
<label tuiLabel="Git Hash">{{ gitHash }}</label>
|
||||
<img
|
||||
alt="Copy Icon"
|
||||
class="block opacity-70 invert w-4 hover:cursor-copy"
|
||||
src="svg/copy-outline.svg"
|
||||
/>
|
||||
<label class="git-hash-label" tuiLabel="Git Hash">{{ gitHash }}</label>
|
||||
<tui-svg src="tuiIconCopyLarge"></tui-svg>
|
||||
</div>
|
||||
<ng-template #noHash>
|
||||
<div class="py-3 px-1">
|
||||
<div class="item-padding">
|
||||
<label tuiLabel="Git Hash">Unknown</label>
|
||||
</div>
|
||||
</ng-template>
|
||||
<!-- license -->
|
||||
<div
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
class="detail-container-item item-padding item-pointer"
|
||||
(click)="presentModalMd('License')"
|
||||
>
|
||||
<div class="flex flex-wrap justify-between items-center">
|
||||
<label tuiLabel="License" class="hover:cursor-pointer">
|
||||
{{ pkg.manifest.license }}
|
||||
</label>
|
||||
<img
|
||||
alt="Open Icon"
|
||||
class="block opacity-70 invert w-4"
|
||||
src="svg/chevron-forward.svg"
|
||||
/>
|
||||
</div>
|
||||
<label tuiLabel="License">
|
||||
{{ pkg.manifest.license }}
|
||||
</label>
|
||||
<tui-svg src="tuiIconChevronRightLarge"></tui-svg>
|
||||
</div>
|
||||
<!-- instructions -->
|
||||
<div
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
class="detail-container-item item-padding item-pointer"
|
||||
(click)="presentModalMd('Instructions')"
|
||||
>
|
||||
<div class="flex flex-wrap justify-between items-center">
|
||||
<label tuiLabel="Instructions" class="hover:cursor-pointer">
|
||||
Click to view instructions
|
||||
</label>
|
||||
<img
|
||||
alt="Open Icon"
|
||||
class="block opacity-70 invert w-4"
|
||||
src="svg/chevron-forward.svg"
|
||||
/>
|
||||
</div>
|
||||
<label tuiLabel="Instructions">Click to view instructions</label>
|
||||
<tui-svg src="tuiIconChevronRightLarge"></tui-svg>
|
||||
</div>
|
||||
|
||||
<!-- versions -->
|
||||
<div
|
||||
class="detail-container-item item-padding item-pointer"
|
||||
(click)="presentAlertVersions(version)"
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
>
|
||||
<div class="flex flex-wrap justify-between items-center">
|
||||
<label tuiLabel="Other versions" class="hover:cursor-pointer">
|
||||
Click to view other versions
|
||||
</label>
|
||||
<img
|
||||
alt="Open Icon"
|
||||
class="block opacity-70 invert w-4"
|
||||
src="svg/chevron-forward.svg"
|
||||
/>
|
||||
</div>
|
||||
<ng-template #version let-data="data" let-completeWith="completeWith">
|
||||
<tui-radio-list
|
||||
class="radio"
|
||||
size="l"
|
||||
[items]="data.items"
|
||||
[itemContent]="displayEmver | tuiStringifyContent"
|
||||
[(ngModel)]="data.value"
|
||||
></tui-radio-list>
|
||||
<footer class="buttons">
|
||||
<button
|
||||
tuiButton
|
||||
appearance="secondary"
|
||||
(click)="completeWith(null)"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
appearance="secondary"
|
||||
(click)="completeWith(data.value)"
|
||||
>
|
||||
Ok
|
||||
</button>
|
||||
</footer>
|
||||
</ng-template>
|
||||
<label tuiLabel="Other versions">Click to view other versions</label>
|
||||
<tui-svg src="tuiIconChevronRightLarge"></tui-svg>
|
||||
</div>
|
||||
<ng-template #version let-data="data" let-completeWith="completeWith">
|
||||
<tui-radio-list
|
||||
size="l"
|
||||
[items]="data.items"
|
||||
[itemContent]="displayEmver | tuiStringifyContent"
|
||||
[(ngModel)]="data.value"
|
||||
></tui-radio-list>
|
||||
<footer class="buttons">
|
||||
<button tuiButton appearance="secondary" (click)="completeWith(null)">
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
appearance="secondary"
|
||||
(click)="completeWith(data.value)"
|
||||
>
|
||||
Ok
|
||||
</button>
|
||||
</footer>
|
||||
</ng-template>
|
||||
<!-- links -->
|
||||
<marketplace-additional-link
|
||||
[url]="pkg.manifest['marketing-site']"
|
||||
*ngIf="pkg.manifest['marketing-site']"
|
||||
label="Marketing Site"
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
class="item-padding item-pointer"
|
||||
></marketplace-additional-link>
|
||||
<marketplace-additional-link
|
||||
[url]="pkg.manifest['upstream-repo']"
|
||||
*ngIf="pkg.manifest['upstream-repo']"
|
||||
label="Source Repository"
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
class="item-padding item-pointer"
|
||||
></marketplace-additional-link>
|
||||
<marketplace-additional-link
|
||||
[url]="pkg.manifest['wrapper-repo']"
|
||||
*ngIf="pkg.manifest['wrapper-repo']"
|
||||
label="Wrapper Repository"
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
class="item-padding item-pointer"
|
||||
></marketplace-additional-link>
|
||||
<marketplace-additional-link
|
||||
[url]="pkg.manifest['support-site']"
|
||||
*ngIf="pkg.manifest['support-site']"
|
||||
label="Support Site"
|
||||
class="py-3 px-1 hover:bg-zinc-500/10 hover:cursor-pointer"
|
||||
class="item-padding item-pointer"
|
||||
></marketplace-additional-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
.box-container {
|
||||
background-color: rgb(39 39 42);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.75rem;
|
||||
}
|
||||
|
||||
.detail-container {
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
|
||||
& > * + * {
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 0px;
|
||||
border-color: rgb(113 113 122);
|
||||
}
|
||||
|
||||
&-item {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
&-padding {
|
||||
padding: 0.75rem 0.25rem;
|
||||
}
|
||||
|
||||
&-pointer:hover {
|
||||
cursor: pointer;
|
||||
background-color: rgb(113 113 122 / 0.1);
|
||||
}
|
||||
|
||||
&-copy:hover {
|
||||
cursor: copy;
|
||||
background-color: rgb(113 113 122 / 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .t-text {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
box-sizing: border-box;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
border-color: rgb(var(--tw-color-gray-200) / 1);
|
||||
}
|
||||
|
||||
.git-hash-label {
|
||||
font-size: 0.73rem;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
TuiStringifyContentPipeModule,
|
||||
} from '@taiga-ui/kit'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { TuiButtonModule, TuiLabelModule } from '@taiga-ui/core'
|
||||
import { TuiButtonModule, TuiLabelModule, TuiSvgModule } from '@taiga-ui/core'
|
||||
import { AdditionalLinkModule } from './additional-link/additional-link.component.module'
|
||||
|
||||
@NgModule({
|
||||
@@ -18,6 +18,7 @@ import { AdditionalLinkModule } from './additional-link/additional-link.componen
|
||||
TuiButtonModule,
|
||||
TuiLabelModule,
|
||||
AdditionalLinkModule,
|
||||
TuiSvgModule,
|
||||
],
|
||||
declarations: [AdditionalComponent],
|
||||
exports: [AdditionalComponent],
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
<div
|
||||
class="bg-zinc-700/40 rounded-xl py-3 px-5 gap-2 drop-shadow-lg hover:bg-zinc-700/70"
|
||||
>
|
||||
<div class="flex items-center gap-6">
|
||||
<tui-avatar
|
||||
class="w-16 pointer-events-none rounded-full object-cover drop-shadow-lg"
|
||||
[src]="getImage(dep.key)"
|
||||
></tui-avatar>
|
||||
<div class="mt-3">
|
||||
<div class="flex flex-wrap items-center gap-1 mb-1">
|
||||
<span class="block text-base font-medium text-zinc-50/90 line-clamp-1">
|
||||
<div class="outer-container">
|
||||
<div class="inner-container">
|
||||
<tui-avatar class="dep-img" [src]="getImage(dep.key)"></tui-avatar>
|
||||
<div class="wrapper-margin">
|
||||
<div class="inner-container-title">
|
||||
<span>
|
||||
{{ getTitle(dep.key) }}
|
||||
</span>
|
||||
<p>
|
||||
@@ -19,10 +14,10 @@
|
||||
</ng-container>
|
||||
</p>
|
||||
</div>
|
||||
<span class="text-sm text-zinc-50/70 line-clamp-1">
|
||||
<span class="inner-container-version">
|
||||
{{ dep.value.version | displayEmver }}
|
||||
</span>
|
||||
<span class="text-sm text-zinc-50/70 h-11 line-clamp-2">
|
||||
<span class="inner-container-description">
|
||||
{{ dep.value.description }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
.outer-container {
|
||||
background-color: rgb(63 63 70 / 0.4);
|
||||
border-radius: 0.75rem;
|
||||
padding: 0.75rem 1.25rem;
|
||||
gap: 0.5rem;
|
||||
filter: drop-shadow(0 10px 8px rgb(0 0 0 / 0.04))
|
||||
drop-shadow(0 4px 3px rgb(0 0 0 / 0.1));
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(63 63 70 / 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
.inner-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
|
||||
&-title {
|
||||
margin-bottom: 0.25rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
font-weight: 500;
|
||||
color: rgb(250 250 250 / 0.9);
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&-version {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: rgb(250 250 250 / 0.7);
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
|
||||
&-description {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: rgb(250 250 250 / 0.7);
|
||||
height: 2.75rem;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep .dep-img {
|
||||
width: 4rem;
|
||||
pointer-events: none;
|
||||
border-radius: 9999px;
|
||||
object-fit: cover;
|
||||
filter: drop-shadow(0 10px 8px rgb(0 0 0 / 0.04))
|
||||
drop-shadow(0 4px 3px rgb(0 0 0 / 0.1));
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.wrapper-margin {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
@@ -7,35 +7,28 @@ import { MimeTypePipeModule } from '../../../pipes/mime-type.pipe'
|
||||
@Component({
|
||||
selector: 'marketplace-package-hero',
|
||||
template: `
|
||||
<div class="flex justify-center mt-10 md:mt-0 z-0">
|
||||
<div
|
||||
class="flex flex-col w-full h-[32vh] xs:h-[26vh] md:min-h-[14rem] relative rounded-3xl pt-16 px-8 shadow-lg"
|
||||
>
|
||||
<div class="outer-container">
|
||||
<div class="inner-container box-shadow-lg">
|
||||
<!-- icon -->
|
||||
<img
|
||||
[src]="pkg | mimeType | trustUrl"
|
||||
class="w-24 h-24 pointer-events-none rounded-full object-cover shadow-lg absolute -top-9 left-7 z-10"
|
||||
class="box-shadow-lg"
|
||||
alt="{{ pkg.manifest.title }} Icon"
|
||||
/>
|
||||
<!-- color background -->
|
||||
<div
|
||||
class="overflow-hidden absolute w-full h-full top-0 left-0 rounded-3xl bg-zinc-800"
|
||||
>
|
||||
<div class="color-background">
|
||||
<img
|
||||
[src]="pkg | mimeType | trustUrl"
|
||||
class="absolute object-cover pointer-events-none w-[200%] h-[200%] max-w-[200%] blur-[100px] saturate-150 rounded-full"
|
||||
alt="{{ pkg.manifest.title }} background image"
|
||||
/>
|
||||
</div>
|
||||
<!-- background darkening overlay -->
|
||||
<div
|
||||
class="overflow-hidden absolute w-full h-full top-0 left-0 rounded-3xl bg-zinc-700 opacity-70"
|
||||
></div>
|
||||
<div class="my-4 text-zinc-50 mix-blend-plus-lighter">
|
||||
<h2 class="text-2xl font-medium line-clamp-1 mb-1">
|
||||
<div class="dark-overlay"></div>
|
||||
<div class="inner-container-title">
|
||||
<h2>
|
||||
{{ pkg.manifest.title }}
|
||||
</h2>
|
||||
<p class="block text-base line-clamp-2">
|
||||
<p>
|
||||
{{ pkg.manifest.description.short }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -44,7 +37,111 @@ import { MimeTypePipeModule } from '../../../pipes/mime-type.pipe'
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: [],
|
||||
styles: [
|
||||
`
|
||||
.outer-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 2.5rem;
|
||||
z-index: 0;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
margin-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.inner-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 32vh;
|
||||
position: relative;
|
||||
border-radius: 1.5rem;
|
||||
padding: 4rem 2rem 0 2rem;
|
||||
|
||||
@media (min-width: 376px) {
|
||||
height: 26vh;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
min-height: 14rem;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 6rem;
|
||||
height: 6rem;
|
||||
pointer-events: none;
|
||||
border-radius: 9999px;
|
||||
object-fit: cover;
|
||||
position: absolute;
|
||||
top: -2.25rem;
|
||||
left: 1.75rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.inner-container-title {
|
||||
margin: 1rem 0;
|
||||
color: rgb(250 250 250);
|
||||
mix-blend-mode: plus-lighter;
|
||||
z-index: 1;
|
||||
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
p {
|
||||
display: block;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.color-background {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: -50;
|
||||
border-radius: 1.5rem;
|
||||
background-color: rgb(39 39 42);
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
object-fit: cover;
|
||||
pointer-events: none;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
max-width: 200%;
|
||||
filter: blur(100px) saturate(1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.dark-overlay {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-radius: 1.5rem;
|
||||
background-color: rgb(63 63 70);
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
`,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [CommonModule, SharedPipesModule, MimeTypePipeModule],
|
||||
|
||||
@@ -18,11 +18,7 @@ import { PolymorpheusContent } from '@tinkoff/ng-polymorpheus'
|
||||
@Component({
|
||||
selector: 'marketplace-package-screenshots',
|
||||
template: `
|
||||
<div
|
||||
*ngIf="pkg.screenshots"
|
||||
tuiCarouselButtons
|
||||
class="flex items-center content-center m-0 lg:-ml-14 lg:-mr-14 lg:min-h-80 lg:h-80 2xl:h-full"
|
||||
>
|
||||
<div *ngIf="pkg.screenshots" tuiCarouselButtons class="outer-container">
|
||||
<button
|
||||
tuiIconButton
|
||||
appearance="flat"
|
||||
@@ -35,27 +31,27 @@ import { PolymorpheusContent } from '@tinkoff/ng-polymorpheus'
|
||||
#carousel
|
||||
[itemsCount]="isMobile ? 1 : 2"
|
||||
[(index)]="index"
|
||||
class="overflow-y-hidden overflow-x-scroll carousel overflow-hidden"
|
||||
class="carousel"
|
||||
>
|
||||
<ng-container *ngFor="let item of pkg.screenshots; let i = index">
|
||||
<div
|
||||
*tuiItem
|
||||
draggable="false"
|
||||
[class.item_active]="i === index + 1"
|
||||
class="object-cover overflow-hidden rounded-lg md:rounded-xl border border-zinc-400/30 hover:cursor-pointer shadow-lg shadow-zinc-400/10"
|
||||
class="screenshot-item box-shadow-lg"
|
||||
>
|
||||
<img
|
||||
#template
|
||||
alt="Service screenshot"
|
||||
src="assets/img/temp/{{ item }}"
|
||||
class="w-full h-full rounded-lg md:rounded-xl"
|
||||
class="screenshot-item-img"
|
||||
(click)="presentModalImg(dialogTemplate)"
|
||||
/>
|
||||
<ng-template #dialogTemplate let-observer>
|
||||
<img
|
||||
alt="Service screenshot"
|
||||
src="assets/img/temp/{{ item }}"
|
||||
class="rounded-none"
|
||||
class="screenshot-item-img-enlarged"
|
||||
/>
|
||||
</ng-template>
|
||||
</div>
|
||||
@@ -71,7 +67,65 @@ import { PolymorpheusContent } from '@tinkoff/ng-polymorpheus'
|
||||
></button>
|
||||
</div>
|
||||
`,
|
||||
styles: [],
|
||||
styles: [
|
||||
`
|
||||
.outer-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
margin: 0px;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
margin-left: -3.5rem;
|
||||
margin-right: -3.5rem;
|
||||
min-height: 20rem;
|
||||
height: 20rem;
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel {
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.screenshot-item {
|
||||
--tw-shadow-color: rgb(161 161 170 / 0.1);
|
||||
--tw-shadow: var(--tw-shadow-colored);
|
||||
|
||||
object-fit: cover;
|
||||
overflow: hidden;
|
||||
border-radius: 0.5rem;
|
||||
border-width: 1px;
|
||||
border-color: rgb(161 161 170 / 0.3);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.screenshot-item-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
border-radius: 0.75rem;
|
||||
}
|
||||
|
||||
.screenshot-item-img-enlarged {
|
||||
border-radius: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [CommonModule, TuiCarouselModule, TuiButtonModule],
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{html,ts}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
fontFamily: {
|
||||
sans: ['Montserrat', 'sans-serif'],
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@start9labs/shared",
|
||||
"version": "0.3.6",
|
||||
"version": "0.3.9",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^17.0.6",
|
||||
"@angular/core": "^17.0.6",
|
||||
|
||||
@@ -41,7 +41,7 @@ import { SetupService } from '../../services/setup.service'
|
||||
padding: 1rem;
|
||||
margin: 1.5rem;
|
||||
text-align: center;
|
||||
// TODO: Theme
|
||||
/* TODO: Theme */
|
||||
background: #e0e0e0;
|
||||
color: #333;
|
||||
--tui-clear-inverse: rgba(0, 0, 0, 0.1);
|
||||
@@ -56,7 +56,7 @@ import { SetupService } from '../../services/setup.service'
|
||||
text-align: left;
|
||||
overflow: hidden;
|
||||
border-radius: 2rem;
|
||||
// TODO: Theme
|
||||
/* TODO: Theme */
|
||||
background: #181818;
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -4,4 +4,15 @@
|
||||
|
||||
:host ::ng-deep img {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
:host ::ng-deep h1,
|
||||
:host ::ng-deep h2,
|
||||
:host ::ng-deep h3,
|
||||
:host ::ng-deep h4,
|
||||
:host ::ng-deep h5,
|
||||
:host ::ng-deep h6,
|
||||
:host ::ng-deep hr,
|
||||
:host ::ng-deep p {
|
||||
margin: revert;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Log } from '../types/api'
|
||||
import { toLocalIsoString } from './to-local-iso-string'
|
||||
import Convert from 'ansi-to-html'
|
||||
|
||||
const Convert = require('ansi-to-html')
|
||||
const CONVERT = new Convert({
|
||||
bg: 'transparent',
|
||||
colors: { 4: 'Cyan' },
|
||||
|
||||
@@ -86,10 +86,12 @@ ion-modal {
|
||||
}
|
||||
|
||||
.divider {
|
||||
background: linear-gradient(90deg,
|
||||
var(--ion-color-light) 0,
|
||||
var(--ion-color-dark) 50%,
|
||||
var(--ion-color-light) 100%);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--ion-color-light) 0,
|
||||
var(--ion-color-dark) 50%,
|
||||
var(--ion-color-light) 100%
|
||||
);
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
@@ -112,11 +114,11 @@ ion-modal {
|
||||
}
|
||||
|
||||
.color-success-shade {
|
||||
color: var(--ion-color-success-shade)
|
||||
color: var(--ion-color-success-shade);
|
||||
}
|
||||
|
||||
.color-primary-shade {
|
||||
color: var(--ion-color-primary-shade)
|
||||
color: var(--ion-color-primary-shade);
|
||||
}
|
||||
|
||||
@keyframes ellipsis-dot {
|
||||
@@ -167,3 +169,63 @@ a {
|
||||
gap: 16px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
/* marketplace */
|
||||
.background-border {
|
||||
border-radius: 0.75rem;
|
||||
background-image: linear-gradient(
|
||||
to bottom left,
|
||||
rgb(161 161 170 / 0.75),
|
||||
#52525b
|
||||
);
|
||||
padding: 1px;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.box-shadow-lg {
|
||||
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1),
|
||||
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color),
|
||||
0 4px 6px -4px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
0 0 #0000,
|
||||
0 0 #0000,
|
||||
var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-color-light {
|
||||
--tw-shadow-color: rgb(161 161 170 / 0.1);
|
||||
--tw-shadow: var(--tw-shadow-colored);
|
||||
}
|
||||
|
||||
.additional-detail-title {
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
font-weight: 700;
|
||||
padding-bottom: 0.75rem;
|
||||
font-variant: all-small-caps;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
margin-top: 0.5rem;
|
||||
|
||||
:first-child {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
hr,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -86,10 +86,49 @@
|
||||
--ion-color-step-900: #e7e7e7;
|
||||
--ion-color-step-950: #f3f3f3;
|
||||
|
||||
--alt-red: #FF4961;
|
||||
--alt-orange: #F89248;
|
||||
--alt-yellow: #E5D53E;
|
||||
--alt-green: #3DCF6F;
|
||||
--alt-blue: #00A8A8;
|
||||
--alt-purple: #9747FF;
|
||||
--alt-red: #ff4961;
|
||||
--alt-orange: #f89248;
|
||||
--alt-yellow: #e5d53e;
|
||||
--alt-green: #3dcf6f;
|
||||
--alt-blue: #00a8a8;
|
||||
--alt-purple: #9747ff;
|
||||
|
||||
--portal-header-height: 56px;
|
||||
|
||||
// @TODO rename when make style lib
|
||||
--tw-color-black: 0 0 0;
|
||||
--tw-color-white: 255 255 255;
|
||||
--tw-color-slate-50: 248 250 252;
|
||||
--tw-color-slate-100: 241 245 249;
|
||||
--tw-color-slate-200: 226 232 240;
|
||||
--tw-color-slate-300: 203 213 225;
|
||||
--tw-color-slate-400: 148 163 184;
|
||||
--tw-color-slate-500: 100 116 139;
|
||||
--tw-color-slate-600: 71 85 105;
|
||||
--tw-color-slate-700: 51 65 85;
|
||||
--tw-color-slate-800: 30 41 59;
|
||||
--tw-color-slate-900: 15 23 42;
|
||||
--tw-color-slate-950: 2 6 23;
|
||||
--tw-color-gray-50: 249 250 251;
|
||||
--tw-color-gray-100: 243 244 246;
|
||||
--tw-color-gray-200: 229 231 235;
|
||||
--tw-color-gray-300: 209 213 219;
|
||||
--tw-color-gray-400: 156 163 175;
|
||||
--tw-color-gray-500: 107 114 128;
|
||||
--tw-color-gray-600: 75 85 99;
|
||||
--tw-color-gray-700: 55 65 81;
|
||||
--tw-color-gray-800: 31 41 55;
|
||||
--tw-color-gray-900: 17 24 39;
|
||||
--tw-color-gray-950: 3 7 18;
|
||||
--tw-color-zinc-50: 250 250 250;
|
||||
--tw-color-zinc-100: 244 244 245;
|
||||
--tw-color-zinc-200: 228 228 231;
|
||||
--tw-color-zinc-300: 212 212 216;
|
||||
--tw-color-zinc-400: 161 161 170;
|
||||
--tw-color-zinc-500: 113 113 122;
|
||||
--tw-color-zinc-600: 82 82 91;
|
||||
--tw-color-zinc-700: 63 63 70;
|
||||
--tw-color-zinc-800: 39 39 42;
|
||||
--tw-color-zinc-900: 24 24 27;
|
||||
--tw-color-zinc-950: 9 9 11;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import { MarketplaceService } from 'src/app/services/marketplace.service'
|
||||
import { hasCurrentDeps } from 'src/app/util/has-deps'
|
||||
import { getAllPackages } from 'src/app/util/get-package-data'
|
||||
import { dryUpdate } from 'src/app/util/dry-update'
|
||||
import { SidebarService } from 'src/app/services/sidebar.service'
|
||||
import { MarketplaceAlertsService } from '../services/alerts.service'
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -15,21 +15,28 @@ import { MARKETPLACE_REGISTRY } from '../modals/registry.component'
|
||||
tuiIconButton
|
||||
type="button"
|
||||
appearance="icon"
|
||||
icon="tuiIconRepeat"
|
||||
icon="tuiIconRepeatLarge"
|
||||
(click)="changeRegistry()"
|
||||
>
|
||||
Change Registry
|
||||
</button>
|
||||
<button
|
||||
slot="mobile"
|
||||
class="flex gap-2 p-5 text-base"
|
||||
(click)="changeRegistry()"
|
||||
>
|
||||
<tui-icon tuiAppearance="icon" icon="tuiIconRepeat"></tui-icon>
|
||||
<button slot="mobile" class="mobile-button" (click)="changeRegistry()">
|
||||
<tui-icon tuiAppearance="icon" icon="tuiIconRepeatLarge"></tui-icon>
|
||||
Change Registry
|
||||
</button>
|
||||
</menu>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.mobile-button {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
padding: 1.25rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
`,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [MenuModule, TuiButtonModule, TuiIconModule, TuiAppearanceModule],
|
||||
})
|
||||
|
||||
@@ -7,7 +7,11 @@ import { ConfigService } from 'src/app/services/config.service'
|
||||
standalone: true,
|
||||
selector: 'marketplace-notification',
|
||||
template: `
|
||||
<tui-notification [status]="status || 'warning'" icon="" class="m-4">
|
||||
<tui-notification
|
||||
[status]="status || 'warning'"
|
||||
icon=""
|
||||
class="notification-wrapper"
|
||||
>
|
||||
@switch (status) {
|
||||
@case ('success') {
|
||||
Services from this registry are packaged and maintained by the Start9
|
||||
@@ -48,6 +52,13 @@ import { ConfigService } from 'src/app/services/config.service'
|
||||
}
|
||||
</tui-notification>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
.notification-wrapper {
|
||||
margin: 1rem;
|
||||
}
|
||||
`,
|
||||
],
|
||||
imports: [TuiNotificationModule],
|
||||
})
|
||||
export class MarketplaceNotificationComponent {
|
||||
|
||||
@@ -30,7 +30,7 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
direction: 'right';
|
||||
autoWidth: true
|
||||
"
|
||||
class="overflow-y-auto max-w-full md:max-w-[30rem]"
|
||||
class="preview-wrapper"
|
||||
[pkg]="pkg"
|
||||
(tuiActiveZoneChange)="toggle($event)"
|
||||
>
|
||||
@@ -38,7 +38,7 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
tuiAutoFocus
|
||||
slot="close"
|
||||
size="xs"
|
||||
class="place-self-end"
|
||||
class="close-button"
|
||||
tuiIconButton
|
||||
type="button"
|
||||
appearance="icon"
|
||||
@@ -47,7 +47,7 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
></button>
|
||||
<marketplace-controls
|
||||
slot="controls"
|
||||
class="flex justify-start gap-2"
|
||||
class="controls-wrapper"
|
||||
[pkg]="pkg"
|
||||
[localPkg]="pkg.manifest.id | toLocal | async"
|
||||
/>
|
||||
@@ -70,6 +70,25 @@ import { MarketplaceSidebarService } from '../services/sidebar.service'
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-wrapper {
|
||||
overflow-y: auto;
|
||||
max-width: 100%;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
max-width: 30rem;
|
||||
}
|
||||
}
|
||||
|
||||
.close-button {
|
||||
place-self: end;
|
||||
}
|
||||
|
||||
.controls-wrapper {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
`,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -17,30 +17,26 @@ import { MarketplaceSidebarsComponent } from './components/sidebars.component'
|
||||
standalone: true,
|
||||
template: `
|
||||
<marketplace-menu />
|
||||
<div
|
||||
class="sm:pl-[34vw] md:pl-[28vw] lg:pl-[22vw] 2xl:pl-[280px] min-h-screen flex justify-between overflow-auto scroll-smooth"
|
||||
>
|
||||
<div class="pt-24 sm:pt-3 md:pb-10 md:px-8">
|
||||
<div class="marketplace-content-wrapper">
|
||||
<div class="marketplace-content-inner">
|
||||
<marketplace-notification [url]="(details$ | async)?.url || ''" />
|
||||
<div class="mt-8 px-6 mb-10">
|
||||
<h1 class="text-4xl sm:text-5xl font-bold text-zinc-50/80">
|
||||
<div class="title-wrapper">
|
||||
<h1>
|
||||
{{ category$ | async | titlecase }}
|
||||
</h1>
|
||||
</div>
|
||||
@if (filtered$ | async; as filtered) {
|
||||
<section
|
||||
class="p-6 md:p-8 grid grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3 gap-16 list-none"
|
||||
>
|
||||
<section class="marketplace-content-list">
|
||||
@for (pkg of filtered; track $index) {
|
||||
<marketplace-tile
|
||||
[pkg]="pkg"
|
||||
[style.--animation-order]="$index"
|
||||
class="block h-full"
|
||||
class="tile-wrapper"
|
||||
/>
|
||||
}
|
||||
</section>
|
||||
} @else {
|
||||
<h1 class="text-xl pl-6">
|
||||
<h1 class="loading-text">
|
||||
Loading
|
||||
<span class="loading-dots"></span>
|
||||
</h1>
|
||||
@@ -58,6 +54,96 @@ import { MarketplaceSidebarsComponent } from './components/sidebars.component'
|
||||
background: #18181b url('/assets/img/background.png') no-repeat top
|
||||
right;
|
||||
}
|
||||
|
||||
::ng-deep menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::ng-deep button {
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.marketplace-content {
|
||||
&-wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
overflow: auto;
|
||||
scroll-behavior: smooth;
|
||||
min-height: 100vh;
|
||||
|
||||
@media (min-width: 640px) {
|
||||
padding-left: 34vw;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
padding-left: 28vw;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
padding-left: 22vw;
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
padding-left: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
&-inner {
|
||||
padding-top: 6rem;
|
||||
|
||||
@media (min-width: 640px) {
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
padding: 0 2rem 2.5rem 2rem;
|
||||
}
|
||||
|
||||
.title-wrapper {
|
||||
margin: 2rem 0 2.5rem 0;
|
||||
padding: 0 1.5rem;
|
||||
|
||||
h1 {
|
||||
font-size: 2.25rem;
|
||||
line-height: 2.5rem;
|
||||
font-weight: 700;
|
||||
color: rgb(250 250 250 / 0.8);
|
||||
|
||||
@media (min-width: 640px) {
|
||||
font-size: 3rem;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
gap: 4rem;
|
||||
list-style-type: none;
|
||||
padding: 1.5rem;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
padding: 2rem;
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
@media (min-width: 1536px) {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.tile-wrapper {
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
`,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -22,7 +22,7 @@ import { Router } from '@angular/router'
|
||||
@Component({
|
||||
selector: 'marketplace-preview',
|
||||
template: `
|
||||
<div class="grid gap-8 p-7 justify-center">
|
||||
<div class="outer-container">
|
||||
<ng-content select="[slot=close]" />
|
||||
<marketplace-package-hero [pkg]="pkg">
|
||||
<ng-content select="[slot=controls]" />
|
||||
@@ -38,17 +38,13 @@ import { Router } from '@angular/router'
|
||||
View more details
|
||||
</a>
|
||||
}
|
||||
<div class="grid grid-cols-1 gap-x-8">
|
||||
<div class="inner-container">
|
||||
<marketplace-about [pkg]="pkg" />
|
||||
@if (!(pkg.manifest.dependencies | empty)) {
|
||||
<div
|
||||
class="rounded-xl bg-gradient-to-bl from-zinc-400/75 to-zinc-600 p-px shadow-lg shadow-zinc-400/10 mt-6"
|
||||
>
|
||||
<div class="lg:col-span-5 xl:col-span-4 bg-zinc-800 rounded-xl p-7">
|
||||
<h2 class="text-lg font-bold small-caps my-2 pb-3">
|
||||
Dependencies
|
||||
</h2>
|
||||
<div class="grid grid-row-auto gap-3">
|
||||
<div class="background-border shadow-color-light box-shadow-lg">
|
||||
<div class="dependencies-container">
|
||||
<h2>Dependencies</h2>
|
||||
<div class="dependencies-list">
|
||||
@for (
|
||||
dep of pkg.manifest.dependencies | keyvalue;
|
||||
track $index
|
||||
@@ -64,11 +60,64 @@ import { Router } from '@angular/router'
|
||||
</div>
|
||||
}
|
||||
<release-notes [pkg]="pkg" />
|
||||
<marketplace-additional class="mt-6" [pkg]="pkg" />
|
||||
<marketplace-additional class="additional-wrapper" [pkg]="pkg" />
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: [':host { pointer-events: auto }'],
|
||||
styles: [
|
||||
`
|
||||
:host {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.outer-container {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
padding: 1.75rem;
|
||||
}
|
||||
|
||||
.inner-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
column-gap: 2rem;
|
||||
}
|
||||
|
||||
.dependencies {
|
||||
&-container {
|
||||
background-color: rgb(39 39 42);
|
||||
border-radius: 0.75rem;
|
||||
padding: 1.75rem;
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
grid-column: span 5 / span 5;
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
grid-column: span 4 / span 4;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
font-weight: 700;
|
||||
margin: 0.5rem 0;
|
||||
padding-bottom: 0.75rem;
|
||||
font-variant: all-small-caps;
|
||||
}
|
||||
}
|
||||
|
||||
&-list {
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.additional-wrapper {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
`,
|
||||
],
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
|
||||
@@ -102,7 +102,7 @@ export module Mock {
|
||||
icon: 'icon.png',
|
||||
},
|
||||
'release-notes':
|
||||
'Dual funded channels! And lots more amazing new features. Also includes several bugfixes and performance enhancements.',
|
||||
'* Dual funded channels! And lots more amazing new features. Also includes several bugfixes and performance enhancements.',
|
||||
license: 'MIT',
|
||||
'wrapper-repo': 'https://github.com/start9labs/lnd-wrapper',
|
||||
'upstream-repo': 'https://github.com/lightningnetwork/lnd',
|
||||
|
||||
@@ -104,7 +104,8 @@ export class MockApiService extends ApiService {
|
||||
|
||||
async getStatic(url: string): Promise<string> {
|
||||
await pauseFor(2000)
|
||||
return '' // markdown
|
||||
return `* Test markdown instructions
|
||||
* Test markdown instructions with [link](https://start9.com)`
|
||||
}
|
||||
|
||||
async uploadPackage(guid: string, body: Blob): Promise<void> {
|
||||
@@ -458,6 +459,7 @@ export class MockApiService extends ApiService {
|
||||
'messaging',
|
||||
'social',
|
||||
'alt coin',
|
||||
'ai',
|
||||
],
|
||||
}
|
||||
return info
|
||||
@@ -466,7 +468,8 @@ export class MockApiService extends ApiService {
|
||||
} else if (path.startsWith('/package/v0/release-notes')) {
|
||||
return Mock.ReleaseNotes
|
||||
} else if (path.includes('instructions') || path.includes('license')) {
|
||||
return '' // markdown
|
||||
return `* Test markdown instructions
|
||||
* Test markdown instructions with [link](https://start9.com)`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import '@taiga-ui/core/styles/taiga-ui-local';
|
||||
|
||||
@font-face {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ['./src/**/*.{html,ts}', '../marketplace/src/**/*.{html,ts}'],
|
||||
theme: {
|
||||
extend: {
|
||||
screens: {
|
||||
xs: '376px',
|
||||
'3xl': '1792px',
|
||||
'4xl': '2048px',
|
||||
},
|
||||
colors: {
|
||||
folly: '#FF4961',
|
||||
lime: '#BCFF49',
|
||||
cyan: '#49FFE7',
|
||||
veronica: '#9747ff',
|
||||
tangerine: '#ff8c49',
|
||||
royal: '#4961ff',
|
||||
background: '#222428',
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Montserrat', 'sans-serif'],
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user