npm package: @peteai/presentation-editor
Description: This project is a Svelte component library which lets you create a customizable presentation editors.
Latest version: 0.0.10

# @peteai/presentation-editor

## Introduction

This project is a Svelte component library which lets you create a customizable presentation editors.

## Install

```bash
npm install @peteai/presentation-editor
```

## Types

```typescript
type Image = {
	id: string;
	src: string;
	width: number;
	height: number;
};

interface BaseLayer {
	id: string;
	x: number;
	y: number;
	width: number;
	height: number;
	rotate: number | null;
	opacity: number | null;
	sortOrder: number;
}

interface TextLayer extends BaseLayer {
	type: 'text';
	scale: number | null;
	html: JSONContent;
}

type LayerBorder = {
	borderStyle: 'solid' | 'dashed' | 'dotted' | null;
	borderWidth: number | null;
	borderColor: string | null;
};

interface ImageLayer extends BaseLayer, LayerBorder {
	type: 'image';
	scale: number | null;
	image: Image;
	offsetX: number | null;
	offsetY: number | null;
	cornerRadius: number | null;
	flipX: boolean;
	flipY: boolean;
}

type Layer = TextLayer | ImageLayer;

type Page = {
	id: string;
	backgroundColor: string | null;
	layers: Layer[];
	sortOrder: number;
};
```

### Html editor

PresentationEditor is using `Tiptap` editor for `TextLayer` content editing.

`JSONContent` type provided by `@tiptap/core` is used for html content of `TextLayer` to store data in json format.

## Settings

The PresentationEditor component accepts a bunch of settings. Here is a typescript definition of all available settings:

```typescript
interface BaseOptions {
	images?: Image[];
	width?: number;
	height?: number;
	generateId?: () => string;
	onImageUpload?: (file: File) => Promise<Image>;
	onLayerAdd?: (pageId: string, layer: Layer) => Promise<Layer>;
	onLayerUpdate?: (pageId: string, layerId: string, layerType: string, changes: object) => void;
	onLayerRemove?: (pageId: string, layerId: string, layerType: string) => Promise<void>;
}

interface MultipleModeOption extends BaseOptions {
	mode?: 'multiple';
	pages?: Page[];
	onPageAdd?: (page: Page) => Promise<Page>;
	onPageUpdate?: (pageId: string, changes: object) => void;
	onPageRemove?: (pageId: string) => Promise<void>;
}

interface SingleModeOption extends BaseOptions {
	mode: 'single';
	page?: Page;
}

export type PresentationEditorOptions = MultipleModeOption | SingleModeOption;
```

## Getting Started

```typescript
import { createEditor } from '@peteai/presentation-editor';

// images list
const images: Image[];
// pages list
const pages: Page[];

const editor = new createEditor({
	target: document.querySelector('.target'),
	props: {
		// function for new pages and layers ids generation
		generateId: () => crypto.randomUUID(),
		images,
		pages,
		onImageUpload: async (file) => {
			// called when user uploads image
			// callback to store file and return Image
			// which will be added to the images list
			// new ImageLayer gonna be created if image file was dropped on page
			// ...
			return image;
		},
		onPageAdd: async (page) => {
			// called when new page is added
			// expect Page to be returned to overwrite newly created page
		},
		onPageUpdate: async (pageId, values) => {
			// called when page is updated
		},
		onPageRemove: async (pageId) => {
			// called when page is removed
		},
		onLayerAdd: async (pageId, layer) => {
			// called when new layer is added
			// expect Layer to be returned to overwrite newly created layer
		},
		onLayerUpdate: async (pageId, layerId, layerType, values) => {
			// called when layer is updated
		},
		onLayerRemove: async (pageId, layerId, layerType) => {
			// called when layer is removed
		},
	},
});
```

## Single Page Mode

```typescript
import { createEditor } from '@peteai/presentation-editor';

// images list
const images: Image[];
// pages list
const page: Page;

const editor = new createEditor({
	target: document.querySelector('.target'),
	props: {
		mode: 'single',
		// function for new pages and layers ids generation
		generateId: () => crypto.randomUUID(),
		images,
		page,
		onImageUpload: async (file) => {
			// called when user uploads image
			// callback to store file and return Image
			// which will be added to the images list
			// new ImageLayer gonna be created if image file was dropped on page
			// ...
			return image;
		},
		onLayerAdd: async (pageId, layer) => {
			// called when new layer is added
			// expect Layer to be returned to overwrite newly created layer
		},
		onLayerUpdate: async (pageId, layerId, layerType, values) => {
			// called when layer is updated
		},
		onLayerRemove: async (pageId, layerId, layerType) => {
			// called when layer is removed
		},
	},
});
```