@contentful/react-apps-toolkit 0.4.2 → 0.5.2
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 +20 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/useFieldValue.d.ts +14 -0
- package/dist/useFieldValue.js +86 -0
- package/dist/useFieldValue.spec.d.ts +1 -0
- package/dist/useFieldValue.spec.js +197 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -18,7 +18,26 @@ yarn add @contentful/react-apps-toolkit
|
|
|
18
18
|
|
|
19
19
|
## Available features
|
|
20
20
|
|
|
21
|
-
The following hooks and utilities are exported from the package:
|
|
21
|
+
The following hooks and utilities are exported from the package:
|
|
22
|
+
|
|
23
|
+
### `useSDK`
|
|
24
|
+
|
|
25
|
+
This hook returns the App SDK.
|
|
26
|
+
|
|
27
|
+
The only requirement for using it is that the component that uses it is wrapped within the `SDKProvider`.
|
|
28
|
+
If it is not, the hook will throw an error.
|
|
29
|
+
|
|
30
|
+
Here is an example of how you can use it:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
function App() {
|
|
34
|
+
const sdk = useSDK<FieldExtensionSDK>();
|
|
35
|
+
|
|
36
|
+
return <>App Id: {sdk.ids.app}</>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
|
|
22
41
|
|
|
23
42
|
#### SDKProvider
|
|
24
43
|
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./useSDK"), exports);
|
|
18
17
|
__exportStar(require("./SDKProvider"), exports);
|
|
19
18
|
__exportStar(require("./useCMA"), exports);
|
|
19
|
+
__exportStar(require("./useFieldValue"), exports);
|
|
20
|
+
__exportStar(require("./useSDK"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare type UseFieldValueReturnValue<Value = unknown> = [
|
|
2
|
+
value: Value,
|
|
3
|
+
setValue: (newValue: Value) => Promise<void>
|
|
4
|
+
];
|
|
5
|
+
/**
|
|
6
|
+
* Returns field value and a function to update it.
|
|
7
|
+
* Must be wrapped by SDKProvider.
|
|
8
|
+
* Can only be used when app is rendered in field, sidebar or entry editor location.
|
|
9
|
+
*
|
|
10
|
+
* @param {string=} fieldId Id of the field to read and update. Can be omitted when app is rendered in field location.
|
|
11
|
+
* @param {string=} locale Locale to read and update. When omitted, default locale is used.
|
|
12
|
+
* @returns {UseFieldValueReturnValue} Field value, function to update it
|
|
13
|
+
*/
|
|
14
|
+
export declare function useFieldValue<Value = unknown>(fieldId?: string, locale?: string): UseFieldValueReturnValue<Value>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (_) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.useFieldValue = void 0;
|
|
40
|
+
var react_1 = require("react");
|
|
41
|
+
var useSDK_1 = require("./useSDK");
|
|
42
|
+
/**
|
|
43
|
+
* Returns field value and a function to update it.
|
|
44
|
+
* Must be wrapped by SDKProvider.
|
|
45
|
+
* Can only be used when app is rendered in field, sidebar or entry editor location.
|
|
46
|
+
*
|
|
47
|
+
* @param {string=} fieldId Id of the field to read and update. Can be omitted when app is rendered in field location.
|
|
48
|
+
* @param {string=} locale Locale to read and update. When omitted, default locale is used.
|
|
49
|
+
* @returns {UseFieldValueReturnValue} Field value, function to update it
|
|
50
|
+
*/
|
|
51
|
+
function useFieldValue(fieldId, locale) {
|
|
52
|
+
var _this = this;
|
|
53
|
+
var sdk = (0, useSDK_1.useSDK)();
|
|
54
|
+
var entryFieldApi = (0, react_1.useMemo)(function () { return getEntryFieldApi(sdk, fieldId); }, [sdk, fieldId]);
|
|
55
|
+
var localeWithDefault = locale !== null && locale !== void 0 ? locale : sdk.locales.default;
|
|
56
|
+
var _a = (0, react_1.useState)(entryFieldApi.getValue(localeWithDefault)), value = _a[0], setValue = _a[1];
|
|
57
|
+
(0, react_1.useEffect)(function () { return entryFieldApi.onValueChanged(localeWithDefault, setValue); }, [entryFieldApi, localeWithDefault]);
|
|
58
|
+
var updateValue = (0, react_1.useCallback)(function (newValue) { return __awaiter(_this, void 0, void 0, function () {
|
|
59
|
+
return __generator(this, function (_a) {
|
|
60
|
+
switch (_a.label) {
|
|
61
|
+
case 0:
|
|
62
|
+
setValue(newValue);
|
|
63
|
+
return [4 /*yield*/, entryFieldApi.setValue(newValue, localeWithDefault)];
|
|
64
|
+
case 1:
|
|
65
|
+
_a.sent();
|
|
66
|
+
return [2 /*return*/];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}); }, [entryFieldApi, localeWithDefault]);
|
|
70
|
+
return [value, updateValue];
|
|
71
|
+
}
|
|
72
|
+
exports.useFieldValue = useFieldValue;
|
|
73
|
+
function getEntryFieldApi(sdk, fieldId) {
|
|
74
|
+
if (!('entry' in sdk)) {
|
|
75
|
+
throw new Error('`useFieldValue` can only be used in field, sidebar or entry editor location.');
|
|
76
|
+
}
|
|
77
|
+
var fieldIdWithDefault = fieldId !== null && fieldId !== void 0 ? fieldId : ('field' in sdk ? sdk.field.id : undefined);
|
|
78
|
+
if (!fieldIdWithDefault) {
|
|
79
|
+
throw new Error('Missing `fieldId`. The `fieldId` can only be omitted when your app is renderd in field location.');
|
|
80
|
+
}
|
|
81
|
+
var field = sdk.entry.fields[fieldIdWithDefault];
|
|
82
|
+
if (!field) {
|
|
83
|
+
throw new Error("Invalid `fieldId`. The current entry does not have a field \"".concat(fieldIdWithDefault, "\"."));
|
|
84
|
+
}
|
|
85
|
+
return field;
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (_) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
var react_hooks_1 = require("@testing-library/react-hooks");
|
|
51
|
+
var useFieldValue_1 = require("./useFieldValue");
|
|
52
|
+
var useSDK_1 = require("./useSDK");
|
|
53
|
+
var mockSDK = {
|
|
54
|
+
field: {
|
|
55
|
+
id: 'fieldId',
|
|
56
|
+
},
|
|
57
|
+
locales: {
|
|
58
|
+
default: 'defaultLocale',
|
|
59
|
+
},
|
|
60
|
+
entry: {
|
|
61
|
+
fields: {
|
|
62
|
+
fieldId: {
|
|
63
|
+
getValue: function (locale) { return "fieldId ".concat(locale, " value"); },
|
|
64
|
+
onValueChanged: jest.fn(),
|
|
65
|
+
setValue: jest.fn(),
|
|
66
|
+
},
|
|
67
|
+
otherFieldId: {
|
|
68
|
+
getValue: function (locale) { return "otherFieldId ".concat(locale, " value"); },
|
|
69
|
+
onValueChanged: jest.fn(),
|
|
70
|
+
setValue: jest.fn(),
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
jest.mock('./useSDK', function () { return (__assign(__assign({}, jest.requireActual('./useSDK')), { useSDK: jest.fn() })); });
|
|
76
|
+
var useSDKMock = useSDK_1.useSDK;
|
|
77
|
+
beforeEach(function () {
|
|
78
|
+
jest.resetAllMocks();
|
|
79
|
+
mockSDK.entry.fields.fieldId.onValueChanged.mockImplementation(function () { return function () { }; });
|
|
80
|
+
mockSDK.entry.fields.otherFieldId.onValueChanged.mockImplementation(function () { return function () { }; });
|
|
81
|
+
});
|
|
82
|
+
describe('useFieldValue', function () {
|
|
83
|
+
describe('throws error', function () {
|
|
84
|
+
it('when rendered in wrong location', function () {
|
|
85
|
+
useSDKMock.mockImplementation(function () { return ({}); });
|
|
86
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)(); }).result;
|
|
87
|
+
expect(function () {
|
|
88
|
+
expect(result.current).not.toBe(undefined);
|
|
89
|
+
}).toThrowErrorMatchingInlineSnapshot("\"`useFieldValue` can only be used in field, sidebar or entry editor location.\"");
|
|
90
|
+
});
|
|
91
|
+
it('when rendered omitting `fieldId` outside of field location', function () {
|
|
92
|
+
// @ts-expect-error
|
|
93
|
+
useSDKMock.mockImplementation(function () { return ({
|
|
94
|
+
entry: mockSDK.entry,
|
|
95
|
+
}); });
|
|
96
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)(); }).result;
|
|
97
|
+
expect(function () {
|
|
98
|
+
expect(result.current).not.toBe(undefined);
|
|
99
|
+
}).toThrowErrorMatchingInlineSnapshot("\"Missing `fieldId`. The `fieldId` can only be omitted when your app is renderd in field location.\"");
|
|
100
|
+
});
|
|
101
|
+
it('when providing unknown `fieldId`', function () {
|
|
102
|
+
// @ts-expect-error
|
|
103
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
104
|
+
var result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)('unknownFieldId'); }).result;
|
|
105
|
+
expect(function () {
|
|
106
|
+
expect(result.current).not.toBe(undefined);
|
|
107
|
+
}).toThrowErrorMatchingInlineSnapshot("\"Invalid `fieldId`. The current entry does not have a field \\\"unknownFieldId\\\".\"");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('with no params', function () {
|
|
111
|
+
var result;
|
|
112
|
+
beforeEach(function () {
|
|
113
|
+
// @ts-expect-error
|
|
114
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
115
|
+
result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)(); }).result;
|
|
116
|
+
});
|
|
117
|
+
it('returns initial value', function () {
|
|
118
|
+
expect(result.current[0]).toBe('fieldId defaultLocale value');
|
|
119
|
+
});
|
|
120
|
+
it('updates value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
121
|
+
return __generator(this, function (_a) {
|
|
122
|
+
switch (_a.label) {
|
|
123
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return result.current[1]('new value'); })];
|
|
124
|
+
case 1:
|
|
125
|
+
_a.sent();
|
|
126
|
+
expect(result.current[0]).toBe('new value');
|
|
127
|
+
expect(mockSDK.entry.fields['fieldId'].setValue).toHaveBeenCalledWith('new value', 'defaultLocale');
|
|
128
|
+
return [2 /*return*/];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}); });
|
|
132
|
+
it('updates value when `onValueChanged` is called', function () {
|
|
133
|
+
var calls = mockSDK.entry.fields.fieldId.onValueChanged.mock.calls;
|
|
134
|
+
expect(calls[0][0]).toBe('defaultLocale');
|
|
135
|
+
(0, react_hooks_1.act)(function () { return calls[0][1]('new value'); });
|
|
136
|
+
expect(result.current[0]).toBe('new value');
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe('with `fieldId`', function () {
|
|
140
|
+
var result;
|
|
141
|
+
beforeEach(function () {
|
|
142
|
+
// @ts-expect-error
|
|
143
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
144
|
+
result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)('otherFieldId'); }).result;
|
|
145
|
+
});
|
|
146
|
+
it('returns initial value', function () {
|
|
147
|
+
expect(result.current[0]).toBe('otherFieldId defaultLocale value');
|
|
148
|
+
});
|
|
149
|
+
it('updates value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
150
|
+
return __generator(this, function (_a) {
|
|
151
|
+
switch (_a.label) {
|
|
152
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return result.current[1]('new value'); })];
|
|
153
|
+
case 1:
|
|
154
|
+
_a.sent();
|
|
155
|
+
expect(result.current[0]).toBe('new value');
|
|
156
|
+
expect(mockSDK.entry.fields['otherFieldId'].setValue).toHaveBeenCalledWith('new value', 'defaultLocale');
|
|
157
|
+
return [2 /*return*/];
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}); });
|
|
161
|
+
it('updates value when `onValueChanged` is called', function () {
|
|
162
|
+
var calls = mockSDK.entry.fields.otherFieldId.onValueChanged.mock.calls;
|
|
163
|
+
expect(calls[0][0]).toBe('defaultLocale');
|
|
164
|
+
(0, react_hooks_1.act)(function () { return calls[0][1]('new value'); });
|
|
165
|
+
expect(result.current[0]).toBe('new value');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
describe('with `locale`', function () {
|
|
169
|
+
var result;
|
|
170
|
+
beforeEach(function () {
|
|
171
|
+
// @ts-expect-error
|
|
172
|
+
useSDKMock.mockImplementation(function () { return mockSDK; });
|
|
173
|
+
result = (0, react_hooks_1.renderHook)(function () { return (0, useFieldValue_1.useFieldValue)('fieldId', 'locale'); }).result;
|
|
174
|
+
});
|
|
175
|
+
it('returns initial value', function () {
|
|
176
|
+
expect(result.current[0]).toBe('fieldId locale value');
|
|
177
|
+
});
|
|
178
|
+
it('updates value', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
179
|
+
return __generator(this, function (_a) {
|
|
180
|
+
switch (_a.label) {
|
|
181
|
+
case 0: return [4 /*yield*/, (0, react_hooks_1.act)(function () { return result.current[1]('new value'); })];
|
|
182
|
+
case 1:
|
|
183
|
+
_a.sent();
|
|
184
|
+
expect(result.current[0]).toBe('new value');
|
|
185
|
+
expect(mockSDK.entry.fields['fieldId'].setValue).toHaveBeenCalledWith('new value', 'locale');
|
|
186
|
+
return [2 /*return*/];
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}); });
|
|
190
|
+
it('updates value when `onValueChanged` is called', function () {
|
|
191
|
+
var calls = mockSDK.entry.fields.fieldId.onValueChanged.mock.calls;
|
|
192
|
+
expect(calls[0][0]).toBe('locale');
|
|
193
|
+
(0, react_hooks_1.act)(function () { return calls[0][1]('new value'); });
|
|
194
|
+
expect(result.current[0]).toBe('new value');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/react-apps-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Toolkit for building a Contentful app in React",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"author": "Contentful GmbH",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"@contentful/app-sdk": "^4.0.0",
|
|
51
51
|
"contentful-management": ">=7.30.0"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "174ac57f86e1e9bde1594fa444ba1fd59f5ebe91"
|
|
54
54
|
}
|