init commit

This commit is contained in:
rxliuli
2025-11-04 05:03:50 +08:00
commit bce557cc2d
1396 changed files with 172991 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import type { ProductMediaItem } from '@jet-app/app-store/api/models';
import Artwork from '~/components/Artwork.svelte';
import Video from '~/components/jet/Video.svelte';
export let item: ProductMediaItem;
</script>
{#if item.screenshot}
<article>
<Artwork artwork={item.screenshot} profile="screenshot-mac" />
</article>
{:else if item.video}
<article>
<Video autoplay video={item.video} profile="screenshot-mac" />
</article>
{/if}
<style>
article {
overflow: hidden;
}
article :global(.video) {
aspect-ratio: 16/10;
}
article :global(video) {
object-fit: cover;
}
</style>

View File

@@ -0,0 +1,89 @@
<script lang="ts">
import type {
ProductMediaItem,
MediaType,
} from '@jet-app/app-store/api/models';
import Artwork from '~/components/Artwork.svelte';
import Video from '~/components/jet/Video.svelte';
export let item: ProductMediaItem;
export let hasPortraitMedia: boolean;
export let mediaType: MediaType | undefined;
</script>
{#if item.screenshot || item.video}
<article>
<div
class="artwork-container"
class:ipad-pro-2018={mediaType === 'ipadPro_2018'}
class:ipad-11={mediaType === 'ipad_11'}
class:portrait={hasPortraitMedia}
>
{#if item.screenshot}
<Artwork
artwork={item.screenshot}
profile={hasPortraitMedia
? 'screenshot-pad-portrait'
: 'screenshot-pad'}
/>
{:else if item.video}
<Video
autoplay
video={item.video}
profile={hasPortraitMedia
? 'screenshot-pad-portrait'
: 'screenshot-pad'}
/>
{/if}
</div>
</article>
{/if}
<style>
.artwork-container,
.artwork-container :global(video) {
mask-position: center;
mask-repeat: no-repeat;
mask-size: contain;
border-radius: 1.3% / 1.9%;
overflow: hidden;
/* This `transform` is required to make the `overflow: hidden` clip properly on Chrome */
transform: translateZ(0);
}
.artwork-container.portrait {
aspect-ratio: 3/4;
background: var(--systemQuaternary);
}
.artwork-container.portrait,
.artwork-container.portrait :global(video) {
border-radius: 1.9% / 1.3%;
}
.ipad-pro-2018,
.ipad-pro-2018 :global(video) {
mask-image: url('/assets/images/masks/ipad-pro-2018-mask-landscape.svg');
}
.ipad-pro-2018.portrait,
.ipad-pro-2018.portrait :global(video) {
mask-image: url('/assets/images/masks/ipad-pro-2018-mask.svg');
}
.ipad-11,
.ipad-11 :global(video) {
mask-image: url('/assets/images/masks/ipad-11-mask-landscape.svg');
}
.ipad-11.portrait,
.ipad-11.portrait :global(video) {
mask-image: url('/assets/images/masks/ipad-11-mask.svg');
}
.artwork-container :global(video):fullscreen {
mask-image: none;
border-radius: 0;
}
</style>

View File

@@ -0,0 +1,142 @@
<script lang="ts">
import type {
ProductMediaItem,
MediaType,
} from '@jet-app/app-store/api/models';
import { getAspectRatio } from '@amp/web-app-components/src/components/Artwork/utils/artProfile';
import Artwork from '~/components/Artwork.svelte';
import Video from '~/components/jet/Video.svelte';
import type { NamedProfile } from '~/config/components/artwork';
export let item: ProductMediaItem;
export let hasPortraitMedia: boolean;
export let mediaType: MediaType | undefined;
const getArtworkProfile = (
mediaType: MediaType | undefined,
hasPortraitMedia: boolean,
): NamedProfile => {
const suffix = hasPortraitMedia ? '_portrait' : '';
// Map specific media types to their artwork profile names
const mediaTypeProfiles: Record<string, string> = {
iphone_6_5: 'screenshot-iphone_6_5',
iphone_5_8: 'screenshot-iphone_5_8',
iphone_d74: 'screenshot-iphone_d74',
};
const baseProfile =
mediaType && mediaTypeProfiles[mediaType]
? mediaTypeProfiles[mediaType]
: 'screenshot-phone';
return `${baseProfile}${suffix}` as NamedProfile;
};
$: isLandscapeScreenshot =
item.screenshot && item.screenshot.width > item.screenshot.height;
$: profile = getArtworkProfile(mediaType, !isLandscapeScreenshot);
$: restOfShelfAspectRatio = getAspectRatio(
getArtworkProfile(mediaType, hasPortraitMedia),
);
</script>
{#if item.screenshot || item.video}
<article
class:with-rotated-artwork={isLandscapeScreenshot && hasPortraitMedia}
style:--aspect-ratio={`${restOfShelfAspectRatio}`}
>
<div
class="artwork-container"
class:iphone-6-5={mediaType === 'iphone_6_5'}
class:iphone-5-8={mediaType === 'iphone_5_8'}
class:iphone-d74={mediaType === 'iphone_d74'}
class:portrait={hasPortraitMedia}
>
{#if item.screenshot}
<Artwork
{profile}
artwork={item.screenshot}
disableAutoCenter={true}
withoutBorder={true}
/>
{:else if item.video}
<Video autoplay video={item.video} {profile} />
{/if}
</div>
</article>
{/if}
<style>
article.with-rotated-artwork {
position: relative;
aspect-ratio: var(--aspect-ratio);
}
/*
* For iPhone screenshots that are landscape, but in a shelf/list with portrait screenshots,
* as denoted by `hasPortraitMedia`, we rotate the landscape screenshot to be in the portrait
* orientation, and scale it up so it fills the container.
*/
article.with-rotated-artwork .artwork-container {
position: absolute;
top: 50%;
left: 50%;
height: auto;
width: calc((1 / var(--aspect-ratio)) * 100%);
transform: translate(-50%, -50%) rotate(-90deg);
transform-origin: center;
}
.artwork-container,
.artwork-container :global(video) {
mask-position: center;
mask-repeat: no-repeat;
mask-size: 100%;
border-radius: 20px;
overflow: hidden;
/* This `transform` is required to make the `overflow: hidden` clip properly on Chrome */
transform: translateZ(0);
}
.iphone-5-8,
.iphone-5-8 :global(video) {
/* need to confirm with design for correct value */
border-radius: 23px;
mask-image: url('/assets/images/masks/iphone-5-8-mask-landscape.svg');
}
.iphone-5-8.portrait,
.iphone-5-8.portrait :global(video) {
mask-image: url('/assets/images/masks/iphone-5-8-mask.svg');
}
.iphone-6-5,
.iphone-6-5 :global(video) {
/* need to confirm with design for correct value */
border-radius: 21px;
mask-image: url('/assets/images/masks/iphone-6-5-mask-landscape.svg');
}
.iphone-6-5.portrait,
.iphone-6-5.portrait :global(video) {
mask-image: url('/assets/images/masks/iphone-6-5-mask.svg');
}
.iphone-d74,
.iphone-d74 :global(video) {
border-radius: 5.7% / 12.8%;
}
.iphone-d74.portrait,
.iphone-d74.portrait :global(video) {
border-radius: 12.8% / 5.7%;
}
.artwork-container :global(video):fullscreen {
mask-image: none;
border-radius: 0;
object-fit: contain;
}
</style>

View File

@@ -0,0 +1,34 @@
<script lang="ts">
import type { ProductMediaItem } from '@jet-app/app-store/api/models';
import Artwork from '~/components/Artwork.svelte';
import Video from '~/components/jet/Video.svelte';
export let item: ProductMediaItem;
</script>
{#if item.screenshot || item.video}
<article>
<div class="artwork-container">
{#if item.screenshot}
<Artwork artwork={item.screenshot} profile="screenshot-tv" />
{:else if item.video}
<Video autoplay video={item.video} profile="screenshot-tv" />
{/if}
</div>
</article>
{/if}
<style>
.artwork-container,
.artwork-container :global(video) {
border-radius: 1.3% / 1.9%;
overflow: hidden;
/* This `transform` is required to make the `overflow: hidden` clip properly on Chrome */
transform: translateZ(0);
}
.artwork-container :global(video):fullscreen {
border-radius: 0;
}
</style>

View File

@@ -0,0 +1,38 @@
<script lang="ts">
import type { ProductMediaItem } from '@jet-app/app-store/api/models';
import Artwork from '~/components/Artwork.svelte';
import Video from '~/components/jet/Video.svelte';
export let item: ProductMediaItem;
</script>
{#if item.screenshot || item.video}
<article>
<div class="artwork-container">
{#if item.screenshot}
<Artwork
artwork={item.screenshot}
profile="screenshot-vision"
/>
{:else if item.video}
<Video
autoplay
video={item.video}
profile="screenshot-vision"
/>
{/if}
</div>
</article>
{/if}
<style>
.artwork-container,
.artwork-container :global(video) {
border-radius: 20px;
overflow: hidden;
}
.artwork-container :global(video):fullscreen {
border-radius: 0;
}
</style>

View File

@@ -0,0 +1,50 @@
<script lang="ts">
import type {
ProductMediaItem,
MediaType,
} from '@jet-app/app-store/api/models';
import Artwork from '~/components/Artwork.svelte';
export let item: ProductMediaItem;
export let mediaType: MediaType | undefined;
</script>
{#if item.screenshot}
<article>
<div
class="artwork-container"
class:apple-watch-2018={mediaType === 'appleWatch_2018'}
class:apple-watch-2021={mediaType === 'appleWatch_2021'}
class:apple-watch-2022={mediaType === 'appleWatch_2022'}
class:apple-watch-2024={mediaType === 'appleWatch_2024'}
>
<Artwork artwork={item.screenshot} profile="screenshot-watch" />
</div>
</article>
{/if}
<style>
.artwork-container {
mask-position: center;
mask-size: contain;
mask-repeat: no-repeat;
border-radius: 12px;
overflow: hidden;
}
.apple-watch-2018 {
mask-image: url('/assets/images/masks/apple-watch-2018-mask.svg');
}
.apple-watch-2021 {
mask-image: url('/assets/images/masks/apple-watch-2021-mask.svg');
}
.apple-watch-2022 {
mask-image: url('/assets/images/masks/apple-watch-2022-mask.svg');
}
.apple-watch-2024 {
mask-image: url('/assets/images/masks/apple-watch-2024-mask.svg');
}
</style>