@contentful/field-editor-shared 0.22.0 → 0.25.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.
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import throttle from 'lodash-es/throttle';
3
2
  import isEqual from 'lodash-es/isEqual';
3
+ import throttle from 'lodash-es/throttle';
4
4
  import { Note, Modal } from '@contentful/forma-36-react-components';
5
5
  import tokens from '@contentful/forma-36-tokens';
6
6
  import { cx, css } from 'emotion';
@@ -67,256 +67,18 @@ function _extends() {
67
67
  function _inheritsLoose(subClass, superClass) {
68
68
  subClass.prototype = Object.create(superClass.prototype);
69
69
  subClass.prototype.constructor = subClass;
70
- subClass.__proto__ = superClass;
71
- }
72
-
73
- var FieldConnector = /*#__PURE__*/function (_React$Component) {
74
- _inheritsLoose(FieldConnector, _React$Component);
75
-
76
- function FieldConnector(props) {
77
- var _this;
78
-
79
- _this = _React$Component.call(this, props) || this;
80
- _this.unsubscribeErrors = null;
81
- _this.unsubscribeDisabled = null;
82
- _this.unsubscribeValue = null;
83
- _this.setValue = throttle(function (value) {
84
- if (_this.props.isEmptyValue(value === undefined ? null : value)) {
85
- return new Promise(function (resolve, reject) {
86
- _this.setState({
87
- lastSetValue: undefined
88
- }, function () {
89
- _this.props.field.removeValue().then(resolve)["catch"](reject);
90
- });
91
- });
92
- } else {
93
- return new Promise(function (resolve, reject) {
94
- _this.setState({
95
- lastSetValue: value
96
- }, function () {
97
- _this.props.field.setValue(value).then(resolve)["catch"](reject);
98
- });
99
- });
100
- }
101
- }, _this.props.throttle, {
102
- leading: _this.props.throttle === 0
103
- });
104
- var initialValue = props.field.getValue();
105
- _this.state = {
106
- isLocalValueChange: false,
107
- externalReset: 0,
108
- value: initialValue,
109
- lastSetValue: initialValue,
110
- lastRemoteValue: initialValue,
111
- disabled: props.isInitiallyDisabled,
112
- errors: []
113
- };
114
- return _this;
115
- }
116
-
117
- var _proto = FieldConnector.prototype;
118
-
119
- _proto.componentDidMount = function componentDidMount() {
120
- var _this2 = this;
121
-
122
- var field = this.props.field;
123
- this.unsubscribeErrors = field.onSchemaErrorsChanged(function (errors) {
124
- _this2.setState({
125
- errors: errors || []
126
- });
127
- });
128
- this.unsubscribeDisabled = field.onIsDisabledChanged(function (disabled) {
129
- _this2.setState({
130
- disabled: disabled
131
- });
132
- });
133
- this.unsubscribeValue = field.onValueChanged(function (value) {
134
- _this2.setState(function (currentState) {
135
- var isLocalValueChange = _this2.props.isEqualValues(value, currentState.lastSetValue);
136
-
137
- var lastRemoteValue = isLocalValueChange ? currentState.lastRemoteValue : value;
138
- var externalReset = currentState.externalReset + (isLocalValueChange ? 0 : 1);
139
- return {
140
- value: value,
141
- lastSetValue: value,
142
- lastRemoteValue: lastRemoteValue,
143
- isLocalValueChange: isLocalValueChange,
144
- externalReset: externalReset
145
- };
146
- });
147
- });
148
- };
149
-
150
- _proto.componentWillUnmount = function componentWillUnmount() {
151
- if (typeof this.unsubscribeErrors === 'function') {
152
- this.unsubscribeErrors();
153
- }
154
-
155
- if (typeof this.unsubscribeDisabled === 'function') {
156
- this.unsubscribeDisabled();
157
- }
158
-
159
- if (typeof this.unsubscribeValue === 'function') {
160
- this.unsubscribeValue();
161
- }
162
- };
163
-
164
- _proto.render = function render() {
165
- var childProps = _extends({}, this.state); // `lastSetValue` can be either the `setValue()` value right after it got called
166
- // or the current remote value. No use-case for passing this to child.
167
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
168
- // @ts-ignore
169
-
170
-
171
- delete childProps.lastSetValue;
172
- return this.props.children(_extends({}, childProps, {
173
- // @ts-expect-error
174
- setValue: this.setValue
175
- }));
176
- };
177
-
178
- return FieldConnector;
179
- }(React.Component);
180
- FieldConnector.defaultProps = {
181
- children: function children() {
182
- return null;
183
- },
184
- // eslint-disable-next-line
185
- isEmptyValue: function isEmptyValue(value) {
186
- return value === null || value === '';
187
- },
188
- // eslint-disable-next-line
189
- isEqualValues: function isEqualValues(value1, value2) {
190
- return isEqual(value1, value2);
191
- },
192
- throttle: 300
193
- };
194
-
195
- function PredefinedValuesError() {
196
- return React.createElement(Note, {
197
- noteType: "warning",
198
- testId: "predefined-values-warning"
199
- }, "The widget failed to initialize. You can fix the problem by providing predefined values under the validations tab in the field settings.");
200
- }
201
-
202
- var styles = {
203
- invalid: /*#__PURE__*/css({
204
- color: tokens.red600
205
- })
206
- };
207
- function CharCounter(props) {
208
- var _cx;
209
-
210
- var count = 0;
211
-
212
- if (props.value) {
213
- count = props.value.length;
214
- }
215
70
 
216
- var valid = count === 0 || props.checkConstraint(count);
217
- return React.createElement("span", {
218
- "data-status-code": valid ? null : 'invalid-size',
219
- className: cx((_cx = {}, _cx[styles.invalid] = !valid, _cx))
220
- }, count, " characters");
71
+ _setPrototypeOf(subClass, superClass);
221
72
  }
222
73
 
223
- function CharValidation(props) {
224
- var constraints = props.constraints;
225
-
226
- if (constraints.type === 'max') {
227
- return React.createElement("span", null, "Maximum ", constraints.max, " characters");
228
- } else if (constraints.type === 'min') {
229
- return React.createElement("span", null, "Requires at least ", constraints.min, " characters");
230
- } else {
231
- return React.createElement("span", null, "Requires between ", constraints.min, " and ", constraints.max, " characters");
232
- }
233
- }
234
-
235
- function open(componentRenderer) {
236
- var rootDom = null;
237
-
238
- var getRoot = function getRoot() {
239
- if (rootDom === null) {
240
- rootDom = document.createElement('div');
241
- rootDom.setAttribute('id', 'field-editor-modal-root');
242
- document.body.appendChild(rootDom);
243
- }
244
-
245
- return rootDom;
74
+ function _setPrototypeOf(o, p) {
75
+ _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
76
+ o.__proto__ = p;
77
+ return o;
246
78
  };
247
79
 
248
- return new Promise(function (resolve) {
249
- var currentConfig = {
250
- onClose: onClose,
251
- isShown: true
252
- };
253
-
254
- function render(_ref) {
255
- var onClose = _ref.onClose,
256
- isShown = _ref.isShown;
257
- ReactDOM.render(componentRenderer({
258
- onClose: onClose,
259
- isShown: isShown
260
- }), getRoot());
261
- }
262
-
263
- function onClose() {
264
- currentConfig = _extends({}, currentConfig, {
265
- isShown: false
266
- });
267
- render(currentConfig);
268
- resolve.apply(void 0, arguments);
269
- getRoot().remove();
270
- }
271
-
272
- render(currentConfig);
273
- });
80
+ return _setPrototypeOf(o, p);
274
81
  }
275
- function openDialog(options, Component) {
276
- var key = Date.now();
277
- var size = isNumber(options.width) ? options.width + "px" : options.width;
278
- return open(function (_ref2) {
279
- var isShown = _ref2.isShown,
280
- onClose = _ref2.onClose;
281
-
282
- var onCloseHandler = function onCloseHandler() {
283
- return onClose();
284
- };
285
-
286
- return React.createElement(Modal, {
287
- key: key,
288
- shouldCloseOnOverlayClick: options.shouldCloseOnOverlayClick || false,
289
- shouldCloseOnEscapePress: options.shouldCloseOnEscapePress || false,
290
- allowHeightOverflow: options.allowHeightOverflow || false,
291
- position: options.position || 'center',
292
- isShown: isShown,
293
- onClose: onCloseHandler,
294
- size: size || '700px'
295
- }, function () {
296
- return React.createElement(React.Fragment, null, options.title && React.createElement(Modal.Header, {
297
- testId: "dialog-title",
298
- title: options.title,
299
- onClose: onCloseHandler
300
- }), React.createElement("div", {
301
- style: {
302
- minHeight: options.minHeight || 'auto'
303
- }
304
- }, React.createElement(Component, {
305
- onClose: onClose
306
- })));
307
- });
308
- });
309
- }
310
- var ModalDialogLauncher = {
311
- openDialog: openDialog
312
- };
313
-
314
- var ModalDialogLauncher$1 = {
315
- __proto__: null,
316
- open: open,
317
- openDialog: openDialog,
318
- 'default': ModalDialogLauncher
319
- };
320
82
 
321
83
  function createCommonjsModule(fn, module) {
322
84
  return module = { exports: {} }, fn(module, module.exports), module.exports;
@@ -1046,6 +808,267 @@ var runtime_1 = /*#__PURE__*/createCommonjsModule(function (module) {
1046
808
  }
1047
809
  });
1048
810
 
811
+ var FieldConnector = /*#__PURE__*/function (_React$Component) {
812
+ _inheritsLoose(FieldConnector, _React$Component);
813
+
814
+ function FieldConnector(props) {
815
+ var _this;
816
+
817
+ _this = _React$Component.call(this, props) || this;
818
+ _this.unsubscribeErrors = null;
819
+ _this.unsubscribeDisabled = null;
820
+ _this.unsubscribeValue = null;
821
+
822
+ _this.setValue = /*#__PURE__*/function () {
823
+ var _ref = _asyncToGenerator( /*#__PURE__*/runtime_1.mark(function _callee(value) {
824
+ return runtime_1.wrap(function _callee$(_context) {
825
+ while (1) {
826
+ switch (_context.prev = _context.next) {
827
+ case 0:
828
+ if (_this.props.isEmptyValue(value != null ? value : null)) {
829
+ _this.setState({
830
+ value: undefined
831
+ });
832
+ } else {
833
+ _this.setState({
834
+ value: value
835
+ });
836
+ }
837
+
838
+ _context.next = 3;
839
+ return _this.triggerSetValueCallbacks(value);
840
+
841
+ case 3:
842
+ case "end":
843
+ return _context.stop();
844
+ }
845
+ }
846
+ }, _callee);
847
+ }));
848
+
849
+ return function (_x) {
850
+ return _ref.apply(this, arguments);
851
+ };
852
+ }();
853
+
854
+ _this.triggerSetValueCallbacks = throttle(function (value) {
855
+ return new Promise(function (resolve, reject) {
856
+ if (_this.props.isEmptyValue(value != null ? value : null)) {
857
+ _this.props.field.removeValue().then(resolve)["catch"](reject);
858
+ } else {
859
+ _this.props.field.setValue(value).then(resolve)["catch"](reject);
860
+ }
861
+ });
862
+ }, _this.props.throttle, {
863
+ leading: _this.props.throttle === 0
864
+ });
865
+ var initialValue = props.field.getValue();
866
+ _this.state = {
867
+ isLocalValueChange: false,
868
+ externalReset: 0,
869
+ value: initialValue,
870
+ lastRemoteValue: initialValue,
871
+ disabled: props.isInitiallyDisabled,
872
+ errors: []
873
+ };
874
+ return _this;
875
+ }
876
+
877
+ var _proto = FieldConnector.prototype;
878
+
879
+ _proto.componentDidMount = function componentDidMount() {
880
+ var _this2 = this;
881
+
882
+ var field = this.props.field;
883
+ this.unsubscribeErrors = field.onSchemaErrorsChanged(function (errors) {
884
+ _this2.setState({
885
+ errors: errors || []
886
+ });
887
+ });
888
+ this.unsubscribeDisabled = field.onIsDisabledChanged(function (disabled) {
889
+ _this2.setState({
890
+ disabled: disabled
891
+ });
892
+ });
893
+ this.unsubscribeValue = field.onValueChanged(function (value) {
894
+ _this2.setState(function (currentState) {
895
+ var isLocalValueChange = _this2.props.isEqualValues(value, currentState.value);
896
+
897
+ var lastRemoteValue = isLocalValueChange ? currentState.lastRemoteValue : value;
898
+ var externalReset = currentState.externalReset + (isLocalValueChange ? 0 : 1);
899
+ return {
900
+ value: value,
901
+ lastRemoteValue: lastRemoteValue,
902
+ isLocalValueChange: isLocalValueChange,
903
+ externalReset: externalReset
904
+ };
905
+ });
906
+ });
907
+ };
908
+
909
+ _proto.componentWillUnmount = function componentWillUnmount() {
910
+ if (typeof this.unsubscribeErrors === 'function') {
911
+ this.unsubscribeErrors();
912
+ }
913
+
914
+ if (typeof this.unsubscribeDisabled === 'function') {
915
+ this.unsubscribeDisabled();
916
+ }
917
+
918
+ if (typeof this.unsubscribeValue === 'function') {
919
+ this.unsubscribeValue();
920
+ }
921
+ };
922
+
923
+ _proto.render = function render() {
924
+ return this.props.children(_extends({}, this.state, {
925
+ setValue: this.setValue
926
+ }));
927
+ };
928
+
929
+ return FieldConnector;
930
+ }(React.Component);
931
+ FieldConnector.defaultProps = {
932
+ children: function children() {
933
+ return null;
934
+ },
935
+ // eslint-disable-next-line
936
+ isEmptyValue: function isEmptyValue(value) {
937
+ return value === null || value === '';
938
+ },
939
+ // eslint-disable-next-line
940
+ isEqualValues: function isEqualValues(value1, value2) {
941
+ return isEqual(value1, value2);
942
+ },
943
+ throttle: 300
944
+ };
945
+
946
+ function PredefinedValuesError() {
947
+ return React.createElement(Note, {
948
+ noteType: "warning",
949
+ testId: "predefined-values-warning"
950
+ }, "The widget failed to initialize. You can fix the problem by providing predefined values under the validations tab in the field settings.");
951
+ }
952
+
953
+ var styles = {
954
+ invalid: /*#__PURE__*/css({
955
+ color: tokens.red600
956
+ })
957
+ };
958
+ function CharCounter(props) {
959
+ var _cx;
960
+
961
+ var count = 0;
962
+
963
+ if (props.value) {
964
+ count = props.value.length;
965
+ }
966
+
967
+ var valid = count === 0 || props.checkConstraint(count);
968
+ return React.createElement("span", {
969
+ "data-status-code": valid ? null : 'invalid-size',
970
+ className: cx((_cx = {}, _cx[styles.invalid] = !valid, _cx))
971
+ }, count, " characters");
972
+ }
973
+
974
+ function CharValidation(props) {
975
+ var constraints = props.constraints;
976
+
977
+ if (constraints.type === 'max') {
978
+ return React.createElement("span", null, "Maximum ", constraints.max, " characters");
979
+ } else if (constraints.type === 'min') {
980
+ return React.createElement("span", null, "Requires at least ", constraints.min, " characters");
981
+ } else {
982
+ return React.createElement("span", null, "Requires between ", constraints.min, " and ", constraints.max, " characters");
983
+ }
984
+ }
985
+
986
+ function open(componentRenderer) {
987
+ var rootDom = null;
988
+
989
+ var getRoot = function getRoot() {
990
+ if (rootDom === null) {
991
+ rootDom = document.createElement('div');
992
+ rootDom.setAttribute('id', 'field-editor-modal-root');
993
+ document.body.appendChild(rootDom);
994
+ }
995
+
996
+ return rootDom;
997
+ };
998
+
999
+ return new Promise(function (resolve) {
1000
+ var currentConfig = {
1001
+ onClose: onClose,
1002
+ isShown: true
1003
+ };
1004
+
1005
+ function render(_ref) {
1006
+ var onClose = _ref.onClose,
1007
+ isShown = _ref.isShown;
1008
+ ReactDOM.render(componentRenderer({
1009
+ onClose: onClose,
1010
+ isShown: isShown
1011
+ }), getRoot());
1012
+ }
1013
+
1014
+ function onClose() {
1015
+ currentConfig = _extends({}, currentConfig, {
1016
+ isShown: false
1017
+ });
1018
+ render(currentConfig);
1019
+ resolve.apply(void 0, arguments);
1020
+ getRoot().remove();
1021
+ }
1022
+
1023
+ render(currentConfig);
1024
+ });
1025
+ }
1026
+ function openDialog(options, Component) {
1027
+ var key = Date.now();
1028
+ var size = isNumber(options.width) ? options.width + "px" : options.width;
1029
+ return open(function (_ref2) {
1030
+ var isShown = _ref2.isShown,
1031
+ onClose = _ref2.onClose;
1032
+
1033
+ var onCloseHandler = function onCloseHandler() {
1034
+ return onClose();
1035
+ };
1036
+
1037
+ return React.createElement(Modal, {
1038
+ key: key,
1039
+ shouldCloseOnOverlayClick: options.shouldCloseOnOverlayClick || false,
1040
+ shouldCloseOnEscapePress: options.shouldCloseOnEscapePress || false,
1041
+ allowHeightOverflow: options.allowHeightOverflow || false,
1042
+ position: options.position || 'center',
1043
+ isShown: isShown,
1044
+ onClose: onCloseHandler,
1045
+ size: size || '700px'
1046
+ }, function () {
1047
+ return React.createElement(React.Fragment, null, options.title && React.createElement(Modal.Header, {
1048
+ testId: "dialog-title",
1049
+ title: options.title,
1050
+ onClose: onCloseHandler
1051
+ }), React.createElement("div", {
1052
+ style: {
1053
+ minHeight: options.minHeight || 'auto'
1054
+ }
1055
+ }, React.createElement(Component, {
1056
+ onClose: onClose
1057
+ })));
1058
+ });
1059
+ });
1060
+ }
1061
+ var ModalDialogLauncher = {
1062
+ openDialog: openDialog
1063
+ };
1064
+
1065
+ var ModalDialogLauncher$1 = {
1066
+ __proto__: null,
1067
+ open: open,
1068
+ openDialog: openDialog,
1069
+ 'default': ModalDialogLauncher
1070
+ };
1071
+
1049
1072
  function titleOrDefault(title, defaultTitle) {
1050
1073
  if (!isString(title)) {
1051
1074
  return defaultTitle;
@@ -1353,5 +1376,80 @@ var constraints = {
1353
1376
  makeChecker: makeChecker
1354
1377
  };
1355
1378
 
1356
- export { CharCounter, CharValidation, constraints as ConstraintsUtils, FieldConnector, ModalDialogLauncher$1 as ModalDialogLauncher, PredefinedValuesError, entityHelpers };
1379
+ /**
1380
+ * Checks whether the passed content type matches one of our valid MIME types
1381
+ */
1382
+ function isValidImage(file) {
1383
+ var validMimeTypes = ['image/bmp', 'image/x-windows-bmp', 'image/gif', 'image/webp', // This is not a valid MIME type but we supported it in the past.
1384
+ 'image/jpg', 'image/jpeg', 'image/pjpeg', 'image/x-jps', 'image/png', 'image/svg+xml'];
1385
+ return validMimeTypes.includes(file.contentType);
1386
+ }
1387
+
1388
+ /**
1389
+ * Transforms a number into a localized string (en-US)
1390
+ * toLocaleString(1000); // "1,000"
1391
+ * @param {Number} number
1392
+ */
1393
+ function toLocaleString(number) {
1394
+ return number.toLocaleString('en-US');
1395
+ }
1396
+
1397
+ function formatFloat(value, localize) {
1398
+ return localize ? toLocaleString(value) : value.toFixed(2) // remove floating point if not necessary
1399
+ .replace(/\.(0)*$|0*$/, '');
1400
+ }
1401
+ /**
1402
+ * Make a storage unit number more readable by making them smaller
1403
+ * shortenStorageUnit(1000, 'GB'); // "1 TB"
1404
+ * shortenStorageUnit(0.001, 'TB'); // "1 GB"
1405
+ * @param value
1406
+ * @param uom Unit of measure
1407
+ * @returns
1408
+ */
1409
+
1410
+
1411
+ function shortenStorageUnit(value, uom) {
1412
+ if (value <= 0) {
1413
+ return '0 B';
1414
+ }
1415
+
1416
+ var units = ['PB', 'TB', 'GB', 'MB', 'KB', 'B'];
1417
+
1418
+ var getBigger = function getBigger(unit) {
1419
+ return units[units.indexOf(unit) - 1];
1420
+ };
1421
+
1422
+ var getSmaller = function getSmaller(unit) {
1423
+ return units[units.indexOf(unit) + 1];
1424
+ };
1425
+
1426
+ var isBiggestUnit = function isBiggestUnit(unit) {
1427
+ return units.indexOf(unit) === 0;
1428
+ };
1429
+
1430
+ var isSmallestUnit = function isSmallestUnit(unit) {
1431
+ return units.indexOf(unit) === units.length - 1;
1432
+ };
1433
+
1434
+ var reduce = function reduce(number, unit) {
1435
+ if (number < 0.99 && !isSmallestUnit(unit)) {
1436
+ return reduce(number * 1000, getSmaller(unit));
1437
+ } else if (number >= 1000 && !isBiggestUnit(unit)) {
1438
+ return reduce(number / 1000, getBigger(unit));
1439
+ } else {
1440
+ return {
1441
+ number: number,
1442
+ unit: unit
1443
+ };
1444
+ }
1445
+ };
1446
+
1447
+ var _reduce = reduce(value, uom),
1448
+ number = _reduce.number,
1449
+ unit = _reduce.unit;
1450
+
1451
+ return formatFloat(number, false) + " " + unit;
1452
+ }
1453
+
1454
+ export { CharCounter, CharValidation, constraints as ConstraintsUtils, FieldConnector, ModalDialogLauncher$1 as ModalDialogLauncher, PredefinedValuesError, entityHelpers, isValidImage, shortenStorageUnit, toLocaleString };
1357
1455
  //# sourceMappingURL=field-editor-shared.esm.js.map