> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kleep.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Mobile SDK - React Native

**Github Repository:** [https://github.com/KlipFit/kleep-rn](https://github.com/KlipFit/kleep-rn)

En tunn WebView-wrapper runt `drawer.kleep.ai`. SDK:n exponerar en komponent + två metoder, speglar iOS-ytan.

## Installation

***

Varje utgåva publiceras som en npm-tarball på `cdn.kleep.ai`. Två URL-format är tillgängliga:

**Senaste stabila** (uppdateras automatiskt vid varje ny stabil utgåva — förhandsversioner flyttar aldrig denna pekare):

```bash theme={null}
npm install https://cdn.kleep.ai/react-native-sdk/latest.tgz \
  react-native-webview \
  @react-native-async-storage/async-storage
```

**Fixera en specifik version** (rekommenderas för produktion — helt oföränderlig):

```bash theme={null}
npm install https://cdn.kleep.ai/react-native-sdk/releases/v1.0.0/kleep-react-native-1.0.0.tgz \
  react-native-webview \
  @react-native-async-storage/async-storage
```

Ersätt `v1.0.0` och `1.0.0` med önskad release-tagg. De två listade paketen är peer-beroenden — SDK:n kräver dem men låter dig kontrollera versionen.

Den publicerade tarballen inkluderar en SHA-256 bredvid (`<tarball>.sha256` / `latest.tgz.sha256`) om du vill verifiera integriteten före installation.

### Expo

Båda peer-beroendena är förpaketerade i Expo Go (SDK 54+). Ingen extra konfiguration behövs i dev. För produktionsbuilds plockar `expo prebuild` upp dem automatiskt.

### Bare React Native

```bash theme={null}
cd ios && pod install
```

## Behörigheter

***

För skoflödet (kameraskanningen), lägg till i `ios/<App>/Info.plist`:

```xml theme={null}
<key>NSCameraUsageDescription</key>
<string>Used to scan your shoe size</string>
```

Och i `android/app/src/main/AndroidManifest.xml`:

```xml theme={null}
<uses-permission android:name="android.permission.CAMERA" />
```

## Konfigurera en gång vid appstart

***

```tsx theme={null}
import { Kleep } from '@kleep/react-native';

Kleep.configure({
  publicId: 'YOUR_KLEEP_PUBLIC_ID',  // UUID provided by Kleep
  language: 'fr',                      // optional, default UI language
});
```

| Fält       | Obligatorisk | Beskrivning                                                                                                            |
| ---------- | ------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `publicId` | ja           | UUID som identifierar din återförsäljare (tillhandahålls av Kleep)                                                     |
| `language` | nej          | `'fr' \| 'en' \| 'de' \| 'it' \| 'es' \| 'nl' \| 'pt' \| 'ja' \| 'ko' \| 'pl' \| 'br' \| 'dk' \| 'fi' \| 'se' \| 'gb'` |

## Användning

***

### Metod 1: `Kleep.checkProduct`

Anropa detta vid PDP-montering. Resultatet styr CTA "Hitta min storlek" — om den ska renderas och vilken etikett som ska visas.

| parameter   | prioritet      | beskrivning                         |
| ----------- | -------------- | ----------------------------------- |
| `productId` | *obligatorisk* | Ditt produkt-ID hos återförsäljaren |

**Returnerar**

```ts theme={null}
{
  recommendable: boolean;
  productFound: boolean;
  category?: 'clothing' | 'lingerie' | 'footwear' | 'children';
  recommendedSize?: string;   // e.g. "M", "38"
}
```

**Logikschema**

| `recommendable` | `recommendedSize` | Vad som renderas                                  |
| --------------- | ----------------- | ------------------------------------------------- |
| `false`         | —                 | **Dölj CTA** (produkt inte berättigad till Kleep) |
| `true`          | saknas            | CTA: **"Trouver ma taille"**                      |
| `true`          | `"M"`             | CTA: **"Taille recommandée: M"**                  |

SDK:n cachelagrar resultatet i 5 min i minnet, indexerat på `(publicId, productId)` för porten och `(publicId, productId, mid)` för den rekommenderade storleken. Att återrendera PDP eller navigera tillbaka är kostnadsfritt.

**Implementeringsexempel**

```tsx theme={null}
import { useEffect, useState } from 'react';
import { Pressable, Text } from 'react-native';
import { Kleep, KleepFindSizeView, type KleepCheckProductResult } from '@kleep/react-native';

function ProductPage({ product }) {
  const [check, setCheck] = useState<KleepCheckProductResult | null>(null);
  const [open, setOpen] = useState(false);

  useEffect(() => {
    Kleep.checkProduct({ productId: product.id }).then(setCheck);
  }, [product.id]);

  if (!check?.recommendable) return <ProductContent />;

  return (
    <>
      <ProductContent />
      <Pressable onPress={() => setOpen(true)}>
        <Text>
          {check.recommendedSize
            ? `Taille recommandée : ${check.recommendedSize}`
            : 'Trouver ma taille'}
        </Text>
      </Pressable>
      <KleepFindSizeView
        visible={open}
        productId={product.id}
        variantId={selectedVariant?.id}
        onAddToCart={(e) => cart.add(e.variantId)}
        onSelectSize={(e) => pdp.setSize(e.size)}
        onDismiss={() => setOpen(false)}
      />
    </>
  );
}
```

### Metod 2: `<KleepFindSizeView>`

Montera denna komponent för att öppna storleksguiden i en helskärms Modal+WebView. Kontrollerat komponentmönster: du äger `visible`-tillståndet, SDK:n begär stängning via `onDismiss`.

| prop           | prioritet      | beskrivning                                                                                                                                        |
| -------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `visible`      | *obligatorisk* | Kontrollerar Modal-synlighet                                                                                                                       |
| `productId`    | *obligatorisk* | Samma som i `checkProduct`                                                                                                                         |
| `onDismiss`    | *obligatorisk* | Aktiveras när användaren stänger lådan (X / svep / bakåt). Värden MÅSTE ändra `visible` till `false`                                               |
| `variantId`    | *valfritt*     | Förhandsväljer en variant för rekommendationen                                                                                                     |
| `customerId`   | *valfritt*     | CRM-identifierare för länkning mellan sessioner                                                                                                    |
| `language`     | *valfritt*     | Åsidosätter SDK-nivåspråket för denna öppning                                                                                                      |
| `countryCode`  | *valfritt*     | t.ex. `"FR"`, `"US"` — styr enhetssystem + standardstorlekar för bh                                                                                |
| `stocks`       | *valfritt*     | `{ [variantId]: number \| boolean }` — lådan renderar otillgängligt / delvis lager-UI                                                              |
| `mock`         | *valfritt*     | `true` → lådan hoppar över riktiga rekommendations-API-anrop (endast QA)                                                                           |
| `forceState`   | *valfritt*     | `'outOfRange' \| 'unavailable' \| 'error' \| 'qrcode'` — QA-lucka för att rendera ett slutläge direkt                                              |
| `warmRestore`  | *valfritt*     | `{ mid, uid }` — förladda en befintlig mätning (hoppa över introduktionsflödet). Återställning på samma enhet är redan automatisk via AsyncStorage |
| `extraParams`  | *valfritt*     | Rå `Record<string, string>` bifogad till låd-URL:en (nödutgång)                                                                                    |
| `onAddToCart`  | *valfritt*     | `(event: { variantId, size? }) => void` — användaren tryckte på "Lägg i varukorg" CTA i lådan. **Värden lägger till varianten i sin varukorg**     |
| `onSelectSize` | *valfritt*     | `(event: { size }) => void` — användaren valde en storlek på Resultatsidan. **Värden bör synkronisera sin PDP-storleksväljare**                    |
| `onMessage`    | *valfritt*     | Felsökningskrok — aktiveras för varje inkommande postMessage tolkad från lådan                                                                     |
| `style`        | *valfritt*     | `StyleProp<ViewStyle>` — behållarstilöverskridning                                                                                                 |
| `webViewProps` | *valfritt*     | Vidarebefordrad till `react-native-webview` för avancerad anpassning                                                                               |

**Automatiskt kopplad av SDK:n (du behöver inte göra något):**

* Bryggar lådans iframe-stil `window.parent.postMessage` till React Native-bryggan
* Bevarar `mid` / `uid` till AsyncStorage när lådan skickar dem
* Svarar på `getMid` / `getUid` / `getSizes` postMessages från lådan
* Anropar `Kleep.checkProduct` vid öppning för att lösa flödet (clothing / lingerie / footwear / children) — använder samma 5-min-cache som ditt CTA-anrop, så det är kostnadsfritt om du redan anropat `checkProduct`

### Metod 3: `Kleep.track`

Skjut-och-glöm-analys. Kastar aldrig undantag.

| parameter            | prioritet      | beskrivning                                         |
| -------------------- | -------------- | --------------------------------------------------- |
| `eventName`          | *obligatorisk* | Händelsens namn                                     |
| `options.customerId` | *valfritt*     | CRM-identifierare                                   |
| `options.parameters` | *valfritt*     | `Record<string, unknown>` — godtycklig händelsedata |

```tsx theme={null}
import { Kleep } from '@kleep/react-native';

await Kleep.track('product_viewed', {
  parameters: { productId: product.id },
});

await Kleep.track('product_added_to_cart', {
  customerId: user.id,
  parameters: {
    productId: product.id,
    variantId: selectedVariant.id,
    cart: cart.items,
  },
});

await Kleep.track('checkout_completed', {
  customerId: user.id,
  parameters: { orderId: order.id, cart: order.items },
});
```

Vi vill spåra 3 händelser:

| eventName               | Utlösare                             |
| ----------------------- | ------------------------------------ |
| `product_viewed`        | När PDP visas                        |
| `product_added_to_cart` | När produkt läggs i varukorgen       |
| `checkout_completed`    | Vid orderbekräftelse efter betalning |

**Exempel för `product_viewed`**

```jsx theme={null}
{
  productId: "123ABC456"
}
```

**Exempel för `product_added_to_cart`**

```jsx theme={null}
{
  productId: "123ABC456",
  variantId: "123ABC456-00R",
  cart: [
    {
      productId: "123ABC456",
      variantId: "123ABC456-00R",
      sku: "XYZ",
      size: "S",
      quantity: 2,
      price: { amount: "50", currencyCode: "EUR" }
    }
  ]
}
```

**Exempel för `checkout_completed`**

```jsx theme={null}
{
  orderId: "000001",
  cart: [
    {
      lineItemId: "000001#1",
      productId: "123ABC456",
      variantId: "123ABC456-00R",
      sku: "XYZ",
      size: "S",
      quantity: 2,
      price: { amount: "50", currencyCode: "EUR" }
    }
  ]
}
```

## Cacheinvalidering

***

SDK:n håller två cacheminnen i minnet (5 min TTL vardera):

* **Produktport** — `(publicId, productId) → { recommendable, category, productFound }`
* **Rekommenderad storlek** — `(publicId, productId, mid) → size label`

Båda invalideras automatiskt. Om du behöver tvingad uppdatering (användare loggade ut, återförsäljare byttes, manuell uppdateringsknapp):

```tsx theme={null}
Kleep.clearCheckProductCache();
```
