@measured/puck 0.11.0-canary.6145c32 → 0.11.0-canary.7f13efc
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 +218 -24
- package/dist/index.css +265 -182
- package/dist/index.d.ts +118 -55
- package/dist/index.js +30894 -1134
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# puck
|
|
2
2
|
|
|
3
|
+
The self-hosted, drag and drop editor for React.
|
|
4
|
+
|
|
3
5
|
<p align="left">
|
|
4
6
|
<a aria-label="Measured logo" href="https://measured.co">
|
|
5
7
|
<img src="https://img.shields.io/badge/MADE%20BY%20Measured-000000.svg?style=for-the-badge&labelColor=000">
|
|
@@ -15,7 +17,7 @@
|
|
|
15
17
|
</a>
|
|
16
18
|
</p>
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
## Features
|
|
19
21
|
|
|
20
22
|
- 🖱️ **Drag and drop**: Visual editing for your existing React component library
|
|
21
23
|
- 🌐 **Integrations**: Load your content from a 3rd party headless CMS
|
|
@@ -111,10 +113,11 @@ The plugin API follows a React paradigm. Each plugin passed to the Puck editor c
|
|
|
111
113
|
- `renderRoot` (`Component`): Render the root node of the preview content
|
|
112
114
|
- `renderRootFields` (`Component`): Render the root fields
|
|
113
115
|
- `renderFields` (`Component`): Render the fields for the currently selected component
|
|
116
|
+
- `renderComponentList` (`Component`): Render the component list
|
|
114
117
|
|
|
115
118
|
Each render function receives three props:
|
|
116
119
|
|
|
117
|
-
- **children** (`ReactNode`): The normal contents of the root or field. You must render this.
|
|
120
|
+
- **children** (`ReactNode`): The normal contents of the root or field. You must render this if provided.
|
|
118
121
|
- **state** (`AppState`): The current application state, including data and UI state
|
|
119
122
|
- **dispatch** (`(action: PuckAction) => void`): The Puck dispatcher, used for making data changes or updating the UI. See the [action definitions](https://github.com/measuredco/puck/blob/main/packages/core/reducer/actions.tsx) for a full reference of available mutations.
|
|
120
123
|
|
|
@@ -231,6 +234,146 @@ The current DropZone implementation has certain rules and limitations:
|
|
|
231
234
|
3. You can't drag between DropZones that don't share a parent (or _area_)
|
|
232
235
|
4. Your mouse must be directly over a DropZone for a collision to be detected
|
|
233
236
|
|
|
237
|
+
## External fields
|
|
238
|
+
|
|
239
|
+
External fields can be used to import data from a third-party API, such as a headless CMS.
|
|
240
|
+
|
|
241
|
+
### Example
|
|
242
|
+
|
|
243
|
+
The `external` field type enables us to query data from a third party API:
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
const config = {
|
|
247
|
+
components: {
|
|
248
|
+
HeadingBlock: {
|
|
249
|
+
fields: {
|
|
250
|
+
myData: {
|
|
251
|
+
type: "external",
|
|
252
|
+
fetchList: async () => {
|
|
253
|
+
const response = await fetch("https://www.example.com/api");
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
text: response.json().text,
|
|
257
|
+
};
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
render: ({ myData }) => {
|
|
262
|
+
return <h1>{myData.text}</h1>;
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
When the user interacts with this external field, they'll be presented with a list of items to choose from. Once they select an item, the value will be mapped onto the prop. In this case, `myData`.
|
|
270
|
+
|
|
271
|
+
## Dynamic prop resolution
|
|
272
|
+
|
|
273
|
+
Dynamic prop resolution allows developers to resolve props for components without saving the data to the Puck data model.
|
|
274
|
+
|
|
275
|
+
### resolveData()
|
|
276
|
+
|
|
277
|
+
`resolveData` is defined in the component config, and allows the developer to make asynchronous calls to change the [ComponentData](#componentdata) after they've been set by Puck. Receives [ComponentData](#componentdata) and returns [ComponentData](#componentdata).
|
|
278
|
+
|
|
279
|
+
#### Examples
|
|
280
|
+
|
|
281
|
+
##### Basic example
|
|
282
|
+
|
|
283
|
+
In this example, we remap the `text` prop to the `title` prop and mark the `title` field as read-only.
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
const config = {
|
|
287
|
+
components: {
|
|
288
|
+
HeadingBlock: {
|
|
289
|
+
fields: {
|
|
290
|
+
text: {
|
|
291
|
+
type: "text",
|
|
292
|
+
},
|
|
293
|
+
title: {
|
|
294
|
+
type: "text",
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
resolveData: async (props) => {
|
|
298
|
+
return {
|
|
299
|
+
props: {
|
|
300
|
+
title: props.text,
|
|
301
|
+
},
|
|
302
|
+
readOnly: {
|
|
303
|
+
title: true,
|
|
304
|
+
},
|
|
305
|
+
};
|
|
306
|
+
},
|
|
307
|
+
render: ({ title }) => {
|
|
308
|
+
return <h1>{title}</h1>;
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
##### Combining with external fields
|
|
316
|
+
|
|
317
|
+
A more advanced pattern is to combine the `resolveData` method with `external` fields to dynamically fetch data when rendering the component.
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
const config = {
|
|
321
|
+
components: {
|
|
322
|
+
HeadingBlock: {
|
|
323
|
+
fields: {
|
|
324
|
+
myData: {
|
|
325
|
+
type: "external",
|
|
326
|
+
placeholder: "Select from example.com",
|
|
327
|
+
fetchList: async () => {
|
|
328
|
+
const response = await fetch("https://www.example.com/api");
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
id: response.json().id,
|
|
332
|
+
};
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
title: {
|
|
336
|
+
type: "text",
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
resolveData: async (props) => {
|
|
340
|
+
if (!myData.id) {
|
|
341
|
+
return { props, readOnly: { title: false } };
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const latestData = await fetch(
|
|
345
|
+
`https://www.example.com/api/${myData.id}`
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
props: {
|
|
350
|
+
title: latestData.json().text,
|
|
351
|
+
},
|
|
352
|
+
readOnly: {
|
|
353
|
+
title: true,
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
},
|
|
357
|
+
render: ({ title }) => {
|
|
358
|
+
return <h1>{title}</h1>;
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### resolveAllData()
|
|
366
|
+
|
|
367
|
+
`resolveAllData` is a utility function exported by Puck to enable the developer to run all their `resolveData` methods before rendering the component with `<Render>`.
|
|
368
|
+
|
|
369
|
+
If your `resolveData` methods rely on any external APIs, you should run this before rendering your page.
|
|
370
|
+
|
|
371
|
+
```tsx
|
|
372
|
+
import { resolveAllData } from "@measured/puck";
|
|
373
|
+
|
|
374
|
+
const resolvedData = resolveAllData(data, config);
|
|
375
|
+
```
|
|
376
|
+
|
|
234
377
|
## Reference
|
|
235
378
|
|
|
236
379
|
### `<Puck>`
|
|
@@ -241,6 +384,7 @@ The `<Puck>` component renders the Puck editor.
|
|
|
241
384
|
- **data** (`Data`): Initial data to render
|
|
242
385
|
- **onChange** (`(Data) => void` [optional]): Callback that triggers when the user makes a change
|
|
243
386
|
- **onPublish** (`(Data) => void` [optional]): Callback that triggers when the user hits the "Publish" button
|
|
387
|
+
- **renderComponentList** (`Component` [optional]): Render function for wrapping the component list
|
|
244
388
|
- **renderHeader** (`Component` [optional]): Render function for overriding the Puck header component
|
|
245
389
|
- **renderHeaderActions** (`Component` [optional]): Render function for overriding the Puck header actions. Use a fragment.
|
|
246
390
|
- **headerTitle** (`string` [optional]): Set the title shown in the header title
|
|
@@ -270,27 +414,74 @@ The `Config` object describes which components Puck should render, how they shou
|
|
|
270
414
|
- **title** (`Field`): Title of the content, typically used for the page title.
|
|
271
415
|
- **[fieldName]** (`Field`): User defined fields, used to describe the input data stored in the `root` key.
|
|
272
416
|
- **render** (`Component`): Render a React component at the root of your component tree. Useful for defining context providers.
|
|
417
|
+
- **resolveData** (`async (data: ComponentData) => ComponentData` [optional]): Function to dynamically change props before rendering the root.
|
|
273
418
|
- **components** (`object`): Definitions for each of the components you want to show in the visual editor
|
|
274
419
|
- **[componentName]** (`object`)
|
|
275
420
|
- **fields** (`Field`): The Field objects describing the input data stored against this component.
|
|
276
421
|
- **render** (`Component`): Render function for your React component. Receives props as defined in fields.
|
|
277
422
|
- **defaultProps** (`object` [optional]): Default props to pass to your component. Will show in fields.
|
|
423
|
+
- **resolveData** (`async (data: ComponentData) => ComponentData` [optional]): Function to dynamically change props before rendering the component.
|
|
424
|
+
- **categories** (`object`): Component categories for rendering in the side bar or restricting in DropZones
|
|
425
|
+
- **[categoryName]** (`object`)
|
|
426
|
+
- **components** (`sting[]`, [optional]): Array containing the names of components in this category
|
|
427
|
+
- **title** (`sting`, [optional]): Title of the category
|
|
428
|
+
- **visible** (`boolean`, [optional]): Whether or not the category should be visible in the side bar
|
|
429
|
+
- **defaultExpanded** (`boolean`, [optional]): Whether or not the category should be expanded in the side bar by default
|
|
278
430
|
|
|
279
431
|
### `Field`
|
|
280
432
|
|
|
281
433
|
A `Field` represents a user input field shown in the Puck interface.
|
|
282
434
|
|
|
283
|
-
|
|
435
|
+
### All Fields
|
|
436
|
+
|
|
284
437
|
- **label** (`text` [optional]): A label for the input. Will use the key if not provided.
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
- **
|
|
289
|
-
|
|
438
|
+
|
|
439
|
+
### Text Fields
|
|
440
|
+
|
|
441
|
+
- **type** (`"text"`)
|
|
442
|
+
|
|
443
|
+
### Textarea Fields
|
|
444
|
+
|
|
445
|
+
- **type** (`"textarea"`)
|
|
446
|
+
|
|
447
|
+
### Number Fields
|
|
448
|
+
|
|
449
|
+
- **type** (`"number"`)
|
|
450
|
+
|
|
451
|
+
### Select Fields
|
|
452
|
+
|
|
453
|
+
- **type** (`"select"`)
|
|
454
|
+
- **options** (`object[]`): array of items to render
|
|
290
455
|
- **label** (`string`)
|
|
291
456
|
- **value** (`string` | `number` | `boolean`)
|
|
292
|
-
|
|
293
|
-
|
|
457
|
+
|
|
458
|
+
### Radio Fields
|
|
459
|
+
|
|
460
|
+
- **type** (`"radio"`)
|
|
461
|
+
- **options** (`object[]`): array of items to render
|
|
462
|
+
- **label** (`string`)
|
|
463
|
+
- **value** (`string` | `number` | `boolean`)
|
|
464
|
+
|
|
465
|
+
### Array Fields
|
|
466
|
+
|
|
467
|
+
- **type** (`"array"`)
|
|
468
|
+
- **arrayFields** (`object`): Object describing sub-fields for each item
|
|
469
|
+
- **[fieldName]** (`Field`): The Field objects describing the input data for each item
|
|
470
|
+
- **getItemSummary** (`(object, number) => string` [optional]): Function to get the label of each item
|
|
471
|
+
- **defaultItemProps** (`object` [optional]): Default props to pass to each new item added, when using a `array` field type
|
|
472
|
+
|
|
473
|
+
### External Fields
|
|
474
|
+
|
|
475
|
+
External fields can be used to load content from an external content repository, like Strapi.js.
|
|
476
|
+
|
|
477
|
+
- **type** (`"external"`)
|
|
478
|
+
- **placeholder** (`string`): A placeholder for the external field button
|
|
479
|
+
- **fetchList** (`() => object`): Fetch content from a third-party API and return an array
|
|
480
|
+
- **mapProp** (`(selectedItem: object) => object`): Map the selected item into another shape
|
|
481
|
+
|
|
482
|
+
### Custom Fields
|
|
483
|
+
|
|
484
|
+
- **type** (`"custom"`)
|
|
294
485
|
- **render** (`Component`): Render a custom field. Receives the props:
|
|
295
486
|
- **field** (`Field`): Field configuration
|
|
296
487
|
- **name** (`string`): Name of the field
|
|
@@ -307,27 +498,30 @@ The `AppState` object stores the puck application state.
|
|
|
307
498
|
- **leftSideBarVisible** (boolean): Whether or not the left side bar is visible
|
|
308
499
|
- **itemSelector** (object): An object describing which item is selected
|
|
309
500
|
- **arrayState** (object): An object describing the internal state of array items
|
|
501
|
+
- **componentList** (object): An object describing the component list. Similar shape to `Config.categories`.
|
|
502
|
+
- **components** (`sting[]`, [optional]): Array containing the names of components in this category
|
|
503
|
+
- **title** (`sting`, [optional]): Title of the category
|
|
504
|
+
- **visible** (`boolean`, [optional]): Whether or not the category is visible in the side bar
|
|
505
|
+
- **expanded** (`boolean`, [optional]): Whether or not the category is expanded in the side bar
|
|
310
506
|
|
|
311
507
|
### `Data`
|
|
312
508
|
|
|
313
509
|
The `Data` object stores the puck page data.
|
|
314
510
|
|
|
315
|
-
- **root** (`
|
|
316
|
-
- **
|
|
317
|
-
|
|
318
|
-
- **content** (`
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
- **[prop]** (string): User defined data from component fields
|
|
322
|
-
|
|
323
|
-
### `Adaptor`
|
|
324
|
-
|
|
325
|
-
An `Adaptor` can be used to load content from an external content repository, like Strapi.js.
|
|
511
|
+
- **root** (`ComponentData`): The component data for the root of your configuration.
|
|
512
|
+
- **props** (object): Extends `ComponentData.props`, with some additional props
|
|
513
|
+
- **title** (`string`, [optional]): Title of the content, typically used for the page title
|
|
514
|
+
- **content** (`ComponentData[]`): Component data for the main content
|
|
515
|
+
- **zones** (`object`, [optional]): Component data for all DropZones
|
|
516
|
+
**[zoneCompound]** (`ComponentData[]`): Component data for a specific DropZone `zone` within a component instance
|
|
326
517
|
|
|
327
|
-
|
|
328
|
-
- **fetchList** (`(adaptorParams: object) => object`): Fetch a list of content and return an array
|
|
518
|
+
### `ComponentData`
|
|
329
519
|
|
|
330
|
-
|
|
520
|
+
- **type** (`string`): Component name
|
|
521
|
+
- **props** (`object`):
|
|
522
|
+
- **[prop]** (`any`): User defined data from component fields
|
|
523
|
+
- **readOnly** (`object`): Object describing which fields on the component are currently read-only. Can use dot-notation for arrays, like `array[1].text` or `array[*].text`.
|
|
524
|
+
- **[prop]** (`boolean`): boolean describing whether or not the prop field is read-only
|
|
331
525
|
|
|
332
526
|
### `Plugin`
|
|
333
527
|
|