@measured/puck-field-contentful 0.14.0-canary.053d4c6

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 ADDED
@@ -0,0 +1,132 @@
1
+ # field-contentful
2
+
3
+ Select [entries](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/entries) from a [Contentful](https://www.contentful.com) space.
4
+
5
+ ## Quick start
6
+
7
+ ```sh
8
+ npm i @measured/puck-field-contentful
9
+ ```
10
+
11
+ ```jsx
12
+ import createFieldContentful from "@measured/puck-field-contentful";
13
+
14
+ const config = {
15
+ components: {
16
+ Example: {
17
+ fields: {
18
+ movie: createFieldContentful("movies", {
19
+ space: "my_space",
20
+ accessToken: "abcdefg123456",
21
+ }),
22
+ },
23
+ render: ({ data }) => {
24
+ return <p>{data?.fields.title || "No data selected"}</p>;
25
+ },
26
+ },
27
+ },
28
+ };
29
+ ```
30
+
31
+ ## Args
32
+
33
+ | Param | Example | Type | Status |
34
+ | ----------------------------- | -------- | ------ | -------- |
35
+ | [`contentType`](#contenttype) | `movies` | String | Required |
36
+ | [`options`](#options) | `{}` | Object | Required |
37
+
38
+ ### Required args
39
+
40
+ #### `contentType`
41
+
42
+ ID of the Contentful [Content Type](https://www.contentful.com/help/content-model-and-content-type/) to query.
43
+
44
+ #### `options`
45
+
46
+ | Param | Example | Type | Status |
47
+ | ------------------------------------------ | --------------------------------------- | --------------------------------------------------------------- | ------------------------------ |
48
+ | [`accessToken`](#optionsaccesstoken) | `"abc123"` | String | Required (unless using client) |
49
+ | [`space`](#optionsspace) | `"my-space"` | String | Required (unless using client) |
50
+ | [`client`](#optionsclient) | `createClient()` | [ContentfulClientApi](https://www.npmjs.com/package/contentful) | - |
51
+ | [`filterFields`](#optionsfilterfields) | `{ "rating[gte]": { type: "number" } }` | Object | - |
52
+ | [`initialFilters`](#optionsinitialfilters) | `{ "rating[gte]": 1 }` | Object | - |
53
+ | [`titleField`](#optionstitlefield) | `"name"` | String | - |
54
+
55
+ ##### `options.accessToken`
56
+
57
+ Your Contentful access token.
58
+
59
+ ##### `options.space`
60
+
61
+ The id for the Contentful space that contains your content.
62
+
63
+ ##### `options.client`
64
+
65
+ A Contentful client as created by the [`contentful` Node.js package](https://www.npmjs.com/package/contentful). You can use this instead of `accessToken` and `space` if you want to reuse your client, or customise it more fully.
66
+
67
+ ##### `options.filterFields`
68
+
69
+ An object describing which [`filterFields`](https://puckeditor.com/docs/api-reference/fields/external#filterfields) to render and pass the result directly to Contentful as [search parameters](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters).
70
+
71
+ ```jsx
72
+ createFieldContentful("movies", {
73
+ // ...
74
+ filterFields: {
75
+ // Filter the "rating" field by value greater than the user input
76
+ "fields.rating[gte]": {
77
+ type: "number",
78
+ },
79
+ },
80
+ });
81
+ ```
82
+
83
+ ##### `options.initialFilters`
84
+
85
+ The initial values for the filters defined in [`filterFields`](#optionsfilterfields). This data is passed directly directly to Contentful as [search parameters](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/search-parameters).
86
+
87
+ ```jsx
88
+ createFieldContentful("movies", {
89
+ // ...
90
+ initialFilters: {
91
+ "fields.rating[gte]": 1,
92
+ select: "name,rating", // Can include search parameters not included in filterFields
93
+ },
94
+ });
95
+ ```
96
+
97
+ ##### `options.titleField`
98
+
99
+ The field to use as the title for the selected item. Defaults to `"title"`.
100
+
101
+ ```jsx
102
+ createFieldContentful("movies", {
103
+ // ...
104
+ titleField: "name",
105
+ });
106
+ ```
107
+
108
+ ## Returns
109
+
110
+ An [External field](https://puckeditor.com/docs/api-reference/fields/external) type that loads Contentful [entries](https://contentful.github.io/contentful.js/contentful/10.6.16/types/Entry.html).
111
+
112
+ ## TypeScript
113
+
114
+ You can use the `Entry` type for data loaded via Contentful:
115
+
116
+ ```tsx
117
+ import createFieldContentful, { Entry } from "@/field-contentful";
118
+
119
+ type MyProps = {
120
+ Example: {
121
+ movie: Entry<{ title: string; description: string; rating: number }>;
122
+ };
123
+ };
124
+
125
+ const config: Config<MyProps> = {
126
+ // ...
127
+ };
128
+ ```
129
+
130
+ ## License
131
+
132
+ MIT © [Measured Corporation Ltd](https://measured.co)
@@ -0,0 +1,123 @@
1
+ import { ReactElement } from 'react';
2
+ import { BaseEntry, ContentfulClientApi } from 'contentful';
3
+ export { createClient } from 'contentful';
4
+
5
+ type FieldOption = {
6
+ label: string;
7
+ value: string | number | boolean;
8
+ };
9
+ type FieldOptions = Array<FieldOption> | ReadonlyArray<FieldOption>;
10
+ type BaseField = {
11
+ label?: string;
12
+ };
13
+ type TextField = BaseField & {
14
+ type: "text";
15
+ };
16
+ type NumberField = BaseField & {
17
+ type: "number";
18
+ min?: number;
19
+ max?: number;
20
+ };
21
+ type TextareaField = BaseField & {
22
+ type: "textarea";
23
+ };
24
+ type SelectField = BaseField & {
25
+ type: "select";
26
+ options: FieldOptions;
27
+ };
28
+ type RadioField = BaseField & {
29
+ type: "radio";
30
+ options: FieldOptions;
31
+ };
32
+ type ArrayField<Props extends {
33
+ [key: string]: any;
34
+ } = {
35
+ [key: string]: any;
36
+ }> = BaseField & {
37
+ type: "array";
38
+ arrayFields: {
39
+ [SubPropName in keyof Props[0]]: Field<Props[0][SubPropName]>;
40
+ };
41
+ defaultItemProps?: Props[0];
42
+ getItemSummary?: (item: Props[0], index?: number) => string;
43
+ max?: number;
44
+ min?: number;
45
+ };
46
+ type ObjectField<Props extends {
47
+ [key: string]: any;
48
+ } = {
49
+ [key: string]: any;
50
+ }> = BaseField & {
51
+ type: "object";
52
+ objectFields: {
53
+ [SubPropName in keyof Props]: Field<Props[SubPropName]>;
54
+ };
55
+ };
56
+ type Adaptor<AdaptorParams = {}, TableShape extends Record<string, any> = {}, PropShape = TableShape> = {
57
+ name: string;
58
+ fetchList: (adaptorParams?: AdaptorParams) => Promise<TableShape[] | null>;
59
+ mapProp?: (value: TableShape) => PropShape;
60
+ };
61
+ type ExternalFieldWithAdaptor<Props extends {
62
+ [key: string]: any;
63
+ } = {
64
+ [key: string]: any;
65
+ }> = BaseField & {
66
+ type: "external";
67
+ placeholder?: string;
68
+ adaptor: Adaptor<any, any, Props>;
69
+ adaptorParams?: object;
70
+ getItemSummary: (item: Props, index?: number) => string;
71
+ };
72
+ type ExternalField<Props extends {
73
+ [key: string]: any;
74
+ } = {
75
+ [key: string]: any;
76
+ }> = BaseField & {
77
+ type: "external";
78
+ placeholder?: string;
79
+ fetchList: (params: {
80
+ query: string;
81
+ filters: Record<string, any>;
82
+ }) => Promise<any[] | null>;
83
+ mapProp?: (value: any) => Props;
84
+ mapRow?: (value: any) => Record<string, string | number>;
85
+ getItemSummary?: (item: Props, index?: number) => string;
86
+ showSearch?: boolean;
87
+ initialQuery?: string;
88
+ filterFields?: Record<string, Field>;
89
+ initialFilters?: Record<string, any>;
90
+ };
91
+ type CustomField<Props extends {
92
+ [key: string]: any;
93
+ } = {
94
+ [key: string]: any;
95
+ }> = BaseField & {
96
+ type: "custom";
97
+ render: (props: {
98
+ field: CustomField;
99
+ name: string;
100
+ value: any;
101
+ onChange: (value: Props) => void;
102
+ readOnly?: boolean;
103
+ }) => ReactElement;
104
+ };
105
+ type Field<Props extends {
106
+ [key: string]: any;
107
+ } = {
108
+ [key: string]: any;
109
+ }> = TextField | NumberField | TextareaField | SelectField | RadioField | ArrayField<Props> | ObjectField<Props> | ExternalField<Props> | ExternalFieldWithAdaptor<Props> | CustomField;
110
+
111
+ type Entry<Fields extends Record<string, any> = {}> = BaseEntry & {
112
+ fields: Fields;
113
+ };
114
+ declare function createFieldContentful<T extends Entry = Entry>(contentType: string, options?: {
115
+ client?: ContentfulClientApi<undefined>;
116
+ space?: string;
117
+ accessToken?: string;
118
+ titleField?: string;
119
+ filterFields?: ExternalField["filterFields"];
120
+ initialFilters?: ExternalField["initialFilters"];
121
+ }): ExternalField<T>;
122
+
123
+ export { Entry, createFieldContentful, createFieldContentful as default };
package/dist/index.js ADDED
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
10
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
+ var __spreadValues = (a, b) => {
14
+ for (var prop in b || (b = {}))
15
+ if (__hasOwnProp.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ if (__getOwnPropSymbols)
18
+ for (var prop of __getOwnPropSymbols(b)) {
19
+ if (__propIsEnum.call(b, prop))
20
+ __defNormalProp(a, prop, b[prop]);
21
+ }
22
+ return a;
23
+ };
24
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
+ var __export = (target, all) => {
26
+ for (var name in all)
27
+ __defProp(target, name, { get: all[name], enumerable: true });
28
+ };
29
+ var __copyProps = (to, from, except, desc) => {
30
+ if (from && typeof from === "object" || typeof from === "function") {
31
+ for (let key of __getOwnPropNames(from))
32
+ if (!__hasOwnProp.call(to, key) && key !== except)
33
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
+ }
35
+ return to;
36
+ };
37
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
+ // If the importer is in node compatibility mode or this is not an ESM
39
+ // file that has been converted to a CommonJS file using a Babel-
40
+ // compatible transform (i.e. "__esModule" has not been set), then set
41
+ // "default" to the CommonJS "module.exports" for node compatibility.
42
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
+ mod
44
+ ));
45
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
+ var __async = (__this, __arguments, generator) => {
47
+ return new Promise((resolve, reject) => {
48
+ var fulfilled = (value) => {
49
+ try {
50
+ step(generator.next(value));
51
+ } catch (e) {
52
+ reject(e);
53
+ }
54
+ };
55
+ var rejected = (value) => {
56
+ try {
57
+ step(generator.throw(value));
58
+ } catch (e) {
59
+ reject(e);
60
+ }
61
+ };
62
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
63
+ step((generator = generator.apply(__this, __arguments)).next());
64
+ });
65
+ };
66
+
67
+ // index.ts
68
+ var field_contentful_exports = {};
69
+ __export(field_contentful_exports, {
70
+ createClient: () => import_contentful.createClient,
71
+ createFieldContentful: () => createFieldContentful,
72
+ default: () => field_contentful_default
73
+ });
74
+ module.exports = __toCommonJS(field_contentful_exports);
75
+
76
+ // ../tsup-config/react-import.js
77
+ var import_react = __toESM(require("react"));
78
+
79
+ // index.ts
80
+ var import_contentful = require("contentful");
81
+ function createFieldContentful(contentType, options = {}) {
82
+ const {
83
+ space,
84
+ accessToken,
85
+ titleField = "title",
86
+ filterFields,
87
+ initialFilters
88
+ } = options;
89
+ if (!options.client) {
90
+ if (!space || !accessToken) {
91
+ throw new Error(
92
+ 'field-contentful: Must either specify "client", or "space" and "accessToken"'
93
+ );
94
+ }
95
+ }
96
+ const client = options.client || (0, import_contentful.createClient)({ space, accessToken });
97
+ const field = {
98
+ type: "external",
99
+ placeholder: "Select from Contentful",
100
+ showSearch: true,
101
+ fetchList: (_0) => __async(this, [_0], function* ({ query, filters = {} }) {
102
+ const entries = yield client.getEntries(__spreadProps(__spreadValues({}, filters), {
103
+ content_type: contentType,
104
+ query
105
+ }));
106
+ return entries.items;
107
+ }),
108
+ mapRow: ({ fields }) => fields,
109
+ getItemSummary: (item) => item.fields[titleField],
110
+ filterFields,
111
+ initialFilters
112
+ };
113
+ return field;
114
+ }
115
+ var field_contentful_default = createFieldContentful;
116
+ // Annotate the CommonJS export names for ESM import in node:
117
+ 0 && (module.exports = {
118
+ createClient,
119
+ createFieldContentful
120
+ });
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@measured/puck-field-contentful",
3
+ "version": "0.14.0-canary.053d4c6",
4
+ "author": "Measured Corporation Ltd <hello@measured.co>",
5
+ "repository": "measuredco/puck",
6
+ "bugs": "https://github.com/measuredco/puck/issues",
7
+ "homepage": "https://puckeditor.com",
8
+ "private": false,
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "license": "MIT",
12
+ "scripts": {
13
+ "lint": "eslint \"**/*.ts*\"",
14
+ "build": "rm -rf dist && tsup index.ts",
15
+ "prepare": "yarn build"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "devDependencies": {
21
+ "@measured/puck": "^0.14.0-canary.053d4c6",
22
+ "@types/react": "^18.2.0",
23
+ "@types/react-dom": "^18.2.0",
24
+ "contentful": "^10.8.6",
25
+ "eslint": "^7.32.0",
26
+ "eslint-config-custom": "*",
27
+ "tsconfig": "*",
28
+ "tsup-config": "*",
29
+ "typescript": "^4.5.2"
30
+ },
31
+ "peerDependencies": {
32
+ "@measured/puck": "^0.13.0",
33
+ "contentful": "^10.0.0",
34
+ "react": "^17.0.0 || ^18.0.0"
35
+ }
36
+ }