@contentful/field-editor-shared 1.6.3 → 1.7.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.
Files changed (22) hide show
  1. package/dist/cjs/LocalePublishingEntityStatusBadge/Banner.js +44 -0
  2. package/dist/cjs/LocalePublishingEntityStatusBadge/LocalePublishingPopover.js +311 -0
  3. package/dist/cjs/LocalePublishingEntityStatusBadge/LocalePublishingStatus.js +50 -0
  4. package/dist/cjs/LocalePublishingEntityStatusBadge/LocalePublishingStatusList.js +85 -0
  5. package/dist/cjs/LocalePublishingEntityStatusBadge/ScheduledBanner.js +44 -0
  6. package/dist/cjs/LocalePublishingEntityStatusBadge/index.js +18 -0
  7. package/dist/cjs/index.js +14 -0
  8. package/dist/esm/LocalePublishingEntityStatusBadge/Banner.js +29 -0
  9. package/dist/esm/LocalePublishingEntityStatusBadge/LocalePublishingPopover.js +255 -0
  10. package/dist/esm/LocalePublishingEntityStatusBadge/LocalePublishingStatus.js +35 -0
  11. package/dist/esm/LocalePublishingEntityStatusBadge/LocalePublishingStatusList.js +70 -0
  12. package/dist/esm/LocalePublishingEntityStatusBadge/ScheduledBanner.js +29 -0
  13. package/dist/esm/LocalePublishingEntityStatusBadge/index.js +1 -0
  14. package/dist/esm/index.js +1 -0
  15. package/dist/types/LocalePublishingEntityStatusBadge/Banner.d.ts +5 -0
  16. package/dist/types/LocalePublishingEntityStatusBadge/LocalePublishingPopover.d.ts +16 -0
  17. package/dist/types/LocalePublishingEntityStatusBadge/LocalePublishingStatus.d.ts +9 -0
  18. package/dist/types/LocalePublishingEntityStatusBadge/LocalePublishingStatusList.d.ts +10 -0
  19. package/dist/types/LocalePublishingEntityStatusBadge/ScheduledBanner.d.ts +8 -0
  20. package/dist/types/LocalePublishingEntityStatusBadge/index.d.ts +1 -0
  21. package/dist/types/index.d.ts +1 -0
  22. package/package.json +4 -2
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "Banner", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Banner;
9
+ }
10
+ });
11
+ const _react = _interop_require_default(require("react"));
12
+ const _f36components = require("@contentful/f36-components");
13
+ const _f36tokens = _interop_require_default(require("@contentful/f36-tokens"));
14
+ const _emotion = require("emotion");
15
+ function _interop_require_default(obj) {
16
+ return obj && obj.__esModule ? obj : {
17
+ default: obj
18
+ };
19
+ }
20
+ const styles = {
21
+ content: (0, _emotion.css)({
22
+ display: 'block'
23
+ }),
24
+ banner: (0, _emotion.css)({
25
+ background: _f36tokens.default.gray100,
26
+ padding: _f36tokens.default.spacingXs,
27
+ margin: `${_f36tokens.default.spacingXs} ${_f36tokens.default.spacingS}`,
28
+ borderRadius: _f36tokens.default.borderRadiusSmall
29
+ })
30
+ };
31
+ function Banner({ content, highlight }) {
32
+ return _react.default.createElement("div", {
33
+ className: styles.banner
34
+ }, _react.default.createElement(_f36components.Text, {
35
+ fontSize: "fontSizeS",
36
+ fontColor: "gray700",
37
+ className: styles.content
38
+ }, content), highlight && _react.default.createElement(_f36components.Text, {
39
+ fontSize: "fontSizeS",
40
+ fontColor: "gray700",
41
+ as: "strong",
42
+ fontWeight: "fontWeightDemiBold"
43
+ }, highlight));
44
+ }
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "LocalePublishingPopover", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return LocalePublishingPopover;
9
+ }
10
+ });
11
+ const _react = _interop_require_wildcard(require("react"));
12
+ const _f36components = require("@contentful/f36-components");
13
+ const _f36tokens = _interop_require_default(require("@contentful/f36-tokens"));
14
+ const _emotion = require("emotion");
15
+ const _entityHelpers = _interop_require_wildcard(require("../utils/entityHelpers"));
16
+ const _LocalePublishingStatusList = require("./LocalePublishingStatusList");
17
+ const _ScheduledBanner = require("./ScheduledBanner");
18
+ function _interop_require_default(obj) {
19
+ return obj && obj.__esModule ? obj : {
20
+ default: obj
21
+ };
22
+ }
23
+ function _getRequireWildcardCache(nodeInterop) {
24
+ if (typeof WeakMap !== "function") return null;
25
+ var cacheBabelInterop = new WeakMap();
26
+ var cacheNodeInterop = new WeakMap();
27
+ return (_getRequireWildcardCache = function(nodeInterop) {
28
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
29
+ })(nodeInterop);
30
+ }
31
+ function _interop_require_wildcard(obj, nodeInterop) {
32
+ if (!nodeInterop && obj && obj.__esModule) {
33
+ return obj;
34
+ }
35
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
36
+ return {
37
+ default: obj
38
+ };
39
+ }
40
+ var cache = _getRequireWildcardCache(nodeInterop);
41
+ if (cache && cache.has(obj)) {
42
+ return cache.get(obj);
43
+ }
44
+ var newObj = {
45
+ __proto__: null
46
+ };
47
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
48
+ for(var key in obj){
49
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
50
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
51
+ if (desc && (desc.get || desc.set)) {
52
+ Object.defineProperty(newObj, key, desc);
53
+ } else {
54
+ newObj[key] = obj[key];
55
+ }
56
+ }
57
+ }
58
+ newObj.default = obj;
59
+ if (cache) {
60
+ cache.set(obj, newObj);
61
+ }
62
+ return newObj;
63
+ }
64
+ const colors = {
65
+ published: {
66
+ default: _f36tokens.default.green300,
67
+ hover: _f36tokens.default.green400,
68
+ icon: _f36tokens.default.green400
69
+ },
70
+ draft: {
71
+ default: _f36tokens.default.orange300,
72
+ hover: _f36tokens.default.orange400,
73
+ icon: _f36tokens.default.orange400
74
+ },
75
+ changed: {
76
+ default: _f36tokens.default.blue300,
77
+ hover: _f36tokens.default.blue400,
78
+ icon: _f36tokens.default.blue400
79
+ },
80
+ archived: {
81
+ default: _f36tokens.default.gray300,
82
+ hover: _f36tokens.default.gray400,
83
+ icon: _f36tokens.default.gray400
84
+ },
85
+ deleted: {
86
+ default: _f36tokens.default.red300,
87
+ hover: _f36tokens.default.red400,
88
+ icon: _f36tokens.default.red400
89
+ },
90
+ new: {
91
+ default: _f36tokens.default.blue600,
92
+ hover: _f36tokens.default.blue700,
93
+ icon: _f36tokens.default.blue700
94
+ }
95
+ };
96
+ const getColor = ({ secondary, tertiary, isHover })=>{
97
+ const status = secondary || tertiary;
98
+ return isHover ? colors[status]?.hover : colors[status]?.default;
99
+ };
100
+ const generateDynamicStyles = (status)=>{
101
+ const wrapperClass = (0, _emotion.css)({
102
+ '& svg[data-status="secondary"]': {
103
+ fill: getColor({
104
+ secondary: status?.secondary,
105
+ isHover: false
106
+ })
107
+ },
108
+ '& svg[data-status="tertiary"]': {
109
+ fill: getColor({
110
+ tertiary: status?.tertiary,
111
+ isHover: false
112
+ })
113
+ },
114
+ '&:hover svg[data-status="secondary"]': {
115
+ fill: getColor({
116
+ secondary: status?.secondary,
117
+ isHover: true
118
+ })
119
+ },
120
+ '&:hover svg[data-status="tertiary"]': {
121
+ fill: getColor({
122
+ tertiary: status?.tertiary,
123
+ isHover: true
124
+ })
125
+ }
126
+ });
127
+ return wrapperClass;
128
+ };
129
+ const getIconColor = (status)=>colors[status].icon;
130
+ const styles = {
131
+ badge: (0, _emotion.css)({
132
+ '&:focus': {
133
+ outline: 'none',
134
+ boxShadow: `inset ${_f36tokens.default.glowPrimary}`
135
+ }
136
+ }),
137
+ wrapper: (0, _emotion.css)({
138
+ '& svg': {
139
+ transition: 'fill 0.2s ease-in-out'
140
+ },
141
+ '& svg[data-status="tertiary"]': {
142
+ marginLeft: '-1px'
143
+ }
144
+ }),
145
+ popoverContent: (0, _emotion.css)({
146
+ maxWidth: '336px',
147
+ maxHeight: '368px',
148
+ overflowY: 'auto',
149
+ padding: `${_f36tokens.default.spacing2Xs} 0`
150
+ })
151
+ };
152
+ const ArrowDownIcon = (0, _f36components.generateIcon)({
153
+ name: 'ArrowDownIcon',
154
+ viewBox: '0 0 12 20',
155
+ path: _react.default.createElement("path", {
156
+ d: "M3.03076 8C2.20109 8 1.73228 8.95209 2.23814 9.60971L5.20727 13.4696C5.60757 13.99 6.39223 13.99 6.79252 13.4696L9.76166 9.60971C10.2675 8.95209 9.79871 8 8.96904 8L3.03076 8Z",
157
+ fill: "currentColor"
158
+ })
159
+ });
160
+ const determineBadgeStatus = (localesStatusMap, activeLocales)=>{
161
+ if (!localesStatusMap) return;
162
+ if (localesStatusMap.size === 1) return {
163
+ primary: [
164
+ ...localesStatusMap.values()
165
+ ][0].status
166
+ };
167
+ let draftCount = 0, publishedCount = 0, changedCount = 0;
168
+ for (const localeStatus of localesStatusMap.values()){
169
+ if (!activeLocales || activeLocales.find((selectedLocale)=>selectedLocale.code === localeStatus.locale.code)) {
170
+ switch(localeStatus.status){
171
+ case 'changed':
172
+ changedCount += 1;
173
+ break;
174
+ case 'draft':
175
+ draftCount += 1;
176
+ break;
177
+ case 'published':
178
+ publishedCount += 1;
179
+ break;
180
+ }
181
+ }
182
+ }
183
+ const hasChanged = changedCount > 0;
184
+ const hasPublished = publishedCount > 0;
185
+ const hasDraft = draftCount > 0;
186
+ switch(true){
187
+ case hasChanged && hasPublished && hasDraft:
188
+ return {
189
+ primary: 'changed',
190
+ secondary: 'published',
191
+ tertiary: 'draft'
192
+ };
193
+ case hasChanged && hasPublished:
194
+ return {
195
+ primary: 'changed',
196
+ secondary: 'published'
197
+ };
198
+ case hasChanged && hasDraft:
199
+ return {
200
+ primary: 'changed',
201
+ secondary: 'draft'
202
+ };
203
+ case hasPublished && hasDraft:
204
+ return {
205
+ primary: 'published',
206
+ secondary: 'draft'
207
+ };
208
+ case hasChanged:
209
+ return {
210
+ primary: 'changed',
211
+ secondary: 'changed'
212
+ };
213
+ case hasPublished:
214
+ return {
215
+ primary: 'published',
216
+ secondary: 'published'
217
+ };
218
+ default:
219
+ return {
220
+ primary: 'draft',
221
+ secondary: 'draft'
222
+ };
223
+ }
224
+ };
225
+ function LocalePublishingPopover({ entity, jobs, isScheduled, localesStatusMap, activeLocales }) {
226
+ const [isOpen, setIsOpen] = (0, _react.useState)(false);
227
+ const timeoutRef = (0, _react.useRef)();
228
+ const onMouseEnter = (0, _react.useCallback)(()=>{
229
+ clearTimeout(timeoutRef.current);
230
+ timeoutRef.current = setTimeout(()=>{
231
+ setIsOpen(true);
232
+ }, 300);
233
+ }, []);
234
+ const onMouseLeave = (0, _react.useCallback)(()=>{
235
+ clearTimeout(timeoutRef.current);
236
+ timeoutRef.current = setTimeout(()=>{
237
+ setIsOpen(false);
238
+ }, 300);
239
+ }, []);
240
+ const entityStatus = _entityHelpers.getEntityStatus(entity.sys, activeLocales?.map((locale)=>locale.code));
241
+ if ([
242
+ 'archived',
243
+ 'deleted'
244
+ ].includes(entityStatus)) {
245
+ return _react.default.createElement(_f36components.EntityStatusBadge, {
246
+ className: styles.badge,
247
+ testId: "entity-state",
248
+ entityStatus: entityStatus,
249
+ tabIndex: 0,
250
+ isScheduled: isScheduled
251
+ });
252
+ }
253
+ const status = determineBadgeStatus(localesStatusMap, activeLocales);
254
+ const ariaLabel = status && status.secondary ? 'Multiple statuses' : status?.primary;
255
+ const wrapperClass = generateDynamicStyles(status);
256
+ return _react.default.createElement(_f36components.Popover, {
257
+ isOpen: localesStatusMap && isOpen,
258
+ onClose: ()=>setIsOpen(false),
259
+ autoFocus: false,
260
+ placement: "bottom-end"
261
+ }, _react.default.createElement(_f36components.Popover.Trigger, null, _react.default.createElement(_f36components.Flex, {
262
+ "aria-label": ariaLabel,
263
+ alignItems: "center",
264
+ className: (0, _emotion.cx)(styles.wrapper, wrapperClass)
265
+ }, _react.default.createElement(_f36components.EntityStatusBadge, {
266
+ className: styles.badge,
267
+ testId: "entity-state",
268
+ entityStatus: entityStatus,
269
+ tabIndex: 0,
270
+ onFocus: ()=>setIsOpen(true),
271
+ onBlur: ()=>setIsOpen(false),
272
+ endIcon: _react.default.createElement(ArrowDownIcon, {
273
+ color: getIconColor(entityStatus)
274
+ }),
275
+ onMouseOver: onMouseEnter,
276
+ isScheduled: isScheduled,
277
+ onMouseEnter: onMouseEnter,
278
+ onMouseLeave: onMouseLeave
279
+ }), status?.secondary && _react.default.createElement("svg", {
280
+ "data-status": "secondary",
281
+ "aria-hidden": "true",
282
+ width: "4",
283
+ height: "18",
284
+ viewBox: "0 0 4 18"
285
+ }, _react.default.createElement("path", {
286
+ fillRule: "evenodd",
287
+ clipRule: "evenodd",
288
+ d: "M1.45942e-06 18H0.00296171C2.2121 18 4.00296 16.2091 4.00296 14V4C4.00296 1.79086 2.2121 0 0.00295914 0H0C0.830421 0.732944 1.35418 1.80531 1.35418 3V15C1.35418 16.1947 0.830422 17.2671 1.45942e-06 18Z"
289
+ })), status?.tertiary && _react.default.createElement("svg", {
290
+ "data-status": "tertiary",
291
+ "aria-hidden": "true",
292
+ width: "5",
293
+ height: "16",
294
+ viewBox: "0 0 5 16"
295
+ }, _react.default.createElement("path", {
296
+ fillRule: "evenodd",
297
+ clipRule: "evenodd",
298
+ d: "M0.673828 16.0055H0.675391C2.88453 16.0055 4.67539 14.2146 4.67539 12.0055V3.9955C4.67539 1.88216 3.03648 0.151608 0.960312 0.00549316C1.78382 0.738158 2.30257 1.80597 2.30257 2.99493V12.7838C2.30257 14.1053 1.66172 15.2771 0.673828 16.0055Z"
299
+ })))), _react.default.createElement(_f36components.Popover.Content, {
300
+ className: styles.popoverContent,
301
+ onMouseEnter: onMouseEnter,
302
+ onMouseLeave: onMouseLeave
303
+ }, !!localesStatusMap && _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(_ScheduledBanner.ScheduledBanner, {
304
+ entityId: entity.sys.id,
305
+ jobs: jobs
306
+ }), _react.default.createElement(_LocalePublishingStatusList.LocalePublishingStatusList, {
307
+ isScheduled: isScheduled,
308
+ statusMap: localesStatusMap,
309
+ activeLocales: activeLocales
310
+ }))));
311
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "LocalePublishingStatus", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return LocalePublishingStatus;
9
+ }
10
+ });
11
+ const _react = _interop_require_default(require("react"));
12
+ const _f36components = require("@contentful/f36-components");
13
+ const _f36tokens = _interop_require_default(require("@contentful/f36-tokens"));
14
+ const _emotion = require("emotion");
15
+ function _interop_require_default(obj) {
16
+ return obj && obj.__esModule ? obj : {
17
+ default: obj
18
+ };
19
+ }
20
+ const styles = {
21
+ locale: (0, _emotion.css)({
22
+ textOverflow: 'ellipsis',
23
+ overflow: 'hidden',
24
+ whiteSpace: 'nowrap'
25
+ }),
26
+ status: (0, _emotion.css)({
27
+ flexShrink: 0
28
+ }),
29
+ localePublishStatus: (0, _emotion.css)({
30
+ display: 'flex',
31
+ gap: _f36tokens.default.spacingXs,
32
+ justifyContent: 'space-between',
33
+ padding: `${_f36tokens.default.spacingXs} ${_f36tokens.default.spacingS}`
34
+ })
35
+ };
36
+ function LocalePublishingStatus({ locale, status, isScheduled }) {
37
+ return _react.default.createElement("div", {
38
+ className: styles.localePublishStatus,
39
+ "data-test-id": "locale-publishing-status"
40
+ }, _react.default.createElement(_f36components.Text, {
41
+ className: styles.locale,
42
+ fontColor: "gray700"
43
+ }, locale.name, ' ', _react.default.createElement(_f36components.Text, {
44
+ fontColor: "gray500"
45
+ }, "(", locale.code, ")", locale.default && ' | default')), _react.default.createElement(_f36components.EntityStatusBadge, {
46
+ entityStatus: status,
47
+ isScheduled: isScheduled,
48
+ className: styles.status
49
+ }));
50
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "LocalePublishingStatusList", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return LocalePublishingStatusList;
9
+ }
10
+ });
11
+ const _react = _interop_require_default(require("react"));
12
+ const _f36components = require("@contentful/f36-components");
13
+ const _lodash = require("lodash");
14
+ const _Banner = require("./Banner");
15
+ const _LocalePublishingStatus = require("./LocalePublishingStatus");
16
+ function _interop_require_default(obj) {
17
+ return obj && obj.__esModule ? obj : {
18
+ default: obj
19
+ };
20
+ }
21
+ function groupAndSortLocales(entries, activeLocales) {
22
+ const { selected, nonSelected } = entries.reduce((prev, [localeCode, localeStatusType])=>{
23
+ return activeLocales?.some((sl)=>sl.code === localeCode) ? {
24
+ ...prev,
25
+ selected: [
26
+ ...prev.selected,
27
+ localeStatusType
28
+ ]
29
+ } : {
30
+ ...prev,
31
+ nonSelected: [
32
+ ...prev.nonSelected,
33
+ localeStatusType
34
+ ]
35
+ };
36
+ }, {
37
+ selected: [],
38
+ nonSelected: []
39
+ });
40
+ return {
41
+ selected: (0, _lodash.sortBy)(selected, 'locale.name'),
42
+ nonSelected: nonSelected.sort((a, b)=>{
43
+ if (a.status === b.status) {
44
+ return a.locale.name.localeCompare(b.locale.name);
45
+ }
46
+ if (a.status === 'changed' || a.status === 'published' && b.status === 'draft') {
47
+ return -1;
48
+ }
49
+ return 1;
50
+ })
51
+ };
52
+ }
53
+ function LocalePublishingStatusList({ isScheduled, statusMap, activeLocales }) {
54
+ const entries = [
55
+ ...statusMap.entries()
56
+ ];
57
+ const counters = entries.reduce((prev, [, { status }])=>({
58
+ changed: prev.changed + (status === 'changed' ? 1 : 0),
59
+ published: prev.published + (status === 'published' ? 1 : 0),
60
+ draft: prev.draft + (status === 'draft' ? 1 : 0)
61
+ }), {
62
+ published: 0,
63
+ changed: 0,
64
+ draft: 0
65
+ });
66
+ const { selected, nonSelected } = groupAndSortLocales(entries, activeLocales);
67
+ return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement(_Banner.Banner, {
68
+ content: "The entry has locales with the following statuses:",
69
+ highlight: `${counters.changed} changed, ${counters.published} published, ${counters.draft} draft`
70
+ }), _react.default.createElement("div", {
71
+ "data-test-id": "locale-publishing-selected"
72
+ }, _react.default.createElement(_f36components.MenuSectionTitle, null, "Locales in the entry editor:"), selected.map(({ locale, status })=>_react.default.createElement(_LocalePublishingStatus.LocalePublishingStatus, {
73
+ key: `selected-${locale.code}`,
74
+ status: status,
75
+ locale: locale,
76
+ isScheduled: isScheduled
77
+ }))), nonSelected.length > 0 && _react.default.createElement("div", {
78
+ "data-test-id": "locale-publishing-others"
79
+ }, _react.default.createElement(_f36components.MenuSectionTitle, null, "Other locales:"), nonSelected.map(({ locale, status })=>_react.default.createElement(_LocalePublishingStatus.LocalePublishingStatus, {
80
+ key: `others-${locale.code}`,
81
+ status: status,
82
+ locale: locale,
83
+ isScheduled: isScheduled
84
+ }))));
85
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "ScheduledBanner", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return ScheduledBanner;
9
+ }
10
+ });
11
+ const _react = _interop_require_default(require("react"));
12
+ const _f36components = require("@contentful/f36-components");
13
+ const _lodash = require("lodash");
14
+ const _Banner = require("./Banner");
15
+ function _interop_require_default(obj) {
16
+ return obj && obj.__esModule ? obj : {
17
+ default: obj
18
+ };
19
+ }
20
+ var ScheduledActionTypes;
21
+ (function(ScheduledActionTypes) {
22
+ ScheduledActionTypes["publish"] = "publish";
23
+ ScheduledActionTypes["unpublish"] = "unpublish";
24
+ ScheduledActionTypes["patch+publish"] = "patch+publish";
25
+ })(ScheduledActionTypes || (ScheduledActionTypes = {}));
26
+ function ScheduledBanner({ entityId, jobs }) {
27
+ const scheduledJobs = jobs.filter((job)=>job.entity.sys.id === entityId);
28
+ const sortedScheduledJobs = (0, _lodash.orderBy)(scheduledJobs, [
29
+ 'scheduledFor.datetime'
30
+ ], [
31
+ 'asc'
32
+ ]);
33
+ const scheduledAction = sortedScheduledJobs[0];
34
+ if (!scheduledAction) {
35
+ return null;
36
+ }
37
+ const pendingJobsCount = scheduledJobs.length - 1;
38
+ const lowerCaseAction = scheduledAction.action.toLowerCase();
39
+ const action = lowerCaseAction === "patch+publish" ? `${lowerCaseAction} (via Schedule Series)` : lowerCaseAction;
40
+ return _react.default.createElement(_Banner.Banner, {
41
+ content: `All locales are scheduled to ${action} on:`,
42
+ highlight: `${(0, _f36components.formatDateAndTime)(scheduledAction.scheduledFor.datetime)}${pendingJobsCount > 0 ? ` [and +${pendingJobsCount} more]` : ''}`
43
+ });
44
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./LocalePublishingPopover"), exports);
6
+ function _export_star(from, to) {
7
+ Object.keys(from).forEach(function(k) {
8
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
9
+ Object.defineProperty(to, k, {
10
+ enumerable: true,
11
+ get: function() {
12
+ return from[k];
13
+ }
14
+ });
15
+ }
16
+ });
17
+ return from;
18
+ }
package/dist/cjs/index.js CHANGED
@@ -111,9 +111,23 @@ const _PredefinedValuesError = require("./PredefinedValuesError");
111
111
  const _typesEntity = require("./typesEntity");
112
112
  const _isValidImage = require("./utils/isValidImage");
113
113
  const _shortenStorageUnit = require("./utils/shortenStorageUnit");
114
+ _export_star(require("./LocalePublishingEntityStatusBadge"), exports);
114
115
  const _ModalDialogLauncher = _interop_require_wildcard(require("./ModalDialogLauncher"));
115
116
  const _constraints = _interop_require_wildcard(require("./utils/constraints"));
116
117
  const _entityHelpers = _interop_require_wildcard(require("./utils/entityHelpers"));
118
+ function _export_star(from, to) {
119
+ Object.keys(from).forEach(function(k) {
120
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
121
+ Object.defineProperty(to, k, {
122
+ enumerable: true,
123
+ get: function() {
124
+ return from[k];
125
+ }
126
+ });
127
+ }
128
+ });
129
+ return from;
130
+ }
117
131
  function _getRequireWildcardCache(nodeInterop) {
118
132
  if (typeof WeakMap !== "function") return null;
119
133
  var cacheBabelInterop = new WeakMap();
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { Text } from '@contentful/f36-components';
3
+ import tokens from '@contentful/f36-tokens';
4
+ import { css } from 'emotion';
5
+ const styles = {
6
+ content: css({
7
+ display: 'block'
8
+ }),
9
+ banner: css({
10
+ background: tokens.gray100,
11
+ padding: tokens.spacingXs,
12
+ margin: `${tokens.spacingXs} ${tokens.spacingS}`,
13
+ borderRadius: tokens.borderRadiusSmall
14
+ })
15
+ };
16
+ export function Banner({ content, highlight }) {
17
+ return React.createElement("div", {
18
+ className: styles.banner
19
+ }, React.createElement(Text, {
20
+ fontSize: "fontSizeS",
21
+ fontColor: "gray700",
22
+ className: styles.content
23
+ }, content), highlight && React.createElement(Text, {
24
+ fontSize: "fontSizeS",
25
+ fontColor: "gray700",
26
+ as: "strong",
27
+ fontWeight: "fontWeightDemiBold"
28
+ }, highlight));
29
+ }
@@ -0,0 +1,255 @@
1
+ import React, { useCallback, useRef, useState } from 'react';
2
+ import { EntityStatusBadge, Flex, Popover, generateIcon } from '@contentful/f36-components';
3
+ import tokens from '@contentful/f36-tokens';
4
+ import { cx, css } from 'emotion';
5
+ import * as entityHelpers from '../utils/entityHelpers';
6
+ import { LocalePublishingStatusList } from './LocalePublishingStatusList';
7
+ import { ScheduledBanner } from './ScheduledBanner';
8
+ const colors = {
9
+ published: {
10
+ default: tokens.green300,
11
+ hover: tokens.green400,
12
+ icon: tokens.green400
13
+ },
14
+ draft: {
15
+ default: tokens.orange300,
16
+ hover: tokens.orange400,
17
+ icon: tokens.orange400
18
+ },
19
+ changed: {
20
+ default: tokens.blue300,
21
+ hover: tokens.blue400,
22
+ icon: tokens.blue400
23
+ },
24
+ archived: {
25
+ default: tokens.gray300,
26
+ hover: tokens.gray400,
27
+ icon: tokens.gray400
28
+ },
29
+ deleted: {
30
+ default: tokens.red300,
31
+ hover: tokens.red400,
32
+ icon: tokens.red400
33
+ },
34
+ new: {
35
+ default: tokens.blue600,
36
+ hover: tokens.blue700,
37
+ icon: tokens.blue700
38
+ }
39
+ };
40
+ const getColor = ({ secondary, tertiary, isHover })=>{
41
+ const status = secondary || tertiary;
42
+ return isHover ? colors[status]?.hover : colors[status]?.default;
43
+ };
44
+ const generateDynamicStyles = (status)=>{
45
+ const wrapperClass = css({
46
+ '& svg[data-status="secondary"]': {
47
+ fill: getColor({
48
+ secondary: status?.secondary,
49
+ isHover: false
50
+ })
51
+ },
52
+ '& svg[data-status="tertiary"]': {
53
+ fill: getColor({
54
+ tertiary: status?.tertiary,
55
+ isHover: false
56
+ })
57
+ },
58
+ '&:hover svg[data-status="secondary"]': {
59
+ fill: getColor({
60
+ secondary: status?.secondary,
61
+ isHover: true
62
+ })
63
+ },
64
+ '&:hover svg[data-status="tertiary"]': {
65
+ fill: getColor({
66
+ tertiary: status?.tertiary,
67
+ isHover: true
68
+ })
69
+ }
70
+ });
71
+ return wrapperClass;
72
+ };
73
+ const getIconColor = (status)=>colors[status].icon;
74
+ const styles = {
75
+ badge: css({
76
+ '&:focus': {
77
+ outline: 'none',
78
+ boxShadow: `inset ${tokens.glowPrimary}`
79
+ }
80
+ }),
81
+ wrapper: css({
82
+ '& svg': {
83
+ transition: 'fill 0.2s ease-in-out'
84
+ },
85
+ '& svg[data-status="tertiary"]': {
86
+ marginLeft: '-1px'
87
+ }
88
+ }),
89
+ popoverContent: css({
90
+ maxWidth: '336px',
91
+ maxHeight: '368px',
92
+ overflowY: 'auto',
93
+ padding: `${tokens.spacing2Xs} 0`
94
+ })
95
+ };
96
+ const ArrowDownIcon = generateIcon({
97
+ name: 'ArrowDownIcon',
98
+ viewBox: '0 0 12 20',
99
+ path: React.createElement("path", {
100
+ d: "M3.03076 8C2.20109 8 1.73228 8.95209 2.23814 9.60971L5.20727 13.4696C5.60757 13.99 6.39223 13.99 6.79252 13.4696L9.76166 9.60971C10.2675 8.95209 9.79871 8 8.96904 8L3.03076 8Z",
101
+ fill: "currentColor"
102
+ })
103
+ });
104
+ const determineBadgeStatus = (localesStatusMap, activeLocales)=>{
105
+ if (!localesStatusMap) return;
106
+ if (localesStatusMap.size === 1) return {
107
+ primary: [
108
+ ...localesStatusMap.values()
109
+ ][0].status
110
+ };
111
+ let draftCount = 0, publishedCount = 0, changedCount = 0;
112
+ for (const localeStatus of localesStatusMap.values()){
113
+ if (!activeLocales || activeLocales.find((selectedLocale)=>selectedLocale.code === localeStatus.locale.code)) {
114
+ switch(localeStatus.status){
115
+ case 'changed':
116
+ changedCount += 1;
117
+ break;
118
+ case 'draft':
119
+ draftCount += 1;
120
+ break;
121
+ case 'published':
122
+ publishedCount += 1;
123
+ break;
124
+ }
125
+ }
126
+ }
127
+ const hasChanged = changedCount > 0;
128
+ const hasPublished = publishedCount > 0;
129
+ const hasDraft = draftCount > 0;
130
+ switch(true){
131
+ case hasChanged && hasPublished && hasDraft:
132
+ return {
133
+ primary: 'changed',
134
+ secondary: 'published',
135
+ tertiary: 'draft'
136
+ };
137
+ case hasChanged && hasPublished:
138
+ return {
139
+ primary: 'changed',
140
+ secondary: 'published'
141
+ };
142
+ case hasChanged && hasDraft:
143
+ return {
144
+ primary: 'changed',
145
+ secondary: 'draft'
146
+ };
147
+ case hasPublished && hasDraft:
148
+ return {
149
+ primary: 'published',
150
+ secondary: 'draft'
151
+ };
152
+ case hasChanged:
153
+ return {
154
+ primary: 'changed',
155
+ secondary: 'changed'
156
+ };
157
+ case hasPublished:
158
+ return {
159
+ primary: 'published',
160
+ secondary: 'published'
161
+ };
162
+ default:
163
+ return {
164
+ primary: 'draft',
165
+ secondary: 'draft'
166
+ };
167
+ }
168
+ };
169
+ export function LocalePublishingPopover({ entity, jobs, isScheduled, localesStatusMap, activeLocales }) {
170
+ const [isOpen, setIsOpen] = useState(false);
171
+ const timeoutRef = useRef();
172
+ const onMouseEnter = useCallback(()=>{
173
+ clearTimeout(timeoutRef.current);
174
+ timeoutRef.current = setTimeout(()=>{
175
+ setIsOpen(true);
176
+ }, 300);
177
+ }, []);
178
+ const onMouseLeave = useCallback(()=>{
179
+ clearTimeout(timeoutRef.current);
180
+ timeoutRef.current = setTimeout(()=>{
181
+ setIsOpen(false);
182
+ }, 300);
183
+ }, []);
184
+ const entityStatus = entityHelpers.getEntityStatus(entity.sys, activeLocales?.map((locale)=>locale.code));
185
+ if ([
186
+ 'archived',
187
+ 'deleted'
188
+ ].includes(entityStatus)) {
189
+ return React.createElement(EntityStatusBadge, {
190
+ className: styles.badge,
191
+ testId: "entity-state",
192
+ entityStatus: entityStatus,
193
+ tabIndex: 0,
194
+ isScheduled: isScheduled
195
+ });
196
+ }
197
+ const status = determineBadgeStatus(localesStatusMap, activeLocales);
198
+ const ariaLabel = status && status.secondary ? 'Multiple statuses' : status?.primary;
199
+ const wrapperClass = generateDynamicStyles(status);
200
+ return React.createElement(Popover, {
201
+ isOpen: localesStatusMap && isOpen,
202
+ onClose: ()=>setIsOpen(false),
203
+ autoFocus: false,
204
+ placement: "bottom-end"
205
+ }, React.createElement(Popover.Trigger, null, React.createElement(Flex, {
206
+ "aria-label": ariaLabel,
207
+ alignItems: "center",
208
+ className: cx(styles.wrapper, wrapperClass)
209
+ }, React.createElement(EntityStatusBadge, {
210
+ className: styles.badge,
211
+ testId: "entity-state",
212
+ entityStatus: entityStatus,
213
+ tabIndex: 0,
214
+ onFocus: ()=>setIsOpen(true),
215
+ onBlur: ()=>setIsOpen(false),
216
+ endIcon: React.createElement(ArrowDownIcon, {
217
+ color: getIconColor(entityStatus)
218
+ }),
219
+ onMouseOver: onMouseEnter,
220
+ isScheduled: isScheduled,
221
+ onMouseEnter: onMouseEnter,
222
+ onMouseLeave: onMouseLeave
223
+ }), status?.secondary && React.createElement("svg", {
224
+ "data-status": "secondary",
225
+ "aria-hidden": "true",
226
+ width: "4",
227
+ height: "18",
228
+ viewBox: "0 0 4 18"
229
+ }, React.createElement("path", {
230
+ fillRule: "evenodd",
231
+ clipRule: "evenodd",
232
+ d: "M1.45942e-06 18H0.00296171C2.2121 18 4.00296 16.2091 4.00296 14V4C4.00296 1.79086 2.2121 0 0.00295914 0H0C0.830421 0.732944 1.35418 1.80531 1.35418 3V15C1.35418 16.1947 0.830422 17.2671 1.45942e-06 18Z"
233
+ })), status?.tertiary && React.createElement("svg", {
234
+ "data-status": "tertiary",
235
+ "aria-hidden": "true",
236
+ width: "5",
237
+ height: "16",
238
+ viewBox: "0 0 5 16"
239
+ }, React.createElement("path", {
240
+ fillRule: "evenodd",
241
+ clipRule: "evenodd",
242
+ d: "M0.673828 16.0055H0.675391C2.88453 16.0055 4.67539 14.2146 4.67539 12.0055V3.9955C4.67539 1.88216 3.03648 0.151608 0.960312 0.00549316C1.78382 0.738158 2.30257 1.80597 2.30257 2.99493V12.7838C2.30257 14.1053 1.66172 15.2771 0.673828 16.0055Z"
243
+ })))), React.createElement(Popover.Content, {
244
+ className: styles.popoverContent,
245
+ onMouseEnter: onMouseEnter,
246
+ onMouseLeave: onMouseLeave
247
+ }, !!localesStatusMap && React.createElement(React.Fragment, null, React.createElement(ScheduledBanner, {
248
+ entityId: entity.sys.id,
249
+ jobs: jobs
250
+ }), React.createElement(LocalePublishingStatusList, {
251
+ isScheduled: isScheduled,
252
+ statusMap: localesStatusMap,
253
+ activeLocales: activeLocales
254
+ }))));
255
+ }
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { EntityStatusBadge, Text } from '@contentful/f36-components';
3
+ import tokens from '@contentful/f36-tokens';
4
+ import { css } from 'emotion';
5
+ const styles = {
6
+ locale: css({
7
+ textOverflow: 'ellipsis',
8
+ overflow: 'hidden',
9
+ whiteSpace: 'nowrap'
10
+ }),
11
+ status: css({
12
+ flexShrink: 0
13
+ }),
14
+ localePublishStatus: css({
15
+ display: 'flex',
16
+ gap: tokens.spacingXs,
17
+ justifyContent: 'space-between',
18
+ padding: `${tokens.spacingXs} ${tokens.spacingS}`
19
+ })
20
+ };
21
+ export function LocalePublishingStatus({ locale, status, isScheduled }) {
22
+ return React.createElement("div", {
23
+ className: styles.localePublishStatus,
24
+ "data-test-id": "locale-publishing-status"
25
+ }, React.createElement(Text, {
26
+ className: styles.locale,
27
+ fontColor: "gray700"
28
+ }, locale.name, ' ', React.createElement(Text, {
29
+ fontColor: "gray500"
30
+ }, "(", locale.code, ")", locale.default && ' | default')), React.createElement(EntityStatusBadge, {
31
+ entityStatus: status,
32
+ isScheduled: isScheduled,
33
+ className: styles.status
34
+ }));
35
+ }
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ import { MenuSectionTitle } from '@contentful/f36-components';
3
+ import { sortBy } from 'lodash';
4
+ import { Banner } from './Banner';
5
+ import { LocalePublishingStatus } from './LocalePublishingStatus';
6
+ function groupAndSortLocales(entries, activeLocales) {
7
+ const { selected, nonSelected } = entries.reduce((prev, [localeCode, localeStatusType])=>{
8
+ return activeLocales?.some((sl)=>sl.code === localeCode) ? {
9
+ ...prev,
10
+ selected: [
11
+ ...prev.selected,
12
+ localeStatusType
13
+ ]
14
+ } : {
15
+ ...prev,
16
+ nonSelected: [
17
+ ...prev.nonSelected,
18
+ localeStatusType
19
+ ]
20
+ };
21
+ }, {
22
+ selected: [],
23
+ nonSelected: []
24
+ });
25
+ return {
26
+ selected: sortBy(selected, 'locale.name'),
27
+ nonSelected: nonSelected.sort((a, b)=>{
28
+ if (a.status === b.status) {
29
+ return a.locale.name.localeCompare(b.locale.name);
30
+ }
31
+ if (a.status === 'changed' || a.status === 'published' && b.status === 'draft') {
32
+ return -1;
33
+ }
34
+ return 1;
35
+ })
36
+ };
37
+ }
38
+ export function LocalePublishingStatusList({ isScheduled, statusMap, activeLocales }) {
39
+ const entries = [
40
+ ...statusMap.entries()
41
+ ];
42
+ const counters = entries.reduce((prev, [, { status }])=>({
43
+ changed: prev.changed + (status === 'changed' ? 1 : 0),
44
+ published: prev.published + (status === 'published' ? 1 : 0),
45
+ draft: prev.draft + (status === 'draft' ? 1 : 0)
46
+ }), {
47
+ published: 0,
48
+ changed: 0,
49
+ draft: 0
50
+ });
51
+ const { selected, nonSelected } = groupAndSortLocales(entries, activeLocales);
52
+ return React.createElement(React.Fragment, null, React.createElement(Banner, {
53
+ content: "The entry has locales with the following statuses:",
54
+ highlight: `${counters.changed} changed, ${counters.published} published, ${counters.draft} draft`
55
+ }), React.createElement("div", {
56
+ "data-test-id": "locale-publishing-selected"
57
+ }, React.createElement(MenuSectionTitle, null, "Locales in the entry editor:"), selected.map(({ locale, status })=>React.createElement(LocalePublishingStatus, {
58
+ key: `selected-${locale.code}`,
59
+ status: status,
60
+ locale: locale,
61
+ isScheduled: isScheduled
62
+ }))), nonSelected.length > 0 && React.createElement("div", {
63
+ "data-test-id": "locale-publishing-others"
64
+ }, React.createElement(MenuSectionTitle, null, "Other locales:"), nonSelected.map(({ locale, status })=>React.createElement(LocalePublishingStatus, {
65
+ key: `others-${locale.code}`,
66
+ status: status,
67
+ locale: locale,
68
+ isScheduled: isScheduled
69
+ }))));
70
+ }
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { formatDateAndTime } from '@contentful/f36-components';
3
+ import { orderBy } from 'lodash';
4
+ import { Banner } from './Banner';
5
+ var ScheduledActionTypes;
6
+ (function(ScheduledActionTypes) {
7
+ ScheduledActionTypes["publish"] = "publish";
8
+ ScheduledActionTypes["unpublish"] = "unpublish";
9
+ ScheduledActionTypes["patch+publish"] = "patch+publish";
10
+ })(ScheduledActionTypes || (ScheduledActionTypes = {}));
11
+ export function ScheduledBanner({ entityId, jobs }) {
12
+ const scheduledJobs = jobs.filter((job)=>job.entity.sys.id === entityId);
13
+ const sortedScheduledJobs = orderBy(scheduledJobs, [
14
+ 'scheduledFor.datetime'
15
+ ], [
16
+ 'asc'
17
+ ]);
18
+ const scheduledAction = sortedScheduledJobs[0];
19
+ if (!scheduledAction) {
20
+ return null;
21
+ }
22
+ const pendingJobsCount = scheduledJobs.length - 1;
23
+ const lowerCaseAction = scheduledAction.action.toLowerCase();
24
+ const action = lowerCaseAction === "patch+publish" ? `${lowerCaseAction} (via Schedule Series)` : lowerCaseAction;
25
+ return React.createElement(Banner, {
26
+ content: `All locales are scheduled to ${action} on:`,
27
+ highlight: `${formatDateAndTime(scheduledAction.scheduledFor.datetime)}${pendingJobsCount > 0 ? ` [and +${pendingJobsCount} more]` : ''}`
28
+ });
29
+ }
@@ -0,0 +1 @@
1
+ export * from './LocalePublishingPopover';
package/dist/esm/index.js CHANGED
@@ -9,6 +9,7 @@ export { shortenStorageUnit, toLocaleString } from './utils/shortenStorageUnit';
9
9
  export { ModalDialogLauncher };
10
10
  export { entityHelpers };
11
11
  export { ConstraintsUtils };
12
+ export * from './LocalePublishingEntityStatusBadge';
12
13
  import * as ModalDialogLauncher from './ModalDialogLauncher';
13
14
  import * as ConstraintsUtils from './utils/constraints';
14
15
  import * as entityHelpers from './utils/entityHelpers';
@@ -0,0 +1,5 @@
1
+ import React, { ReactNode } from 'react';
2
+ export declare function Banner({ content, highlight }: {
3
+ content: ReactNode;
4
+ highlight?: ReactNode;
5
+ }): React.JSX.Element;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import type { LocaleProps, EntryProps, AssetProps, ScheduledActionProps } from 'contentful-management';
3
+ export type LocalePublishStatus = {
4
+ status: 'draft' | 'published' | 'changed';
5
+ locale: LocaleProps;
6
+ };
7
+ export type LocalePublishStatusMap = Map<string, LocalePublishStatus>;
8
+ type LocalePublishingPopoverProps = {
9
+ entity: EntryProps | AssetProps;
10
+ jobs: ScheduledActionProps[];
11
+ isScheduled: boolean;
12
+ activeLocales: LocaleProps[] | null;
13
+ localesStatusMap?: LocalePublishStatusMap;
14
+ };
15
+ export declare function LocalePublishingPopover({ entity, jobs, isScheduled, localesStatusMap, activeLocales, }: LocalePublishingPopoverProps): React.JSX.Element;
16
+ export {};
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { LocaleProps } from 'contentful-management';
3
+ type LocalePublishingStatusProps = {
4
+ locale: LocaleProps;
5
+ status: 'draft' | 'published' | 'changed';
6
+ isScheduled: boolean;
7
+ };
8
+ export declare function LocalePublishingStatus({ locale, status, isScheduled, }: LocalePublishingStatusProps): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import type { LocaleProps } from 'contentful-management';
3
+ import type { LocalePublishStatusMap } from './LocalePublishingPopover';
4
+ type LocalePublishingStatusListProps = {
5
+ isScheduled: boolean;
6
+ statusMap: LocalePublishStatusMap;
7
+ activeLocales: LocaleProps[] | null;
8
+ };
9
+ export declare function LocalePublishingStatusList({ isScheduled, statusMap, activeLocales, }: LocalePublishingStatusListProps): React.JSX.Element;
10
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { ScheduledActionProps } from 'contentful-management';
3
+ type ScheduledBannerProps = {
4
+ entityId: string;
5
+ jobs: ScheduledActionProps[];
6
+ };
7
+ export declare function ScheduledBanner({ entityId, jobs }: ScheduledBannerProps): React.JSX.Element | null;
8
+ export {};
@@ -0,0 +1 @@
1
+ export * from './LocalePublishingPopover';
@@ -10,6 +10,7 @@ export { shortenStorageUnit, toLocaleString } from './utils/shortenStorageUnit';
10
10
  export { ModalDialogLauncher };
11
11
  export { entityHelpers };
12
12
  export { ConstraintsUtils };
13
+ export * from './LocalePublishingEntityStatusBadge';
13
14
  import * as ModalDialogLauncher from './ModalDialogLauncher';
14
15
  import * as ConstraintsUtils from './utils/constraints';
15
16
  import * as entityHelpers from './utils/entityHelpers';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/field-editor-shared",
3
- "version": "1.6.3",
3
+ "version": "1.7.1",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -39,8 +39,10 @@
39
39
  "@contentful/field-editor-test-utils": "^1.5.2"
40
40
  },
41
41
  "dependencies": {
42
+ "@contentful/f36-components": "^4.70.0",
42
43
  "@contentful/f36-note": "^4.70.0",
43
44
  "@contentful/f36-tokens": "^4.0.5",
45
+ "contentful-management": "^11.35.1",
44
46
  "emotion": "^10.0.17",
45
47
  "fast-deep-equal": "^3.1.3",
46
48
  "lodash": "^4.17.15"
@@ -52,5 +54,5 @@
52
54
  "publishConfig": {
53
55
  "registry": "https://npm.pkg.github.com/"
54
56
  },
55
- "gitHead": "d717a9230fac05999c0f4804087740b5666efb4a"
57
+ "gitHead": "4f029f8d8ad0d8b8e270db4619fa1e8fb278a509"
56
58
  }