1.2.14 • Published 3 months ago

@siali/sorolla v1.2.14

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

Sorolla

Sorolla is a React component library optimized for both vanilla React and Next.js projects, providing efficient canvas-based annotation tools powered by Konva.

Installation

Ensure you have react, react-dom, and konva installed in your project as peer dependencies.

npm install react react-dom konva @siali/sorolla
# or
yarn add react react-dom konva @siali/sorolla
# or
pnpm add react react-dom konva @siali/sorolla

Basic Usage

Here's a comprehensive example demonstrating how to initialize annotations, pass them as props, and manage them using the provided hooks and context.

In Vanilla React

Este ejemplo no esta muy trabajado puede tener errores.

import React, { useState } from 'react';
import { SorollaAnnotator, Annotation } from '@siali/sorolla';

const initialAnnotations: Rectangle[] = [
    {
        id: "1",
        position: { x: 466, y: 62 },
        width: 106,
        height: 209,
        type: "rectangle",
    },
    {
        id: "2",
        position: { x: 702, y: 30 },
        width: 92,
        height: 200,
        type: "rectangle",
    },
];

export default function AnnotatorPage() {
    const { setAnnotationAttributes, setAnnotations } = useCanvas();

    // Example: Update global annotation attributes
    const updateAnnotationStyle = () => {
        setAnnotationAttributes((prev) => ({
            ...prev,
            color: '#ff0000',
            opacity: 0.5,
            strokeWidth: 2,
            label: "custom-label",
            visible: true,
        }));
    };

    // Example: Move all annotations
    const moveAnnotations = () => {
        setAnnotations((prevAnnotations) =>
            prevAnnotations.map((annotation) => {
                const ann = annotation as Rectangle;
                return {
                    ...ann,
                    position: {
                        x: ann.position.x + 10,
                        y: ann.position.y + 10,
                    },
                };
            })
        );
    };

    return (
        <main className="min-h-screen p-4 flex flex-col items-center justify-center gap-4">
            <div className="w-[1280px] h-[640px] border border-gray-200 rounded-lg">
                <Suspense fallback={<div>Loading...</div>}>
                    <SorollaAnnotator
                        image="/sample-image.jpg"
                        initialAnnotations={initialAnnotations}
                        onUpdate={setAnnotations}
                    />
                </Suspense>
            </div>
            <div className="flex gap-2">
                <button
                    onClick={updateAnnotationStyle}
                    className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
                >
                    Update Style
                </button>
                <button
                    onClick={moveAnnotations}
                    className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
                >
                    Move Annotations
                </button>
            </div>
        </main>
    );
}

In Next.js

First, set up the provider in your layout:

"use client";

import dynamic from "next/dynamic";
import { Suspense } from "react";

const AnnotationsProvider = dynamic(
    () => import("@siali/sorolla").then((mod) => mod.AnnotationsProvider),
    {
        ssr: false,
        loading: () => <div>Loading provider...</div>,
    }
);

export default function AppLayout({ children }: { children: React.ReactNode }) {
    return (
        <Suspense fallback={<div>Loading app...</div>}>
            <AnnotationsProvider>{children}</AnnotationsProvider>
        </Suspense>
    );
}

Then in your page component:

"use client";

import dynamic from "next/dynamic";
import { Rectangle, useCanvas } from "@siali/sorolla";
import { Suspense } from "react";

const SorollaAnnotator = dynamic(
    () => import("@siali/sorolla").then((mod) => mod.SorollaAnnotator),
    {
        ssr: false,
        loading: () => (
            <div className="w-[1280px] h-[640px] animate-pulse bg-gray-200">
                Loading annotator...
            </div>
        ),
    }
);

// Initial annotations only need position, size, and type
const initialAnnotations: Rectangle[] = [
    {
        id: "1",
        position: { x: 466, y: 62 },
        width: 106,
        height: 209,
        type: "rectangle",
    },
    {
        id: "2",
        position: { x: 702, y: 30 },
        width: 92,
        height: 200,
        type: "rectangle",
    },
];

export default function AnnotatorPage() {
    const { setAnnotationAttributes, setAnnotations } = useCanvas();

    // Example: Update global annotation attributes
    const updateAnnotationStyle = () => {
        setAnnotationAttributes((prev) => ({
            ...prev,
            color: '#ff0000',
            opacity: 0.5,
            strokeWidth: 2,
            label: "custom-label",
            visible: true,
        }));
    };

    // Example: Move all annotations
    const moveAnnotations = () => {
        setAnnotations((prevAnnotations) =>
            prevAnnotations.map((annotation) => {
                const ann = annotation as Rectangle;
                return {
                    ...ann,
                    position: {
                        x: ann.position.x + 10,
                        y: ann.position.y + 10,
                    },
                };
            })
        );
    };

    return (
        <main className="min-h-screen p-4 flex flex-col items-center justify-center gap-4">
            <div className="w-[1280px] h-[640px] border border-gray-200 rounded-lg">
                <Suspense fallback={<div>Loading...</div>}>
                    <SorollaAnnotator
                        image="/sample-image.jpg"
                        initialAnnotations={initialAnnotations}
                        onUpdate={setAnnotations}
                    />
                </Suspense>
            </div>
            <div className="flex gap-2">
                <button
                    onClick={updateAnnotationStyle}
                    className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
                >
                    Update Style
                </button>
                <button
                    onClick={moveAnnotations}
                    className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
                >
                    Move Annotations
                </button>
            </div>
        </main>
    );
}

Key Features

  • Global Annotation Attributes: Use setAnnotationAttributes to update the style of all annotations at once
  • Simplified Annotation Objects: Initial annotations only require position, size, and type - other attributes are inherited from global settings
  • Type Safety: Full TypeScript support for annotation types and attributes
  • Dynamic Updates: Modify annotations and their attributes at runtime
  • Server-Side Rendering: Properly handled through dynamic imports in Next.js

Default Annotation Attributes

The default attributes that will be applied to all annotations unless overridden:

{
    color: '#D3D3D3',
    opacity: 0.3,
    strokeWidth: 1,
    visible: true,
    label: "new",
}

You can override these defaults using setAnnotationAttributes or by specifying attributes in individual annotation objects.

Explanation

State Management

  • Annotations State: Use the useState hook to manage the annotations array.
  • Initial Annotations: Pass the annotations state as the initialAnnotations prop to SorollaAnnotator.
  • Update Annotations: Use the onUpdate callback to keep the state in sync with any changes made within the annotator.

AnnotationsProvider Integration

The AnnotationsProvider is already integrated within the SorollaAnnotator component. This ensures that all child components have access to the annotations context.

Styling

Use the style and className props to apply custom styles to the annotator container.

Advanced Usage

For more advanced scenarios, such as integrating with global state management or handling more complex annotation types, you can utilize the exported hooks and providers.

Optimize Images

Use optimized image formats and sizes to reduce bundle size further (webp).

Conclusion

By following the steps outlined above, you can transform the Sorolla library into a production-ready, optimized package suitable for both vanilla React and Next.js projects. These optimizations ensure minimal bundle sizes, prevent SSR-related issues, and maintain high performance across different environments.

Feel free to reach out if you encounter any issues or need further assistance!

1.2.0

6 months ago

1.1.0

7 months ago

1.2.8

6 months ago

1.2.7

6 months ago

1.2.6

6 months ago

1.2.5

6 months ago

1.2.4

6 months ago

1.1.5

6 months ago

1.2.3

6 months ago

1.1.4

6 months ago

1.2.2

6 months ago

1.1.3

7 months ago

1.2.1

6 months ago

1.1.2

7 months ago

1.2.9

3 months ago

1.2.12

3 months ago

1.2.13

3 months ago

1.2.10

3 months ago

1.2.11

3 months ago

1.2.14

3 months ago

1.0.0

9 months ago