afformative 0.6.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -81,13 +81,13 @@ Although formatters can render icons or custom translation components, we often
81
81
 
82
82
  > Lexicographic sorting of items based on translations is a typical real world example, especially when you are using a custom React component for visualising the translation keys alongside the actual translations.
83
83
 
84
- This is where usage suggestions comes into play. Suggestions can be used to tell formatters that a value needs to be rendered with some special care. For example, pass `"primitive"` to tell a formatter that it should return a primitive value, such as a string.
84
+ This is where usage suggestions come into play. Suggestions can be used to tell formatters that a value needs to be rendered with some special care. For example, pass `"primitive"` to tell a formatter that it should return a primitive value, such as a string.
85
85
 
86
86
  ```js
87
87
  import { makeFormatter } from "afformative"
88
88
 
89
- const booleanFormatter = makeFormatter((value, usageSuggestions) => {
90
- if (usageSuggestions.includes("primitive")) {
89
+ const booleanFormatter = makeFormatter((value, suggestions) => {
90
+ if (suggestions.includes("primitive")) {
91
91
  return value ? "True" : "False"
92
92
  }
93
93
 
@@ -2,33 +2,19 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- function _objectWithoutPropertiesLoose(source, excluded) {
6
- if (source == null) return {};
7
- var target = {};
8
- var sourceKeys = Object.keys(source);
9
- var key, i;
5
+ var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
10
6
 
11
- for (i = 0; i < sourceKeys.length; i++) {
12
- key = sourceKeys[i];
13
- if (excluded.indexOf(key) >= 0) continue;
14
- target[key] = source[key];
15
- }
7
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
8
 
17
- return target;
18
- }
9
+ var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray);
19
10
 
20
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
21
- // verify the return type of the format definition based on the suggestions, printing errors such
22
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
23
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
24
- //
25
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput> {
26
- // <TSuggestion extends Suggestion>(
27
- // value: TInput,
28
- // usageSuggestions: TSuggestion[],
29
- // dataContext: DataContext,
30
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
31
- // }
11
+ var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
12
+ return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray__default["default"](suggestions));
13
+ };
14
+
15
+ var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
16
+ return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray__default["default"](suggestions));
17
+ };
32
18
 
33
19
  /**
34
20
  * Creates a new formatter.
@@ -37,50 +23,33 @@ function _objectWithoutPropertiesLoose(source, excluded) {
37
23
  * @param formatterOptions Additional options for the formatter.
38
24
  */
39
25
  var makeFormatter = function makeFormatter(format, formatterOptions) {
40
- var formatter = function formatter(_ref) {
41
- var _format;
42
-
43
- var children = _ref.children,
44
- _ref$suggestions = _ref.suggestions,
45
- suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions,
46
- dataContext = _objectWithoutPropertiesLoose(_ref, ["children", "suggestions"]);
26
+ var formatter = function formatter(props) {
27
+ var _format, _props$suggestions;
47
28
 
48
- return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null;
29
+ return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
49
30
  };
50
31
 
51
- formatter.displayName = formatterOptions == null ? void 0 : formatterOptions.displayName;
32
+ formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
52
33
 
53
- formatter.format = function (value, usageSuggestions, dataContext) {
54
- if (usageSuggestions === void 0) {
55
- usageSuggestions = [];
56
- }
57
-
58
- if (dataContext === void 0) {
59
- dataContext = {};
60
- }
61
-
62
- return format(value, usageSuggestions, dataContext);
34
+ formatter.format = function (value) {
35
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
36
+ var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
37
+ return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext);
63
38
  };
64
39
 
65
- formatter.formatAsPrimitive = function (value, usageSuggestions, dataContext) {
66
- if (usageSuggestions === void 0) {
67
- usageSuggestions = [];
68
- }
69
-
70
- if (dataContext === void 0) {
71
- dataContext = {};
72
- }
73
-
74
- return format(value, ["primitive"].concat(usageSuggestions), dataContext);
40
+ formatter.formatAsPrimitive = function (value) {
41
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
42
+ var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
43
+ return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext);
75
44
  };
76
45
 
77
46
  formatter.wrap = function (nextFormat, nextFormatterOptions) {
78
- var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) {
79
- var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) {
80
- return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
47
+ var nextFormatter = makeFormatter(function (value, suggestions, dataContext) {
48
+ var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) {
49
+ return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
81
50
  };
82
51
 
83
- return nextFormat(delegate, value, usageSuggestions, dataContext);
52
+ return nextFormat(delegate, value, suggestions, dataContext);
84
53
  }, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
85
54
  nextFormatter.innerFormatter = formatter;
86
55
  return nextFormatter;
@@ -1,30 +1,12 @@
1
- function _objectWithoutPropertiesLoose(source, excluded) {
2
- if (source == null) return {};
3
- var target = {};
4
- var sourceKeys = Object.keys(source);
5
- var key, i;
1
+ import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
6
2
 
7
- for (i = 0; i < sourceKeys.length; i++) {
8
- key = sourceKeys[i];
9
- if (excluded.indexOf(key) >= 0) continue;
10
- target[key] = source[key];
11
- }
12
-
13
- return target;
14
- }
3
+ var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
4
+ return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
5
+ };
15
6
 
16
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
17
- // verify the return type of the format definition based on the suggestions, printing errors such
18
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
19
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
20
- //
21
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput> {
22
- // <TSuggestion extends Suggestion>(
23
- // value: TInput,
24
- // usageSuggestions: TSuggestion[],
25
- // dataContext: DataContext,
26
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
27
- // }
7
+ var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
8
+ return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
9
+ };
28
10
 
29
11
  /**
30
12
  * Creates a new formatter.
@@ -33,50 +15,33 @@ function _objectWithoutPropertiesLoose(source, excluded) {
33
15
  * @param formatterOptions Additional options for the formatter.
34
16
  */
35
17
  var makeFormatter = function makeFormatter(format, formatterOptions) {
36
- var formatter = function formatter(_ref) {
37
- var _format;
38
-
39
- var children = _ref.children,
40
- _ref$suggestions = _ref.suggestions,
41
- suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions,
42
- dataContext = _objectWithoutPropertiesLoose(_ref, ["children", "suggestions"]);
18
+ var formatter = function formatter(props) {
19
+ var _format, _props$suggestions;
43
20
 
44
- return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null;
21
+ return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
45
22
  };
46
23
 
47
- formatter.displayName = formatterOptions == null ? void 0 : formatterOptions.displayName;
24
+ formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
48
25
 
49
- formatter.format = function (value, usageSuggestions, dataContext) {
50
- if (usageSuggestions === void 0) {
51
- usageSuggestions = [];
52
- }
53
-
54
- if (dataContext === void 0) {
55
- dataContext = {};
56
- }
57
-
58
- return format(value, usageSuggestions, dataContext);
26
+ formatter.format = function (value) {
27
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
28
+ var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
29
+ return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext);
59
30
  };
60
31
 
61
- formatter.formatAsPrimitive = function (value, usageSuggestions, dataContext) {
62
- if (usageSuggestions === void 0) {
63
- usageSuggestions = [];
64
- }
65
-
66
- if (dataContext === void 0) {
67
- dataContext = {};
68
- }
69
-
70
- return format(value, ["primitive"].concat(usageSuggestions), dataContext);
32
+ formatter.formatAsPrimitive = function (value) {
33
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
34
+ var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
35
+ return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext);
71
36
  };
72
37
 
73
38
  formatter.wrap = function (nextFormat, nextFormatterOptions) {
74
- var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) {
75
- var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) {
76
- return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
39
+ var nextFormatter = makeFormatter(function (value, suggestions, dataContext) {
40
+ var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) {
41
+ return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
77
42
  };
78
43
 
79
- return nextFormat(delegate, value, usageSuggestions, dataContext);
44
+ return nextFormat(delegate, value, suggestions, dataContext);
80
45
  }, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
81
46
  nextFormatter.innerFormatter = formatter;
82
47
  return nextFormatter;
@@ -2,35 +2,50 @@
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
3
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Afformative = {}));
5
- }(this, (function (exports) { 'use strict';
6
-
7
- function _objectWithoutPropertiesLoose(source, excluded) {
8
- if (source == null) return {};
9
- var target = {};
10
- var sourceKeys = Object.keys(source);
11
- var key, i;
12
-
13
- for (i = 0; i < sourceKeys.length; i++) {
14
- key = sourceKeys[i];
15
- if (excluded.indexOf(key) >= 0) continue;
16
- target[key] = source[key];
5
+ })(this, (function (exports) { 'use strict';
6
+
7
+ function _arrayLikeToArray(arr, len) {
8
+ if (len == null || len > arr.length) len = arr.length;
9
+
10
+ for (var i = 0, arr2 = new Array(len); i < len; i++) {
11
+ arr2[i] = arr[i];
17
12
  }
18
13
 
19
- return target;
14
+ return arr2;
15
+ }
16
+
17
+ function _arrayWithoutHoles(arr) {
18
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
19
+ }
20
+
21
+ function _iterableToArray(iter) {
22
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
23
+ }
24
+
25
+ function _unsupportedIterableToArray(o, minLen) {
26
+ if (!o) return;
27
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
28
+ var n = Object.prototype.toString.call(o).slice(8, -1);
29
+ if (n === "Object" && o.constructor) n = o.constructor.name;
30
+ if (n === "Map" || n === "Set") return Array.from(o);
31
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
32
+ }
33
+
34
+ function _nonIterableSpread() {
35
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
20
36
  }
21
37
 
22
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
23
- // verify the return type of the format definition based on the suggestions, printing errors such
24
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
25
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
26
- //
27
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput> {
28
- // <TSuggestion extends Suggestion>(
29
- // value: TInput,
30
- // usageSuggestions: TSuggestion[],
31
- // dataContext: DataContext,
32
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
33
- // }
38
+ function _toConsumableArray(arr) {
39
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
40
+ }
41
+
42
+ var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
43
+ return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
44
+ };
45
+
46
+ var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
47
+ return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
48
+ };
34
49
 
35
50
  /**
36
51
  * Creates a new formatter.
@@ -39,50 +54,33 @@ function _objectWithoutPropertiesLoose(source, excluded) {
39
54
  * @param formatterOptions Additional options for the formatter.
40
55
  */
41
56
  var makeFormatter = function makeFormatter(format, formatterOptions) {
42
- var formatter = function formatter(_ref) {
43
- var _format;
57
+ var formatter = function formatter(props) {
58
+ var _format, _props$suggestions;
44
59
 
45
- var children = _ref.children,
46
- _ref$suggestions = _ref.suggestions,
47
- suggestions = _ref$suggestions === void 0 ? [] : _ref$suggestions,
48
- dataContext = _objectWithoutPropertiesLoose(_ref, ["children", "suggestions"]);
49
-
50
- return (_format = format(children, suggestions, dataContext)) !== null && _format !== void 0 ? _format : null;
60
+ return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
51
61
  };
52
62
 
53
- formatter.displayName = formatterOptions == null ? void 0 : formatterOptions.displayName;
54
-
55
- formatter.format = function (value, usageSuggestions, dataContext) {
56
- if (usageSuggestions === void 0) {
57
- usageSuggestions = [];
58
- }
59
-
60
- if (dataContext === void 0) {
61
- dataContext = {};
62
- }
63
+ formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
63
64
 
64
- return format(value, usageSuggestions, dataContext);
65
+ formatter.format = function (value) {
66
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
67
+ var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
68
+ return format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext);
65
69
  };
66
70
 
67
- formatter.formatAsPrimitive = function (value, usageSuggestions, dataContext) {
68
- if (usageSuggestions === void 0) {
69
- usageSuggestions = [];
70
- }
71
-
72
- if (dataContext === void 0) {
73
- dataContext = {};
74
- }
75
-
76
- return format(value, ["primitive"].concat(usageSuggestions), dataContext);
71
+ formatter.formatAsPrimitive = function (value) {
72
+ var suggestions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
73
+ var dataContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
74
+ return format(value, ensureFormatAsPrimitiveSuggestionIntegrity(suggestions), dataContext);
77
75
  };
78
76
 
79
77
  formatter.wrap = function (nextFormat, nextFormatterOptions) {
80
- var nextFormatter = makeFormatter(function (value, usageSuggestions, dataContext) {
81
- var delegate = function delegate(delegatedValue, delegatedUsageSuggestions, delegatedDataContext) {
82
- return formatter.format(delegatedValue, delegatedUsageSuggestions !== null && delegatedUsageSuggestions !== void 0 ? delegatedUsageSuggestions : usageSuggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
78
+ var nextFormatter = makeFormatter(function (value, suggestions, dataContext) {
79
+ var delegate = function delegate(delegatedValue, delegatedSuggestions, delegatedDataContext) {
80
+ return formatter.format(delegatedValue, delegatedSuggestions !== null && delegatedSuggestions !== void 0 ? delegatedSuggestions : suggestions, delegatedDataContext !== null && delegatedDataContext !== void 0 ? delegatedDataContext : dataContext);
83
81
  };
84
82
 
85
- return nextFormat(delegate, value, usageSuggestions, dataContext);
83
+ return nextFormat(delegate, value, suggestions, dataContext);
86
84
  }, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
87
85
  nextFormatter.innerFormatter = formatter;
88
86
  return nextFormatter;
@@ -95,4 +93,4 @@ exports.makeFormatter = makeFormatter;
95
93
 
96
94
  Object.defineProperty(exports, '__esModule', { value: true });
97
95
 
98
- })));
96
+ }));
@@ -1 +1 @@
1
- !function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).Afformative={})}(this,(function(n){"use strict";n.makeFormatter=function n(e,t){var i=function(n){var t,i=n.children,r=n.suggestions,o=void 0===r?[]:r,u=function(n,e){if(null==n)return{};var t,i,r={},o=Object.keys(n);for(i=0;o.length>i;i++)0>e.indexOf(t=o[i])&&(r[t]=n[t]);return r}(n,["children","suggestions"]);return null!==(t=e(i,o,u))&&void 0!==t?t:null};return i.displayName=null==t?void 0:t.displayName,i.format=function(n,t,i){return void 0===t&&(t=[]),void 0===i&&(i={}),e(n,t,i)},i.formatAsPrimitive=function(n,t,i){return void 0===t&&(t=[]),void 0===i&&(i={}),e(n,["primitive"].concat(t),i)},i.wrap=function(e,r){var o=n((function(n,t,r){return e((function(n,e,o){return i.format(n,null!=e?e:t,null!=o?o:r)}),n,t,r)}),null!=r?r:t);return o.innerFormatter=i,o},i},Object.defineProperty(n,"__esModule",{value:!0})}));
1
+ !function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).Afformative={})}(this,(function(t){"use strict";function n(t,n){(null==n||n>t.length)&&(n=t.length);for(var r=0,e=Array(n);n>r;r++)e[r]=t[r];return e}function r(t){return function(t){if(Array.isArray(t))return n(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,r){if(t){if("string"==typeof t)return n(t,r);var e=Object.prototype.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?n(t,r):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}var e=function(t){return t.includes("primitive")||!t.includes("comparable")?t:["primitive"].concat(r(t))},i=function(t){return t.includes("primitive")?t:["primitive"].concat(r(t))};t.makeFormatter=function t(n,r){var o=function(t){var r,e;return null!==(r=n(t.children,null!==(e=t.suggestions)&&void 0!==e?e:[],t))&&void 0!==r?r:null};return o.displayName=null==r?void 0:r.displayName,o.format=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return n(t,e(r),i)},o.formatAsPrimitive=function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],e=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return n(t,i(r),e)},o.wrap=function(n,e){var i=t((function(t,r,e){return n((function(t,n,i){return o.format(t,null!=n?n:r,null!=i?i:e)}),t,r,e)}),null!=e?e:r);return i.innerFormatter=o,i},o},Object.defineProperty(t,"__esModule",{value:!0})}));
@@ -1,89 +1,90 @@
1
- declare type PrimitiveSuggestion = "primitive";
2
- declare type SemanticSuggestion = "abbreviated" | "icon" | "verbose";
3
- declare type Suggestion = PrimitiveSuggestion | SemanticSuggestion;
1
+ declare type PrimitiveSuggestion = "primitive" | "comparable";
2
+ declare type Suggestion = PrimitiveSuggestion | "abbreviated" | "as-icon"
3
+ /**
4
+ * @deprecated Since v0.6.3. Use `"as-icon"` or `"with-icon"` instead.
5
+ */
6
+ | "icon" | "verbose" | "with-icon";
7
+ declare type DataContext = Record<string, any>;
4
8
  interface FormatterOptions {
5
9
  /** Formatter name, useful for debugging or advanced pattern matching. */
6
10
  displayName?: string;
7
11
  }
8
- declare type DataContext = Record<string, any>;
9
- interface FormatDefinition<TInput, TOutput, TPrimitiveOutput> {
12
+ interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
10
13
  (
11
14
  /** Value to format. */
12
15
  value: TInput,
13
16
  /** Suggestions passed by the consumer of a formatter. */
14
- usageSuggestions: Suggestion[],
17
+ suggestions: Suggestion[],
15
18
  /** Additional data context to be used by the formatter. */
16
- dataContext: DataContext): TOutput | TPrimitiveOutput;
19
+ dataContext: Partial<TDataContext>): TOutput | TPrimitiveOutput;
17
20
  }
18
- interface FormatMethod<TInput, TOutput, TPrimitiveOutput> {
19
- <TSuggestion extends Suggestion>(
21
+ interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
22
+ (
20
23
  /** Value to format. */
21
24
  value: TInput,
22
25
  /** Suggestions the formatter should take note of. */
23
- usageSuggestions?: TSuggestion[],
26
+ suggestions?: Suggestion[],
24
27
  /** Additional data context the formatter might find useful. */
25
- dataContext?: DataContext): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput;
28
+ dataContext?: Partial<TDataContext>): TOutput | TPrimitiveOutput;
26
29
  }
27
- interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput> {
30
+ interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
28
31
  (
29
32
  /** Value to format. */
30
33
  value: TInput,
31
34
  /** Suggestions the formatter should take note of in addition to `primitive`. */
32
- usageSuggestions?: Suggestion[],
35
+ suggestions?: Suggestion[],
33
36
  /** Additional data context the formatter might find useful. */
34
- dataContext?: DataContext): TPrimitiveOutput;
37
+ dataContext?: Partial<TDataContext>): TPrimitiveOutput;
35
38
  }
36
- interface FormatChainDefinition<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TOuterInput, TOuterOutput, TOuterPrimitiveOutput> {
39
+ interface FormatChainDefinition<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext extends DataContext, TOuterInput, TOuterOutput, TOuterPrimitiveOutput, TOuterDataContext extends DataContext> {
37
40
  (
38
41
  /**
39
42
  * The `formatter.format` method which can be used to delegate the formatting
40
43
  * to the wrapped formatter. Delegation is simplified so if no suggestions or contextual
41
44
  * props are passed, the original ones are used instead.
42
45
  */
43
- delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput>,
46
+ delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext>,
44
47
  /** Value to format. */
45
48
  value: TOuterInput,
46
49
  /** Suggestions the formatter should take note of. */
47
- usageSuggestions: Suggestion[],
50
+ suggestions: Suggestion[],
48
51
  /** Additional data context the formatter might find useful. */
49
- dataContext: DataContext): TOuterOutput | TOuterPrimitiveOutput;
52
+ dataContext: Partial<TOuterDataContext>): TOuterOutput | TOuterPrimitiveOutput;
50
53
  }
51
- interface FormatterProps<TInput> {
54
+ declare type FormatterProps<TInput, TDataContext extends DataContext> = {
52
55
  /** Value to format. */
53
56
  children: TInput;
54
57
  /** Suggestions the formatter should take note of. */
55
58
  suggestions?: Suggestion[];
56
- /** Additional data context to be used by the formatter. */
57
- [dataContextPropName: string]: any;
58
- }
59
- export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput> {
59
+ } & Partial<TDataContext>;
60
+ export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext> {
60
61
  /** Formatter name, useful for debugging or advanced pattern matching. */
61
62
  displayName?: string;
62
63
  /** Formats a value. */
63
- format: FormatMethod<TInput, TOutput, TPrimitiveOutput>;
64
+ format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>;
64
65
  /** Formats a value with the `primitive` suggestion. */
65
- formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput>;
66
- /** The callee of the `.wrap` method used to produce this formatter. */
67
- innerFormatter?: Formatter<any, any, any>;
66
+ formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext>;
67
+ /** The callee of the `wrap` method used to produce this formatter. */
68
+ innerFormatter?: Formatter<any, any, any, any>;
68
69
  /**
69
70
  * Creates a new formatter from an existing one. Allows overriding of formatter behaviour
70
71
  * for certain values.
71
72
  */
72
- wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput>(
73
+ wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput, TNextDataContext extends TDataContext = TDataContext>(
73
74
  /**
74
75
  * Function used to format the value. Has the same signature as the one passed
75
76
  * to `makeFormatter`, except a `delegate` function is passed in the first position.
76
77
  * This function can be used to delegate formatting to the original (inner) formatter.
77
78
  */
78
- nextFormat: FormatChainDefinition<TInput, TOutput, TPrimitiveOutput, TNextInput, TNextOutput, TNextPrimitiveOutput>,
79
+ nextFormat: FormatChainDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext, TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>,
79
80
  /** New formatter options, replacing the original ones. */
80
- nextFormatterOptions?: FormatterOptions) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput>;
81
+ nextFormatterOptions?: FormatterOptions) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>;
81
82
  /**
82
83
  * Backwards-compatible way to use the formatter as a React component.
83
84
  *
84
- * @deprecated Since v0.6.0. Prefer using the `Formatter.format` method instead.
85
+ * @deprecated Since v0.6.0. Prefer using the `format` method instead.
85
86
  */
86
- (props: FormatterProps<TInput>): TOutput | TPrimitiveOutput | null;
87
+ (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null;
87
88
  }
88
89
  /**
89
90
  * Creates a new formatter.
@@ -91,6 +92,6 @@ export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput> {
91
92
  * @param format Function used to format the value.
92
93
  * @param formatterOptions Additional options for the formatter.
93
94
  */
94
- export declare const makeFormatter: <TInput, TOutput, TPrimitiveOutput = TOutput>(format: FormatDefinition<TInput, TOutput, TPrimitiveOutput>, formatterOptions?: FormatterOptions | undefined) => Formatter<TInput, TOutput, TPrimitiveOutput>;
95
+ export declare const makeFormatter: <TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext>(format: FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext>, formatterOptions?: FormatterOptions | undefined) => Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext>;
95
96
  export {};
96
97
  //# sourceMappingURL=makeFormatter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"makeFormatter.d.ts","sourceRoot":"","sources":["../../src/makeFormatter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"makeFormatter.d.ts","sourceRoot":"","sources":["../../src/makeFormatter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "afformative",
3
- "version": "0.6.0",
3
+ "version": "0.6.3",
4
4
  "license": "MIT",
5
5
  "main": "dist/afformative.cjs.js",
6
6
  "module": "dist/afformative.esm.js",
@@ -27,9 +27,12 @@
27
27
  "contributors": [
28
28
  "Vaclav Jancarik <vaclav.janc@gmail.com>"
29
29
  ],
30
+ "dependencies": {
31
+ "@babel/runtime": "^7.12.1"
32
+ },
30
33
  "publishConfig": {
31
34
  "access": "public"
32
35
  },
33
36
  "sideEffects": false,
34
- "gitHead": "b5ffb3e48e19a74b2ca89af2ad7a96becbe711e7"
37
+ "gitHead": "ddc8c8682e2777c730108466792b7670d8a43f06"
35
38
  }
@@ -2,111 +2,217 @@ import { makeFormatter } from "./makeFormatter"
2
2
 
3
3
  const toUpperCase = (string: string) => string.toUpperCase()
4
4
 
5
+ const upperCaseFormatter = makeFormatter<string, string>(toUpperCase)
6
+
7
+ interface ValueRecord {
8
+ value: string
9
+ }
10
+
11
+ const valueRecordUpperCaseFormatter = makeFormatter<ValueRecord, ValueRecord, string>(
12
+ ({ value }, suggestions) => {
13
+ if (suggestions.includes("primitive")) {
14
+ return toUpperCase(value)
15
+ }
16
+
17
+ return { value: toUpperCase(value) }
18
+ },
19
+ )
20
+
5
21
  describe("makeFormatter", () => {
6
- it("handles trivial formatting", () => {
7
- const formatter = makeFormatter<string, string>(toUpperCase)
8
- expect(formatter.format("foo")).toBe("FOO")
22
+ const format = jest.fn()
23
+
24
+ afterEach(() => {
25
+ jest.clearAllMocks()
9
26
  })
10
27
 
11
- it("accepts a `name` option", () => {
12
- const formatter = makeFormatter<string, string>(toUpperCase, { displayName: "UpperFormatter" })
13
- expect(formatter.displayName).toBe("UpperFormatter")
28
+ describe("displayName", () => {
29
+ it("accepts a `displayName` option", () => {
30
+ const displayName = "upperCaseFormatter"
31
+ const formatter = makeFormatter<string, string>(toUpperCase, { displayName })
32
+ expect(formatter.displayName).toBe(displayName)
33
+ })
14
34
  })
15
35
 
16
- it("passes `suggestions` to `format`", () => {
17
- const formatter = makeFormatter<string, string>((value, suggestions) => {
18
- if (suggestions.includes("abbreviated")) {
19
- return value[0]
20
- }
36
+ describe("format", () => {
37
+ it("handles trivial formatting", () => {
38
+ expect(upperCaseFormatter.format("foo")).toBe("FOO")
39
+ })
21
40
 
22
- return value
41
+ it("passes through non-empty suggestions", () => {
42
+ const formatter = makeFormatter<string, string>(format)
43
+ formatter.format("foo", ["abbreviated"])
44
+ expect(format.mock.calls[0][1]).toEqual(["abbreviated"])
23
45
  })
24
46
 
25
- expect(formatter.format("foo", ["abbreviated"])).toBe("f")
26
- expect(formatter.format("foo", [])).toBe("foo")
27
- expect(formatter.format("foo")).toBe("foo")
28
- })
47
+ it("passes through empty suggestions", () => {
48
+ const formatter = makeFormatter<string, string>(format)
49
+ formatter.format("foo", [])
50
+ expect(format.mock.calls[0][1]).toEqual([])
51
+ })
29
52
 
30
- it("handles formatting with the `primitive` suggestion", () => {
31
- type Structure = { value: string }
53
+ it("defaults suggestions to an empty array", () => {
54
+ const formatter = makeFormatter<string, string>(format)
55
+ formatter.format("foo")
56
+ expect(format.mock.calls[0][1]).toEqual([])
57
+ })
32
58
 
33
- const formatter = makeFormatter<Structure, Structure, string>((value, suggestions) => {
34
- if (suggestions.includes("primitive")) {
35
- return value.value
36
- }
59
+ it("passes through the `primitive` suggestion", () => {
60
+ const formatter = makeFormatter<string, string>(format)
61
+ formatter.format("foo", ["primitive"])
62
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
63
+ })
37
64
 
38
- return value
65
+ it("passes the `primitive` suggestion alongside `comparable` when missing", () => {
66
+ const formatter = makeFormatter<string, string>(format)
67
+ formatter.format("foo", ["comparable"])
68
+ expect(format.mock.calls[0][1]).toEqual(["primitive", "comparable"])
39
69
  })
40
70
 
41
- expect(formatter.format({ value: "foo" }, ["primitive"])).toBe("foo")
42
- expect(formatter.formatAsPrimitive({ value: "foo" })).toBe("foo")
43
- expect(formatter.formatAsPrimitive({ value: "foo" }, ["primitive"])).toBe("foo")
71
+ it("does not pass the `primitive` suggestion alongside other suggestions when missing", () => {
72
+ const formatter = makeFormatter<string, string>(format)
73
+ formatter.format("foo", ["abbreviated", "verbose"])
74
+ expect(format.mock.calls[0][1]).toEqual(["abbreviated", "verbose"])
75
+ })
76
+
77
+ it("supports data context", () => {
78
+ const formatter = makeFormatter<string, string>(format)
79
+ formatter.format("foo", [], { foo: "bar" })
80
+ expect(format.mock.calls[0][2]).toEqual({ foo: "bar" })
81
+ })
82
+
83
+ it("defaults data context to an empty object", () => {
84
+ const formatter = makeFormatter<string, string>(format)
85
+ formatter.format("foo")
86
+ expect(format.mock.calls[0][2]).toEqual({})
87
+ })
44
88
  })
45
89
 
46
- it("supports simple behavior wrapping", () => {
47
- const formatter = makeFormatter<string, string>(toUpperCase)
90
+ describe("formatAsPrimitive", () => {
91
+ it("handles trivial formatting", () => {
92
+ expect(upperCaseFormatter.formatAsPrimitive("foo")).toBe("FOO")
93
+ })
48
94
 
49
- const wrappedFormatter = formatter.wrap((delegate, value) =>
50
- value === "foo" ? "override" : delegate(value),
51
- )
95
+ it("passes the `primitive` suggestion when no suggestions are passed", () => {
96
+ const formatter = makeFormatter<string, string>(format)
97
+ formatter.formatAsPrimitive("foo")
98
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
99
+ })
52
100
 
53
- expect(wrappedFormatter.format("foo")).toBe("override")
54
- expect(wrappedFormatter.format("bar")).toBe("BAR")
55
- })
101
+ it("passes the `primitive` suggestion when empty suggestions are passed", () => {
102
+ const formatter = makeFormatter<string, string>(format)
103
+ formatter.formatAsPrimitive("foo", [])
104
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
105
+ })
106
+
107
+ it("passes the `primitive` suggestion when a different suggestion is passed", () => {
108
+ const formatter = makeFormatter<string, string>(format)
109
+ formatter.formatAsPrimitive("foo", ["abbreviated"])
110
+ expect(format.mock.calls[0][1]).toEqual(["primitive", "abbreviated"])
111
+ })
112
+
113
+ it("passes through the `primitive` suggestion", () => {
114
+ const formatter = makeFormatter<string, string>(format)
115
+ formatter.formatAsPrimitive("foo", ["primitive"])
116
+ expect(format.mock.calls[0][1]).toEqual(["primitive"])
117
+ })
56
118
 
57
- it("supports simple behavior wrapping with suggestions", () => {
58
- const formatter = makeFormatter<string, string>(toUpperCase)
119
+ it("passes the `primitive` suggestion alongside `comparable`", () => {
120
+ const formatter = makeFormatter<string, string>(format)
121
+ formatter.formatAsPrimitive("foo", ["comparable"])
122
+ expect(format.mock.calls[0][1]).toEqual(["primitive", "comparable"])
123
+ })
59
124
 
60
- const wrappedFormatter = formatter.wrap((delegate, value, suggestions) =>
61
- value === "foo" && suggestions.includes("abbreviated") ? "f" : delegate(value),
62
- )
125
+ it("supports data context", () => {
126
+ const formatter = makeFormatter<string, string>(format)
127
+ formatter.formatAsPrimitive("foo", [], { foo: "bar" })
128
+ expect(format.mock.calls[0][2]).toEqual({ foo: "bar" })
129
+ })
63
130
 
64
- expect(wrappedFormatter.format("foo")).toBe("FOO")
65
- expect(wrappedFormatter.format("foo", ["abbreviated"])).toBe("f")
66
- expect(wrappedFormatter.format("bar")).toBe("BAR")
131
+ it("defaults data context to an empty object", () => {
132
+ const formatter = makeFormatter<string, string>(format)
133
+ formatter.formatAsPrimitive("foo")
134
+ expect(format.mock.calls[0][2]).toEqual({})
135
+ })
67
136
  })
68
137
 
69
- it("supports simple behavior wrapping with the `primitive` suggestion", () => {
70
- type Structure = { value: string }
138
+ describe("wrap", () => {
139
+ it("handles trivial wrapping", () => {
140
+ const formatter = makeFormatter<string, string>(format).wrap(() => "bar")
141
+ expect(formatter.format("foo")).toBe("bar")
142
+ })
71
143
 
72
- const formatter = makeFormatter<string, string>(toUpperCase)
144
+ it("handles single-value mapping", () => {
145
+ const formatter = makeFormatter<string, string>(format).wrap((delegate, value) =>
146
+ value === "ping" ? "pong" : delegate(value),
147
+ )
73
148
 
74
- const wrappedFormatter = formatter.wrap<Structure, Structure, string>(
75
- (delegate, value, suggestions) => (suggestions.includes("primitive") ? value.value : value),
76
- )
149
+ expect(formatter.format("ping")).toBe("pong")
150
+ })
77
151
 
78
- expect(wrappedFormatter.format({ value: "foo" }, ["primitive"])).toBe("foo")
79
- expect(wrappedFormatter.formatAsPrimitive({ value: "foo" })).toBe("foo")
80
- expect(wrappedFormatter.formatAsPrimitive({ value: "foo" }, ["primitive"])).toBe("foo")
81
- })
152
+ it("handles delegation to the original formatter", () => {
153
+ const formatter = upperCaseFormatter.wrap((delegate, value) =>
154
+ value === "ping" ? "pong" : delegate(value),
155
+ )
82
156
 
83
- it("supports simple behavior wrapping with data context", () => {
84
- const formatter = makeFormatter<string, string>(toUpperCase)
157
+ expect(formatter.format("foo")).toBe("FOO")
158
+ })
85
159
 
86
- const wrappedFormatter = formatter.wrap(
87
- (delegate, value, suggestions, { forcedValue }) => forcedValue ?? delegate(value),
88
- )
160
+ it("sets the `innerFormatter` property", () => {
161
+ const wrappedFormatter = upperCaseFormatter.wrap((delegate, value) => delegate(value))
162
+ expect(wrappedFormatter.innerFormatter).toBe(upperCaseFormatter)
163
+ })
89
164
 
90
- expect(wrappedFormatter.format("foo")).toBe("FOO")
91
- expect(wrappedFormatter.format("foo", undefined, { forcedValue: "override" })).toBe("override")
92
- })
165
+ it("passes the `primitive` suggestion to `delegate` when using `formatAsPrimitive`", () => {
166
+ const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value))
167
+ expect(formatter.formatAsPrimitive({ value: "foo" })).toBe("FOO")
168
+ })
93
169
 
94
- it("passes the original suggestions when they are not passed manually to `format` when wrapping", () => {
95
- const formatter = makeFormatter<string, string>((value, suggestions) => {
96
- if (suggestions.includes("abbreviated")) {
97
- return value[0]
98
- }
170
+ it("passes suggestions through to `delegate` when not overriden", () => {
171
+ const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value))
172
+ expect(formatter.format({ value: "foo" }, ["primitive"])).toBe("FOO")
173
+ })
99
174
 
100
- return value
175
+ it("supports overriding of suggestions for `delegate`", () => {
176
+ const formatter = valueRecordUpperCaseFormatter.wrap((delegate, value) => delegate(value, []))
177
+ expect(formatter.format({ value: "foo" }, ["primitive"])).toEqual({ value: "FOO" })
101
178
  })
102
179
 
103
- const wrappedFormatter = formatter.wrap((delegate, value) => delegate(value))
104
- expect(wrappedFormatter.format("foo", ["abbreviated"])).toBe("f")
105
- })
180
+ it("supports modifying the input structure", () => {
181
+ const formatter = upperCaseFormatter.wrap<ValueRecord>((delegate, { value }) =>
182
+ delegate(value),
183
+ )
106
184
 
107
- it("sets the `innerFormatter` static property when wrapping", () => {
108
- const formatter = makeFormatter<string, string>(toUpperCase)
109
- const wrappedFormatter = formatter.wrap((delegate, value) => delegate(value))
110
- expect(wrappedFormatter.innerFormatter).toBe(formatter)
185
+ expect(formatter.format({ value: "foo" })).toBe("FOO")
186
+ })
187
+
188
+ it("supports modifying the output structure", () => {
189
+ const formatter = upperCaseFormatter.wrap<ValueRecord, ValueRecord>(
190
+ (delegate, { value }) => ({ value: delegate(value) }),
191
+ )
192
+
193
+ expect(formatter.format({ value: "foo" })).toEqual({ value: "FOO" })
194
+ })
195
+
196
+ it("supports modifying the data context structure", () => {
197
+ interface ListContext {
198
+ row: string
199
+ }
200
+
201
+ const listFormatter = upperCaseFormatter.wrap<string, string, string, ListContext>(
202
+ (delegate, value, suggestions, { row }) => `${row}: ${delegate(value)}`,
203
+ )
204
+
205
+ interface GridContext extends ListContext {
206
+ column: string
207
+ }
208
+
209
+ expect(listFormatter.format("foo", [], { row: "A" })).toBe("A: FOO")
210
+
211
+ const gridFormatter = listFormatter.wrap<string, string, string, GridContext>(
212
+ (delegate, value, suggestions, { column }) => delegate(value).replace(":", `${column}:`),
213
+ )
214
+
215
+ expect(gridFormatter.format("foo", [], { row: "B", column: "1" })).toBe("B1: FOO")
216
+ })
111
217
  })
112
218
  })
@@ -1,57 +1,61 @@
1
- type PrimitiveSuggestion = "primitive"
2
- type SemanticSuggestion = "abbreviated" | "icon" | "verbose"
3
- type Suggestion = PrimitiveSuggestion | SemanticSuggestion
1
+ type PrimitiveSuggestion = "primitive" | "comparable"
2
+
3
+ type Suggestion =
4
+ | PrimitiveSuggestion
5
+ | "abbreviated"
6
+ | "as-icon"
7
+ /**
8
+ * @deprecated Since v0.6.3. Use `"as-icon"` or `"with-icon"` instead.
9
+ */
10
+ | "icon"
11
+ | "verbose"
12
+ | "with-icon"
13
+
14
+ const ensureFormatSuggestionIntegrity = (suggestions: Suggestion[]): Suggestion[] =>
15
+ suggestions.includes("primitive") || !suggestions.includes("comparable")
16
+ ? suggestions
17
+ : ["primitive", ...suggestions]
18
+
19
+ const ensureFormatAsPrimitiveSuggestionIntegrity = (suggestions: Suggestion[]): Suggestion[] =>
20
+ suggestions.includes("primitive") ? suggestions : ["primitive", ...suggestions]
21
+
22
+ type DataContext = Record<string, any>
4
23
 
5
24
  interface FormatterOptions {
6
25
  /** Formatter name, useful for debugging or advanced pattern matching. */
7
26
  displayName?: string
8
27
  }
9
28
 
10
- type DataContext = Record<string, any>
11
-
12
- // TODO: Update `FormatDefinition` type based on this snippet. Sadly, TypeScript cannot correctly
13
- // verify the return type of the format definition based on the suggestions, printing errors such
14
- // as `Type 'string' is not assignable to type '"primitive" extends TSuggestion ? string : string'`
15
- // which is, of course, nonsense. Same applies to `FormatChainDefinition`.
16
- //
17
- // interface FormatDefinition<TInput, TOutput, TPrimitiveOutput> {
18
- // <TSuggestion extends Suggestion>(
19
- // value: TInput,
20
- // usageSuggestions: TSuggestion[],
21
- // dataContext: DataContext,
22
- // ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
23
- // }
24
-
25
- interface FormatDefinition<TInput, TOutput, TPrimitiveOutput> {
29
+ interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
26
30
  (
27
31
  /** Value to format. */
28
32
  value: TInput,
29
33
  /** Suggestions passed by the consumer of a formatter. */
30
- usageSuggestions: Suggestion[],
34
+ suggestions: Suggestion[],
31
35
  /** Additional data context to be used by the formatter. */
32
- dataContext: DataContext,
36
+ dataContext: Partial<TDataContext>,
33
37
  ): TOutput | TPrimitiveOutput
34
38
  }
35
39
 
36
- interface FormatMethod<TInput, TOutput, TPrimitiveOutput> {
37
- <TSuggestion extends Suggestion>(
40
+ interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
41
+ (
38
42
  /** Value to format. */
39
43
  value: TInput,
40
44
  /** Suggestions the formatter should take note of. */
41
- usageSuggestions?: TSuggestion[],
45
+ suggestions?: Suggestion[],
42
46
  /** Additional data context the formatter might find useful. */
43
- dataContext?: DataContext,
44
- ): PrimitiveSuggestion extends TSuggestion ? TPrimitiveOutput : TOutput
47
+ dataContext?: Partial<TDataContext>,
48
+ ): TOutput | TPrimitiveOutput
45
49
  }
46
50
 
47
- interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput> {
51
+ interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
48
52
  (
49
53
  /** Value to format. */
50
54
  value: TInput,
51
55
  /** Suggestions the formatter should take note of in addition to `primitive`. */
52
- usageSuggestions?: Suggestion[],
56
+ suggestions?: Suggestion[],
53
57
  /** Additional data context the formatter might find useful. */
54
- dataContext?: DataContext,
58
+ dataContext?: Partial<TDataContext>,
55
59
  ): TPrimitiveOutput
56
60
  }
57
61
 
@@ -59,9 +63,11 @@ interface FormatChainDefinition<
59
63
  TInnerInput,
60
64
  TInnerOutput,
61
65
  TInnerPrimitiveInput,
66
+ TInnerDataContext extends DataContext,
62
67
  TOuterInput,
63
68
  TOuterOutput,
64
- TOuterPrimitiveOutput
69
+ TOuterPrimitiveOutput,
70
+ TOuterDataContext extends DataContext
65
71
  > {
66
72
  (
67
73
  /**
@@ -69,39 +75,47 @@ interface FormatChainDefinition<
69
75
  * to the wrapped formatter. Delegation is simplified so if no suggestions or contextual
70
76
  * props are passed, the original ones are used instead.
71
77
  */
72
- delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput>,
78
+ delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext>,
73
79
  /** Value to format. */
74
80
  value: TOuterInput,
75
81
  /** Suggestions the formatter should take note of. */
76
- usageSuggestions: Suggestion[],
82
+ suggestions: Suggestion[],
77
83
  /** Additional data context the formatter might find useful. */
78
- dataContext: DataContext,
84
+ dataContext: Partial<TOuterDataContext>,
79
85
  ): TOuterOutput | TOuterPrimitiveOutput
80
86
  }
81
87
 
82
- interface FormatterProps<TInput> {
88
+ type FormatterProps<TInput, TDataContext extends DataContext> = {
83
89
  /** Value to format. */
84
90
  children: TInput
85
91
  /** Suggestions the formatter should take note of. */
86
92
  suggestions?: Suggestion[]
87
- /** Additional data context to be used by the formatter. */
88
- [dataContextPropName: string]: any
89
- }
93
+ } & Partial<TDataContext>
90
94
 
91
- export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput> {
95
+ export interface Formatter<
96
+ TInput,
97
+ TOutput,
98
+ TPrimitiveOutput = TOutput,
99
+ TDataContext extends DataContext = DataContext
100
+ > {
92
101
  /** Formatter name, useful for debugging or advanced pattern matching. */
93
102
  displayName?: string
94
103
  /** Formats a value. */
95
- format: FormatMethod<TInput, TOutput, TPrimitiveOutput>
104
+ format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>
96
105
  /** Formats a value with the `primitive` suggestion. */
97
- formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput>
98
- /** The callee of the `.wrap` method used to produce this formatter. */
99
- innerFormatter?: Formatter<any, any, any>
106
+ formatAsPrimitive: FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext>
107
+ /** The callee of the `wrap` method used to produce this formatter. */
108
+ innerFormatter?: Formatter<any, any, any, any>
100
109
  /**
101
110
  * Creates a new formatter from an existing one. Allows overriding of formatter behaviour
102
111
  * for certain values.
103
112
  */
104
- wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput>(
113
+ wrap: <
114
+ TNextInput = TInput,
115
+ TNextOutput = TOutput,
116
+ TNextPrimitiveOutput = TPrimitiveOutput,
117
+ TNextDataContext extends TDataContext = TDataContext
118
+ >(
105
119
  /**
106
120
  * Function used to format the value. Has the same signature as the one passed
107
121
  * to `makeFormatter`, except a `delegate` function is passed in the first position.
@@ -111,19 +125,21 @@ export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput> {
111
125
  TInput,
112
126
  TOutput,
113
127
  TPrimitiveOutput,
128
+ TDataContext,
114
129
  TNextInput,
115
130
  TNextOutput,
116
- TNextPrimitiveOutput
131
+ TNextPrimitiveOutput,
132
+ TNextDataContext
117
133
  >,
118
134
  /** New formatter options, replacing the original ones. */
119
135
  nextFormatterOptions?: FormatterOptions,
120
- ) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput>
136
+ ) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>
121
137
  /**
122
138
  * Backwards-compatible way to use the formatter as a React component.
123
139
  *
124
- * @deprecated Since v0.6.0. Prefer using the `Formatter.format` method instead.
140
+ * @deprecated Since v0.6.0. Prefer using the `format` method instead.
125
141
  */
126
- (props: FormatterProps<TInput>): TOutput | TPrimitiveOutput | null
142
+ (props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null
127
143
  }
128
144
 
129
145
  /**
@@ -132,52 +148,67 @@ export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput> {
132
148
  * @param format Function used to format the value.
133
149
  * @param formatterOptions Additional options for the formatter.
134
150
  */
135
- export const makeFormatter = <TInput, TOutput, TPrimitiveOutput = TOutput>(
136
- format: FormatDefinition<TInput, TOutput, TPrimitiveOutput>,
151
+ export const makeFormatter = <
152
+ TInput,
153
+ TOutput,
154
+ TPrimitiveOutput = TOutput,
155
+ TDataContext extends DataContext = DataContext
156
+ >(
157
+ format: FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext>,
137
158
  formatterOptions?: FormatterOptions,
138
- ): Formatter<TInput, TOutput, TPrimitiveOutput> => {
139
- const formatter: Formatter<TInput, TOutput, TPrimitiveOutput> = ({
140
- children,
141
- suggestions = [],
142
- ...dataContext
143
- }) => format(children, suggestions, dataContext) ?? null
159
+ ): Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> => {
160
+ const formatter: Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> = props =>
161
+ format(props.children, props.suggestions ?? [], props) ?? null
144
162
 
145
163
  formatter.displayName = formatterOptions?.displayName
146
164
 
147
- formatter.format = (value, usageSuggestions = [], dataContext = {}) =>
148
- format(value, usageSuggestions, dataContext) as any
149
-
150
- formatter.formatAsPrimitive = (value, usageSuggestions = [], dataContext = {}) =>
151
- format(value, ["primitive", ...usageSuggestions], dataContext) as any
152
-
153
- formatter.wrap = <TNextInput, TNextOutput, TNextPrimitiveOutput>(
165
+ formatter.format = (value, suggestions = [], dataContext = {}) =>
166
+ format(value, ensureFormatSuggestionIntegrity(suggestions), dataContext)
167
+
168
+ formatter.formatAsPrimitive = (value, suggestions = [], dataContext = {}) =>
169
+ format(
170
+ value,
171
+ ensureFormatAsPrimitiveSuggestionIntegrity(suggestions),
172
+ dataContext,
173
+ ) as TPrimitiveOutput
174
+
175
+ formatter.wrap = <
176
+ TNextInput,
177
+ TNextOutput,
178
+ TNextPrimitiveOutput,
179
+ TNextDataContext extends TDataContext
180
+ >(
154
181
  nextFormat: FormatChainDefinition<
155
182
  TInput,
156
183
  TOutput,
157
184
  TPrimitiveOutput,
185
+ TDataContext,
158
186
  TNextInput,
159
187
  TNextOutput,
160
- TNextPrimitiveOutput
188
+ TNextPrimitiveOutput,
189
+ TNextDataContext
161
190
  >,
162
191
  nextFormatterOptions?: FormatterOptions,
163
192
  ) => {
164
- const nextFormatter: Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput> = makeFormatter(
165
- (value, usageSuggestions, dataContext) => {
166
- const delegate: FormatMethod<TInput, TOutput, TPrimitiveOutput> = (
193
+ const nextFormatter = makeFormatter<
194
+ TNextInput,
195
+ TNextOutput,
196
+ TNextPrimitiveOutput,
197
+ TNextDataContext
198
+ >((value, suggestions, dataContext) => {
199
+ const delegate: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext> = (
200
+ delegatedValue,
201
+ delegatedSuggestions,
202
+ delegatedDataContext,
203
+ ) =>
204
+ formatter.format(
167
205
  delegatedValue,
168
- delegatedUsageSuggestions,
169
- delegatedDataContext,
170
- ) =>
171
- formatter.format(
172
- delegatedValue,
173
- delegatedUsageSuggestions ?? usageSuggestions,
174
- delegatedDataContext ?? dataContext,
175
- ) as any
176
-
177
- return nextFormat(delegate, value, usageSuggestions, dataContext) as any
178
- },
179
- nextFormatterOptions ?? formatterOptions,
180
- )
206
+ delegatedSuggestions ?? suggestions,
207
+ delegatedDataContext ?? dataContext,
208
+ )
209
+
210
+ return nextFormat(delegate, value, suggestions, dataContext)
211
+ }, nextFormatterOptions ?? formatterOptions)
181
212
 
182
213
  nextFormatter.innerFormatter = formatter
183
214