@rocketium/auto-adapt 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +237 -0
- package/dist/index.d.mts +696 -0
- package/dist/index.d.ts +696 -0
- package/dist/index.js +930 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +897 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rocketium
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# @rocketium/auto-adapt
|
|
2
|
+
|
|
3
|
+
Layout adaptation engine for auto-sizing canvas elements across different dimensions. Ports the proven frontend auto-adapt algorithm to a reusable package for use in both client and server environments.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@rocketium/auto-adapt` intelligently adapts canvas layouts from one size to another. Given a set of canvas elements (text, images, shapes, groups, SVGs) designed for one dimension, it produces a proportionally adapted layout for a target dimension while preserving alignment, edge-snapping, and visual hierarchy.
|
|
8
|
+
|
|
9
|
+
### Key Features
|
|
10
|
+
|
|
11
|
+
- **Closest-size matching** -- finds the best reference size from available sizes using aspect-ratio + Euclidean distance scoring
|
|
12
|
+
- **Smart skew detection** -- decides whether to stretch (skew) or proportionally scale each element based on its canvas coverage
|
|
13
|
+
- **Per-element-type adaptation** -- specialized handling for text (font sizes, word styles, autofit), images (crop offsets, scale), shapes (SVG, rounded-rect, path), and groups (recursive child adaptation)
|
|
14
|
+
- **Edge-aware positioning** -- preserves alignment to canvas edges and centering
|
|
15
|
+
- **Override system** -- stores adapted layouts as per-size overrides on the original objects, keeping the base variant untouched
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @rocketium/auto-adapt
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**For local development** (before publishing):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install ../auto-adapt
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Peer Dependencies
|
|
30
|
+
|
|
31
|
+
| Package | Version | Required |
|
|
32
|
+
|---------|---------|----------|
|
|
33
|
+
| `@types/fabric` | `^5.3.9` | Optional (compile-time only) |
|
|
34
|
+
|
|
35
|
+
The package uses `@types/fabric` for canvas element type definitions. If you're consuming typed APIs, ensure it's installed as a devDependency.
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { generateBaseLayoutForSize } from '@rocketium/auto-adapt';
|
|
41
|
+
|
|
42
|
+
const newCapsule = generateBaseLayoutForSize({
|
|
43
|
+
originalCapsule, // ServerCapsule with existing sizes and objects
|
|
44
|
+
capsuleId: 'abc123',
|
|
45
|
+
creativeId: null, // null = auto-detect best reference size
|
|
46
|
+
sizeId: 'new-size-id',
|
|
47
|
+
sizeToGenerate: '300x250',
|
|
48
|
+
sizeName: 'Medium Rectangle',
|
|
49
|
+
sizeCategory: 'Display',
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## API Reference
|
|
54
|
+
|
|
55
|
+
### `generateBaseLayoutForSize(params)`
|
|
56
|
+
|
|
57
|
+
Main entry point. Generates a complete adapted capsule for a target size.
|
|
58
|
+
|
|
59
|
+
**Parameters:**
|
|
60
|
+
|
|
61
|
+
| Param | Type | Description |
|
|
62
|
+
|-------|------|-------------|
|
|
63
|
+
| `originalCapsule` | `ServerCapsule` | Source capsule with canvas data, sizes, and objects |
|
|
64
|
+
| `capsuleId` | `string` | ID of the capsule being adapted |
|
|
65
|
+
| `creativeId` | `string \| null` | Reference size ID to adapt from. Pass `null` to auto-detect the closest match |
|
|
66
|
+
| `sizeId` | `string` | ID for the new size entry |
|
|
67
|
+
| `sizeToGenerate` | `string` | Target dimensions as `"WIDTHxHEIGHT"` (e.g. `"1080x1080"`) |
|
|
68
|
+
| `sizeName` | `string?` | Display name for the new size |
|
|
69
|
+
| `sizeCategory` | `string?` | Category label for the new size |
|
|
70
|
+
|
|
71
|
+
**Returns:** `ServerCapsule` -- a deep copy of the original capsule with the new size added, objects adapted as overrides, and metadata updated.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### `getAdaptedObjectsJSON(params)`
|
|
76
|
+
|
|
77
|
+
Core adaptation algorithm. Adapts a flat record of canvas elements from one size to another.
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
|
|
81
|
+
| Param | Type | Description |
|
|
82
|
+
|-------|------|-------------|
|
|
83
|
+
| `adaptSize` | `string` | Target dimensions (`"WIDTHxHEIGHT"`) |
|
|
84
|
+
| `objects` | `Record<string, CanvasElementJSON>` | Source elements keyed by ID |
|
|
85
|
+
| `closestSize` | `string` | Reference dimensions (`"WIDTHxHEIGHT"`) |
|
|
86
|
+
|
|
87
|
+
**Returns:** `Record<string, CanvasElementJSON>` -- adapted elements.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### `findClosestSizeWithMatches(params)`
|
|
92
|
+
|
|
93
|
+
Finds the closest matching size from a list, with match-quality scores.
|
|
94
|
+
|
|
95
|
+
**Parameters:**
|
|
96
|
+
|
|
97
|
+
| Param | Type | Description |
|
|
98
|
+
|-------|------|-------------|
|
|
99
|
+
| `availableSizes` | `string[]` | Array of dimension strings |
|
|
100
|
+
| `adaptSize` | `string` | Target dimension string |
|
|
101
|
+
|
|
102
|
+
**Returns:** `{ closestSize: string; sortedMatches: Record<string, number> }` -- best match and percentage scores for all sizes.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### `findBestReferenceSize(availableSizes, targetSize)`
|
|
107
|
+
|
|
108
|
+
Finds the best reference size ID from a sizes record.
|
|
109
|
+
|
|
110
|
+
**Parameters:**
|
|
111
|
+
|
|
112
|
+
| Param | Type | Description |
|
|
113
|
+
|-------|------|-------------|
|
|
114
|
+
| `availableSizes` | `Record<string, { width: number; height: number }>` | Available sizes keyed by ID |
|
|
115
|
+
| `targetSize` | `string` | Target dimension string |
|
|
116
|
+
|
|
117
|
+
**Returns:** `string` -- the key of the best matching size.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Utility Exports
|
|
122
|
+
|
|
123
|
+
| Function | Description |
|
|
124
|
+
|----------|-------------|
|
|
125
|
+
| `resolveObjectsForSize(objects, sizeId)` | Flatten overrides for a specific size into base objects |
|
|
126
|
+
| `applyAdaptedAsOverrides(originals, adapted, sizeId)` | Store adapted objects as overrides on originals |
|
|
127
|
+
| `getNormalizedSizeValue(sizeValue)` | Normalize named sizes (`"square"` -> `"720x720"`) |
|
|
128
|
+
| `getEuclideanDistanceBetweenSizes({ size1, size2 })` | Distance between two size strings |
|
|
129
|
+
|
|
130
|
+
### Type Guard Exports
|
|
131
|
+
|
|
132
|
+
| Function | Checks for |
|
|
133
|
+
|----------|------------|
|
|
134
|
+
| `isTextJSON(object)` | `TextContainerJSON` |
|
|
135
|
+
| `isImageJSON(object)` | `ImageContainerJSON` |
|
|
136
|
+
| `isShapeJSON(object)` | `PathJSON \| RoundedRectJSON \| SvgJSON` |
|
|
137
|
+
| `isSVGContainerJSON(object)` | `SvgJSON` |
|
|
138
|
+
| `isRoundedRectJSON(object)` | `RoundedRectJSON` |
|
|
139
|
+
| `isGroupJSON(object)` | `GroupContainerJSON` |
|
|
140
|
+
| `isCreativeBoxJSON(object)` | Creative box elements |
|
|
141
|
+
| `isAudioJSON(object)` | Audio elements |
|
|
142
|
+
|
|
143
|
+
## Algorithm
|
|
144
|
+
|
|
145
|
+
### Size Matching
|
|
146
|
+
|
|
147
|
+
Uses a weighted scoring system combining:
|
|
148
|
+
- **Aspect ratio similarity** (90% weight) -- prefers sizes with matching proportions
|
|
149
|
+
- **Euclidean distance** (10% weight) -- tiebreaks with absolute dimension proximity
|
|
150
|
+
|
|
151
|
+
### Element Adaptation
|
|
152
|
+
|
|
153
|
+
For each element, the algorithm decides between two paths:
|
|
154
|
+
|
|
155
|
+
1. **Skew path** -- stretches the element to fill proportionally. Used when:
|
|
156
|
+
- Element covers >90% of the canvas area
|
|
157
|
+
- Element spans the full width or full height of the canvas
|
|
158
|
+
- Groups are excluded from skewing
|
|
159
|
+
|
|
160
|
+
2. **Non-skew path** -- proportionally scales while preserving position. Uses:
|
|
161
|
+
- Edge alignment detection (snaps to nearest edge within 1px threshold)
|
|
162
|
+
- Horizontal centering detection (area-based left/right balance)
|
|
163
|
+
- Quadrant-based positioning for non-centered, non-edge-aligned elements
|
|
164
|
+
|
|
165
|
+
### Per-Type Handling
|
|
166
|
+
|
|
167
|
+
| Type | Special Handling |
|
|
168
|
+
|------|-----------------|
|
|
169
|
+
| **Text** | Scales fontSize, wordStyle font sizes (px only), autoFitSizes, padding, wordSpacing |
|
|
170
|
+
| **Image** | Scales imageScale, imageLeft/imageTop offsets, cornerRadius |
|
|
171
|
+
| **SVG** | Same as image + colorMap passthrough |
|
|
172
|
+
| **RoundedRect** | Scales cornerRadius |
|
|
173
|
+
| **Path/Shape** | Scales scaleX/scaleY instead of width/height |
|
|
174
|
+
| **Group** | Recursively adapts all children with group-relative scaling |
|
|
175
|
+
| **CreativeBox** | Resized to target dimensions (canvas background) |
|
|
176
|
+
| **Audio** | Passed through unchanged |
|
|
177
|
+
|
|
178
|
+
## Project Structure
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
src/
|
|
182
|
+
├── index.ts # Public API exports
|
|
183
|
+
├── adapter.ts # Core adapt logic + entry function
|
|
184
|
+
├── constants.ts # Thresholds and defaults
|
|
185
|
+
├── types/
|
|
186
|
+
│ ├── index.ts # Type barrel exports
|
|
187
|
+
│ ├── canvas.ts # Canvas element type definitions
|
|
188
|
+
│ └── capsule.ts # ServerCapsule type
|
|
189
|
+
└── utils/
|
|
190
|
+
├── sizeMatching.ts # Size comparison and closest-match algorithms
|
|
191
|
+
├── scaling.ts # Element scaling, border, padding helpers
|
|
192
|
+
└── typeGuards.ts # Runtime type guards for canvas elements
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Development
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# Install dependencies
|
|
199
|
+
npm install
|
|
200
|
+
|
|
201
|
+
# Type check
|
|
202
|
+
npm run typecheck
|
|
203
|
+
|
|
204
|
+
# Build (CJS + ESM + .d.ts)
|
|
205
|
+
npm run build
|
|
206
|
+
|
|
207
|
+
# Lint
|
|
208
|
+
npm run lint
|
|
209
|
+
|
|
210
|
+
# Format
|
|
211
|
+
npm run format
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
For local linking: `npm install ../auto-adapt` from a consumer project.
|
|
215
|
+
|
|
216
|
+
## Publishing
|
|
217
|
+
|
|
218
|
+
Publishing uses the Rocketium org account. Personal `~/.npmrc` is left unchanged.
|
|
219
|
+
|
|
220
|
+
1. Create `.npmrc` in the project root (gitignored). Use this structure:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
//registry.npmjs.org/:_authToken=REPLACE_WITH_ROCKETIUM_NPM_TOKEN
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
2. Replace `REPLACE_WITH_ROCKETIUM_NPM_TOKEN` with the actual token (or `${NPM_TOKEN}` for env-based auth).
|
|
227
|
+
|
|
228
|
+
3. Publish:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
npm run release:patch/minor/major
|
|
232
|
+
```
|
|
233
|
+
as per the requirement
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|