afformative 0.6.3 → 0.7.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -101
- package/dist/index.d.mts +33 -0
- package/dist/index.mjs +14 -0
- package/package.json +35 -12
- package/dist/afformative.cjs.js +0 -61
- package/dist/afformative.esm.js +0 -53
- package/dist/afformative.umd.js +0 -96
- package/dist/afformative.umd.min.js +0 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/makeFormatter.d.ts +0 -97
- package/dist/types/makeFormatter.d.ts.map +0 -1
- package/src/index.ts +0 -1
- package/src/makeFormatter.test.ts +0 -218
- package/src/makeFormatter.ts +0 -219
- package/tsconfig.build.json +0 -6
package/README.md
CHANGED
|
@@ -11,11 +11,11 @@ A standardized way to format values in your React components.
|
|
|
11
11
|
</h3>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
|
-
Afformative helps UI component libraries
|
|
14
|
+
Afformative helps UI component libraries display arbitrary data in a reusable, plug-and-play fashion. Formatting dates and enum translations in your select fields and data grids has never been easier.
|
|
15
15
|
</p>
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
|
-
<a href="https://github.com/wafflepie/
|
|
18
|
+
<a href="https://github.com/wafflepie/afformative/blob/master/LICENSE">
|
|
19
19
|
<img src="https://flat.badgen.net/badge/license/MIT/blue" alt="MIT License" />
|
|
20
20
|
</a>
|
|
21
21
|
|
|
@@ -26,94 +26,113 @@ Afformative helps UI component libraries visualise arbitrary data in a reusable,
|
|
|
26
26
|
|
|
27
27
|
## Installation
|
|
28
28
|
|
|
29
|
-
Use
|
|
29
|
+
Use one of these commands, depending on your preferred package manager:
|
|
30
30
|
|
|
31
31
|
```sh
|
|
32
32
|
yarn add afformative
|
|
33
33
|
|
|
34
|
+
pnpm add afformative
|
|
35
|
+
|
|
34
36
|
npm i afformative
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
## Quick Start
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
### The Holy Standard
|
|
41
|
+
A formatter is an object with `format`, `stringify`, and `compare` methods. Formatters must be created using the `createFormatter` function.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
`createFormatter` accepts a single object parameter. `format` is the only required property, but specifying `stringify` is recommended in most cases.
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
```tsx
|
|
46
|
+
import { createFormatter } from "afformative"
|
|
47
|
+
import { ReactNode } from "react"
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
const dateFormatter = createFormatter<Date, ReactNode>({
|
|
50
|
+
format: value => <time dateTime={value.toISOString()}>{value.toLocaleDateString()}</time>,
|
|
51
|
+
stringify: value => value.toLocaleDateString(),
|
|
52
|
+
})
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
dateFormatter.format(new Date()) // <time dateTime="2026-05-30T09:17:26.263Z">30/05/2026</time>
|
|
55
|
+
dateFormatter.formatAsString(new Date()) // "30/05/2026"
|
|
53
56
|
```
|
|
54
57
|
|
|
55
|
-
Consume formatters in your UI component library
|
|
58
|
+
Consume formatters in your UI component library via a conventional `formatter` prop.
|
|
56
59
|
|
|
57
|
-
```
|
|
58
|
-
import {
|
|
60
|
+
```tsx
|
|
61
|
+
import { Formatter } from "afformative"
|
|
62
|
+
import { ReactNode } from "react"
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<select {...otherProps}>
|
|
65
|
-
{items.map(item => {
|
|
66
|
-
const text = formatter.format(item)
|
|
64
|
+
interface ListProps<TItem> {
|
|
65
|
+
formatter: Formatter<TItem, ReactNode>
|
|
66
|
+
items: TItem[]
|
|
67
|
+
}
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
</select>
|
|
69
|
+
const List = <TItem extends unknown>({ formatter, items }: ListProps<TItem>) => (
|
|
70
|
+
<ul>
|
|
71
|
+
{items.map(item => (
|
|
72
|
+
<li key={formatter.stringify(item)}>{formatter.format(item)}</li>
|
|
73
|
+
))}
|
|
74
|
+
</ul>
|
|
75
75
|
)
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
Although formatters can render icons or custom translation components, we often need to access primitive data instead of React elements.
|
|
78
|
+
The `stringify` method is useful when you need a plain string representation of a value. For example, a combobox component can use it to match items against the user's typed input.
|
|
81
79
|
|
|
82
|
-
|
|
80
|
+
## Compare
|
|
83
81
|
|
|
84
|
-
|
|
82
|
+
Every formatter exposes a `compare` method, which can be used to sort values. The default implementation compares the return values of `stringify` via `localeCompare`. In the following example, `Amount` objects are sorted first by currency, then by value.
|
|
85
83
|
|
|
86
|
-
```
|
|
87
|
-
import {
|
|
84
|
+
```tsx
|
|
85
|
+
import { createFormatter } from "afformative"
|
|
86
|
+
import { ReactNode } from "react"
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
interface Amount {
|
|
89
|
+
currency: string
|
|
90
|
+
value: number
|
|
91
|
+
}
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
const amountFormatter = createFormatter<Amount, ReactNode>({
|
|
94
|
+
format: ({ currency, value }) => (
|
|
95
|
+
<span className="currency">{`${currency} ${value.toFixed(2)}`}</span>
|
|
96
|
+
),
|
|
97
|
+
stringify: ({ currency, value }) => `${currency} ${value.toFixed(2)}`,
|
|
98
|
+
compare: (a, b) => a.currency.localeCompare(b.currency) || a.value - b.value,
|
|
95
99
|
})
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
const amounts: Amount[] = [
|
|
102
|
+
{ currency: "USD", value: 3 },
|
|
103
|
+
{ currency: "EUR", value: 1 },
|
|
104
|
+
{ currency: "EUR", value: 5 },
|
|
105
|
+
{ currency: "USD", value: 2 },
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
amounts.sort(amountFormatter.compare)
|
|
109
|
+
// [{ EUR, 1 }, { EUR, 5 }, { USD, 2 }, { USD, 3 }]
|
|
99
110
|
```
|
|
100
111
|
|
|
101
|
-
|
|
112
|
+
## Usage Context
|
|
102
113
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
You can pass an optional usage context object to all formatter methods. Let's use a dummy table component as an example.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { Formatter } from "afformative"
|
|
118
|
+
import { ReactNode } from "react"
|
|
107
119
|
|
|
108
|
-
|
|
120
|
+
interface TableFormatterUsageContext {
|
|
121
|
+
row: number[]
|
|
122
|
+
cellIndex: number
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
interface TableProps {
|
|
126
|
+
rows: number[][]
|
|
127
|
+
formatter: Formatter<number, ReactNode, TableFormatterUsageContext>
|
|
128
|
+
}
|
|
109
129
|
|
|
110
|
-
|
|
111
|
-
const Table = ({ rows, formatter = identityFormatter }) => (
|
|
130
|
+
const Table = ({ rows, formatter }: TableProps) => (
|
|
112
131
|
<table>
|
|
113
132
|
{rows.map(row => (
|
|
114
133
|
<tr>
|
|
115
134
|
{row.map((cell, cellIndex) => (
|
|
116
|
-
<td>{formatter.format(cell,
|
|
135
|
+
<td>{formatter.format(cell, { row, cellIndex })}</td>
|
|
117
136
|
))}
|
|
118
137
|
</tr>
|
|
119
138
|
))}
|
|
@@ -121,72 +140,49 @@ const Table = ({ rows, formatter = identityFormatter }) => (
|
|
|
121
140
|
)
|
|
122
141
|
```
|
|
123
142
|
|
|
124
|
-
|
|
143
|
+
Usage context allows the users of this table component to write purpose-built formatters, making it possible to take other values in the same row into account. For example, the following formatter would change the color of the cell value based on the previous value in the same row.
|
|
125
144
|
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return <span>{value}</span>
|
|
130
|
-
}
|
|
145
|
+
```tsx
|
|
146
|
+
import { createFormatter } from "afformative"
|
|
147
|
+
import { ReactNode } from "react"
|
|
131
148
|
|
|
132
|
-
|
|
149
|
+
import { TableFormatterUsageContext } from "./Table"
|
|
133
150
|
|
|
134
|
-
|
|
151
|
+
const rowTrendFormatter = createFormatter<number, ReactNode, TableFormatterUsageContext>({
|
|
152
|
+
format: (value, { row, cellIndex }) => {
|
|
153
|
+
if (cellIndex === 0) {
|
|
154
|
+
return <span>{value}</span>
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const previousValue = row[cellIndex - 1]
|
|
158
|
+
|
|
159
|
+
return <span style={{ color: value >= previousValue ? "green" : "red" }}>{value}</span>
|
|
160
|
+
},
|
|
135
161
|
})
|
|
136
162
|
```
|
|
137
163
|
|
|
138
|
-
|
|
164
|
+
This formatter only makes sense in the context of our table component.
|
|
139
165
|
|
|
140
|
-
Because `row` and `cellIndex` are passed as the
|
|
166
|
+
Because `row` and `cellIndex` are passed as the usage context, the formatter still receives only the cell value as its first parameter. This means generic formatters (e.g. a currency formatter) can be passed to the table component without any changes.
|
|
141
167
|
|
|
142
|
-
|
|
168
|
+
## Accessing React Context
|
|
143
169
|
|
|
144
|
-
|
|
170
|
+
Create formatters inside custom hooks to access React context values such as translations or application state.
|
|
145
171
|
|
|
146
|
-
```
|
|
147
|
-
const useEnumFormatter = enumType => {
|
|
148
|
-
|
|
149
|
-
// `makeSelectEnumTranslationKeys` is a made-up Redux selector factory.
|
|
150
|
-
const enumTranslationKeys = useSelector(makeSelectEnumTranslationKeys(enumType))
|
|
172
|
+
```tsx
|
|
173
|
+
const useEnumFormatter = (enumType: string): Formatter<string, ReactNode> => {
|
|
174
|
+
const enumTranslationKeys = useSelector(selectEnumTranslationKeys(enumType))
|
|
151
175
|
const intl = useIntl()
|
|
152
176
|
|
|
153
177
|
return useMemo(
|
|
154
178
|
() =>
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
id: enumTranslationKeys[value],
|
|
159
|
-
}),
|
|
179
|
+
createFormatter<string, ReactNode>(
|
|
180
|
+
value => <FormattedMessage defaultMessage={value} id={enumTranslationKeys[value]} />,
|
|
181
|
+
value => intl.formatMessage({ defaultMessage: value, id: enumTranslationKeys[value] }),
|
|
160
182
|
),
|
|
161
183
|
[intl, enumTranslationKeys],
|
|
162
184
|
)
|
|
163
185
|
}
|
|
164
|
-
|
|
165
|
-
const someEnumFormatter = useEnumFormatter("someEnum")
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
### Consuming Formatters
|
|
169
|
-
|
|
170
|
-
As mentioned earlier, formatters should be passed to components using the conventional `formatter` prop. Alternatively, if you need to pass multiple formatters (e.g. in case of column definitions), pass an array of objects where each object has a `formatter` property.
|
|
171
|
-
|
|
172
|
-
All formatters also expose the `wrap` method. You can use this method to alter the behaviour of the formatter for some specific values.
|
|
173
|
-
|
|
174
|
-
```js
|
|
175
|
-
const useSnowflakeAwareFormatter = formatter => {
|
|
176
|
-
const intl = useIntl()
|
|
177
|
-
|
|
178
|
-
return useMemo(
|
|
179
|
-
() =>
|
|
180
|
-
formatter.wrap((delegate, value) => {
|
|
181
|
-
if (isSnowflake(value)) {
|
|
182
|
-
return intl.formatMessage(messages.snowflake)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return delegate(value)
|
|
186
|
-
}),
|
|
187
|
-
[formatter, intl],
|
|
188
|
-
)
|
|
189
|
-
}
|
|
190
186
|
```
|
|
191
187
|
|
|
192
188
|
## Changelog
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/createFormatter.d.ts
|
|
2
|
+
interface FormatterFormatDefinition<TInput, TOutput, TUsageContext extends object = object> {
|
|
3
|
+
(value: TInput, usageContext: Partial<TUsageContext>): TOutput;
|
|
4
|
+
}
|
|
5
|
+
interface FormatterFormat<TInput, TOutput, TUsageContext extends object = object> {
|
|
6
|
+
(value: TInput, usageContext?: Partial<TUsageContext>): TOutput;
|
|
7
|
+
}
|
|
8
|
+
interface FormatterStringifyDefinition<TInput, TUsageContext extends object = object> {
|
|
9
|
+
(value: TInput, usageContext: Partial<TUsageContext>): string;
|
|
10
|
+
}
|
|
11
|
+
interface FormatterStringify<TInput, TUsageContext extends object = object> {
|
|
12
|
+
(value: TInput, usageContext?: Partial<TUsageContext>): string;
|
|
13
|
+
}
|
|
14
|
+
interface FormatterCompareDefinition<TInput, TUsageContext extends object = object> {
|
|
15
|
+
(a: TInput, b: TInput, usageContext: Partial<TUsageContext>): number;
|
|
16
|
+
}
|
|
17
|
+
interface FormatterCompare<TInput, TUsageContext extends object = object> {
|
|
18
|
+
(a: TInput, b: TInput, usageContext?: Partial<TUsageContext>): number;
|
|
19
|
+
}
|
|
20
|
+
interface Formatter<TInput, TOutput, TUsageContext extends object = object> {
|
|
21
|
+
compare: FormatterCompare<TInput, TUsageContext>;
|
|
22
|
+
format: FormatterFormat<TInput, TOutput, TUsageContext>;
|
|
23
|
+
stringify: FormatterStringify<TInput, TUsageContext>;
|
|
24
|
+
name?: string;
|
|
25
|
+
}
|
|
26
|
+
interface CreateFormatterParam<TInput, TOutput, TUsageContext extends object = object> {
|
|
27
|
+
compare?: FormatterCompareDefinition<TInput, TUsageContext>;
|
|
28
|
+
format: FormatterFormatDefinition<TInput, TOutput, TUsageContext>;
|
|
29
|
+
stringify?: FormatterStringifyDefinition<TInput, TUsageContext>;
|
|
30
|
+
}
|
|
31
|
+
declare const createFormatter: <TInput, TOutput, TUsageContext extends object = object>(param: CreateFormatterParam<TInput, TOutput, TUsageContext>) => Formatter<TInput, TOutput, TUsageContext>;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { CreateFormatterParam, Formatter, FormatterCompare, FormatterCompareDefinition, FormatterFormat, FormatterFormatDefinition, FormatterStringify, FormatterStringifyDefinition, createFormatter };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/createFormatter.ts
|
|
2
|
+
const createFormatter = (param) => {
|
|
3
|
+
const { format: formatParam, stringify: stringifyParam, compare: compareParam, ...rest } = param;
|
|
4
|
+
const format = (value, usageContext) => formatParam(value, usageContext ?? {});
|
|
5
|
+
const stringify = stringifyParam ? (value, usageContext) => stringifyParam(value, usageContext ?? {}) : (value, usageContext) => String(format(value, usageContext ?? {}));
|
|
6
|
+
return {
|
|
7
|
+
compare: compareParam ? (a, b, usageContext) => compareParam(a, b, usageContext ?? {}) : (a, b, usageContext) => stringify(a, usageContext ?? {}).localeCompare(stringify(b, usageContext ?? {})),
|
|
8
|
+
format,
|
|
9
|
+
stringify,
|
|
10
|
+
...rest
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createFormatter };
|
package/package.json
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "afformative",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"license": "MIT",
|
|
5
|
-
"main": "dist/afformative.cjs.js",
|
|
6
|
-
"module": "dist/afformative.esm.js",
|
|
7
|
-
"unpkg": "dist/afformative.umd.js",
|
|
8
|
-
"types": "dist/types/index.d.ts",
|
|
3
|
+
"version": "0.7.0-beta.1",
|
|
9
4
|
"description": "A standardized way to format values in your React components.",
|
|
10
5
|
"keywords": [
|
|
11
6
|
"react",
|
|
@@ -24,15 +19,43 @@
|
|
|
24
19
|
"values"
|
|
25
20
|
],
|
|
26
21
|
"repository": "https://github.com/wafflepie/afformative",
|
|
22
|
+
"license": "MIT",
|
|
27
23
|
"contributors": [
|
|
28
|
-
"Vaclav Jancarik <
|
|
24
|
+
"Vaclav Jancarik <hi@wafflepie.dev>"
|
|
25
|
+
],
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": "./dist/index.mjs",
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist"
|
|
29
34
|
],
|
|
30
|
-
"
|
|
31
|
-
"
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsdown",
|
|
37
|
+
"prepublishOnly": "pnpm run build",
|
|
38
|
+
"release": "bumpp",
|
|
39
|
+
"test": "pnpm test:prettier && pnpm run test:typescript && pnpm run test:eslint && pnpm run test:vitest",
|
|
40
|
+
"test:eslint": "eslint src",
|
|
41
|
+
"test:prettier": "prettier --check src",
|
|
42
|
+
"test:typescript": "tsc --noEmit",
|
|
43
|
+
"test:vitest": "vitest run"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@eslint/js": "^10.0.1",
|
|
47
|
+
"@types/node": "^25.6.2",
|
|
48
|
+
"@typescript/native-preview": "^7.0.0-dev.20260527.2",
|
|
49
|
+
"bumpp": "^11.1.0",
|
|
50
|
+
"eslint": "^10.4.1",
|
|
51
|
+
"prettier": "^3.8.3",
|
|
52
|
+
"tsdown": "^0.22.1",
|
|
53
|
+
"typescript": "^6.0.3",
|
|
54
|
+
"typescript-eslint": "^8.60.0",
|
|
55
|
+
"vitest": "^4.1.7"
|
|
32
56
|
},
|
|
57
|
+
"packageManager": "pnpm@11.5.0+sha512.dbfcc4f81cf48597afd4bc391ffdf12c11f1a9fb83a395bfa6b0a2d9cc2fd8ffebafdb1ccbd529632153f793904c2615b7f09fe1a345473fd1c35845172a8eb1",
|
|
33
58
|
"publishConfig": {
|
|
34
59
|
"access": "public"
|
|
35
|
-
}
|
|
36
|
-
"sideEffects": false,
|
|
37
|
-
"gitHead": "ddc8c8682e2777c730108466792b7670d8a43f06"
|
|
60
|
+
}
|
|
38
61
|
}
|
package/dist/afformative.cjs.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
|
|
6
|
-
|
|
7
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
-
|
|
9
|
-
var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray);
|
|
10
|
-
|
|
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
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Creates a new formatter.
|
|
21
|
-
*
|
|
22
|
-
* @param format Function used to format the value.
|
|
23
|
-
* @param formatterOptions Additional options for the formatter.
|
|
24
|
-
*/
|
|
25
|
-
var makeFormatter = function makeFormatter(format, formatterOptions) {
|
|
26
|
-
var formatter = function formatter(props) {
|
|
27
|
-
var _format, _props$suggestions;
|
|
28
|
-
|
|
29
|
-
return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
|
|
33
|
-
|
|
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);
|
|
38
|
-
};
|
|
39
|
-
|
|
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);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
formatter.wrap = function (nextFormat, nextFormatterOptions) {
|
|
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);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return nextFormat(delegate, value, suggestions, dataContext);
|
|
53
|
-
}, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
|
|
54
|
-
nextFormatter.innerFormatter = formatter;
|
|
55
|
-
return nextFormatter;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
return formatter;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
exports.makeFormatter = makeFormatter;
|
package/dist/afformative.esm.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
|
|
2
|
-
|
|
3
|
-
var ensureFormatSuggestionIntegrity = function ensureFormatSuggestionIntegrity(suggestions) {
|
|
4
|
-
return suggestions.includes("primitive") || !suggestions.includes("comparable") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
var ensureFormatAsPrimitiveSuggestionIntegrity = function ensureFormatAsPrimitiveSuggestionIntegrity(suggestions) {
|
|
8
|
-
return suggestions.includes("primitive") ? suggestions : ["primitive"].concat(_toConsumableArray(suggestions));
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Creates a new formatter.
|
|
13
|
-
*
|
|
14
|
-
* @param format Function used to format the value.
|
|
15
|
-
* @param formatterOptions Additional options for the formatter.
|
|
16
|
-
*/
|
|
17
|
-
var makeFormatter = function makeFormatter(format, formatterOptions) {
|
|
18
|
-
var formatter = function formatter(props) {
|
|
19
|
-
var _format, _props$suggestions;
|
|
20
|
-
|
|
21
|
-
return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
|
|
25
|
-
|
|
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);
|
|
30
|
-
};
|
|
31
|
-
|
|
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);
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
formatter.wrap = function (nextFormat, nextFormatterOptions) {
|
|
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);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
return nextFormat(delegate, value, suggestions, dataContext);
|
|
45
|
-
}, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
|
|
46
|
-
nextFormatter.innerFormatter = formatter;
|
|
47
|
-
return nextFormatter;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
return formatter;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export { makeFormatter };
|
package/dist/afformative.umd.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Afformative = {}));
|
|
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];
|
|
12
|
-
}
|
|
13
|
-
|
|
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.");
|
|
36
|
-
}
|
|
37
|
-
|
|
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
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Creates a new formatter.
|
|
52
|
-
*
|
|
53
|
-
* @param format Function used to format the value.
|
|
54
|
-
* @param formatterOptions Additional options for the formatter.
|
|
55
|
-
*/
|
|
56
|
-
var makeFormatter = function makeFormatter(format, formatterOptions) {
|
|
57
|
-
var formatter = function formatter(props) {
|
|
58
|
-
var _format, _props$suggestions;
|
|
59
|
-
|
|
60
|
-
return (_format = format(props.children, (_props$suggestions = props.suggestions) !== null && _props$suggestions !== void 0 ? _props$suggestions : [], props)) !== null && _format !== void 0 ? _format : null;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
formatter.displayName = formatterOptions === null || formatterOptions === void 0 ? void 0 : formatterOptions.displayName;
|
|
64
|
-
|
|
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);
|
|
69
|
-
};
|
|
70
|
-
|
|
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);
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
formatter.wrap = function (nextFormat, nextFormatterOptions) {
|
|
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);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
return nextFormat(delegate, value, suggestions, dataContext);
|
|
84
|
-
}, nextFormatterOptions !== null && nextFormatterOptions !== void 0 ? nextFormatterOptions : formatterOptions);
|
|
85
|
-
nextFormatter.innerFormatter = formatter;
|
|
86
|
-
return nextFormatter;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
return formatter;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
exports.makeFormatter = makeFormatter;
|
|
93
|
-
|
|
94
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
95
|
-
|
|
96
|
-
}));
|
|
@@ -1 +0,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})}));
|
package/dist/types/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA"}
|
|
@@ -1,97 +0,0 @@
|
|
|
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>;
|
|
8
|
-
interface FormatterOptions {
|
|
9
|
-
/** Formatter name, useful for debugging or advanced pattern matching. */
|
|
10
|
-
displayName?: string;
|
|
11
|
-
}
|
|
12
|
-
interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
|
|
13
|
-
(
|
|
14
|
-
/** Value to format. */
|
|
15
|
-
value: TInput,
|
|
16
|
-
/** Suggestions passed by the consumer of a formatter. */
|
|
17
|
-
suggestions: Suggestion[],
|
|
18
|
-
/** Additional data context to be used by the formatter. */
|
|
19
|
-
dataContext: Partial<TDataContext>): TOutput | TPrimitiveOutput;
|
|
20
|
-
}
|
|
21
|
-
interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
|
|
22
|
-
(
|
|
23
|
-
/** Value to format. */
|
|
24
|
-
value: TInput,
|
|
25
|
-
/** Suggestions the formatter should take note of. */
|
|
26
|
-
suggestions?: Suggestion[],
|
|
27
|
-
/** Additional data context the formatter might find useful. */
|
|
28
|
-
dataContext?: Partial<TDataContext>): TOutput | TPrimitiveOutput;
|
|
29
|
-
}
|
|
30
|
-
interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
|
|
31
|
-
(
|
|
32
|
-
/** Value to format. */
|
|
33
|
-
value: TInput,
|
|
34
|
-
/** Suggestions the formatter should take note of in addition to `primitive`. */
|
|
35
|
-
suggestions?: Suggestion[],
|
|
36
|
-
/** Additional data context the formatter might find useful. */
|
|
37
|
-
dataContext?: Partial<TDataContext>): TPrimitiveOutput;
|
|
38
|
-
}
|
|
39
|
-
interface FormatChainDefinition<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext extends DataContext, TOuterInput, TOuterOutput, TOuterPrimitiveOutput, TOuterDataContext extends DataContext> {
|
|
40
|
-
(
|
|
41
|
-
/**
|
|
42
|
-
* The `formatter.format` method which can be used to delegate the formatting
|
|
43
|
-
* to the wrapped formatter. Delegation is simplified so if no suggestions or contextual
|
|
44
|
-
* props are passed, the original ones are used instead.
|
|
45
|
-
*/
|
|
46
|
-
delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext>,
|
|
47
|
-
/** Value to format. */
|
|
48
|
-
value: TOuterInput,
|
|
49
|
-
/** Suggestions the formatter should take note of. */
|
|
50
|
-
suggestions: Suggestion[],
|
|
51
|
-
/** Additional data context the formatter might find useful. */
|
|
52
|
-
dataContext: Partial<TOuterDataContext>): TOuterOutput | TOuterPrimitiveOutput;
|
|
53
|
-
}
|
|
54
|
-
declare type FormatterProps<TInput, TDataContext extends DataContext> = {
|
|
55
|
-
/** Value to format. */
|
|
56
|
-
children: TInput;
|
|
57
|
-
/** Suggestions the formatter should take note of. */
|
|
58
|
-
suggestions?: Suggestion[];
|
|
59
|
-
} & Partial<TDataContext>;
|
|
60
|
-
export interface Formatter<TInput, TOutput, TPrimitiveOutput = TOutput, TDataContext extends DataContext = DataContext> {
|
|
61
|
-
/** Formatter name, useful for debugging or advanced pattern matching. */
|
|
62
|
-
displayName?: string;
|
|
63
|
-
/** Formats a value. */
|
|
64
|
-
format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>;
|
|
65
|
-
/** Formats a value with the `primitive` suggestion. */
|
|
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>;
|
|
69
|
-
/**
|
|
70
|
-
* Creates a new formatter from an existing one. Allows overriding of formatter behaviour
|
|
71
|
-
* for certain values.
|
|
72
|
-
*/
|
|
73
|
-
wrap: <TNextInput = TInput, TNextOutput = TOutput, TNextPrimitiveOutput = TPrimitiveOutput, TNextDataContext extends TDataContext = TDataContext>(
|
|
74
|
-
/**
|
|
75
|
-
* Function used to format the value. Has the same signature as the one passed
|
|
76
|
-
* to `makeFormatter`, except a `delegate` function is passed in the first position.
|
|
77
|
-
* This function can be used to delegate formatting to the original (inner) formatter.
|
|
78
|
-
*/
|
|
79
|
-
nextFormat: FormatChainDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext, TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>,
|
|
80
|
-
/** New formatter options, replacing the original ones. */
|
|
81
|
-
nextFormatterOptions?: FormatterOptions) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>;
|
|
82
|
-
/**
|
|
83
|
-
* Backwards-compatible way to use the formatter as a React component.
|
|
84
|
-
*
|
|
85
|
-
* @deprecated Since v0.6.0. Prefer using the `format` method instead.
|
|
86
|
-
*/
|
|
87
|
-
(props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Creates a new formatter.
|
|
91
|
-
*
|
|
92
|
-
* @param format Function used to format the value.
|
|
93
|
-
* @param formatterOptions Additional options for the formatter.
|
|
94
|
-
*/
|
|
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>;
|
|
96
|
-
export {};
|
|
97
|
-
//# sourceMappingURL=makeFormatter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"makeFormatter.d.ts","sourceRoot":"","sources":["../../src/makeFormatter.ts"],"names":[],"mappings":"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"}
|
package/src/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./makeFormatter"
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import { makeFormatter } from "./makeFormatter"
|
|
2
|
-
|
|
3
|
-
const toUpperCase = (string: string) => string.toUpperCase()
|
|
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
|
-
|
|
21
|
-
describe("makeFormatter", () => {
|
|
22
|
-
const format = jest.fn()
|
|
23
|
-
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
jest.clearAllMocks()
|
|
26
|
-
})
|
|
27
|
-
|
|
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
|
-
})
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
describe("format", () => {
|
|
37
|
-
it("handles trivial formatting", () => {
|
|
38
|
-
expect(upperCaseFormatter.format("foo")).toBe("FOO")
|
|
39
|
-
})
|
|
40
|
-
|
|
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"])
|
|
45
|
-
})
|
|
46
|
-
|
|
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
|
-
})
|
|
52
|
-
|
|
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
|
-
})
|
|
58
|
-
|
|
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
|
-
})
|
|
64
|
-
|
|
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"])
|
|
69
|
-
})
|
|
70
|
-
|
|
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
|
-
})
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
describe("formatAsPrimitive", () => {
|
|
91
|
-
it("handles trivial formatting", () => {
|
|
92
|
-
expect(upperCaseFormatter.formatAsPrimitive("foo")).toBe("FOO")
|
|
93
|
-
})
|
|
94
|
-
|
|
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
|
-
})
|
|
100
|
-
|
|
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
|
-
})
|
|
118
|
-
|
|
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
|
-
})
|
|
124
|
-
|
|
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
|
-
})
|
|
130
|
-
|
|
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
|
-
})
|
|
136
|
-
})
|
|
137
|
-
|
|
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
|
-
})
|
|
143
|
-
|
|
144
|
-
it("handles single-value mapping", () => {
|
|
145
|
-
const formatter = makeFormatter<string, string>(format).wrap((delegate, value) =>
|
|
146
|
-
value === "ping" ? "pong" : delegate(value),
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
expect(formatter.format("ping")).toBe("pong")
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
it("handles delegation to the original formatter", () => {
|
|
153
|
-
const formatter = upperCaseFormatter.wrap((delegate, value) =>
|
|
154
|
-
value === "ping" ? "pong" : delegate(value),
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
expect(formatter.format("foo")).toBe("FOO")
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
it("sets the `innerFormatter` property", () => {
|
|
161
|
-
const wrappedFormatter = upperCaseFormatter.wrap((delegate, value) => delegate(value))
|
|
162
|
-
expect(wrappedFormatter.innerFormatter).toBe(upperCaseFormatter)
|
|
163
|
-
})
|
|
164
|
-
|
|
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
|
-
})
|
|
169
|
-
|
|
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
|
-
})
|
|
174
|
-
|
|
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" })
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
it("supports modifying the input structure", () => {
|
|
181
|
-
const formatter = upperCaseFormatter.wrap<ValueRecord>((delegate, { value }) =>
|
|
182
|
-
delegate(value),
|
|
183
|
-
)
|
|
184
|
-
|
|
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
|
-
})
|
|
217
|
-
})
|
|
218
|
-
})
|
package/src/makeFormatter.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
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>
|
|
23
|
-
|
|
24
|
-
interface FormatterOptions {
|
|
25
|
-
/** Formatter name, useful for debugging or advanced pattern matching. */
|
|
26
|
-
displayName?: string
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
|
|
30
|
-
(
|
|
31
|
-
/** Value to format. */
|
|
32
|
-
value: TInput,
|
|
33
|
-
/** Suggestions passed by the consumer of a formatter. */
|
|
34
|
-
suggestions: Suggestion[],
|
|
35
|
-
/** Additional data context to be used by the formatter. */
|
|
36
|
-
dataContext: Partial<TDataContext>,
|
|
37
|
-
): TOutput | TPrimitiveOutput
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
interface FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext extends DataContext> {
|
|
41
|
-
(
|
|
42
|
-
/** Value to format. */
|
|
43
|
-
value: TInput,
|
|
44
|
-
/** Suggestions the formatter should take note of. */
|
|
45
|
-
suggestions?: Suggestion[],
|
|
46
|
-
/** Additional data context the formatter might find useful. */
|
|
47
|
-
dataContext?: Partial<TDataContext>,
|
|
48
|
-
): TOutput | TPrimitiveOutput
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
interface FormatAsPrimitiveMethod<TInput, TPrimitiveOutput, TDataContext extends DataContext> {
|
|
52
|
-
(
|
|
53
|
-
/** Value to format. */
|
|
54
|
-
value: TInput,
|
|
55
|
-
/** Suggestions the formatter should take note of in addition to `primitive`. */
|
|
56
|
-
suggestions?: Suggestion[],
|
|
57
|
-
/** Additional data context the formatter might find useful. */
|
|
58
|
-
dataContext?: Partial<TDataContext>,
|
|
59
|
-
): TPrimitiveOutput
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
interface FormatChainDefinition<
|
|
63
|
-
TInnerInput,
|
|
64
|
-
TInnerOutput,
|
|
65
|
-
TInnerPrimitiveInput,
|
|
66
|
-
TInnerDataContext extends DataContext,
|
|
67
|
-
TOuterInput,
|
|
68
|
-
TOuterOutput,
|
|
69
|
-
TOuterPrimitiveOutput,
|
|
70
|
-
TOuterDataContext extends DataContext
|
|
71
|
-
> {
|
|
72
|
-
(
|
|
73
|
-
/**
|
|
74
|
-
* The `formatter.format` method which can be used to delegate the formatting
|
|
75
|
-
* to the wrapped formatter. Delegation is simplified so if no suggestions or contextual
|
|
76
|
-
* props are passed, the original ones are used instead.
|
|
77
|
-
*/
|
|
78
|
-
delegate: FormatMethod<TInnerInput, TInnerOutput, TInnerPrimitiveInput, TInnerDataContext>,
|
|
79
|
-
/** Value to format. */
|
|
80
|
-
value: TOuterInput,
|
|
81
|
-
/** Suggestions the formatter should take note of. */
|
|
82
|
-
suggestions: Suggestion[],
|
|
83
|
-
/** Additional data context the formatter might find useful. */
|
|
84
|
-
dataContext: Partial<TOuterDataContext>,
|
|
85
|
-
): TOuterOutput | TOuterPrimitiveOutput
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
type FormatterProps<TInput, TDataContext extends DataContext> = {
|
|
89
|
-
/** Value to format. */
|
|
90
|
-
children: TInput
|
|
91
|
-
/** Suggestions the formatter should take note of. */
|
|
92
|
-
suggestions?: Suggestion[]
|
|
93
|
-
} & Partial<TDataContext>
|
|
94
|
-
|
|
95
|
-
export interface Formatter<
|
|
96
|
-
TInput,
|
|
97
|
-
TOutput,
|
|
98
|
-
TPrimitiveOutput = TOutput,
|
|
99
|
-
TDataContext extends DataContext = DataContext
|
|
100
|
-
> {
|
|
101
|
-
/** Formatter name, useful for debugging or advanced pattern matching. */
|
|
102
|
-
displayName?: string
|
|
103
|
-
/** Formats a value. */
|
|
104
|
-
format: FormatMethod<TInput, TOutput, TPrimitiveOutput, TDataContext>
|
|
105
|
-
/** Formats a value with the `primitive` suggestion. */
|
|
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>
|
|
109
|
-
/**
|
|
110
|
-
* Creates a new formatter from an existing one. Allows overriding of formatter behaviour
|
|
111
|
-
* for certain values.
|
|
112
|
-
*/
|
|
113
|
-
wrap: <
|
|
114
|
-
TNextInput = TInput,
|
|
115
|
-
TNextOutput = TOutput,
|
|
116
|
-
TNextPrimitiveOutput = TPrimitiveOutput,
|
|
117
|
-
TNextDataContext extends TDataContext = TDataContext
|
|
118
|
-
>(
|
|
119
|
-
/**
|
|
120
|
-
* Function used to format the value. Has the same signature as the one passed
|
|
121
|
-
* to `makeFormatter`, except a `delegate` function is passed in the first position.
|
|
122
|
-
* This function can be used to delegate formatting to the original (inner) formatter.
|
|
123
|
-
*/
|
|
124
|
-
nextFormat: FormatChainDefinition<
|
|
125
|
-
TInput,
|
|
126
|
-
TOutput,
|
|
127
|
-
TPrimitiveOutput,
|
|
128
|
-
TDataContext,
|
|
129
|
-
TNextInput,
|
|
130
|
-
TNextOutput,
|
|
131
|
-
TNextPrimitiveOutput,
|
|
132
|
-
TNextDataContext
|
|
133
|
-
>,
|
|
134
|
-
/** New formatter options, replacing the original ones. */
|
|
135
|
-
nextFormatterOptions?: FormatterOptions,
|
|
136
|
-
) => Formatter<TNextInput, TNextOutput, TNextPrimitiveOutput, TNextDataContext>
|
|
137
|
-
/**
|
|
138
|
-
* Backwards-compatible way to use the formatter as a React component.
|
|
139
|
-
*
|
|
140
|
-
* @deprecated Since v0.6.0. Prefer using the `format` method instead.
|
|
141
|
-
*/
|
|
142
|
-
(props: FormatterProps<TInput, TDataContext>): TOutput | TPrimitiveOutput | null
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Creates a new formatter.
|
|
147
|
-
*
|
|
148
|
-
* @param format Function used to format the value.
|
|
149
|
-
* @param formatterOptions Additional options for the formatter.
|
|
150
|
-
*/
|
|
151
|
-
export const makeFormatter = <
|
|
152
|
-
TInput,
|
|
153
|
-
TOutput,
|
|
154
|
-
TPrimitiveOutput = TOutput,
|
|
155
|
-
TDataContext extends DataContext = DataContext
|
|
156
|
-
>(
|
|
157
|
-
format: FormatDefinition<TInput, TOutput, TPrimitiveOutput, TDataContext>,
|
|
158
|
-
formatterOptions?: FormatterOptions,
|
|
159
|
-
): Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> => {
|
|
160
|
-
const formatter: Formatter<TInput, TOutput, TPrimitiveOutput, TDataContext> = props =>
|
|
161
|
-
format(props.children, props.suggestions ?? [], props) ?? null
|
|
162
|
-
|
|
163
|
-
formatter.displayName = formatterOptions?.displayName
|
|
164
|
-
|
|
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
|
-
>(
|
|
181
|
-
nextFormat: FormatChainDefinition<
|
|
182
|
-
TInput,
|
|
183
|
-
TOutput,
|
|
184
|
-
TPrimitiveOutput,
|
|
185
|
-
TDataContext,
|
|
186
|
-
TNextInput,
|
|
187
|
-
TNextOutput,
|
|
188
|
-
TNextPrimitiveOutput,
|
|
189
|
-
TNextDataContext
|
|
190
|
-
>,
|
|
191
|
-
nextFormatterOptions?: FormatterOptions,
|
|
192
|
-
) => {
|
|
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(
|
|
205
|
-
delegatedValue,
|
|
206
|
-
delegatedSuggestions ?? suggestions,
|
|
207
|
-
delegatedDataContext ?? dataContext,
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
return nextFormat(delegate, value, suggestions, dataContext)
|
|
211
|
-
}, nextFormatterOptions ?? formatterOptions)
|
|
212
|
-
|
|
213
|
-
nextFormatter.innerFormatter = formatter
|
|
214
|
-
|
|
215
|
-
return nextFormatter
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return formatter
|
|
219
|
-
}
|