Search by

carbon / editor-image

jonnitto

Image focal point and map editor for Neos CMS

Package info

github.com/CarbonPackages/Carbon.Editor.Image

Language:JavaScript

Type:neos-carbon

pkg:composer/carbon/editor-image

Statistics

Installs: 20

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.2.1 2026-10-30 15:33 UTC

This package is auto-updated.

Last update: 2026-11-01 15:10:29 UTC


README

Carbon.Editor.Image provides two Neos inspector editors for image properties:

  • FocalPoint lets editors choose the focal point on an image.
  • Map lets editors define clickable areas on an image, including a link and alternative text for each area.

The FocalPoint editor was inspired by Neos.ImageFocalPointEditor.

Both editors use the image selected in the configured image property. By default, they look for an image property on the current node. Dialog previews scale proportionally to fit the available width and height, including SVGs without dimension metadata. SVG previews are also enlarged to use the available dialog space; raster previews are only scaled down. The configured image crop is preserved; resizing the preview does not change saved coordinates.

Installation

Install the package in your Neos project with Composer:

composer require carbon/editor-image

Usage

Vendor.Site:Content.Image:
  properties:
    imageFocalPoint:
      # If `saveAsJsonString` is set to `true` in `editorOptions` or global configuration, set the property type to `string`
      type: array
      ui:
        # label: The label is optional; if omitted, it defaults to the translated text “Edit focal point”.
        inspector:
          editor: "Carbon.Editor.Image/FocalPoint"
    imageMap:
      # If `saveAsJsonString` is set to `true` in `editorOptions` or global configuration, set the property type to `string`
      type: array
      ui:
        # label: The label is optional; if omitted, it defaults to the translated text “Edit image map”.
        inspector:
          editor: "Carbon.Editor.Image/Map"

FocalPoint

The FocalPoint editor displays the selected image and lets editors set its focal point. The value is stored as an object with x and y coordinates. The editor always opens in a modal dialog. Changes are saved with Apply and discarded with Cancel.

Map

The Map editor opens an image annotation dialog where editors can create and edit clickable areas. Each area can have a link and alternative text. The editor saves the areas to the property.

Global configuration

Default options for both editors are provided in Configuration/Settings.Config.yaml under Neos.Neos.Ui.frontendConfiguration:

Neos:
  Neos:
    Ui:
      frontendConfiguration:
        "Carbon.Editor.Image.FocalPoint":
          imageProperty: "image"
          labelIfEmpty: "Carbon.Editor.Image:Main:selectImage"
          saveAsJsonString: false
        "Carbon.Editor.Image.Map":
          imageProperty: "image"
          labelIfEmpty: "Carbon.Editor.Image:Main:selectImage"
          saveAsJsonString: false
          areaProperties:
            href:
              label: "Carbon.Editor.Image:Main:map.link"
              editor: "Neos.Neos/Inspector/Editors/LinkEditor"
              editorOptions: {}
            title:
              label: "Carbon.Editor.Image:Main:map.title"
              editor: "Neos.Neos/Inspector/Editors/TextFieldEditor"
              editorOptions: {}
            alt:
              label: "Carbon.Editor.Image:Main:map.alt"
              editor: "Neos.Neos/Inspector/Editors/TextFieldEditor"
              editorOptions: {}

These are global defaults. Set an option in a property's editorOptions to override the global value for that editor instance.

Available options:

Option Description
imageProperty Name of the image property used by the editor. Defaults to image. Use parent:propertyName to read the image from the parent node.
labelIfEmpty Text or translation key displayed when no image is selected. Set it to null to hide the editor output in that case.
saveAsJsonString When true, stores the value as a JSON string; the Neos property must then have type: string. When false, the value is stored as a native value, so use type: array.
areaProperties Map editor only. Named fields for each area, with a label, Neos editor identifier and editorOptions. Set a field to null to omit it from the popup and saved data.

For example, to use a different image property only for one focal point field:

editorOptions:
  imageProperty: "heroImage"
  labelIfEmpty: null

Property-level editorOptions take precedence over the corresponding global setting.

Custom area fields

The Map editor creates its popup fields from areaProperties. By default, each area has href, title and alt fields. Add custom fields or override individual field definitions in your property's editorOptions:

editorOptions:
  areaProperties:
    alt: null
    description:
      label: "Description"
      editor: "Neos.Neos/Inspector/Editors/TextAreaEditor"
      editorOptions:
        placeholder: "Describe this area"

This keeps the global href and title fields, removes alt, and adds description. Each field definition replaces the global definition with the same name. Labels support translation keys, and editorOptions are passed to the selected Neos inspector editor. Fields are stored under their configured names alongside shape and coords; those two names are reserved. Disabled and unconfigured fields are not saved when applying changes.

Stored data format

FocalPoint data

The focal point is stored as x and y coordinates, expressed as percentages of the image dimensions:

{
  "x": 30,
  "y": 28
}

Map data

The image map is stored as an array of areas. shape is either rect or poly, coords is an array of alternating x and y floating-point percentages relative to the cropped output image (from 0 to 100). The remaining fields come from areaProperties, such as href, title and alt. X values are relative to the cropped width, Y values to the cropped height, independently of the preview size.

[
  {
    "shape": "rect",
    "coords": [12.5, 15.25, 68.75, 83.5],
    "href": "node://3211e0a0-4066-43f8-8f9c-6ff48a1017e4",
    "title": "Visit our website",
    "alt": "Website"
  },
  {
    "shape": "poly",
    "coords": [21.4, 11.6, 21.3, 25.9, 31.7, 30.2, 31.8, 15.5, 28.1, 14.9],
    "href": "node://e69d08dd-d0e8-464b-8552-bf4707d4f682",
    "title": "",
    "alt": ""
  }
]

These examples show the native values. When saveAsJsonString is true, the same data is stored as a JSON-encoded string instead.

Creating responsive image map areas

Use createAreas whenever creating the frontend <area> elements and whenever the displayed image changes size. Stored coordinates are percentages; HTML image maps require pixel coordinates based on the image's current displayed width and height, not its natural dimensions.

createAreas(map, imageWidth, imageHeight, areas) converts the coordinates to rounded pixel values and replaces all existing areas in the <map>. It also copies the remaining area properties, such as href, title and alt, to HTML attributes.

For example, after importing createAreas into your frontend bundle:

const image = document.querySelector<HTMLImageElement>("#mapped-image")!;
const map = document.querySelector<HTMLMapElement>("#image-map")!;
// `areas` contains the stored percentage-based data, parsed from JSON if necessary.
const updateAreas = () => createAreas(map, image.clientWidth, image.clientHeight, areas);

image.addEventListener("load", updateAreas);
const observer = new ResizeObserver(updateAreas);
observer.observe(image);
if (image.complete) {
  updateAreas();
}

// When removing the image/component:
// image.removeEventListener("load", updateAreas);
// observer.disconnect();

Connect the image and map using <img id="mapped-image" usemap="#image-map" ...> and <map id="image-map" name="image-map"></map>. The image must display the same cropped output used when defining the areas. Resolve Neos node:// links to frontend URLs before calling createAreas, and pass only trusted, HTML-attribute-safe property names and values because the function inserts them directly into HTML.