From bce557cc2dc767628bed6aac87301a1be7c5431b Mon Sep 17 00:00:00 2001
From: rxliuli <rxliuli@gmail.com>
Date: Tue, 4 Nov 2025 05:03:50 +0800
Subject: init commit

---
 src/components/Artwork.svelte | 118 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)
 create mode 100644 src/components/Artwork.svelte

(limited to 'src/components/Artwork.svelte')

diff --git a/src/components/Artwork.svelte b/src/components/Artwork.svelte
new file mode 100644
index 0000000..04de1d4
--- /dev/null
+++ b/src/components/Artwork.svelte
@@ -0,0 +1,118 @@
+<script lang="ts" context="module">
+    import type { Artwork as JetArtworkType } from '@jet-app/app-store/api/models';
+    import type {
+        Artwork as ComponentArtworkType,
+        Profile as ArtworkProfile,
+        CropCode,
+        ImageSizes,
+    } from '@amp/web-app-components/src/components/Artwork/types';
+
+    import type { NamedProfile } from '~/config/components/artwork';
+
+    /**
+     * Creates a {@linkcode Profile} on-the-fly based on the properties of
+     * the {@linkcode artwork}
+     */
+    export function getNaturalProfile(
+        artwork: JetArtworkType,
+        imageSizes: ImageSizes = [artwork.width],
+    ): ArtworkProfile {
+        const aspectRatio = artwork.width / artwork.height;
+
+        return [imageSizes, aspectRatio, artwork.crop as CropCode];
+    }
+
+    export type Profile = NamedProfile | ArtworkProfile;
+</script>
+
+<script lang="ts">
+    import type { ImageSettings } from '@amp/web-app-components/src/components/Artwork/types';
+    import Artwork from '@amp/web-app-components/src/components/Artwork/Artwork.svelte';
+    import { colorAsString, isNamedColor } from '~/utils/color';
+
+    import {
+        ArtworkConfig,
+        type ArtworkProfileMap,
+    } from '@amp/web-app-components/config/components/artwork';
+
+    export let artwork: JetArtworkType;
+    export let profile: Profile;
+    export let alt: string = '';
+    export let topRoundedSecondary: boolean = false;
+    export let useContainerStyle: boolean = false;
+    export let forceFullWidth: boolean = true;
+    export let isDecorative: boolean = true;
+    export let lazyLoad: boolean = true;
+    export let disableAutoCenter: boolean = false;
+    export let noShelfChevronAnchor: boolean = false;
+    export let forceCropCode: boolean = false;
+    export let quality: number | undefined = undefined;
+    export let hasTransparentBackground: boolean =
+        !!artwork.backgroundColor &&
+        isNamedColor(artwork.backgroundColor) &&
+        artwork.backgroundColor.name === 'clear';
+    export let useCropCodeFromArtwork: boolean = true;
+    export let withoutBorder: boolean = false;
+
+    let imageSettings: ImageSettings;
+    $: imageSettings = {
+        forceCropCode,
+        hasTransparentBackground,
+        quality,
+    };
+
+    let PROFILES: ArtworkProfileMap<string> | undefined;
+    let computedProfileAttributes: Profile | undefined;
+
+    $: {
+        const config = ArtworkConfig?.get();
+        PROFILES = config?.PROFILES;
+
+        const defaultProfileAttributes: Profile | undefined =
+            typeof profile === 'string' ? PROFILES?.get(profile) : profile;
+
+        const cropCodeIndex = 2;
+
+        if (
+            useCropCodeFromArtwork &&
+            artwork?.crop &&
+            defaultProfileAttributes
+        ) {
+            computedProfileAttributes = [...defaultProfileAttributes];
+            computedProfileAttributes[cropCodeIndex] =
+                artwork?.crop as CropCode;
+        }
+    }
+
+    $: artworkForComponent = {
+        ...artwork,
+        backgroundColor: artwork.backgroundColor
+            ? colorAsString(artwork.backgroundColor)
+            : undefined,
+    } satisfies ComponentArtworkType;
+</script>
+
+<Artwork
+    artwork={artworkForComponent}
+    profile={computedProfileAttributes || profile}
+    {topRoundedSecondary}
+    {useContainerStyle}
+    {forceFullWidth}
+    {imageSettings}
+    {alt}
+    {isDecorative}
+    {lazyLoad}
+    {disableAutoCenter}
+    {noShelfChevronAnchor}
+    {withoutBorder}
+/>
+
+<style>
+    /* When a user enables the "Smart Invert" accessibility setting, images should not be inverted,
+    so we are re-inverting back to their normal state in this media query, which only currently works for Safari. */
+    @media (inverted-colors: inverted) {
+        :global(.artwork-component img) {
+            filter: invert(1);
+        }
+    }
+</style>
-- 
cgit v1.2.3

