Svelte

Svelte action and helpers for <crop-image>. Works with Svelte 4+ and 5.

Installation

npm install @imazen/crop-image-svelte

Peer dependency: svelte >= 4.

Basic Usage

The cropImage action registers the web component and sets up the element:

<script>
  import { cropImage } from '@imazen/crop-image-svelte';

  let querystring = '';

  function handleCommit(e) {
    querystring = e.detail.riapi.querystring;
  }
</script>

<crop-image
  use:cropImage
  src="/photo.jpg"
  aspect-ratio="16/9"
  on:crop-commit={handleCommit}
/>

<p>Querystring: {querystring}</p>

Action: cropImage

The use:cropImage action handles the web component registration. Apply it to any <crop-image> element. The action has no parameters and no cleanup needed — the web component manages its own lifecycle.

Helper Functions

setCropSelection(element, selection)

Imperatively set the crop selection on an element:

<script>
  import { cropImage, setCropSelection } from '@imazen/crop-image-svelte';

  let el;

  function resetToCenter() {
    setCropSelection(el, {
      crop: { x1: 0.25, y1: 0.25, x2: 0.75, y2: 0.75 },
      pad: { top: 0, right: 0, bottom: 0, left: 0 }
    });
  }
</script>

<crop-image bind:this={el} use:cropImage src="/photo.jpg" />
<button on:click={resetToCenter}>Center Crop</button>

getCropSelection(element)

Read the current selection from the element:

<script>
  import { cropImage, getCropSelection } from '@imazen/crop-image-svelte';

  let el;

  function logCrop() {
    const sel = getCropSelection(el);
    console.log(sel?.crop);
  }
</script>

<crop-image bind:this={el} use:cropImage src="/photo.jpg" />
<button on:click={logCrop}>Log Crop</button>

Event Handling

Both crop-change and crop-commit are standard DOM custom events. Use Svelte's on: directive:

<script>
  import { cropImage } from '@imazen/crop-image-svelte';

  let selection = null;
  let querystring = '';

  function handleChange(e) {
    selection = e.detail.selection;
  }

  function handleCommit(e) {
    querystring = e.detail.riapi.querystring;
  }
</script>

<crop-image
  use:cropImage
  src="/photo.jpg"
  on:crop-change={handleChange}
  on:crop-commit={handleCommit}
/>

{#if selection}
  <p>Crop: ({selection.crop.x1}, {selection.crop.y1}) to ({selection.crop.x2}, {selection.crop.y2})</p>
{/if}
<p>RIAPI: {querystring}</p>

Reactive Attributes

Bind Svelte reactive variables to attributes:

<script>
  import { cropImage } from '@imazen/crop-image-svelte';

  let mode = 'crop';
  let ratio = '16/9';
</script>

<crop-image
  use:cropImage
  src="/photo.jpg"
  mode={mode}
  aspect-ratio={ratio}
/>

<select bind:value={mode}>
  <option value="crop">Crop</option>
  <option value="crop-pad">Crop + Pad</option>
</select>

<select bind:value={ratio}>
  <option value="">Free</option>
  <option value="1/1">1:1</option>
  <option value="4/3">4:3</option>
  <option value="16/9">16:9</option>
</select>

TypeScript

Type exports for Svelte components:

import type {
  CropImageProps,
  CropImageEvents,
  CropRect,
  PadRect,
  CropSelection,
  AspectRatio,
  CropConfig,
} from '@imazen/crop-image-svelte';

The CropImageEvents interface types the custom events:

interface CropImageEvents {
  'crop-change': CustomEvent<{
    selection: CropSelection;
    riapi: { params: Record<string, string>; querystring: string };
  }>;
  'crop-commit': CustomEvent<{
    selection: CropSelection;
    riapi: { params: Record<string, string>; querystring: string };
  }>;
}

Complete Example

<script lang="ts">
  import { cropImage, getCropSelection, type CropSelection } from '@imazen/crop-image-svelte';

  export let imageUrl: string;

  let querystring = '';
  let selection: CropSelection | undefined;
  let cropEl: HTMLElement;

  function handleCommit(e: CustomEvent) {
    querystring = e.detail.riapi.querystring;
    selection = e.detail.selection;
  }

  async function save() {
    const res = await fetch(`/api/resize?src=${imageUrl}${querystring}`);
    // handle result
  }
</script>

<crop-image
  bind:this={cropEl}
  use:cropImage
  src={imageUrl}
  aspect-ratio="4/3"
  adapter="imageflow"
  on:crop-commit={handleCommit}
  style="max-width: 600px;"
/>

<pre>{querystring}</pre>
<button on:click={save}>Save</button>