### Basic Annotorious Setup Source: https://annotorious.dev/react/component-reference A minimal setup for Annotorious using the root context component and ImageAnnotator. ```jsx ``` -------------------------------- ### React Image Annotation Setup Source: https://annotorious.dev/ Basic setup for image annotation using Annotorious React bindings. Ensure you import the necessary CSS styles. ```jsx import { Annotorious, ImageAnnotator } from '@annotorious/react'; import '@annotorious/react/annotorious-react.css'; export default function App() { return ( ) } ``` -------------------------------- ### Install Annotorious React Package (npm) Source: https://annotorious.dev/installation Use this command to install the Annotorious React package, which includes bindings for both standard and OpenSeadragon versions. ```bash npm install @annotorious/react ``` -------------------------------- ### Install Annotorious Standard Package (npm) Source: https://annotorious.dev/installation Use this command to install the standard Annotorious package for annotating JPEG or PNG images. ```bash npm install @annotorious/annotorious ``` -------------------------------- ### Basic React Image Annotation Setup Source: https://annotorious.dev/react/image-annotation This is the fundamental setup for using Annotorious in a React application. It requires importing the necessary components and CSS, and wrapping the application with the Annotorious context provider. ```jsx import { Annotorious, ImageAnnotator } from '@annotorious/react'; import '@annotorious/react/annotorious-react.css'; export default function App() { return ( ); } ``` -------------------------------- ### Install Annotorious OpenSeadragon Package (npm) Source: https://annotorious.dev/installation Use this command to install the Annotorious package for annotating zoomable images in OpenSeadragon. ```bash npm install openseadragon @annotorious/openseadragon ``` -------------------------------- ### Install Annotorious Svelte Package (npm) Source: https://annotorious.dev/installation Use this command to install the Annotorious Svelte package, which includes bindings for both standard and OpenSeadragon versions. ```bash npm install @annotorious/svelte ``` -------------------------------- ### Image Annotation Object Example Source: https://annotorious.dev/api-reference/image-annotation An example of a typical Annotorious annotation object, illustrating its structure and properties. ```APIDOC ## Image Annotation Object Example ### Description This example shows the structure of a typical Annotorious annotation object, including its ID, bodies, and target. ### Properties - **id** (string): Unique ID. Will be auto-generated if not provided. - **target** (ImageAnnotationTarget): Defines the annotated image region. - **bodies** (AnnotationBody[]): List of annotation bodies. Defaults to []. - **properties** (object): Can hold any custom properties you want to associate with the annotation. ### Example ```json { "id": "97d01785-bdc3-46ec-94d6-c03700c72d7c", "bodies": [ { "id": "5883e985-5b62-412b-b114-471b8b77c48d", "annotation": "97d01785-bdc3-46ec-94d6-c03700c72d7c", "purpose": "commenting", "value": "This is an interesting area!", "creator": { "id": "aboutgeo", "name": "Rainer" }, "created": "2023-08-23T10:30:00Z" } ], "target": { "annotation": "97d01785-bdc3-46ec-94d6-c03700c72d7c", "selector": { "type": "RECTANGLE", "geometry": { "x": 100, "y": 100, "w": 100, "h": 50 } }, "creator": { "id": "aboutgeo", "name": "Rainer" }, "created": "2023-08-23T10:30:00Z" } } ``` ``` -------------------------------- ### Basic React Setup with OpenSeadragon Annotator Source: https://annotorious.dev/react/openseadragon-iiif Set up the Annotorious context and OpenSeadragon viewer in a React application. Ensure OpenSeadragon options are memoized to prevent re-renders. ```jsx import { useMemo } from 'react'; import { Annotorious, OpenSeadragonAnnotator, OpenSeadragonViewer } from '@annotorious/react'; import '@annotorious/react/annotorious-react.css'; export default function App() { // IMPORTANT! Memo-ize your options to avoid // unexpected re-renders of the OSD viewer. const options = useMemo(() => ({ tileSources: { type: 'image', url: '/images/sample-image.jpg' } }), []); return ( ); } ``` -------------------------------- ### Basic OpenSeadragon and Annotorious Setup Source: https://annotorious.dev/guides/openseadragon-iiif Initializes an OpenSeadragon viewer, sets up Annotorious, adds an event listener, and loads annotations from a file. Ensure essential CSS is imported. ```javascript import OpenSeadragon from 'openseadragon'; import { createOSDAnnotator } from '@annotorious/openseadragon'; // Import essential CSS styles import '@annotorious/openseadragon/annotorious-openseadragon.css'; // Initialize OpenSeadragon viewer const viewer = OpenSeadragon({ element: document.getElementById('my-openseadragon-container'), tileSources: { type: 'image', url: '/images/sample-image.jpg' } }); // Initialize annotator const anno = createOSDAnnotator(viewer); // Attach listeners to handle annotation events anno.on('createAnnotation', function(annotation) { console.log('created', annotation); }); // Load annotations from a JSON file anno.loadAnnotations('./annotations.json'); ``` -------------------------------- ### Polygon Shape Example Source: https://annotorious.dev/api-reference/shape An example of a Polygon shape object. This includes its type, geometry (an array of points), and bounding box. ```javascript const polygon = { type: 'POLYGON', geometry: { points: [[10, 10], [20, 20], [10, 20]], bounds: { minX: 10, minY: 10, maxX: 20, maxY: 20 } } }; ``` -------------------------------- ### Basic OpenSeadragon Integration with Annotorious React Source: https://annotorious.dev/react/component-reference Demonstrates how to set up Annotorious with OpenSeadragon, enabling annotation on a viewer. This example shows the basic structure for integrating OpenSeadragonViewer and OpenSeadragonPopup within an OpenSeadragonAnnotator. ```jsx import { Annotorious, OpenSeadragonAnnotator, OpenSeadragonPopup OpenSeadragonViewer } from '@annotorious/react'; import '@annotorious/react/annotorious-react.css'; export default function App() { return ( (
Hello World
)} />
); } ``` -------------------------------- ### Initialize Annotorious with Event Listeners and Load Annotations Source: https://annotorious.dev/guides/annotating-images Basic example to initialize Annotorious on an image, attach an event listener for annotation creation, and load annotations from a JSON file. Requires importing the Annotorious library and its CSS. ```javascript import { createImageAnnotator } from '@annotorious/annotorious'; // Import essential CSS styles import '@annotorious/annotorious/annotorious.css'; // Image element ID or DOM element const anno = createImageAnnotator('sample-image'); // Attach listeners to handle annotation events anno.on('createAnnotation', function(annotation) { console.log('created', annotation); }); // Load annotations from a JSON file anno.loadAnnotations('./annotations.json'); ``` -------------------------------- ### Create ImageAnnotator with Options Source: https://annotorious.dev/api-reference/image-annotator Customize the annotator's behavior by providing an options object during initialization. This example shows how to set custom drawing styles. ```javascript const anno = createImageAnnotator('sample-image', { style: { fill: #ff0000, fillOpacity: 0.4 } }); ``` -------------------------------- ### Rectangle Shape Example Source: https://annotorious.dev/api-reference/shape An example of a Rectangle shape object. This includes its type, geometry (x, y, width, height), and bounding box. ```javascript const rectangle = { type: 'RECTANGLE', geometry: { x: 10, y: 10, w: 100, h: 50, bounds: { minX: 10, minY: 10, maxX: 110, maxY: 60 } } }; ``` -------------------------------- ### Basic React Image Annotation Popup Source: https://annotorious.dev/react/custom-popups A basic example demonstrating how to use the ImageAnnotationPopup component to display a simple 'Hello World' popup for annotations in a React application. Ensure you include the necessary CSS for styling. ```jsx import { Annotorious, ImageAnnotationPopup, ImageAnnotator } from '@annotorious/react'; import './App.css'; import '@annotorious/react/annotorious-react.css'; export default function App() { return ( (
Hello World
)} />
); } ``` ```css .a9s-popup { background-color: #ffffff; border-radius: 3px; padding: 0.25rem 0.625rem; } /** SVG popup arrow style **/ .a9s-popup svg { fill: #fff; } ``` -------------------------------- ### getAnnotations Source: https://annotorious.dev/api-reference/openseadragon-annotator Get all annotations on the image. ```APIDOC ## getAnnotations ### Description Get all annotations on the image. ### Method `anno.getAnnotations()` ### Returns - **Array**: An array of all annotation objects. ### Request Example ```javascript const allAnnotations = anno.getAnnotations(); ``` ``` -------------------------------- ### Create Annotator with Options Source: https://annotorious.dev/guides/annotating-images Customize the annotator's behavior and appearance by passing an options object during initialization. For example, enabling drawing and setting custom styles. ```javascript const anno = createImageAnnotator('sample-image', { drawingEnabled: true, style: { fill: '#ff0000', fillOpacity: 0.25 } }); ``` -------------------------------- ### Get All Annotations Source: https://annotorious.dev/api-reference/openseadragon-annotator Fetch all annotations currently present on the image. Returns an array of annotation objects. ```javascript const all = anno.getAnnotations(); ``` -------------------------------- ### getUser Source: https://annotorious.dev/api-reference/openseadragon-annotator Get the the user object, if any. ```APIDOC ## getUser ### Description Get the the user object, if any. ### Method `anno.getUser()` ### Returns - **User**: The user object, or `undefined` if no user is set. ### Request Example ```javascript const currentUser = anno.getUser(); ``` ``` -------------------------------- ### getSelected Source: https://annotorious.dev/api-reference/openseadragon-annotator Get the currently selected annotations. ```APIDOC ## getSelected ### Description Get the currently selected annotations. ### Method `anno.getSelected()` ### Returns - **Array**: An array of the currently selected annotation objects. ### Request Example ```javascript const selectedAnnotations = anno.getSelected(); ``` ``` -------------------------------- ### Attach Event Listener with anno.on() Source: https://annotorious.dev/api-reference/events Use the `anno.on()` method to attach a handler to an annotator instance for specific lifecycle events. This example shows how to log a message when an annotation is clicked. ```javascript anno.on('clickAnnotation', (annotation) => { console.log('User clicked annotation: ' + annotation.id); }); ``` -------------------------------- ### Get live annotation state with useAnnotations Source: https://annotorious.dev/react/hooks-reference Returns the live annotation state. To limit re-rendering, you can optionally debounce the state updates by providing a number of milliseconds. ```javascript const annotations: ImageAnnotation[] = useAnnotations(debounce); ``` -------------------------------- ### Dynamically Style Annotations with AnnotationState Source: https://annotorious.dev/api-reference/annotation-state Use the AnnotationState to dynamically style annotations based on their selection or hover status. This example shows how to set different styles for selected and non-selected annotations. ```javascript anno.setStyle((annotation, state) => { if (state.selected) { return { fill: '#ff0000', fillOpacity: 0.3, stroke: '#ff0000', strokeOpacity: 1 }; } // Default style for non-selected annotations return { fill: '#00ff00', fillOpacity: 0.2, stroke: '#00ff00', strokeOpacity: 1 }; }); ``` -------------------------------- ### Getting the current user Source: https://annotorious.dev/api-reference/user To retrieve the currently set user, you can use the getUser method. ```APIDOC ## getUser ### Description Retrieves the current user object. ### Method ```javascript getUser(): User ``` ### Response #### Success Response (User) - **id** (string) - A unique identifier for the user. - **name** (string) - User display name. - **avatar** (string) - URL to the user’s avatar image. - **isGuest** (boolean) - Indicates whether the user is a guest. ``` -------------------------------- ### Memoized OpenSeadragon Options in Custom Viewer Source: https://annotorious.dev/react/openseadragon-iiif Define and memoize OpenSeadragon viewer options within a custom component to prevent unnecessary re-renders. This example also shows the usage of Annotorious hooks. ```jsx export const MyAnnotatableViewer = () => { // You can use Annotorious hooks here! const annotations = useAnnotations(); // ... // IMPORTANT! Memo-ize your options to avoid // unexpected re-renders of the OSD viewer. const options = useMemo(() => ({ tileSources: { type: 'image', url: '/images/sample-image.jpg' } }), []); return ( ); } ``` -------------------------------- ### Get Current User Source: https://annotorious.dev/api-reference/openseadragon-annotator Retrieve the current user object, if it has been configured. Returns the user object or null/undefined. ```javascript const currentUser = anno.getUser(); ``` -------------------------------- ### Example Annotorious Annotation Object Source: https://annotorious.dev/api-reference/image-annotation This object demonstrates the structure of a typical annotation created with Annotorious, including its ID, bodies, and target region. ```javascript { id: '97d01785-bdc3-46ec-94d6-c03700c72d7c', bodies: [ { id: '5883e985-5b62-412b-b114-471b8b77c48d', annotation: '97d01785-bdc3-46ec-94d6-c03700c72d7c', purpose: 'commenting', value: 'This is an interesting area!', creator: { id: 'aboutgeo', name: 'Rainer' }, created: new Date('2023-08-23T10:30:00Z') } ] target: { annotation: '97d01785-bdc3-46ec-94d6-c03700c72d7c', selector: { type: 'RECTANGLE', geometry: { x: 100, y: 100, w: 100, h: 50 } }, creator: { id: 'aboutgeo', name: 'Rainer' }, created: new Date('2023-08-23T10:30:00Z') } }; ``` -------------------------------- ### Get viewport state with useViewportState (OpenSeadragon only) Source: https://annotorious.dev/react/hooks-reference OpenSeadragon only. Returns the annotations currently visible in the viewport, responding to zooming and panning. You can optionally debounce this hook to limit re-rendering. ```javascript const annotations: ImageAnnotation[] = useViewportState(debounce); ``` -------------------------------- ### Get Current User - JavaScript Source: https://annotorious.dev/api-reference/user Retrieve the currently set user object using getUser. The returned object contains user details such as name, which can be logged or used in the UI. ```javascript const currentUser = anno.getUser(); console.log(currentUser.name); // Outputs: 'Rainer' ``` -------------------------------- ### Initialize Annotorious with W3CImageFormat Adapter Source: https://annotorious.dev/react/openseadragon-iiif Use the `W3CImageFormat` adapter to enable W3C Web Annotation Data Model support within Annotorious and OpenSeadragon. This requires importing necessary components from `@annotorious/react`. ```jsx import { Annotorious, OpenSeadragonAnnotator, OpenSeadragonViewer, W3CImageFormat } from '@annotorious/react'; ``` -------------------------------- ### Annotation Attribution Example - JSON Source: https://annotorious.dev/api-reference/user When a user is set, Annotorious automatically includes their data in the 'creator' field of annotation bodies and targets. This JSON structure shows an example of an annotation with user attribution embedded. ```json { id: '7fb76422-3a8c-4c87-bbad-7c8bb68399a0', bodies: [{ purpose: 'commenting', value: 'A comment!', creator: { id: 'aboutgeo', name: 'Rainer', avatar: 'https://example.com/lego-saruman.jpg' }, created: 'Fri Aug 23 2024 13:02:44 GMT+0200' }], target: { selector: { type: 'RECTANGLE', geometry: { bounds: { minX: 272, minY: 169, maxX: 393, maxY: 259 }, x: 272, y: 169, w: 121, h: 90, } }, creator: { id: 'aboutgeo', name: 'Rainer', avatar: 'https://example.com/lego-saruman.jpg' }, created: 'Fri Aug 23 2024 13:02:44 GMT+0200' } } ``` -------------------------------- ### Import Annotorious Script and Stylesheet (HTML) Source: https://annotorious.dev/installation Include these links in your HTML's to use the standard version of Annotorious without a bundler. ```html ``` -------------------------------- ### Initialize Annotorious with W3C Adapter Source: https://annotorious.dev/guides/data-model Use the W3CImageFormat adapter to initialize Annotorious, allowing direct use of W3C Web annotations. This enables crosswalking between W3C and Annotorious models. ```javascript import { createImageAnnotator, W3CImageFormat } from '@annotorious/annotorious'; import '@annotorious/annotorious/annotorious.css'; const anno = createImageAnnotator('sample-image', { adapter: W3CImageFormat('sample-image') }); ``` -------------------------------- ### Initialize OpenSeadragon Viewer Source: https://annotorious.dev/guides/openseadragon-iiif Creates an OpenSeadragon viewer instance within a specified DIV element. Refer to OpenSeadragon documentation for more configuration options. ```javascript const viewer = OpenSeadragon({ element: document.getElementById('my-openseadragon-container'), tileSources: { type: 'image', url: '/images/sample-image.jpg' } }; ``` -------------------------------- ### getAnnotationById Source: https://annotorious.dev/api-reference/openseadragon-annotator Get the annotation with the specified ID. ```APIDOC ## getAnnotationById ### Description Get the annotation with the specified ID. ### Method `anno.getAnnotationById(id)` ### Parameters #### Path Parameters - **id** (string) - Required - The annotation ID. ### Returns - **ImageAnnotation | undefined**: The annotation object if found, otherwise `undefined`. ### Request Example ```javascript const annotation = anno.getAnnotationById('annotation-id'); ``` ``` -------------------------------- ### Initialize Annotorious with W3CImageFormat Adapter Source: https://annotorious.dev/api-reference/format-adapter Initializes Annotorious with the W3CImageFormat adapter to use the W3C Web Annotation Data Model. Ensure the adapter is imported. ```javascript import { createImageAnnotator, W3CImageFormat } from '@annotorious/annotorious'; const anno = createImageAnnotator('sample-image', { adapter: W3CImageFormat() }); ``` -------------------------------- ### Get Selected Annotations Source: https://annotorious.dev/api-reference/openseadragon-annotator Retrieve an array of annotations that are currently selected by the user. Returns an empty array if no annotations are selected. ```javascript const selected = anno.getSelected(); ``` -------------------------------- ### Import Annotorious OpenSeadragon Script and Stylesheet (HTML) Source: https://annotorious.dev/installation Include these links in your HTML's to use the OpenSeadragon version of Annotorious without a bundler. ```html ``` -------------------------------- ### Create OpenSeadragon Annotator with Options Source: https://annotorious.dev/api-reference/openseadragon-annotator Customize the annotator's behavior during initialization by providing an options object. This allows for fine-tuning of styles and other functionalities. ```javascript const anno = createOSDAnnotator(viewer, { style: { fill: #ff0000, fillOpacity: 0.4 } }); ``` -------------------------------- ### Get Annotation by ID Source: https://annotorious.dev/api-reference/openseadragon-annotator Retrieve a specific annotation using its unique ID. Returns the annotation object or undefined if not found. ```javascript const annotation = anno.getAnnotationById(id); ``` -------------------------------- ### CDN Import for OpenSeadragon and Annotorious Source: https://annotorious.dev/guides/openseadragon-iiif Includes OpenSeadragon and Annotorious via CDN for use without a build system. The `createOSDAnnotator` function is available globally as `AnnotoriousOSD`. ```html
window.onload = function() { var viewer = OpenSeadragon({ element: document.getElementById('my-openseadragon-container'), tileSources: { type: 'image', url: '/images/sample-image.jpg' } }; var anno = AnnotoriousOSD.createOSDAnnotator(viewer); } ``` -------------------------------- ### Get current annotator user with useAnnotatorUser Source: https://annotorious.dev/react/hooks-reference Returns the current annotator user set via the `anno.setUser()` method, if any. The return type is `User`. ```javascript const user: User = useAnnotatorUser(); ``` -------------------------------- ### Create Annotator with Options Source: https://annotorious.dev/guides/openseadragon-iiif Initializes the Annotorious annotator with custom options, such as enabling drawing and defining style properties for annotations. ```javascript const anno = createOSDAnnotator(viewer, { drawingEnabled: true, style: { fill: '#ff0000', fillOpacity: 0.25 } }); ``` -------------------------------- ### Create Annotator Instance Source: https://annotorious.dev/guides/openseadragon-iiif Initializes the Annotorious annotator on an existing OpenSeadragon viewer instance. ```javascript const anno = createOSDAnnotator(viewer); ``` -------------------------------- ### Dynamic Styling with Functions Source: https://annotorious.dev/api-reference/drawing-style The `setStyle` method also accepts a function that returns a style object. This function receives the `ImageAnnotation` and `AnnotationState` as input, allowing for dynamic styling based on annotation data. ```APIDOC ## Dynamic Styling Function ### Description Allows for dynamic styling of annotations based on their data and state. ### Method Signature `setStyle((annotation: ImageAnnotation, state: AnnotationState) => StyleProperties)` ### Parameters - **annotation** (ImageAnnotation) - The current image annotation. - **state** (AnnotationState) - The current state of the annotation (e.g., selected). ### Returns - **StyleProperties** - An object defining the style for the annotation. ### Request Example ```javascript anno.setStyle((annotation, state) => { const label = annotation.bodies.find(b => b.purpose === 'tagging')?.value; // If the annotation has an 'important' label, make it red const color = label === 'important' ? '#ff0000' : '#ffffff'; const opacity = state.selected ? 0.9 : 0.25; return { fill: color, fillOpacity: opacity, stroke: color, strokeOpacity: 1 }; }); ``` ``` -------------------------------- ### OpenSeadragonAnnotator Initialization Source: https://annotorious.dev/api-reference/openseadragon-annotator The main entry point into the Annotorious API. An object of this type is returned when you call the `createOSDAnnotator` method. You can provide an options object to customize the annotator behavior. ```APIDOC ## createOSDAnnotator ### Description Creates an instance of the OpenSeadragonAnnotator. ### Method `createOSDAnnotator(viewer, options?)` ### Parameters #### Path Parameters - **viewer** (OpenSeadragon.Viewer) - Required - The OpenSeadragon viewer instance. - **options** (object) - Optional - Configuration options for the annotator. ### Init Options #### Property - **adapter** (FormatAdapter) - Optional - An optional format crosswalk adapter. - **autoSave** (boolean) - Optional - Default: `false`. When set to `true`, annotation update events trigger instantly when the user is idle. If `false`, update events only trigger after the user actively de-selects the annotation after editing. - **drawingEnabled** (boolean) - Optional - Default: `false`. Enables or disables drawing functionality. - **drawingMode** (string) - Optional - Default: determined by device type ('click' for desktop, 'drag' for touch). Determines how drawing is initiated. - **userSelectAction** (UserSelectActionExpression) - Optional - Default: `"EDIT"`. Action to perform on user selection. - **style** (DrawingStyleExpression) - Optional - Annotation style. ### Request Example ```javascript import { createOSDAnnotator } from '@annotorious/openseadragon'; const viewer = new OpenSeadragon.Viewer(...); const anno = createOSDAnnotator(viewer); // With options const annoWithOptions = createOSDAnnotator(viewer, { style: { fill: '#ff0000', fillOpacity: 0.4 } }); ``` ``` -------------------------------- ### Configure Annotation Selection Mode Source: https://annotorious.dev/api-reference/selection Set the initial behavior for annotation selection. Use 'SELECT' to allow selection and trigger events without making the annotation editable. ```javascript const anno = createImageAnnotator('sample-image', { userSelectAction: 'SELECT' // Allow selection, but don't make editable }); ``` -------------------------------- ### W3C Web Annotation Data Model Adapter Source: https://annotorious.dev/react/image-annotation Integrate support for the W3C Web Annotation Data Model using the `adapter` prop on ImageAnnotator. This enables interoperability with other systems using this standard. ```javascript import { Annotorious, ImageAnnotator, W3CImageFormat } from '@annotorious/react'; ``` ```jsx ``` -------------------------------- ### ImageAnnotator Initialization Source: https://annotorious.dev/api-reference/image-annotator The ImageAnnotator is the main entry point into the Annotorious API. It is created using the `createImageAnnotator` method, optionally accepting an image element or selector and an options object for customization. ```APIDOC ## createImageAnnotator ### Description Creates a new ImageAnnotator instance for a given image element or selector. ### Parameters #### Argument 1: `element` - **element** (string | HTMLImageElement | HTMLDivElement) - Required - The image element or a CSS selector for the image. #### Argument 2: `options` - **options** (object) - Optional - Configuration options for the annotator. - **adapter** (FormatAdapter) - An optional format crosswalk adapter. - **autoSave** (boolean) - Default: `false` - If `true`, annotation updates are saved instantly when the user is idle. - **drawingEnabled** (boolean) - Default: `true` - Enables or disables drawing functionality. - **drawingMode** (string) - Default: `"drag"` - Determines how drawing is initiated (`"click"` or `"drag"`). - **userSelectAction** (UserSelectActionExpression) - Default: `"EDIT"` - Action to perform on user selection. - **style** (DrawingStyleExpression) - Default: `Annotation style` - Style for annotations. ### Request Example ```javascript import { createImageAnnotator } from '@annotorious/annotorious'; // Basic initialization const anno = createImageAnnotator('sample-image'); // Initialization with options const annoWithOptions = createImageAnnotator('sample-image', { style: { fill: '#ff0000', fillOpacity: 0.4 } }); ``` ``` -------------------------------- ### Get current selection state with useSelection Source: https://annotorious.dev/react/hooks-reference Returns the current selection state object and, optionally, the associated pointer event. The selection object contains the selected annotations and an `editable` flag. ```javascript const { selected, event } = useSelection(); ``` -------------------------------- ### Editable Comment Popup in React Source: https://annotorious.dev/react/custom-popups An advanced example of a custom popup that allows users to view and edit comments associated with an annotation. It utilizes the `onCreateBody` and `onUpdateBody` props of ImageAnnotationPopup to manage comment bodies. ```jsx import { useState, useEffect } from 'react'; import { Annotorious, ImageAnnotationPopup, ImageAnnotator, AnnotationBody } from '@annotorious/react'; const CommentPopup = (props: PopupProps) => { const { annotation, onCreateBody, onUpdateBody } = props; const [comment, setComment] = useState(''); useEffect(() => { const commentBody = annotation.bodies.find(body => body.purpose === 'commenting'); setComment(commentBody ? commentBody.value : ''); }, [annotation.bodies]); const onSave = () => { const updated = { purpose: 'commenting', value: comment }; const commentBody = annotation.bodies.find(body => body.purpose === 'commenting'); if (commentBody) { onUpdateBody(commentBody, updated); } else { onCreateBody(updated); } }; return (