Skip to content

Commit a5fbd41

Browse files
authored
Merge pull request #11 from imagekit-developer/creative-templates
feat: user workflows for creative templates
2 parents cfa3827 + e315d57 commit a5fbd41

54 files changed

Lines changed: 13945 additions & 331 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ jobs:
2222
node-version: 20.x
2323
cache: yarn
2424

25-
- name: 📦 Install deps, build, pack
25+
- name: 📦 Install deps, lint, test, build, pack
2626
run: |
2727
yarn install --frozen-lockfile
2828
yarn lint
29+
yarn test:coverage
2930
yarn package
3031
env:
3132
CI: true

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ packages/imagekit-editor/*.tgz
1919
.yarn
2020
builds
2121
packages/imagekit-editor/README.md
22-
.cursor
22+
.cursor
23+
coverage

README.md

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ A powerful, React-based image editor component powered by ImageKit transformatio
1212

1313
- 🖼️ **Visual Image Editor**: Interactive UI for applying ImageKit transformations
1414
- 📝 **Transformation History**: Track and manage applied transformations using ImageKit's chain transformations
15+
- 💾 **Template Management**: Save and restore editor templates with built-in serialization support
1516
- 🎨 **Multiple Transformation Types**: Support for resize, crop, focus, quality adjustments, and more
1617
- 🖥️ **Desktop Interface**: Modern interface built with Chakra UI for desktop environments
1718
- 🔧 **TypeScript Support**: Full TypeScript support with comprehensive type definitions
@@ -141,9 +142,15 @@ interface ImageKitEditorRef {
141142
loadImage: (image: string | FileElement) => void;
142143
loadImages: (images: Array<string | FileElement>) => void;
143144
setCurrentImage: (imageSrc: string) => void;
145+
getTemplate: () => Transformation[];
146+
loadTemplate: (template: Omit<Transformation, 'id'>[]) => void;
144147
}
145148
```
146149

150+
**Template Management Methods:**
151+
- `getTemplate()` - Returns the current editor template (transformation stack)
152+
- `loadTemplate(template)` - Loads a previously saved template into the editor
153+
147154
### Export Options
148155

149156
You can configure export functionality in two ways:
@@ -212,6 +219,124 @@ The `metadata` object can contain any contextual information your application ne
212219

213220
## Advanced Usage
214221

222+
### Template Management
223+
224+
You can save and restore editor templates, enabling features like:
225+
- Template library
226+
- Preset transformation stacks
227+
- Collaborative editing workflows
228+
- Quick application of common transformations
229+
230+
**Template Versioning:** All templates are versioned (currently `v1`) to ensure backward compatibility and safe schema evolution.
231+
232+
#### Saving a Template
233+
234+
```tsx
235+
import { useRef } from 'react';
236+
import { ImageKitEditor, type ImageKitEditorRef, type Transformation } from '@imagekit/editor';
237+
238+
function MyComponent() {
239+
const editorRef = useRef<ImageKitEditorRef>(null);
240+
241+
const handleSaveTemplate = () => {
242+
const template = editorRef.current?.getTemplate();
243+
if (template) {
244+
// Remove the auto-generated 'id' field before saving
245+
const templateToSave = template.map(({ id, ...rest }) => rest);
246+
247+
// Save to localStorage
248+
localStorage.setItem('editorTemplate', JSON.stringify(templateToSave));
249+
250+
// Or save to your backend
251+
await api.saveTemplate(templateToSave);
252+
}
253+
};
254+
255+
return (
256+
<ImageKitEditor
257+
ref={editorRef}
258+
// ... other props
259+
exportOptions={[
260+
{
261+
type: 'button',
262+
label: 'Save Template',
263+
isVisible: true,
264+
onClick: handleSaveTemplate
265+
}
266+
]}
267+
/>
268+
);
269+
}
270+
```
271+
272+
#### Loading a Template
273+
274+
```tsx
275+
const handleLoadTemplate = () => {
276+
// Load from localStorage
277+
const saved = localStorage.getItem('editorTemplate');
278+
279+
// Or load from your backend
280+
// const saved = await api.getTemplate();
281+
282+
if (saved) {
283+
const template = JSON.parse(saved);
284+
editorRef.current?.loadTemplate(template);
285+
}
286+
};
287+
```
288+
289+
#### Template Structure
290+
291+
A template is an array of transformation objects with version information:
292+
293+
```tsx
294+
interface Transformation {
295+
id: string; // Auto-generated, omit when saving
296+
key: string; // e.g., 'adjust-background'
297+
name: string; // e.g., 'Background'
298+
type: 'transformation';
299+
value: Record<string, unknown>; // Transformation parameters
300+
version?: 'v1'; // Template version for compatibility
301+
}
302+
303+
// Version constant
304+
import { TRANSFORMATION_STATE_VERSION } from '@imagekit/editor';
305+
console.log(TRANSFORMATION_STATE_VERSION); // 'v1'
306+
```
307+
308+
**Example template:**
309+
```json
310+
[
311+
{
312+
"key": "adjust-background",
313+
"name": "Background",
314+
"type": "transformation",
315+
"value": {
316+
"backgroundType": "color",
317+
"background": "#FFFFFF"
318+
},
319+
"version": "v1"
320+
},
321+
{
322+
"key": "resize_and_crop-resize_and_crop",
323+
"name": "Resize and Crop",
324+
"type": "transformation",
325+
"value": {
326+
"width": 800,
327+
"height": 600,
328+
"mode": "pad_resize"
329+
},
330+
"version": "v1"
331+
}
332+
]
333+
```
334+
335+
**Version Compatibility:**
336+
- `v1` - Current version with all transformation features
337+
- The `version` field is optional for backward compatibility
338+
- Future versions will maintain backward compatibility where possible
339+
215340
### Signed URLs
216341

217342
For private images that require signed URLs, you can pass file metadata that will be available in the signer function:
@@ -269,10 +394,40 @@ import type {
269394
ImageKitEditorProps,
270395
ImageKitEditorRef,
271396
FileElement,
272-
Signer
397+
Signer,
398+
Transformation // For template management
273399
} from '@imagekit/editor';
400+
401+
// Version constant for template compatibility
402+
import { TRANSFORMATION_STATE_VERSION } from '@imagekit/editor';
274403
```
275404

405+
## Testing
406+
407+
The package includes comprehensive tests to ensure schema stability and API consistency. Run tests:
408+
409+
```bash
410+
# Run tests once
411+
yarn test
412+
413+
# Watch mode
414+
yarn test:watch
415+
416+
# With UI
417+
yarn test:ui
418+
```
419+
420+
### Schema Versioning
421+
422+
The transformation schema is locked down with tests to ensure:
423+
- All transformation categories exist and are stable
424+
- All transformation items have required properties
425+
- Schemas validate correctly
426+
- Template serialization/deserialization works consistently
427+
- Version compatibility is maintained
428+
429+
Current schema version: **v1**
430+
276431
## Contributing
277432

278433
We welcome contributions! Please see our [contributing guidelines](./CONTRIBUTING.md) for more details.

examples/react-example/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@imagekit/editor": "2.1.0",
6+
"@imagekit/editor": "workspace:*",
77
"@types/node": "^20.11.24",
88
"@types/react": "^17.0.2",
99
"@types/react-dom": "^17.0.2",
@@ -18,7 +18,8 @@
1818
"scripts": {
1919
"dev": "vite --port 3000",
2020
"start": "vite --port 3000",
21-
"preview": "vite preview"
21+
"preview": "vite preview",
22+
"test": "echo \"No tests in this example\""
2223
},
2324
"eslintConfig": {
2425
"extends": [

0 commit comments

Comments
 (0)