datocms-plugin-media-layouts 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -9,10 +9,12 @@ A DatoCMS plugin that extends JSON fields to allow editors to select assets with
9
9
  - **Self-contained data**: Stores URL, filename, and all metadata directly in JSON—no additional API calls needed
10
10
  - **Three operational modes**: Single asset, multiple assets (gallery), or predefined layout slots
11
11
  - **Aspect ratio control**: 9 presets plus custom ratios for precise cropping
12
- - **Width presets**: Original (max) plus 320px mobile to 4K resolution
12
+ - **Width presets**: Original (max) plus 320px mobile to 4K resolution, with named custom presets and custom widths
13
13
  - **Focal point support**: Preserves focal point data from DatoCMS media library
14
14
  - **Metadata editing**: Edit alt text, title, and focal point directly from the field
15
- - **Layout mode**: Define grid-based slot configurations with required fields
15
+ - **Per-asset options**: Optional CSS class and lazy loading toggle per image
16
+ - **Layout builder**: Grid or masonry layouts with drag-and-drop placement, slot spans, and auto-sizing from aspect ratio
17
+ - **Layout metadata**: Optional layout aspect ratio + width for overall composition sizing
16
18
  - **Automatic height calculation**: Heights computed from width and aspect ratio for easy imgix integration
17
19
 
18
20
  ## Installation
@@ -34,6 +36,7 @@ Configure default values that apply to all fields using this plugin:
34
36
  |---------|-------------|---------|
35
37
  | Default Aspect Ratio | Applied to new assets when no field override exists | 16:9 |
36
38
  | Default Width | Applied to new assets when no field override exists | 1920px |
39
+ | Width Presets | Named width options shown in all width selectors | (none) |
37
40
 
38
41
  ### Field Configuration
39
42
 
@@ -49,13 +52,26 @@ Select multiple images, each with independent layout settings. Stores an array o
49
52
 
50
53
  #### Layout Mode (Predefined Slots)
51
54
 
52
- Define a grid with named slots that editors fill with assets. Each slot has:
55
+ Define a layout with named slots that editors fill with assets. Choose a style:
56
+
57
+ - **Grid**: Explicit rows/columns (1–4 columns, 1–6 rows), slots placed in cells
58
+ - **Masonry**: Column-based layout with variable heights and ordered slots
59
+
60
+ Each slot has:
53
61
  - **Label**: Descriptive name (e.g., "Hero Image", "Sidebar Thumbnail")
54
- - **Aspect Ratio**: Fixed ratio for this slot
55
- - **Width**: Fixed output width for this slot (including Original)
62
+ - **Aspect Ratio**: Fixed ratio for this slot (including Custom)
63
+ - **Width**: Fixed output width for this slot (including Custom)
56
64
  - **Required**: Whether the slot must be filled
57
65
 
58
- Grid supports 1-4 columns and 1-6 rows.
66
+ Layout builder enhancements:
67
+ - **Drag-and-drop placement**: Move or swap slots directly in the preview
68
+ - **Slot spans** (grid): Slots can span multiple rows/columns
69
+ - **Auto size from aspect ratio** (grid): Let spans be calculated based on the slot ratio
70
+ - **Column span** (masonry): Control the width of a masonry tile
71
+
72
+ Optional layout metadata:
73
+ - **Layout aspect ratio**: Auto, preset, or custom ratio for the overall composition
74
+ - **Layout width**: Auto, preset, or custom width for the overall composition (used to compute layout dimensions)
59
75
 
60
76
  ### Field Overrides
61
77
 
@@ -63,6 +79,12 @@ For single/multiple modes, you can optionally override global defaults:
63
79
  - Toggle "Override default aspect ratio" to set a field-specific ratio
64
80
  - Toggle "Override default width" to set a field-specific width
65
81
 
82
+ ### Per-Asset Options
83
+
84
+ You can optionally enable extra per-image fields:
85
+ - **CSS class**: Text input to pass a custom class name
86
+ - **Lazy loading**: Boolean toggle for lazy loading preference
87
+
66
88
  ## Aspect Ratio Options
67
89
 
68
90
  | Value | Label | Use Case |
@@ -92,6 +114,17 @@ For single/multiple modes, you can optionally override global defaults:
92
114
  | 2560px | 2K | High-resolution displays |
93
115
  | 3840px | 4K | Ultra HD displays |
94
116
 
117
+ Custom widths are supported: select "Custom..." and enter any pixel value
118
+ between 1 and 10000. Heights are still calculated automatically.
119
+
120
+ You can also add named custom presets in the plugin configuration (label + width),
121
+ which appear alongside the built-in options to guide editors with context-specific
122
+ sizes.
123
+
124
+ Custom presets are available in all width selectors (global defaults, field overrides,
125
+ asset/slot width pickers, and layout width). Layout width excludes the "Original"
126
+ option and supports Auto + Custom values.
127
+
95
128
  ## Data Model
96
129
 
97
130
  The plugin stores all asset data directly in the JSON field, including the URL. No additional API calls are needed to render images.
@@ -107,6 +140,8 @@ The plugin stores all asset data directly in the JSON field, including the URL.
107
140
  "size": 245000,
108
141
  "alt": "A beautiful sunset",
109
142
  "title": "Sunset at the beach",
143
+ "cssClass": "hero-image",
144
+ "lazyLoading": true,
110
145
  "focalPoint": { "x": 0.5, "y": 0.3 },
111
146
  "aspectRatio": "16:9",
112
147
  "width": 1920,
@@ -128,6 +163,8 @@ The plugin stores all asset data directly in the JSON field, including the URL.
128
163
  "size": 180000,
129
164
  "alt": "First image",
130
165
  "title": null,
166
+ "cssClass": "",
167
+ "lazyLoading": false,
131
168
  "focalPoint": null,
132
169
  "aspectRatio": "1:1",
133
170
  "width": 640,
@@ -143,6 +180,8 @@ The plugin stores all asset data directly in the JSON field, including the URL.
143
180
  "size": 320000,
144
181
  "alt": "Second image",
145
182
  "title": null,
183
+ "cssClass": "gallery-item",
184
+ "lazyLoading": true,
146
185
  "focalPoint": { "x": 0.3, "y": 0.5 },
147
186
  "aspectRatio": "4:3",
148
187
  "width": 1024,
@@ -156,40 +195,79 @@ The plugin stores all asset data directly in the JSON field, including the URL.
156
195
  ### Layout Mode
157
196
 
158
197
  ```json
159
- [
160
- {
161
- "slotId": "hero",
162
- "uploadId": "abc123",
163
- "url": "https://www.datocms-assets.com/12345/hero.jpg",
164
- "filename": "hero.jpg",
165
- "format": "jpg",
166
- "size": 450000,
167
- "alt": "Hero banner",
168
- "title": null,
169
- "focalPoint": { "x": 0.5, "y": 0.5 },
170
- "aspectRatio": "21:9",
171
- "width": 1920,
172
- "height": 823,
173
- "originalWidth": 4000,
174
- "originalHeight": 2000
198
+ {
199
+ "layout": {
200
+ "columns": 2,
201
+ "rows": 2,
202
+ "layoutStyle": "grid",
203
+ "layoutAspectRatio": "16:9",
204
+ "layoutWidth": 1920,
205
+ "slots": [
206
+ {
207
+ "id": "hero",
208
+ "label": "Hero",
209
+ "aspectRatio": "21:9",
210
+ "width": 1920,
211
+ "row": 0,
212
+ "col": 0,
213
+ "rowSpan": 1,
214
+ "colSpan": 2,
215
+ "autoSpan": false,
216
+ "required": true
217
+ },
218
+ {
219
+ "id": "sidebar",
220
+ "label": "Sidebar",
221
+ "aspectRatio": "1:1",
222
+ "width": 320,
223
+ "row": 1,
224
+ "col": 1,
225
+ "rowSpan": 1,
226
+ "colSpan": 1,
227
+ "autoSpan": false,
228
+ "required": false
229
+ }
230
+ ]
175
231
  },
176
- {
177
- "slotId": "sidebar",
178
- "uploadId": "def456",
179
- "url": "https://www.datocms-assets.com/12345/sidebar.jpg",
180
- "filename": "sidebar.jpg",
181
- "format": "jpg",
182
- "size": 85000,
183
- "alt": "Sidebar image",
184
- "title": null,
185
- "focalPoint": null,
186
- "aspectRatio": "1:1",
187
- "width": 320,
188
- "height": 320,
189
- "originalWidth": 800,
190
- "originalHeight": 800
191
- }
192
- ]
232
+ "assignments": [
233
+ {
234
+ "slotId": "hero",
235
+ "uploadId": "abc123",
236
+ "url": "https://www.datocms-assets.com/12345/hero.jpg",
237
+ "filename": "hero.jpg",
238
+ "format": "jpg",
239
+ "size": 450000,
240
+ "alt": "Hero banner",
241
+ "title": null,
242
+ "cssClass": "hero-image",
243
+ "lazyLoading": true,
244
+ "focalPoint": { "x": 0.5, "y": 0.5 },
245
+ "aspectRatio": "21:9",
246
+ "width": 1920,
247
+ "height": 823,
248
+ "originalWidth": 4000,
249
+ "originalHeight": 2000
250
+ },
251
+ {
252
+ "slotId": "sidebar",
253
+ "uploadId": "def456",
254
+ "url": "https://www.datocms-assets.com/12345/sidebar.jpg",
255
+ "filename": "sidebar.jpg",
256
+ "format": "jpg",
257
+ "size": 85000,
258
+ "alt": "Sidebar image",
259
+ "title": null,
260
+ "cssClass": "",
261
+ "lazyLoading": false,
262
+ "focalPoint": null,
263
+ "aspectRatio": "1:1",
264
+ "width": 320,
265
+ "height": 320,
266
+ "originalWidth": 800,
267
+ "originalHeight": 800
268
+ }
269
+ ]
270
+ }
193
271
  ```
194
272
 
195
273
  ### TypeScript Types
@@ -203,6 +281,8 @@ type MediaLayoutItem = {
203
281
  size: number;
204
282
  alt: string | null;
205
283
  title: string | null;
284
+ cssClass?: string;
285
+ lazyLoading?: boolean;
206
286
  focalPoint: { x: number; y: number } | null;
207
287
  aspectRatio: string;
208
288
  customAspectRatio?: string; // When aspectRatio is "custom"
@@ -212,6 +292,30 @@ type MediaLayoutItem = {
212
292
  originalHeight: number | null;
213
293
  };
214
294
 
295
+ type LayoutSlot = {
296
+ id: string;
297
+ label: string;
298
+ aspectRatio: string;
299
+ customAspectRatio?: string; // When aspectRatio is "custom"
300
+ width: number | 'original';
301
+ row: number;
302
+ col: number;
303
+ rowSpan?: number;
304
+ colSpan?: number;
305
+ autoSpan?: boolean;
306
+ required: boolean;
307
+ };
308
+
309
+ type LayoutConfig = {
310
+ slots: LayoutSlot[];
311
+ columns: number;
312
+ rows: number;
313
+ layoutStyle?: 'grid' | 'masonry';
314
+ layoutAspectRatio?: string;
315
+ layoutCustomAspectRatio?: string;
316
+ layoutWidth?: number;
317
+ };
318
+
215
319
  // Single mode value
216
320
  type SingleFieldValue = MediaLayoutItem | null;
217
321
 
@@ -220,7 +324,10 @@ type MultipleFieldValue = MediaLayoutItem[];
220
324
 
221
325
  // Layout mode value
222
326
  type SlotAssignment = MediaLayoutItem & { slotId: string };
223
- type LayoutFieldValue = SlotAssignment[];
327
+ type LayoutFieldValue = {
328
+ layout: LayoutConfig;
329
+ assignments: SlotAssignment[];
330
+ };
224
331
  ```
225
332
 
226
333
  ## Usage with imgix