npm package: @hg-storefront/product-animation
Description: React components for rendering product images and Lottie animations in the Hemglass storefront (Web and React Native).
Latest version: 0.0.30

# @hg-storefront/product-animation

React components for rendering product images and Lottie animations in the Hemglass storefront (Web and React Native).

## Installation

This library is part of the Hemglass storefront monorepo and is automatically available when working within the project.

## Usage

### Basic image

```tsx
import { ProductAnimation } from '@hg-storefront/product-animation'

function ProductCard({ productId }: { productId: string }) {
  return (
    <ProductAnimation.Root productId={productId}>
      <ProductAnimation.Img imageType="productImg" alt="Product image" />
    </ProductAnimation.Root>
  )
}
```

### Lottie with fallback image

```tsx
import { ProductAnimation } from '@hg-storefront/product-animation'

function AnimatedHero({ productId }: { productId: string }) {
  return (
    <ProductAnimation.Root productId={productId}>
      <ProductAnimation.LottieAnimation
        animationType="backgroundAnimationPage"
        fallbackImage="backgroundImgPage"
        style={{ width: '100%', height: 400 }}
      />
    </ProductAnimation.Root>
  )
}
```

### Using a preloaded product

```tsx
import { ProductAnimation } from '@hg-storefront/product-animation'
import type { Product } from '@haus-storefront-react/shared-types'

function ProductMedia({ product }: { product: Product }) {
  return (
    <ProductAnimation.Root product={product}>
      <ProductAnimation.Img imageType="backgroundImgCard" />
    </ProductAnimation.Root>
  )
}
```

### Direct media (no product fetch)

```tsx
import { ProductAnimation } from '@hg-storefront/product-animation'

function Hero() {
  return (
    <ProductAnimation.Root
      media={{
        backgroundAnimationPage: 'https://cdn.example.com/anim.json',
        backgroundImgPage: 'https://cdn.example.com/fallback.jpg',
      }}
    >
      <ProductAnimation.LottieAnimation
        animationType="backgroundAnimationPage"
        fallbackImage="backgroundImgPage"
        style={{ width: '100%', height: 400 }}
      />
    </ProductAnimation.Root>
  )
}
```

## Components

### `ProductAnimation.Root`

```ts
type RootProps = {
  children?: React.ReactNode | ((ctx: ProductAnimationContextValue) => React.ReactNode)
  media?: MediaOverrides
} & ({ productId: string } | { product: Product } | { media: MediaOverrides })
```

- If `media` is provided, no product fetch is performed and provided URLs are used.
- If `product` is provided, no fetch is performed.
- If `productId` is provided, the product is fetched via `useProduct`.

### `ProductAnimation.Img`

```ts
type ProductAnimationTypes =
  | 'productImg'
  | 'backgroundImgCard'
  | 'backgroundImgPage'
  | 'backgroundAnimationCard'
  | 'backgroundAnimationPage'

interface ImgProps {
  imageType: ProductAnimationTypes
  alt?: string
  width?: number | string
  height?: number | string
  style?: React.CSSProperties
  className?: string
  onLoad?: () => void
  onError?: () => void
  asChild?: boolean
}
```

### `ProductAnimation.LottieAnimation`

```ts
interface LottieAnimationProps {
  animationType: ProductAnimationTypes
  fallbackImage: ProductAnimationTypes
  onLoad?: () => void
  onError?: () => void
  asChild?: boolean
}
```

## Types

```ts
interface ImageType {
  id: string
  preview: string
  width: number
  height: number
  source: string
}

interface ProductAnimationContextValue {
  productImg?: ImageType
  backgroundImgCard?: ImageType
  backgroundImgPage?: ImageType
  backgroundAnimationCard?: ImageType
  backgroundAnimationPage?: ImageType
  isLoading: boolean
  error: Error | null
}

type ProductAnimationTypes =
  | 'productImg'
  | 'backgroundImgCard'
  | 'backgroundImgPage'
  | 'backgroundAnimationCard'
  | 'backgroundAnimationPage'

type MediaOverrides = Partial<Record<ProductAnimationTypes, string | ImageType>>
```

Media is read from `product.customFields`:

- `productImg`
- `backgroundImgCard`
- `backgroundImgPage`
- `backgroundAnimationCard` (URL to Lottie JSON)
- `backgroundAnimationPage` (URL to Lottie JSON)

## Usage Examples

### Render-prop for loading/error

```tsx
function MediaWithStates({ productId }: { productId: string }) {
  return (
    <ProductAnimation.Root productId={productId}>
      {({ isLoading, error }) => {
        if (isLoading) return <div>Loading…</div>
        if (error) return <div>Error loading media</div>
        return <ProductAnimation.Img imageType="productImg" />
      }}
    </ProductAnimation.Root>
  )
}
```

### React Native

```tsx
import { View, StyleSheet } from 'react-native'
import { ProductAnimation } from '@hg-storefront/product-animation'

function ProductHeroNative({ productId }: { productId: string }) {
  return (
    <View style={styles.container}>
      <ProductAnimation.Root productId={productId}>
        <ProductAnimation.LottieAnimation
          animationType="backgroundAnimationCard"
          fallbackImage="backgroundImgCard"
          style={{ width: '100%', height: 240 }}
        />
      </ProductAnimation.Root>
    </View>
  )
}

const styles = StyleSheet.create({ container: { flex: 1 } })
```

## Dependencies

This library depends on:

- `@haus-storefront-react/core`
- `@haus-storefront-react/hooks`
- `@haus-storefront-react/common-utils`
- `@haus-storefront-react/shared-types`
- `@tanstack/react-query`
- `lottie-react` (Web)
- `lottie-react-native` (Native)

## Development

To build this library:

```bash
nx build components/product-animation
```

To lint this library:

```bash
nx lint components/product-animation
```