@spark-web/field 1.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,14 @@
1
1
  /// <reference types="react" />
2
- export declare type FieldContextType = {
3
- 'aria-describedby'?: string;
4
- id: string;
2
+ export declare type FieldState = {
5
3
  disabled: boolean;
6
4
  invalid: boolean;
7
5
  };
6
+ export declare type InputPropsDerivedFromField = {
7
+ 'aria-describedby'?: string;
8
+ 'aria-invalid': true | undefined;
9
+ id: string;
10
+ };
11
+ export declare type FieldContextType = [FieldState, InputPropsDerivedFromField];
8
12
  export declare const FieldContext: import("react").Context<FieldContextType | null>;
9
13
  export declare const FieldContextProvider: import("react").Provider<FieldContextType | null>;
10
14
  export declare const FIELD_CONTEXT_ERROR_MESSAGE = "Input components must be inside a `Field`.";
@@ -1,4 +1,4 @@
1
1
  export { FieldContextProvider, useFieldContext } from './context';
2
2
  export { Field, FieldMessage, useFieldIds } from './Field';
3
- export type { FieldContextType } from './context';
3
+ export type { FieldContextType, FieldState, InputPropsDerivedFromField, } from './context';
4
4
  export type { FieldProps, Tone } from './Field';
@@ -3,8 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
- var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
7
- var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
8
6
  var css = require('@emotion/css');
9
7
  var a11y = require('@spark-web/a11y');
10
8
  var box = require('@spark-web/box');
@@ -12,7 +10,6 @@ var icon = require('@spark-web/icon');
12
10
  var stack = require('@spark-web/stack');
13
11
  var text = require('@spark-web/text');
14
12
  var theme = require('@spark-web/theme');
15
- var internal = require('@spark-web/utils/internal');
16
13
  var jsxRuntime = require('react/jsx-runtime');
17
14
 
18
15
  var FieldContext = /*#__PURE__*/react.createContext(null);
@@ -28,8 +25,6 @@ function useFieldContext() {
28
25
  return ctx;
29
26
  }
30
27
 
31
- var _excluded = ["children"];
32
-
33
28
  /**
34
29
  * Using a [context](https://reactjs.org/docs/context.html), the field
35
30
  * component connects the label, description, and message to the input element.
@@ -56,12 +51,15 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
56
51
  messageId = _useFieldIds.messageId; // field context
57
52
 
58
53
 
59
- var fieldContext = {
60
- 'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
61
- id: inputId,
54
+ var invalid = Boolean(message && tone === 'critical');
55
+ var fieldContext = [{
62
56
  disabled: disabled,
63
- invalid: Boolean(message && tone === 'critical')
64
- }; // label prep
57
+ invalid: invalid
58
+ }, {
59
+ 'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
60
+ 'aria-invalid': invalid || undefined,
61
+ id: inputId
62
+ }]; // label prep
65
63
 
66
64
  var hiddenLabel = /*#__PURE__*/jsxRuntime.jsxs(a11y.VisuallyHidden, {
67
65
  as: "label",
@@ -75,35 +73,31 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
75
73
  as: "label",
76
74
  htmlFor: inputId,
77
75
  children: /*#__PURE__*/jsxRuntime.jsxs(text.Text, {
78
- inline: true,
79
76
  tone: disabled ? 'disabled' : 'neutral',
80
77
  weight: "semibold",
81
78
  children: [label, ' ', secondaryLabel && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
82
79
  inline: true,
83
80
  tone: disabled ? 'disabled' : 'muted',
81
+ weight: "regular",
84
82
  children: secondaryLabel
85
83
  })]
86
84
  })
87
85
  }),
88
86
  'reserve-space': /*#__PURE__*/jsxRuntime.jsxs(react.Fragment, {
89
87
  children: [hiddenLabel, /*#__PURE__*/jsxRuntime.jsx(text.Text, {
90
- inline: true,
91
88
  "aria-hidden": true,
92
89
  children: "\xA0"
93
90
  })]
94
91
  })
95
92
  };
93
+ var LabelWrapper = labelVisibility === 'hidden' ? react.Fragment : FieldLabelWrapper;
96
94
  return /*#__PURE__*/jsxRuntime.jsx(FieldContextProvider, {
97
95
  value: fieldContext,
98
- children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack, _objectSpread(_objectSpread({
99
- gap: labelVisibility === 'hidden' ? undefined : 'small',
100
- ref: forwardedRef
101
- }, data ? internal.buildDataAttributes(data) : null), {}, {
102
- children: [/*#__PURE__*/jsxRuntime.jsxs(box.Box, {
103
- display: "flex",
104
- alignItems: "center",
105
- justifyContent: "spaceBetween",
106
- gap: "large",
96
+ children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack, {
97
+ ref: forwardedRef,
98
+ data: data,
99
+ gap: "medium",
100
+ children: [/*#__PURE__*/jsxRuntime.jsxs(LabelWrapper, {
107
101
  children: [labelElement[labelVisibility], adornment]
108
102
  }), description && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
109
103
  tone: "muted",
@@ -115,7 +109,7 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
115
109
  id: messageId,
116
110
  message: message
117
111
  })]
118
- }))
112
+ })
119
113
  });
120
114
  });
121
115
  Field.displayName = 'Field'; // Utils
@@ -133,6 +127,17 @@ function useFieldIds(id) {
133
127
  } // Styled components
134
128
  // ------------------------------
135
129
 
130
+ function FieldLabelWrapper(_ref2) {
131
+ var children = _ref2.children;
132
+ return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
133
+ display: "flex",
134
+ alignItems: "center",
135
+ justifyContent: "spaceBetween",
136
+ gap: "large",
137
+ children: children
138
+ });
139
+ }
140
+
136
141
  var messageToneMap = {
137
142
  critical: 'critical',
138
143
  neutral: 'muted',
@@ -144,10 +149,10 @@ var messageIconMap = {
144
149
  neutral: null,
145
150
  positive: icon.CheckCircleIcon
146
151
  };
147
- var FieldMessage = function FieldMessage(_ref2) {
148
- var message = _ref2.message,
149
- id = _ref2.id,
150
- tone = _ref2.tone;
152
+ var FieldMessage = function FieldMessage(_ref3) {
153
+ var message = _ref3.message,
154
+ id = _ref3.id,
155
+ tone = _ref3.tone;
151
156
  var textTone = messageToneMap[tone];
152
157
  var Icon = messageIconMap[tone];
153
158
  return /*#__PURE__*/jsxRuntime.jsxs(box.Box, {
@@ -167,9 +172,8 @@ var FieldMessage = function FieldMessage(_ref2) {
167
172
  });
168
173
  };
169
174
 
170
- function IndicatorContainer(_ref3) {
171
- var children = _ref3.children,
172
- props = _objectWithoutProperties(_ref3, _excluded);
175
+ function IndicatorContainer(_ref4) {
176
+ var children = _ref4.children;
173
177
 
174
178
  var _useTheme = theme.useTheme(),
175
179
  typography = _useTheme.typography,
@@ -186,16 +190,15 @@ function IndicatorContainer(_ref3) {
186
190
  height: tablet.capHeight
187
191
  }
188
192
  });
189
- return /*#__PURE__*/jsxRuntime.jsx(box.Box, _objectSpread(_objectSpread({
193
+ return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
190
194
  display: "flex",
191
195
  alignItems: "center",
192
196
  "aria-hidden": true,
193
197
  cursor: "default",
194
198
  flexShrink: 0,
195
- className: css.css(responsiveStyles)
196
- }, props), {}, {
199
+ className: css.css(responsiveStyles),
197
200
  children: children
198
- }));
201
+ });
199
202
  }
200
203
 
201
204
  exports.Field = Field;
@@ -3,8 +3,6 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var react = require('react');
6
- var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProperties');
7
- var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
8
6
  var css = require('@emotion/css');
9
7
  var a11y = require('@spark-web/a11y');
10
8
  var box = require('@spark-web/box');
@@ -12,7 +10,6 @@ var icon = require('@spark-web/icon');
12
10
  var stack = require('@spark-web/stack');
13
11
  var text = require('@spark-web/text');
14
12
  var theme = require('@spark-web/theme');
15
- var internal = require('@spark-web/utils/internal');
16
13
  var jsxRuntime = require('react/jsx-runtime');
17
14
 
18
15
  var FieldContext = /*#__PURE__*/react.createContext(null);
@@ -28,8 +25,6 @@ function useFieldContext() {
28
25
  return ctx;
29
26
  }
30
27
 
31
- var _excluded = ["children"];
32
-
33
28
  /**
34
29
  * Using a [context](https://reactjs.org/docs/context.html), the field
35
30
  * component connects the label, description, and message to the input element.
@@ -56,12 +51,15 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
56
51
  messageId = _useFieldIds.messageId; // field context
57
52
 
58
53
 
59
- var fieldContext = {
60
- 'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
61
- id: inputId,
54
+ var invalid = Boolean(message && tone === 'critical');
55
+ var fieldContext = [{
62
56
  disabled: disabled,
63
- invalid: Boolean(message && tone === 'critical')
64
- }; // label prep
57
+ invalid: invalid
58
+ }, {
59
+ 'aria-describedby': a11y.mergeIds(message && messageId, description && descriptionId),
60
+ 'aria-invalid': invalid || undefined,
61
+ id: inputId
62
+ }]; // label prep
65
63
 
66
64
  var hiddenLabel = /*#__PURE__*/jsxRuntime.jsxs(a11y.VisuallyHidden, {
67
65
  as: "label",
@@ -75,35 +73,31 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
75
73
  as: "label",
76
74
  htmlFor: inputId,
77
75
  children: /*#__PURE__*/jsxRuntime.jsxs(text.Text, {
78
- inline: true,
79
76
  tone: disabled ? 'disabled' : 'neutral',
80
77
  weight: "semibold",
81
78
  children: [label, ' ', secondaryLabel && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
82
79
  inline: true,
83
80
  tone: disabled ? 'disabled' : 'muted',
81
+ weight: "regular",
84
82
  children: secondaryLabel
85
83
  })]
86
84
  })
87
85
  }),
88
86
  'reserve-space': /*#__PURE__*/jsxRuntime.jsxs(react.Fragment, {
89
87
  children: [hiddenLabel, /*#__PURE__*/jsxRuntime.jsx(text.Text, {
90
- inline: true,
91
88
  "aria-hidden": true,
92
89
  children: "\xA0"
93
90
  })]
94
91
  })
95
92
  };
93
+ var LabelWrapper = labelVisibility === 'hidden' ? react.Fragment : FieldLabelWrapper;
96
94
  return /*#__PURE__*/jsxRuntime.jsx(FieldContextProvider, {
97
95
  value: fieldContext,
98
- children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack, _objectSpread(_objectSpread({
99
- gap: labelVisibility === 'hidden' ? undefined : 'small',
100
- ref: forwardedRef
101
- }, data ? internal.buildDataAttributes(data) : null), {}, {
102
- children: [/*#__PURE__*/jsxRuntime.jsxs(box.Box, {
103
- display: "flex",
104
- alignItems: "center",
105
- justifyContent: "spaceBetween",
106
- gap: "large",
96
+ children: /*#__PURE__*/jsxRuntime.jsxs(stack.Stack, {
97
+ ref: forwardedRef,
98
+ data: data,
99
+ gap: "medium",
100
+ children: [/*#__PURE__*/jsxRuntime.jsxs(LabelWrapper, {
107
101
  children: [labelElement[labelVisibility], adornment]
108
102
  }), description && /*#__PURE__*/jsxRuntime.jsx(text.Text, {
109
103
  tone: "muted",
@@ -115,7 +109,7 @@ var Field = /*#__PURE__*/react.forwardRef(function (_ref, forwardedRef) {
115
109
  id: messageId,
116
110
  message: message
117
111
  })]
118
- }))
112
+ })
119
113
  });
120
114
  });
121
115
  Field.displayName = 'Field'; // Utils
@@ -133,6 +127,17 @@ function useFieldIds(id) {
133
127
  } // Styled components
134
128
  // ------------------------------
135
129
 
130
+ function FieldLabelWrapper(_ref2) {
131
+ var children = _ref2.children;
132
+ return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
133
+ display: "flex",
134
+ alignItems: "center",
135
+ justifyContent: "spaceBetween",
136
+ gap: "large",
137
+ children: children
138
+ });
139
+ }
140
+
136
141
  var messageToneMap = {
137
142
  critical: 'critical',
138
143
  neutral: 'muted',
@@ -144,10 +149,10 @@ var messageIconMap = {
144
149
  neutral: null,
145
150
  positive: icon.CheckCircleIcon
146
151
  };
147
- var FieldMessage = function FieldMessage(_ref2) {
148
- var message = _ref2.message,
149
- id = _ref2.id,
150
- tone = _ref2.tone;
152
+ var FieldMessage = function FieldMessage(_ref3) {
153
+ var message = _ref3.message,
154
+ id = _ref3.id,
155
+ tone = _ref3.tone;
151
156
  var textTone = messageToneMap[tone];
152
157
  var Icon = messageIconMap[tone];
153
158
  return /*#__PURE__*/jsxRuntime.jsxs(box.Box, {
@@ -167,9 +172,8 @@ var FieldMessage = function FieldMessage(_ref2) {
167
172
  });
168
173
  };
169
174
 
170
- function IndicatorContainer(_ref3) {
171
- var children = _ref3.children,
172
- props = _objectWithoutProperties(_ref3, _excluded);
175
+ function IndicatorContainer(_ref4) {
176
+ var children = _ref4.children;
173
177
 
174
178
  var _useTheme = theme.useTheme(),
175
179
  typography = _useTheme.typography,
@@ -186,16 +190,15 @@ function IndicatorContainer(_ref3) {
186
190
  height: tablet.capHeight
187
191
  }
188
192
  });
189
- return /*#__PURE__*/jsxRuntime.jsx(box.Box, _objectSpread(_objectSpread({
193
+ return /*#__PURE__*/jsxRuntime.jsx(box.Box, {
190
194
  display: "flex",
191
195
  alignItems: "center",
192
196
  "aria-hidden": true,
193
197
  cursor: "default",
194
198
  flexShrink: 0,
195
- className: css.css(responsiveStyles)
196
- }, props), {}, {
199
+ className: css.css(responsiveStyles),
197
200
  children: children
198
- }));
201
+ });
199
202
  }
200
203
 
201
204
  exports.Field = Field;
@@ -1,6 +1,4 @@
1
1
  import { createContext, useContext, forwardRef, Fragment } from 'react';
2
- import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
3
- import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
4
2
  import { css } from '@emotion/css';
5
3
  import { mergeIds, useId, composeId, VisuallyHidden } from '@spark-web/a11y';
6
4
  import { Box } from '@spark-web/box';
@@ -8,7 +6,6 @@ import { ExclamationCircleIcon, CheckCircleIcon } from '@spark-web/icon';
8
6
  import { Stack } from '@spark-web/stack';
9
7
  import { Text } from '@spark-web/text';
10
8
  import { useTheme } from '@spark-web/theme';
11
- import { buildDataAttributes } from '@spark-web/utils/internal';
12
9
  import { jsx, jsxs } from 'react/jsx-runtime';
13
10
 
14
11
  var FieldContext = /*#__PURE__*/createContext(null);
@@ -24,8 +21,6 @@ function useFieldContext() {
24
21
  return ctx;
25
22
  }
26
23
 
27
- var _excluded = ["children"];
28
-
29
24
  /**
30
25
  * Using a [context](https://reactjs.org/docs/context.html), the field
31
26
  * component connects the label, description, and message to the input element.
@@ -52,12 +47,15 @@ var Field = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
52
47
  messageId = _useFieldIds.messageId; // field context
53
48
 
54
49
 
55
- var fieldContext = {
56
- 'aria-describedby': mergeIds(message && messageId, description && descriptionId),
57
- id: inputId,
50
+ var invalid = Boolean(message && tone === 'critical');
51
+ var fieldContext = [{
58
52
  disabled: disabled,
59
- invalid: Boolean(message && tone === 'critical')
60
- }; // label prep
53
+ invalid: invalid
54
+ }, {
55
+ 'aria-describedby': mergeIds(message && messageId, description && descriptionId),
56
+ 'aria-invalid': invalid || undefined,
57
+ id: inputId
58
+ }]; // label prep
61
59
 
62
60
  var hiddenLabel = /*#__PURE__*/jsxs(VisuallyHidden, {
63
61
  as: "label",
@@ -71,35 +69,31 @@ var Field = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
71
69
  as: "label",
72
70
  htmlFor: inputId,
73
71
  children: /*#__PURE__*/jsxs(Text, {
74
- inline: true,
75
72
  tone: disabled ? 'disabled' : 'neutral',
76
73
  weight: "semibold",
77
74
  children: [label, ' ', secondaryLabel && /*#__PURE__*/jsx(Text, {
78
75
  inline: true,
79
76
  tone: disabled ? 'disabled' : 'muted',
77
+ weight: "regular",
80
78
  children: secondaryLabel
81
79
  })]
82
80
  })
83
81
  }),
84
82
  'reserve-space': /*#__PURE__*/jsxs(Fragment, {
85
83
  children: [hiddenLabel, /*#__PURE__*/jsx(Text, {
86
- inline: true,
87
84
  "aria-hidden": true,
88
85
  children: "\xA0"
89
86
  })]
90
87
  })
91
88
  };
89
+ var LabelWrapper = labelVisibility === 'hidden' ? Fragment : FieldLabelWrapper;
92
90
  return /*#__PURE__*/jsx(FieldContextProvider, {
93
91
  value: fieldContext,
94
- children: /*#__PURE__*/jsxs(Stack, _objectSpread(_objectSpread({
95
- gap: labelVisibility === 'hidden' ? undefined : 'small',
96
- ref: forwardedRef
97
- }, data ? buildDataAttributes(data) : null), {}, {
98
- children: [/*#__PURE__*/jsxs(Box, {
99
- display: "flex",
100
- alignItems: "center",
101
- justifyContent: "spaceBetween",
102
- gap: "large",
92
+ children: /*#__PURE__*/jsxs(Stack, {
93
+ ref: forwardedRef,
94
+ data: data,
95
+ gap: "medium",
96
+ children: [/*#__PURE__*/jsxs(LabelWrapper, {
103
97
  children: [labelElement[labelVisibility], adornment]
104
98
  }), description && /*#__PURE__*/jsx(Text, {
105
99
  tone: "muted",
@@ -111,7 +105,7 @@ var Field = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
111
105
  id: messageId,
112
106
  message: message
113
107
  })]
114
- }))
108
+ })
115
109
  });
116
110
  });
117
111
  Field.displayName = 'Field'; // Utils
@@ -129,6 +123,17 @@ function useFieldIds(id) {
129
123
  } // Styled components
130
124
  // ------------------------------
131
125
 
126
+ function FieldLabelWrapper(_ref2) {
127
+ var children = _ref2.children;
128
+ return /*#__PURE__*/jsx(Box, {
129
+ display: "flex",
130
+ alignItems: "center",
131
+ justifyContent: "spaceBetween",
132
+ gap: "large",
133
+ children: children
134
+ });
135
+ }
136
+
132
137
  var messageToneMap = {
133
138
  critical: 'critical',
134
139
  neutral: 'muted',
@@ -140,10 +145,10 @@ var messageIconMap = {
140
145
  neutral: null,
141
146
  positive: CheckCircleIcon
142
147
  };
143
- var FieldMessage = function FieldMessage(_ref2) {
144
- var message = _ref2.message,
145
- id = _ref2.id,
146
- tone = _ref2.tone;
148
+ var FieldMessage = function FieldMessage(_ref3) {
149
+ var message = _ref3.message,
150
+ id = _ref3.id,
151
+ tone = _ref3.tone;
147
152
  var textTone = messageToneMap[tone];
148
153
  var Icon = messageIconMap[tone];
149
154
  return /*#__PURE__*/jsxs(Box, {
@@ -163,9 +168,8 @@ var FieldMessage = function FieldMessage(_ref2) {
163
168
  });
164
169
  };
165
170
 
166
- function IndicatorContainer(_ref3) {
167
- var children = _ref3.children,
168
- props = _objectWithoutProperties(_ref3, _excluded);
171
+ function IndicatorContainer(_ref4) {
172
+ var children = _ref4.children;
169
173
 
170
174
  var _useTheme = useTheme(),
171
175
  typography = _useTheme.typography,
@@ -182,16 +186,15 @@ function IndicatorContainer(_ref3) {
182
186
  height: tablet.capHeight
183
187
  }
184
188
  });
185
- return /*#__PURE__*/jsx(Box, _objectSpread(_objectSpread({
189
+ return /*#__PURE__*/jsx(Box, {
186
190
  display: "flex",
187
191
  alignItems: "center",
188
192
  "aria-hidden": true,
189
193
  cursor: "default",
190
194
  flexShrink: 0,
191
- className: css(responsiveStyles)
192
- }, props), {}, {
195
+ className: css(responsiveStyles),
193
196
  children: children
194
- }));
197
+ });
195
198
  }
196
199
 
197
200
  export { Field, FieldContextProvider, FieldMessage, useFieldContext, useFieldIds };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spark-web/field",
3
- "version": "1.1.0",
3
+ "version": "3.0.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/spark-web-field.cjs.js",
6
6
  "module": "dist/spark-web-field.esm.js",
@@ -8,15 +8,15 @@
8
8
  "dist"
9
9
  ],
10
10
  "dependencies": {
11
- "@babel/runtime": "^7.14.6",
12
- "@emotion/css": "^11.7.1",
13
- "@spark-web/a11y": "^1.0.4",
14
- "@spark-web/box": "^1.0.4",
15
- "@spark-web/icon": "^1.1.2",
16
- "@spark-web/stack": "^1.0.4",
17
- "@spark-web/text": "^1.0.4",
18
- "@spark-web/theme": "^3.0.0",
19
- "@spark-web/utils": "^1.1.2"
11
+ "@babel/runtime": "^7.18.0",
12
+ "@emotion/css": "^11.9.0",
13
+ "@spark-web/a11y": "^1.0.5",
14
+ "@spark-web/box": "^1.0.5",
15
+ "@spark-web/icon": "^1.1.3",
16
+ "@spark-web/stack": "^1.0.5",
17
+ "@spark-web/text": "^1.0.5",
18
+ "@spark-web/theme": "^3.0.1",
19
+ "@spark-web/utils": "^1.1.4"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/react": "^17.0.12",