# Widgets

The JavaScript SDK's widgets put CalmLens in your front end without building the interface yourself. The [upload widget](/docs/widgets/upload-widget) sends files from the browser and shows each file's progress and moderation decision, and the [media component](/docs/widgets/media-component) shows an asset from the CDN in a way that fits its moderation status. Both come in the same form for React, React Native, Vue, Svelte and plain HTML.

## Choose your library

Install `@calmlens/sdk` and import the components for your UI library:

| Import                       | Components                                                                                                                                                                  |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `@calmlens/sdk/react`        | `CalmLensUploader`, `CalmLensMedia` and the `useCalmLensUpload` hook. Also works in Preact through `preact/compat`.                                                         |
| `@calmlens/sdk/react-native` | `CalmLensUploader`, `CalmLensMedia` and the `useCalmLensUpload` hook, for React Native and Expo apps. They use React Native's own views, with no native modules to install. |
| `@calmlens/sdk/vue`          | `CalmLensUploader`, `CalmLensMedia` and the `useCalmLensUpload` composable, for Vue 3.                                                                                      |
| `@calmlens/sdk/svelte`       | `CalmLensUploader` and `CalmLensMedia`, for Svelte 5.                                                                                                                       |
| `@calmlens/sdk/elements`     | The `<calmlens-uploader>` and `<calmlens-media>` custom elements, for plain HTML, Angular, Solid, Lit and any library that renders custom elements.                         |

Importing `@calmlens/sdk/elements` defines both elements. The components share one core, `@calmlens/sdk/ui`, which you can use to build your own interface on the same upload queue. The file-type icons the upload widget draws for files without a preview are in `@calmlens/sdk/file-icons`, for showing files the same way elsewhere in your app.

## Style and translate

The React components render their small stylesheet with them: React places it in the page's head once, including when you render on the server, so media keeps its layout before your scripts load. With Vue, Svelte or the web components, import `@calmlens/sdk/styles.css` once in your app, or link it from your page's head. Change the colours and corners with CSS custom properties such as `--calmlens-accent` and `--calmlens-radius`; your values take precedence on any element. To style the `calmlens-*` classes yourself, pass `unstyled` to the React components, or leave out the stylesheet import.

The React Native components take a `theme` instead, with `accent`, `text`, `radius` and the status colours; anything you leave out keeps its default. The secondary text, border and surface colours are mixed from `text`, so a dark screen usually needs only `text` and `accent`.

All text can be replaced through `messages`, keyed by message name (`dropzoneTitle`, `uploading`, `reveal`) or by error code, which also translates the components.

## Test without a network

`MockCalmLensAppClient` from `@calmlens/sdk/testing` stands in for the uploader's client. It applies upload preset rules, such as a required token and size limits, with the API's error codes, and stores uploads in a `MockCalmLensServerClient`, whose CDN serves them with the same moderation rules:

```tsx
import { CalmLensUploader } from "@calmlens/sdk/react";
import { MockCalmLensAppClient } from "@calmlens/sdk/testing";

<CalmLensUploader
  uploadPresetId="test-preset"
  createClient={(options) =>
    new MockCalmLensAppClient({
      ...options,
      mockOptions: { queuedOutcome: "blocked", preset: { maxFileSizeInBytes: 5_000_000 } },
    })
  }
/>;
```

The [widget playground](https://github.com/CalmLens/sdks/tree/main/examples/widget-playground) runs every component in each library against these mocks, so you can try uploads, decisions and age-restricted media without a project.
