@contentful/field-editor-shared 1.2.0 → 1.3.0

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 (50) hide show
  1. package/dist/cjs/CharCounter.js +75 -0
  2. package/dist/cjs/CharValidation.js +60 -0
  3. package/dist/cjs/FieldConnector.js +167 -0
  4. package/dist/cjs/FieldConnector.test.js +81 -0
  5. package/dist/cjs/ModalDialogLauncher.js +132 -0
  6. package/dist/cjs/PredefinedValuesError.js +57 -0
  7. package/dist/cjs/index.js +155 -0
  8. package/dist/cjs/types.js +4 -0
  9. package/dist/cjs/typesEntity.js +31 -0
  10. package/dist/cjs/utils/constraints.js +63 -0
  11. package/dist/cjs/utils/entityHelpers.js +214 -0
  12. package/dist/cjs/utils/isValidImage.js +26 -0
  13. package/dist/cjs/utils/shortenStorageUnit.js +55 -0
  14. package/dist/esm/CharCounter.js +21 -0
  15. package/dist/esm/CharValidation.js +11 -0
  16. package/dist/esm/FieldConnector.js +113 -0
  17. package/dist/esm/FieldConnector.test.js +33 -0
  18. package/dist/esm/ModalDialogLauncher.js +67 -0
  19. package/dist/esm/PredefinedValuesError.js +8 -0
  20. package/dist/esm/index.js +14 -0
  21. package/dist/esm/types.js +1 -0
  22. package/dist/esm/typesEntity.js +1 -0
  23. package/dist/esm/utils/constraints.js +40 -0
  24. package/dist/esm/utils/entityHelpers.js +170 -0
  25. package/dist/esm/utils/isValidImage.js +16 -0
  26. package/dist/esm/utils/shortenStorageUnit.js +37 -0
  27. package/dist/types/CharCounter.d.ts +7 -0
  28. package/dist/{CharValidation.d.ts → types/CharValidation.d.ts} +7 -7
  29. package/dist/{FieldConnector.d.ts → types/FieldConnector.d.ts} +47 -48
  30. package/dist/types/FieldConnector.test.d.ts +1 -0
  31. package/dist/{ModalDialogLauncher.d.ts → types/ModalDialogLauncher.d.ts} +13 -13
  32. package/dist/types/PredefinedValuesError.d.ts +2 -0
  33. package/dist/{index.d.ts → types/index.d.ts} +15 -15
  34. package/dist/{types.d.ts → types/types.d.ts} +11 -11
  35. package/dist/{typesEntity.d.ts → types/typesEntity.d.ts} +9 -9
  36. package/dist/{utils → types/utils}/constraints.d.ts +3 -3
  37. package/dist/{utils → types/utils}/entityHelpers.d.ts +68 -68
  38. package/dist/{utils → types/utils}/isValidImage.d.ts +5 -5
  39. package/dist/{utils → types/utils}/shortenStorageUnit.d.ts +17 -17
  40. package/package.json +26 -11
  41. package/CHANGELOG.md +0 -196
  42. package/dist/CharCounter.d.ts +0 -7
  43. package/dist/PredefinedValuesError.d.ts +0 -2
  44. package/dist/field-editor-shared.cjs.development.js +0 -634
  45. package/dist/field-editor-shared.cjs.development.js.map +0 -1
  46. package/dist/field-editor-shared.cjs.production.min.js +0 -2
  47. package/dist/field-editor-shared.cjs.production.min.js.map +0 -1
  48. package/dist/field-editor-shared.esm.js +0 -619
  49. package/dist/field-editor-shared.esm.js.map +0 -1
  50. package/dist/index.js +0 -8
@@ -1,619 +0,0 @@
1
- import React from 'react';
2
- import isEqual from 'lodash-es/isEqual';
3
- import throttle from 'lodash-es/throttle';
4
- import { Note } from '@contentful/f36-note';
5
- import tokens from '@contentful/f36-tokens';
6
- import { cx, css } from 'emotion';
7
- import ReactDOM from 'react-dom';
8
- import { Modal, ModalHeader } from '@contentful/f36-components';
9
- import isNumber from 'lodash-es/isNumber';
10
- import get from 'lodash-es/get';
11
- import isObject from 'lodash-es/isObject';
12
- import isString from 'lodash-es/isString';
13
-
14
- class FieldConnector extends React.Component {
15
- constructor(props) {
16
- super(props);
17
- this.unsubscribeErrors = null;
18
- this.unsubscribeDisabled = null;
19
- this.unsubscribeValue = null;
20
-
21
- this.setValue = async value => {
22
- if (this.props.isEmptyValue(value ?? null)) {
23
- this.setState({
24
- value: undefined
25
- });
26
- } else {
27
- this.setState({
28
- value
29
- });
30
- }
31
-
32
- await this.triggerSetValueCallbacks(value);
33
- };
34
-
35
- this.triggerSetValueCallbacks = throttle(value => {
36
- return new Promise((resolve, reject) => {
37
- if (this.props.isEmptyValue(value ?? null)) {
38
- this.props.field.removeValue().then(resolve).catch(reject);
39
- } else {
40
- this.props.field.setValue(value).then(resolve).catch(reject);
41
- }
42
- });
43
- }, this.props.throttle, {
44
- leading: this.props.throttle === 0
45
- });
46
- const initialValue = props.field.getValue();
47
- this.state = {
48
- isLocalValueChange: false,
49
- externalReset: 0,
50
- value: initialValue,
51
- lastRemoteValue: initialValue,
52
- disabled: props.isInitiallyDisabled ?? false,
53
- errors: []
54
- };
55
- }
56
-
57
- componentDidMount() {
58
- const {
59
- field
60
- } = this.props;
61
- this.unsubscribeErrors = field.onSchemaErrorsChanged(errors => {
62
- this.setState({
63
- errors: errors || []
64
- });
65
- });
66
- this.unsubscribeDisabled = field.onIsDisabledChanged(disabled => {
67
- this.setState({
68
- disabled
69
- });
70
- });
71
- this.unsubscribeValue = field.onValueChanged(value => {
72
- this.setState(currentState => {
73
- const isLocalValueChange = this.props.isEqualValues(value, currentState.value);
74
- const lastRemoteValue = isLocalValueChange ? currentState.lastRemoteValue : value;
75
- const externalReset = currentState.externalReset + (isLocalValueChange ? 0 : 1);
76
- return {
77
- value,
78
- lastRemoteValue,
79
- isLocalValueChange,
80
- externalReset
81
- };
82
- });
83
- });
84
- }
85
-
86
- componentWillUnmount() {
87
- if (typeof this.unsubscribeErrors === 'function') {
88
- this.unsubscribeErrors();
89
- }
90
-
91
- if (typeof this.unsubscribeDisabled === 'function') {
92
- this.unsubscribeDisabled();
93
- }
94
-
95
- if (typeof this.unsubscribeValue === 'function') {
96
- this.unsubscribeValue();
97
- }
98
- }
99
-
100
- render() {
101
- return this.props.children({ ...this.state,
102
- setValue: this.setValue,
103
- disabled: this.props.isDisabled || this.state.disabled
104
- });
105
- }
106
-
107
- }
108
- FieldConnector.defaultProps = {
109
- children: () => {
110
- return null;
111
- },
112
- // eslint-disable-next-line -- TODO: describe this disable
113
- isEmptyValue: value => {
114
- return value === null || value === '';
115
- },
116
- // eslint-disable-next-line -- TODO: describe this disable
117
- isEqualValues: (value1, value2) => {
118
- return isEqual(value1, value2);
119
- },
120
- throttle: 300
121
- };
122
-
123
- function PredefinedValuesError() {
124
- return React.createElement(Note, {
125
- variant: "warning",
126
- testId: "predefined-values-warning"
127
- }, "The widget failed to initialize. You can fix the problem by providing predefined values under the validations tab in the field settings.");
128
- }
129
-
130
- const styles = {
131
- invalid: /*#__PURE__*/css({
132
- color: tokens.red600
133
- })
134
- };
135
- function CharCounter(props) {
136
- let count = 0;
137
-
138
- if (props.value) {
139
- count = props.value.length;
140
- }
141
-
142
- const valid = count === 0 || props.checkConstraint(count);
143
- return React.createElement("span", {
144
- "data-status-code": valid ? null : 'invalid-size',
145
- className: cx({
146
- [styles.invalid]: !valid
147
- })
148
- }, count, " characters");
149
- }
150
-
151
- function CharValidation(props) {
152
- const {
153
- constraints
154
- } = props;
155
-
156
- if (constraints.type === 'max') {
157
- return React.createElement("span", null, "Maximum ", constraints.max, " characters");
158
- } else if (constraints.type === 'min') {
159
- return React.createElement("span", null, "Requires at least ", constraints.min, " characters");
160
- } else {
161
- return React.createElement("span", null, "Requires between ", constraints.min, " and ", constraints.max, " characters");
162
- }
163
- }
164
-
165
- /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-use-before-define */
166
- function open(componentRenderer) {
167
- let rootDom = null;
168
-
169
- const getRoot = () => {
170
- if (rootDom === null) {
171
- rootDom = document.createElement('div');
172
- rootDom.setAttribute('id', 'field-editor-modal-root');
173
- document.body.appendChild(rootDom);
174
- }
175
-
176
- return rootDom;
177
- };
178
-
179
- return new Promise(resolve => {
180
- let currentConfig = {
181
- onClose,
182
- isShown: true
183
- };
184
-
185
- function render({
186
- onClose,
187
- isShown
188
- }) {
189
- ReactDOM.render(componentRenderer({
190
- onClose,
191
- isShown
192
- }), getRoot());
193
- }
194
-
195
- function onClose(...args) {
196
- currentConfig = { ...currentConfig,
197
- isShown: false
198
- };
199
- render(currentConfig); // eslint-disable-next-line -- TODO: describe this disable @typescript-eslint/ban-ts-comment
200
- // @ts-ignore
201
-
202
- resolve(...args);
203
- getRoot().remove();
204
- }
205
-
206
- render(currentConfig);
207
- });
208
- }
209
- function openDialog(options, Component) {
210
- const key = Date.now();
211
- const size = isNumber(options.width) ? `${options.width}px` : options.width;
212
- return open(({
213
- isShown,
214
- onClose
215
- }) => {
216
- const onCloseHandler = () => onClose();
217
-
218
- return React.createElement(Modal, {
219
- key: key,
220
- shouldCloseOnOverlayClick: options.shouldCloseOnOverlayClick || false,
221
- shouldCloseOnEscapePress: options.shouldCloseOnEscapePress || false,
222
- allowHeightOverflow: options.allowHeightOverflow || false,
223
- position: options.position || 'center',
224
- isShown: isShown,
225
- onClose: onCloseHandler,
226
- size: size || '700px'
227
- }, () => React.createElement(React.Fragment, null, options.title && React.createElement(ModalHeader, {
228
- testId: "dialog-title",
229
- title: options.title,
230
- onClose: onCloseHandler
231
- }), React.createElement("div", {
232
- style: {
233
- minHeight: options.minHeight || 'auto'
234
- }
235
- }, React.createElement(Component, {
236
- onClose: onClose
237
- }))));
238
- });
239
- }
240
- var ModalDialogLauncher = {
241
- openDialog
242
- };
243
-
244
- var ModalDialogLauncher$1 = {
245
- __proto__: null,
246
- open: open,
247
- openDialog: openDialog,
248
- 'default': ModalDialogLauncher
249
- };
250
-
251
- function titleOrDefault(title, defaultTitle) {
252
- if (!isString(title)) {
253
- return defaultTitle;
254
- }
255
-
256
- if (title) {
257
- const trimmedTitle = title.trim();
258
-
259
- if (trimmedTitle.length === 0) {
260
- return defaultTitle;
261
- }
262
-
263
- return trimmedTitle;
264
- }
265
-
266
- return defaultTitle;
267
- }
268
-
269
- function getFieldValue({
270
- /**
271
- * Expects an entity fetched with a flag Skip-Transformation: true
272
- */
273
- entity,
274
- fieldId,
275
- localeCode,
276
- defaultLocaleCode
277
- }) {
278
- const values = get(entity, ['fields', fieldId]);
279
-
280
- if (!isObject(values)) {
281
- return;
282
- }
283
-
284
- const firstLocaleCode = Object.keys(values)[0];
285
- return values[localeCode] || values[defaultLocaleCode] || values[firstLocaleCode];
286
- }
287
- function getAssetTitle({
288
- asset,
289
- localeCode,
290
- defaultLocaleCode,
291
- defaultTitle
292
- }) {
293
- var _asset$fields;
294
-
295
- const title = getFieldValue({
296
- entity: {
297
- fields: {
298
- title: (_asset$fields = asset.fields) == null ? void 0 : _asset$fields.title
299
- }
300
- },
301
- fieldId: 'title',
302
- localeCode,
303
- defaultLocaleCode
304
- });
305
- return titleOrDefault(title, defaultTitle);
306
- }
307
- /**
308
- * Returns true if field is an Asset
309
- *
310
- * @param field
311
- * @returns {boolean}
312
- */
313
-
314
- const isAssetField = field => field.type === 'Link' && field.linkType === 'Asset';
315
- /**
316
- * Returns true if field is a Title
317
- */
318
-
319
- function isDisplayField({
320
- field,
321
- contentType
322
- }) {
323
- return field.id === contentType.displayField;
324
- }
325
- /**
326
- * Returns true if field is a short Description
327
- */
328
-
329
- function isDescriptionField({
330
- field,
331
- contentType
332
- }) {
333
- const isTextField = field => ['Symbol', 'Text'].includes(field.type);
334
-
335
- const isMaybeSlugField = field => /\bslug\b/.test(field.name);
336
-
337
- return isTextField(field) && !isDisplayField({
338
- field,
339
- contentType
340
- }) && !isMaybeSlugField(field);
341
- }
342
- function getEntityDescription({
343
- entity,
344
- contentType,
345
- localeCode,
346
- defaultLocaleCode
347
- }) {
348
- if (!contentType) {
349
- return '';
350
- }
351
-
352
- const descriptionField = contentType.fields.find(field => isDescriptionField({
353
- field,
354
- contentType
355
- }));
356
-
357
- if (!descriptionField) {
358
- return '';
359
- }
360
-
361
- return getFieldValue({
362
- entity,
363
- fieldId: descriptionField.id,
364
- localeCode,
365
- defaultLocaleCode
366
- }) || '';
367
- }
368
- function getEntryTitle({
369
- entry,
370
- contentType,
371
- localeCode,
372
- defaultLocaleCode,
373
- defaultTitle
374
- }) {
375
- let title;
376
-
377
- if (!contentType) {
378
- return defaultTitle;
379
- }
380
-
381
- const displayField = contentType.displayField;
382
-
383
- if (!displayField) {
384
- return defaultTitle;
385
- }
386
-
387
- const displayFieldInfo = contentType.fields.find(field => field.id === displayField);
388
-
389
- if (!displayFieldInfo) {
390
- return defaultTitle;
391
- } // when localization for a field is "turned off",
392
- // we don't clean up the "old" localized data, so it is still in the response.
393
- // Therefore, we're checking if displayField is localizable.
394
-
395
-
396
- if (displayFieldInfo.localized) {
397
- title = getFieldValue({
398
- entity: entry,
399
- fieldId: displayField,
400
- localeCode,
401
- defaultLocaleCode
402
- });
403
-
404
- if (!title) {
405
- // Older content types may return id/apiName, but some entry lookup paths do not fetch raw data
406
- // In order to still return a title in this case, look for displayField as apiName in content type,
407
- // ...but still look for displayField as a field in the entry
408
- title = getFieldValue({
409
- entity: entry,
410
- fieldId: displayFieldInfo.id,
411
- localeCode,
412
- defaultLocaleCode
413
- });
414
- }
415
- } else {
416
- title = getFieldValue({
417
- entity: entry,
418
- fieldId: displayField,
419
- defaultLocaleCode,
420
- localeCode: ''
421
- });
422
-
423
- if (!title) {
424
- title = getFieldValue({
425
- entity: entry,
426
- fieldId: displayFieldInfo.id,
427
- defaultLocaleCode,
428
- localeCode: ''
429
- });
430
- }
431
- }
432
-
433
- return titleOrDefault(title, defaultTitle);
434
- }
435
- function getEntryStatus(sys) {
436
- if (!sys || sys.type !== 'Entry' && sys.type !== 'Asset') {
437
- throw new TypeError('Invalid entity metadata object');
438
- }
439
-
440
- if (sys.deletedVersion) {
441
- return 'deleted';
442
- } else if (sys.archivedVersion) {
443
- return 'archived';
444
- } else if (sys.publishedVersion) {
445
- if (sys.version > sys.publishedVersion + 1) {
446
- return 'changed';
447
- } else {
448
- return 'published';
449
- }
450
- } else {
451
- return 'draft';
452
- }
453
- }
454
- /**
455
- * Gets a promise resolving with a localized asset image field representing a
456
- * given entities file. The promise may resolve with null.
457
- */
458
-
459
- const getEntryImage = async ({
460
- entry,
461
- contentType,
462
- localeCode
463
- }, getAsset) => {
464
- if (!contentType) {
465
- return null;
466
- }
467
-
468
- const assetLink = contentType.fields.find(isAssetField);
469
-
470
- if (!assetLink) {
471
- return null;
472
- }
473
-
474
- const assetId = get(entry.fields, [assetLink.id, localeCode, 'sys', 'id']);
475
-
476
- if (!assetId) {
477
- return null;
478
- }
479
-
480
- try {
481
- const asset = await getAsset(assetId);
482
- const file = get(asset, ['fields', 'file', localeCode]);
483
- const isImage = Boolean(get(file, ['details', 'image'], false));
484
- return isImage ? file : null;
485
- } catch (e) {
486
- return null;
487
- }
488
- };
489
-
490
- var entityHelpers = {
491
- __proto__: null,
492
- getFieldValue: getFieldValue,
493
- getAssetTitle: getAssetTitle,
494
- isAssetField: isAssetField,
495
- isDisplayField: isDisplayField,
496
- isDescriptionField: isDescriptionField,
497
- getEntityDescription: getEntityDescription,
498
- getEntryTitle: getEntryTitle,
499
- getEntryStatus: getEntryStatus,
500
- getEntryImage: getEntryImage
501
- };
502
-
503
- /* eslint-disable @typescript-eslint/no-explicit-any */
504
- function fromFieldValidations(validations = [], fieldType) {
505
- const sizeValidation = validations.find(v => 'size' in v);
506
- const size = sizeValidation && sizeValidation.size || {};
507
- const min = size.min;
508
- const max = size.max;
509
-
510
- if (isNumber(min) && isNumber(max)) {
511
- return {
512
- type: 'min-max',
513
- min,
514
- max
515
- };
516
- } else if (isNumber(min)) {
517
- return {
518
- type: 'min',
519
- min
520
- };
521
- } else if (isNumber(max)) {
522
- return {
523
- type: 'max',
524
- max
525
- };
526
- } else {
527
- return {
528
- type: 'max',
529
- max: fieldType === 'Symbol' ? 256 : 50000
530
- };
531
- }
532
- }
533
- function makeChecker(constraint) {
534
- return function checkConstraint(length) {
535
- if (constraint.type === 'max') {
536
- return length <= constraint.max;
537
- } else if (constraint.type === 'min') {
538
- return length >= constraint.min;
539
- } else {
540
- return length >= constraint.min && length <= constraint.max;
541
- }
542
- };
543
- }
544
-
545
- var constraints = {
546
- __proto__: null,
547
- fromFieldValidations: fromFieldValidations,
548
- makeChecker: makeChecker
549
- };
550
-
551
- /**
552
- * Checks whether the passed content type matches one of our valid MIME types
553
- */
554
- function isValidImage(file) {
555
- const validMimeTypes = ['image/avif', 'image/bmp', 'image/x-windows-bmp', 'image/gif', 'image/webp', // This is not a valid MIME type but we supported it in the past.
556
- 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/x-jps', 'image/png', 'image/svg+xml'];
557
- return validMimeTypes.includes(file.contentType);
558
- }
559
-
560
- /**
561
- * Transforms a number into a localized string (en-US)
562
- * toLocaleString(1000); // "1,000"
563
- * @param {Number} number
564
- */
565
- function toLocaleString(number) {
566
- return number.toLocaleString('en-US');
567
- }
568
-
569
- function formatFloat(value, localize) {
570
- return localize ? toLocaleString(value) : value.toFixed(2) // remove floating point if not necessary
571
- .replace(/\.(0)*$|0*$/, '');
572
- }
573
- /**
574
- * Make a storage unit number more readable by making them smaller
575
- * shortenStorageUnit(1000, 'GB'); // "1 TB"
576
- * shortenStorageUnit(0.001, 'TB'); // "1 GB"
577
- * @param value
578
- * @param uom Unit of measure
579
- * @returns
580
- */
581
-
582
-
583
- function shortenStorageUnit(value, uom) {
584
- if (value <= 0) {
585
- return '0 B';
586
- }
587
-
588
- const units = ['PB', 'TB', 'GB', 'MB', 'KB', 'B'];
589
-
590
- const getBigger = unit => units[units.indexOf(unit) - 1];
591
-
592
- const getSmaller = unit => units[units.indexOf(unit) + 1];
593
-
594
- const isBiggestUnit = unit => units.indexOf(unit) === 0;
595
-
596
- const isSmallestUnit = unit => units.indexOf(unit) === units.length - 1;
597
-
598
- const reduce = (number, unit) => {
599
- if (number < 0.99 && !isSmallestUnit(unit)) {
600
- return reduce(number * 1000, getSmaller(unit));
601
- } else if (number >= 1000 && !isBiggestUnit(unit)) {
602
- return reduce(number / 1000, getBigger(unit));
603
- } else {
604
- return {
605
- number,
606
- unit
607
- };
608
- }
609
- };
610
-
611
- const {
612
- number,
613
- unit
614
- } = reduce(value, uom);
615
- return `${formatFloat(number, false)} ${unit}`;
616
- }
617
-
618
- export { CharCounter, CharValidation, constraints as ConstraintsUtils, FieldConnector, ModalDialogLauncher$1 as ModalDialogLauncher, PredefinedValuesError, entityHelpers, isValidImage, shortenStorageUnit, toLocaleString };
619
- //# sourceMappingURL=field-editor-shared.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"field-editor-shared.esm.js","sources":["../src/FieldConnector.ts","../src/PredefinedValuesError.tsx","../src/CharCounter.tsx","../src/CharValidation.tsx","../src/ModalDialogLauncher.tsx","../src/utils/entityHelpers.ts","../src/utils/constraints.ts","../src/utils/isValidImage.ts","../src/utils/shortenStorageUnit.ts"],"sourcesContent":["import React from 'react';\n\nimport { FieldAPI, ValidationError } from '@contentful/app-sdk';\nimport isEqual from 'lodash/isEqual';\nimport throttle from 'lodash/throttle';\n\ntype Nullable = null | undefined;\n\nexport interface FieldConnectorChildProps<ValueType> {\n isLocalValueChange: boolean;\n externalReset: number;\n lastRemoteValue: ValueType | Nullable;\n value: ValueType | Nullable;\n disabled: boolean;\n errors: ValidationError[];\n setValue: (value: ValueType | Nullable) => Promise<unknown>;\n}\n\ninterface FieldConnectorState<ValueType> {\n isLocalValueChange: boolean;\n externalReset: number;\n lastRemoteValue: ValueType | Nullable;\n value: ValueType | Nullable;\n disabled: boolean;\n errors: ValidationError[];\n}\n\ninterface FieldConnectorProps<ValueType> {\n field: FieldAPI;\n isInitiallyDisabled: boolean;\n isDisabled?: boolean;\n children: (state: FieldConnectorChildProps<ValueType>) => React.ReactNode;\n isEmptyValue: (value: ValueType | null) => boolean;\n isEqualValues: (value1: ValueType | Nullable, value2: ValueType | Nullable) => boolean;\n throttle: number;\n}\n\nexport class FieldConnector<ValueType> extends React.Component<\n FieldConnectorProps<ValueType>,\n FieldConnectorState<ValueType>\n> {\n static defaultProps = {\n children: () => {\n return null;\n },\n // eslint-disable-next-line -- TODO: describe this disable\n isEmptyValue: (value: any | Nullable) => {\n return value === null || value === '';\n },\n // eslint-disable-next-line -- TODO: describe this disable\n isEqualValues: (value1: any | Nullable, value2: any | Nullable) => {\n return isEqual(value1, value2);\n },\n throttle: 300,\n };\n\n constructor(props: FieldConnectorProps<ValueType>) {\n super(props);\n const initialValue = props.field.getValue();\n this.state = {\n isLocalValueChange: false,\n externalReset: 0,\n value: initialValue,\n lastRemoteValue: initialValue,\n disabled: props.isInitiallyDisabled ?? false,\n errors: [],\n };\n }\n\n unsubscribeErrors: Function | null = null;\n unsubscribeDisabled: Function | null = null;\n unsubscribeValue: Function | null = null;\n\n setValue = async (value: ValueType | Nullable) => {\n if (this.props.isEmptyValue(value ?? null)) {\n this.setState({ value: undefined });\n } else {\n this.setState({ value });\n }\n\n await this.triggerSetValueCallbacks(value);\n };\n\n triggerSetValueCallbacks = throttle(\n (value: ValueType | Nullable) => {\n return new Promise((resolve, reject) => {\n if (this.props.isEmptyValue(value ?? null)) {\n this.props.field.removeValue().then(resolve).catch(reject);\n } else {\n this.props.field.setValue(value).then(resolve).catch(reject);\n }\n });\n },\n this.props.throttle,\n {\n leading: this.props.throttle === 0,\n }\n );\n\n componentDidMount() {\n const { field } = this.props;\n this.unsubscribeErrors = field.onSchemaErrorsChanged((errors: ValidationError[]) => {\n this.setState({\n errors: errors || [],\n });\n });\n this.unsubscribeDisabled = field.onIsDisabledChanged((disabled: boolean) => {\n this.setState({\n disabled,\n });\n });\n this.unsubscribeValue = field.onValueChanged((value: ValueType | Nullable) => {\n this.setState((currentState) => {\n const isLocalValueChange = this.props.isEqualValues(value, currentState.value);\n const lastRemoteValue = isLocalValueChange ? currentState.lastRemoteValue : value;\n const externalReset = currentState.externalReset + (isLocalValueChange ? 0 : 1);\n return {\n value,\n lastRemoteValue,\n isLocalValueChange,\n externalReset,\n };\n });\n });\n }\n\n componentWillUnmount() {\n if (typeof this.unsubscribeErrors === 'function') {\n this.unsubscribeErrors();\n }\n if (typeof this.unsubscribeDisabled === 'function') {\n this.unsubscribeDisabled();\n }\n if (typeof this.unsubscribeValue === 'function') {\n this.unsubscribeValue();\n }\n }\n\n render() {\n return this.props.children({\n ...this.state,\n setValue: this.setValue,\n disabled: this.props.isDisabled || this.state.disabled,\n });\n }\n}\n","import React from 'react';\n\nimport { Note } from '@contentful/f36-note';\n\nexport function PredefinedValuesError() {\n return (\n <Note variant=\"warning\" testId=\"predefined-values-warning\">\n The widget failed to initialize. You can fix the problem by providing predefined values under\n the validations tab in the field settings.\n </Note>\n );\n}\n","import React from 'react';\n\nimport tokens from '@contentful/f36-tokens';\nimport { css, cx } from 'emotion';\n\ninterface CharCounterProps {\n value?: string;\n checkConstraint: (n: number) => boolean;\n}\n\nconst styles = {\n invalid: css({\n color: tokens.red600,\n }),\n};\n\nexport function CharCounter(props: CharCounterProps) {\n let count = 0;\n if (props.value) {\n count = props.value.length;\n }\n const valid = count === 0 || props.checkConstraint(count);\n return (\n <span\n data-status-code={valid ? null : 'invalid-size'}\n className={cx({\n [styles.invalid]: !valid,\n })}>\n {count} characters\n </span>\n );\n}\n","import React from 'react';\n\nimport { ValidationType } from './types';\n\ninterface CharValidationProps {\n constraints: ValidationType;\n}\n\nexport function CharValidation(props: CharValidationProps) {\n const { constraints } = props;\n\n if (constraints.type === 'max') {\n return <span>Maximum {constraints.max} characters</span>;\n } else if (constraints.type === 'min') {\n return <span>Requires at least {constraints.min} characters</span>;\n } else {\n return (\n <span>\n Requires between {constraints.min} and {constraints.max} characters\n </span>\n );\n }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-use-before-define */\n\nimport React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport { OpenCustomWidgetOptions } from '@contentful/app-sdk';\nimport { Modal, ModalHeader } from '@contentful/f36-components';\nimport isNumber from 'lodash/isNumber';\n\nexport function open(componentRenderer: (params: { onClose: Function; isShown: boolean }) => any) {\n let rootDom: any = null;\n\n const getRoot = () => {\n if (rootDom === null) {\n rootDom = document.createElement('div');\n rootDom.setAttribute('id', 'field-editor-modal-root');\n document.body.appendChild(rootDom);\n }\n return rootDom;\n };\n\n return new Promise((resolve) => {\n let currentConfig = { onClose, isShown: true };\n\n function render({ onClose, isShown }: { onClose: Function; isShown: boolean }) {\n ReactDOM.render(componentRenderer({ onClose, isShown }), getRoot());\n }\n\n function onClose(...args: any[]) {\n currentConfig = {\n ...currentConfig,\n isShown: false,\n };\n render(currentConfig);\n // eslint-disable-next-line -- TODO: describe this disable @typescript-eslint/ban-ts-comment\n // @ts-ignore\n resolve(...args);\n getRoot().remove();\n }\n\n render(currentConfig);\n });\n}\n\nexport function openDialog<T>(\n options: OpenCustomWidgetOptions,\n Component: React.SFC<{ onClose: (result: T) => void }>\n) {\n const key = Date.now();\n const size = isNumber(options.width) ? `${options.width}px` : options.width;\n return open(({ isShown, onClose }) => {\n const onCloseHandler = () => onClose();\n return (\n <Modal\n key={key}\n shouldCloseOnOverlayClick={options.shouldCloseOnOverlayClick || false}\n shouldCloseOnEscapePress={options.shouldCloseOnEscapePress || false}\n allowHeightOverflow={options.allowHeightOverflow || false}\n position={options.position || 'center'}\n isShown={isShown}\n onClose={onCloseHandler}\n size={size || '700px'}>\n {() => (\n <>\n {options.title && (\n <ModalHeader testId=\"dialog-title\" title={options.title} onClose={onCloseHandler} />\n )}\n <div style={{ minHeight: options.minHeight || 'auto' }}>\n <Component onClose={onClose as any} />\n </div>\n </>\n )}\n </Modal>\n );\n });\n}\n\nexport default {\n openDialog,\n};\n","import get from 'lodash/get';\nimport isObject from 'lodash/isObject';\nimport isString from 'lodash/isString';\n\nimport { Asset, ContentType, ContentTypeField, Entry, File } from '../typesEntity';\n\nfunction titleOrDefault(title: string | undefined, defaultTitle: string): string {\n if (!isString(title)) {\n return defaultTitle;\n }\n if (title) {\n const trimmedTitle = title.trim();\n if (trimmedTitle.length === 0) {\n return defaultTitle;\n }\n return trimmedTitle;\n }\n return defaultTitle;\n}\n\nexport function getFieldValue({\n /**\n * Expects an entity fetched with a flag Skip-Transformation: true\n */\n entity,\n fieldId,\n localeCode,\n defaultLocaleCode,\n}: {\n entity: {\n fields: { [key: string]: { [valueKey: string]: string | undefined } };\n };\n fieldId: string;\n localeCode: string;\n defaultLocaleCode: string;\n}): string | undefined {\n const values = get(entity, ['fields', fieldId]);\n if (!isObject(values)) {\n return;\n }\n\n const firstLocaleCode = Object.keys(values)[0];\n\n return values[localeCode] || values[defaultLocaleCode] || values[firstLocaleCode];\n}\n\nexport function getAssetTitle({\n asset,\n localeCode,\n defaultLocaleCode,\n defaultTitle,\n}: {\n asset: Asset;\n localeCode: string;\n defaultLocaleCode: string;\n defaultTitle: string;\n}) {\n const title = getFieldValue({\n entity: { fields: { title: asset.fields?.title } },\n fieldId: 'title',\n localeCode,\n defaultLocaleCode,\n });\n return titleOrDefault(title, defaultTitle);\n}\n\n/**\n * Returns true if field is an Asset\n *\n * @param field\n * @returns {boolean}\n */\nexport const isAssetField = (field: ContentTypeField): boolean =>\n field.type === 'Link' && field.linkType === 'Asset';\n\n/**\n * Returns true if field is a Title\n */\nexport function isDisplayField({\n field,\n contentType,\n}: {\n field: ContentTypeField;\n contentType: ContentType;\n}): boolean {\n return field.id === contentType.displayField;\n}\n\n/**\n * Returns true if field is a short Description\n */\nexport function isDescriptionField({\n field,\n contentType,\n}: {\n field: ContentTypeField;\n contentType: ContentType;\n}) {\n const isTextField = (field: ContentTypeField) => ['Symbol', 'Text'].includes(field.type);\n const isMaybeSlugField = (field: ContentTypeField) => /\\bslug\\b/.test(field.name);\n return isTextField(field) && !isDisplayField({ field, contentType }) && !isMaybeSlugField(field);\n}\n\nexport function getEntityDescription({\n entity,\n contentType,\n localeCode,\n defaultLocaleCode,\n}: {\n entity: Entry;\n contentType?: ContentType;\n localeCode: string;\n defaultLocaleCode: string;\n}): string {\n if (!contentType) {\n return '';\n }\n\n const descriptionField = contentType.fields.find((field) =>\n isDescriptionField({ field, contentType })\n );\n\n if (!descriptionField) {\n return '';\n }\n\n return (\n getFieldValue({ entity, fieldId: descriptionField.id, localeCode, defaultLocaleCode }) || ''\n );\n}\n\nexport function getEntryTitle({\n entry,\n contentType,\n localeCode,\n defaultLocaleCode,\n defaultTitle,\n}: {\n entry: Entry;\n contentType?: ContentType;\n localeCode: string;\n defaultLocaleCode: string;\n defaultTitle: string;\n}) {\n let title;\n\n if (!contentType) {\n return defaultTitle;\n }\n\n const displayField = contentType.displayField;\n if (!displayField) {\n return defaultTitle;\n }\n\n const displayFieldInfo = contentType.fields.find((field) => field.id === displayField);\n\n if (!displayFieldInfo) {\n return defaultTitle;\n }\n\n // when localization for a field is \"turned off\",\n // we don't clean up the \"old\" localized data, so it is still in the response.\n // Therefore, we're checking if displayField is localizable.\n if (displayFieldInfo.localized) {\n title = getFieldValue({\n entity: entry,\n fieldId: displayField,\n localeCode,\n defaultLocaleCode,\n });\n if (!title) {\n // Older content types may return id/apiName, but some entry lookup paths do not fetch raw data\n // In order to still return a title in this case, look for displayField as apiName in content type,\n // ...but still look for displayField as a field in the entry\n title = getFieldValue({\n entity: entry,\n fieldId: displayFieldInfo.id,\n localeCode,\n defaultLocaleCode,\n });\n }\n } else {\n title = getFieldValue({\n entity: entry,\n fieldId: displayField,\n defaultLocaleCode,\n localeCode: '',\n });\n if (!title) {\n title = getFieldValue({\n entity: entry,\n fieldId: displayFieldInfo.id,\n defaultLocaleCode,\n localeCode: '',\n });\n }\n }\n\n return titleOrDefault(title, defaultTitle);\n}\n\nexport function getEntryStatus(sys: Entry['sys']) {\n if (!sys || (sys.type !== 'Entry' && sys.type !== 'Asset')) {\n throw new TypeError('Invalid entity metadata object');\n }\n if (sys.deletedVersion) {\n return 'deleted';\n } else if (sys.archivedVersion) {\n return 'archived';\n } else if (sys.publishedVersion) {\n if (sys.version > sys.publishedVersion + 1) {\n return 'changed';\n } else {\n return 'published';\n }\n } else {\n return 'draft';\n }\n}\n\n/**\n * Gets a promise resolving with a localized asset image field representing a\n * given entities file. The promise may resolve with null.\n */\nexport const getEntryImage = async (\n {\n entry,\n contentType,\n localeCode,\n }: {\n entry: Entry;\n contentType?: ContentType;\n localeCode: string;\n defaultLocaleCode: string;\n },\n getAsset: (assetId: string) => Promise<unknown>\n): Promise<null | File> => {\n if (!contentType) {\n return null;\n }\n\n const assetLink = contentType.fields.find(isAssetField);\n\n if (!assetLink) {\n return null;\n }\n\n const assetId = get(entry.fields, [assetLink.id, localeCode, 'sys', 'id']);\n\n if (!assetId) {\n return null;\n }\n\n try {\n const asset = await getAsset(assetId);\n const file = get(asset, ['fields', 'file', localeCode]);\n const isImage = Boolean(get(file, ['details', 'image'], false));\n return isImage ? file : null;\n } catch (e) {\n return null;\n }\n};\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\n/**\n * This module parses field validations as a constraint and checks\n * values against that constraint.\n */\n\nimport isNumber from 'lodash/isNumber';\n\nimport { ValidationType } from '../types';\n\nexport function fromFieldValidations(\n validations: Record<string, any>[] = [],\n fieldType: 'Symbol' | 'Text'\n): ValidationType {\n const sizeValidation = validations.find((v) => 'size' in v);\n const size = (sizeValidation && sizeValidation.size) || {};\n const min = size.min;\n const max = size.max;\n\n if (isNumber(min) && isNumber(max)) {\n return {\n type: 'min-max',\n min,\n max,\n };\n } else if (isNumber(min)) {\n return {\n type: 'min',\n min,\n };\n } else if (isNumber(max)) {\n return {\n type: 'max',\n max,\n };\n } else {\n return {\n type: 'max',\n max: fieldType === 'Symbol' ? 256 : 50000,\n };\n }\n}\n\nexport function makeChecker(constraint: ValidationType) {\n return function checkConstraint(length: number) {\n if (constraint.type === 'max') {\n return length <= constraint.max;\n } else if (constraint.type === 'min') {\n return length >= constraint.min;\n } else {\n return length >= constraint.min && length <= constraint.max;\n }\n };\n}\n","import { File } from '../typesEntity';\n\n/**\n * Checks whether the passed content type matches one of our valid MIME types\n */\nexport function isValidImage(file: File) {\n const validMimeTypes = [\n 'image/avif',\n 'image/bmp',\n 'image/x-windows-bmp',\n 'image/gif',\n 'image/webp',\n // This is not a valid MIME type but we supported it in the past.\n 'image/jpg',\n 'image/jpeg',\n 'image/pjpeg',\n 'image/x-jps',\n 'image/png',\n 'image/svg+xml',\n ];\n\n return validMimeTypes.includes(file.contentType);\n}\n","/**\n * Transforms a number into a localized string (en-US)\n * toLocaleString(1000); // \"1,000\"\n * @param {Number} number\n */\nexport function toLocaleString(number: number) {\n return number.toLocaleString('en-US');\n}\n\nfunction formatFloat(value: number, localize: boolean) {\n return localize\n ? toLocaleString(value)\n : value\n .toFixed(2)\n // remove floating point if not necessary\n .replace(/\\.(0)*$|0*$/, '');\n}\n\ntype UnitOfMeasure = 'PB' | 'TB' | 'GB' | 'MB' | 'KB' | 'B';\n\n/**\n * Make a storage unit number more readable by making them smaller\n * shortenStorageUnit(1000, 'GB'); // \"1 TB\"\n * shortenStorageUnit(0.001, 'TB'); // \"1 GB\"\n * @param value\n * @param uom Unit of measure\n * @returns\n */\nexport function shortenStorageUnit(value: number, uom: UnitOfMeasure) {\n if (value <= 0) {\n return '0 B';\n }\n\n const units: UnitOfMeasure[] = ['PB', 'TB', 'GB', 'MB', 'KB', 'B'];\n\n const getBigger = (unit: UnitOfMeasure): UnitOfMeasure => units[units.indexOf(unit) - 1];\n const getSmaller = (unit: UnitOfMeasure) => units[units.indexOf(unit) + 1];\n const isBiggestUnit = (unit: UnitOfMeasure) => units.indexOf(unit) === 0;\n const isSmallestUnit = (unit: UnitOfMeasure) => units.indexOf(unit) === units.length - 1;\n\n const reduce = (number: number, unit: UnitOfMeasure): { number: number; unit: UnitOfMeasure } => {\n if (number < 0.99 && !isSmallestUnit(unit)) {\n return reduce(number * 1000, getSmaller(unit));\n } else if (number >= 1000 && !isBiggestUnit(unit)) {\n return reduce(number / 1000, getBigger(unit));\n } else {\n return { number, unit };\n }\n };\n\n const { number, unit } = reduce(value, uom);\n\n return `${formatFloat(number, false)} ${unit}`;\n}\n"],"names":["FieldConnector","React","Component","constructor","props","unsubscribeErrors","unsubscribeDisabled","unsubscribeValue","setValue","value","isEmptyValue","setState","undefined","triggerSetValueCallbacks","throttle","Promise","resolve","reject","field","removeValue","then","catch","leading","initialValue","getValue","state","isLocalValueChange","externalReset","lastRemoteValue","disabled","isInitiallyDisabled","errors","componentDidMount","onSchemaErrorsChanged","onIsDisabledChanged","onValueChanged","currentState","isEqualValues","componentWillUnmount","render","children","isDisabled","defaultProps","value1","value2","isEqual","PredefinedValuesError","Note","variant","testId","styles","invalid","css","color","tokens","red600","CharCounter","count","length","valid","checkConstraint","className","cx","CharValidation","constraints","type","max","min","open","componentRenderer","rootDom","getRoot","document","createElement","setAttribute","body","appendChild","currentConfig","onClose","isShown","ReactDOM","args","remove","openDialog","options","key","Date","now","size","isNumber","width","onCloseHandler","Modal","shouldCloseOnOverlayClick","shouldCloseOnEscapePress","allowHeightOverflow","position","title","ModalHeader","style","minHeight","titleOrDefault","defaultTitle","isString","trimmedTitle","trim","getFieldValue","entity","fieldId","localeCode","defaultLocaleCode","values","get","isObject","firstLocaleCode","Object","keys","getAssetTitle","asset","fields","isAssetField","linkType","isDisplayField","contentType","id","displayField","isDescriptionField","isTextField","includes","isMaybeSlugField","test","name","getEntityDescription","descriptionField","find","getEntryTitle","entry","displayFieldInfo","localized","getEntryStatus","sys","TypeError","deletedVersion","archivedVersion","publishedVersion","version","getEntryImage","getAsset","assetLink","assetId","file","isImage","Boolean","e","fromFieldValidations","validations","fieldType","sizeValidation","v","makeChecker","constraint","isValidImage","validMimeTypes","toLocaleString","number","formatFloat","localize","toFixed","replace","shortenStorageUnit","uom","units","getBigger","unit","indexOf","getSmaller","isBiggestUnit","isSmallestUnit","reduce"],"mappings":"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"}