@algolia/satellite 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/cjs/Actions/Accordion/Accordion.d.ts +142 -0
  2. package/dist/cjs/Actions/Accordion/Accordion.js +149 -0
  3. package/dist/cjs/Actions/Accordion/Accordion.tailwind.d.ts +5 -0
  4. package/dist/cjs/Actions/Accordion/Accordion.tailwind.js +44 -0
  5. package/dist/cjs/Actions/ToggleGroup/ToggleGroup.d.ts +2 -2
  6. package/dist/cjs/Actions/index.d.ts +2 -0
  7. package/dist/cjs/Actions/index.js +18 -0
  8. package/dist/cjs/Fields/Field/Field.js +1 -1
  9. package/dist/cjs/Fields/Form/Form.d.ts +12 -10
  10. package/dist/cjs/Fields/Form/Form.js +50 -38
  11. package/dist/cjs/Fields/Form/FormContext.d.ts +6 -6
  12. package/dist/cjs/Fields/Form/FormContext.js +2 -2
  13. package/dist/cjs/Fields/Form/index.d.ts +4 -3
  14. package/dist/cjs/Fields/Form/index.js +31 -21
  15. package/dist/cjs/Fields/Form/stories/AsynchronousValidation.js +142 -127
  16. package/dist/cjs/Fields/Form/stories/Complex.js +648 -642
  17. package/dist/cjs/Fields/Form/stories/DependentFieldsValidation.js +127 -121
  18. package/dist/cjs/Fields/Form/stories/DirtyFields.js +195 -189
  19. package/dist/cjs/Fields/Form/stories/DynamicFieldsValidation.js +251 -245
  20. package/dist/cjs/Fields/Form/stories/ExtraErrors.js +289 -0
  21. package/dist/cjs/Fields/Form/stories/FieldArrays.js +180 -174
  22. package/dist/cjs/Fields/Form/stories/JSONForms.js +58 -55
  23. package/dist/cjs/Fields/Form/stories/MultiStep.js +474 -468
  24. package/dist/cjs/Fields/Form/stories/ValidationStrategies.js +243 -237
  25. package/dist/cjs/Fields/Form/useForm.d.ts +1 -1
  26. package/dist/cjs/Fields/Form/useForm.js +3 -3
  27. package/dist/cjs/Helpers/utilities/focusable.tailwind.js +1 -1
  28. package/dist/cjs/Indicators/Skeleton/Skeleton.d.ts +7 -0
  29. package/dist/cjs/Indicators/Skeleton/Skeleton.js +12 -5
  30. package/dist/cjs/Layout/Sidebar/SidebarButtonLink.js +1 -1
  31. package/dist/cjs/Layout/Sidebar/SidebarLink.js +2 -2
  32. package/dist/cjs/Layout/Sidebar/SidebarLinksGroup/SidebarGroupLink.js +1 -1
  33. package/dist/cjs/Layout/Sidebar/SidebarLinksGroup/SidebarLinksGroup.js +4 -5
  34. package/dist/cjs/Layout/Tables/DataTable/DataTable.d.ts +3 -1
  35. package/dist/cjs/Layout/Tables/DataTable/DataTable.js +3 -0
  36. package/dist/cjs/Layout/Tables/Table/Table.d.ts +2 -0
  37. package/dist/cjs/Layout/Tables/Table/Table.js +4 -2
  38. package/dist/cjs/Layout/Tables/Table/Table.tailwind.js +6 -1
  39. package/dist/cjs/Overlay/MenuButton/components/items/LinkItem.d.ts +1 -1
  40. package/dist/cjs/Overlay/MenuButton/components/items/ToggleItem.d.ts +1 -1
  41. package/dist/cjs/styles/tailwind.config.js +1 -1
  42. package/dist/cjs/utils/isCssPropertySupported.d.ts +1 -1
  43. package/dist/esm/Actions/Accordion/Accordion.d.ts +142 -0
  44. package/dist/esm/Actions/Accordion/Accordion.js +139 -0
  45. package/dist/esm/Actions/Accordion/Accordion.tailwind.d.ts +5 -0
  46. package/dist/esm/Actions/Accordion/Accordion.tailwind.js +43 -0
  47. package/dist/esm/Actions/ToggleGroup/ToggleGroup.d.ts +2 -2
  48. package/dist/esm/Actions/index.d.ts +2 -0
  49. package/dist/esm/Actions/index.js +2 -2
  50. package/dist/esm/Fields/Field/Field.js +2 -2
  51. package/dist/esm/Fields/Form/Form.d.ts +12 -10
  52. package/dist/esm/Fields/Form/Form.js +52 -40
  53. package/dist/esm/Fields/Form/FormContext.d.ts +6 -6
  54. package/dist/esm/Fields/Form/FormContext.js +1 -1
  55. package/dist/esm/Fields/Form/index.d.ts +4 -3
  56. package/dist/esm/Fields/Form/index.js +2 -3
  57. package/dist/esm/Fields/Form/stories/AsynchronousValidation.js +143 -128
  58. package/dist/esm/Fields/Form/stories/Complex.js +649 -643
  59. package/dist/esm/Fields/Form/stories/DependentFieldsValidation.js +128 -122
  60. package/dist/esm/Fields/Form/stories/DirtyFields.js +196 -190
  61. package/dist/esm/Fields/Form/stories/DynamicFieldsValidation.js +252 -246
  62. package/dist/esm/Fields/Form/stories/ExtraErrors.js +279 -0
  63. package/dist/esm/Fields/Form/stories/FieldArrays.js +181 -175
  64. package/dist/esm/Fields/Form/stories/JSONForms.js +59 -56
  65. package/dist/esm/Fields/Form/stories/MultiStep.js +475 -469
  66. package/dist/esm/Fields/Form/stories/ValidationStrategies.js +244 -238
  67. package/dist/esm/Fields/Form/useForm.d.ts +1 -1
  68. package/dist/esm/Fields/Form/useForm.js +3 -3
  69. package/dist/esm/Helpers/utilities/focusable.tailwind.js +1 -1
  70. package/dist/esm/Indicators/Skeleton/Skeleton.d.ts +7 -0
  71. package/dist/esm/Indicators/Skeleton/Skeleton.js +12 -5
  72. package/dist/esm/Layout/Sidebar/SidebarButtonLink.js +1 -1
  73. package/dist/esm/Layout/Sidebar/SidebarLink.js +2 -2
  74. package/dist/esm/Layout/Sidebar/SidebarLinksGroup/SidebarGroupLink.js +1 -1
  75. package/dist/esm/Layout/Sidebar/SidebarLinksGroup/SidebarLinksGroup.js +4 -5
  76. package/dist/esm/Layout/Tables/DataTable/DataTable.d.ts +3 -1
  77. package/dist/esm/Layout/Tables/DataTable/DataTable.js +3 -0
  78. package/dist/esm/Layout/Tables/Table/Table.d.ts +2 -0
  79. package/dist/esm/Layout/Tables/Table/Table.js +4 -2
  80. package/dist/esm/Layout/Tables/Table/Table.tailwind.js +6 -1
  81. package/dist/esm/Overlay/MenuButton/components/items/LinkItem.d.ts +1 -1
  82. package/dist/esm/Overlay/MenuButton/components/items/ToggleItem.d.ts +1 -1
  83. package/dist/esm/styles/tailwind.config.js +1 -1
  84. package/dist/esm/utils/isCssPropertySupported.d.ts +1 -1
  85. package/dist/satellite.min.css +1 -1
  86. package/package.json +2 -1
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.RHFExtraErrorsComponent = exports.FormikExtraErrorsComponent = void 0;
9
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
12
+ var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
13
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
14
+ var _zod = require("@hookform/resolvers/zod");
15
+ var _formik = require("formik");
16
+ var _react = require("react");
17
+ var _reactHookForm = require("react-hook-form");
18
+ var yup = _interopRequireWildcard(require("yup"));
19
+ var _zod2 = require("zod");
20
+ var _satellitePrefixer = _interopRequireDefault(require("../../../styles/helpers/satellitePrefixer"));
21
+ var _Field = require("../../Field");
22
+ var _Input = require("../../Input");
23
+ var _Form = require("../Form");
24
+ var _useFormikAutoFocusOnError = require("./utils/useFormikAutoFocusOnError");
25
+ var _jsxRuntime = require("react/jsx-runtime");
26
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12, _templateObject13, _templateObject14;
27
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
28
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
29
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
30
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
31
+ var initialFormData = {
32
+ email: ""
33
+ };
34
+ var sleep = function sleep(ms) {
35
+ return new Promise(function (resolve) {
36
+ return setTimeout(resolve, ms);
37
+ });
38
+ };
39
+ var zodSchema = _zod2.z.object({
40
+ email: _zod2.z.string().email("You must specify an email (hint: example@example.com)")
41
+ });
42
+ var RHFExtraErrorsComponent = exports.RHFExtraErrorsComponent = function RHFExtraErrorsComponent() {
43
+ var _useState = (0, _react.useState)(initialFormData),
44
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
45
+ formData = _useState2[0],
46
+ setFormData = _useState2[1];
47
+ var _useState3 = (0, _react.useState)([]),
48
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
49
+ extraErrors = _useState4[0],
50
+ setExtraErrors = _useState4[1];
51
+ var _useForm = (0, _reactHookForm.useForm)({
52
+ defaultValues: initialFormData,
53
+ reValidateMode: "onChange",
54
+ resolver: (0, _zod.zodResolver)(zodSchema)
55
+ }),
56
+ control = _useForm.control,
57
+ handleSubmit = _useForm.handleSubmit,
58
+ getFieldStateFromReactHookForm = _useForm.getFieldState,
59
+ formState = _useForm.formState,
60
+ reset = _useForm.reset;
61
+ var getFieldState = function getFieldState(fieldName) {
62
+ var _fieldState$error;
63
+ var fieldState = getFieldStateFromReactHookForm(fieldName, formState);
64
+ if ((_fieldState$error = fieldState.error) !== null && _fieldState$error !== void 0 && _fieldState$error.message) {
65
+ return {
66
+ status: "invalid",
67
+ errors: [fieldState.error.message]
68
+ };
69
+ } else if (!fieldState.invalid && formState.isSubmitted) {
70
+ return {
71
+ status: "validated"
72
+ };
73
+ } else {
74
+ return {
75
+ status: "default"
76
+ };
77
+ }
78
+ };
79
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
80
+ className: (0, _satellitePrefixer["default"])(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["@container w-full flex justify-center"]))),
81
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
82
+ className: (0, _satellitePrefixer["default"])(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-8 w-full @lg:w-1/2"]))),
83
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_Form.Form, {
84
+ onSubmit: handleSubmit( /*#__PURE__*/function () {
85
+ var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(data) {
86
+ return _regenerator["default"].wrap(function _callee$(_context) {
87
+ while (1) switch (_context.prev = _context.next) {
88
+ case 0:
89
+ setFormData(data);
90
+ _context.next = 3;
91
+ return sleep(1000);
92
+ case 3:
93
+ setExtraErrors(["A server error occurred. Please try again later."]);
94
+ case 4:
95
+ case "end":
96
+ return _context.stop();
97
+ }
98
+ }, _callee);
99
+ }));
100
+ return function (_x) {
101
+ return _ref.apply(this, arguments);
102
+ };
103
+ }()),
104
+ onChange: function onChange() {
105
+ return setExtraErrors([]);
106
+ },
107
+ onReset: function onReset() {
108
+ return setFormData(initialFormData);
109
+ },
110
+ className: (0, _satellitePrefixer["default"])(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col items-start gap-4 min-w-72"]))),
111
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Form.FormErrorMessage, {
112
+ extraErrors: extraErrors
113
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactHookForm.Controller, {
114
+ name: "email",
115
+ control: control,
116
+ render: function render(_ref2) {
117
+ var field = _ref2.field;
118
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Field.Field, {
119
+ label: "Email",
120
+ labelFor: "email",
121
+ description: "Please enter a valid email address",
122
+ state: getFieldState("email"),
123
+ className: (0, _satellitePrefixer["default"])(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["w-full"]))),
124
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input.Input, _objectSpread({
125
+ id: "email",
126
+ placeholder: "Email",
127
+ required: true
128
+ }, field))
129
+ });
130
+ }
131
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
132
+ className: (0, _satellitePrefixer["default"])(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2["default"])(["flex gap-2"]))),
133
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Form.FormSubmit, {
134
+ variant: "primary",
135
+ "aria-label": "Submit the form",
136
+ loading: formState.isSubmitting,
137
+ children: "Submit"
138
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Form.FormReset, {
139
+ "aria-label": "Reset the form",
140
+ onClick: function onClick() {
141
+ reset();
142
+ setExtraErrors([]);
143
+ },
144
+ children: "Reset"
145
+ })]
146
+ })]
147
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("hr", {
148
+ className: (0, _satellitePrefixer["default"])(_templateObject6 || (_templateObject6 = (0, _taggedTemplateLiteral2["default"])(["text-grey-500"])))
149
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("code", {
150
+ className: (0, _satellitePrefixer["default"])(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2["default"])(["whitespace-pre"]))),
151
+ children: JSON.stringify(formData, null, 2)
152
+ })]
153
+ })
154
+ });
155
+ };
156
+ var yupSchema = yup.object({
157
+ email: yup.string().email("You must specify an email (hint: example@example.com)").required("You must specify an email (hint: example@example.com)")
158
+ });
159
+ var FormikExtraErrorsComponent = exports.FormikExtraErrorsComponent = function FormikExtraErrorsComponent() {
160
+ var _useState5 = (0, _react.useState)(initialFormData),
161
+ _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
162
+ formData = _useState6[0],
163
+ setFormData = _useState6[1];
164
+ var _useState7 = (0, _react.useState)(false),
165
+ _useState8 = (0, _slicedToArray2["default"])(_useState7, 2),
166
+ revalidationEnabled = _useState8[0],
167
+ setRevalidationEnabled = _useState8[1];
168
+ var _useState9 = (0, _react.useState)([]),
169
+ _useState10 = (0, _slicedToArray2["default"])(_useState9, 2),
170
+ extraErrors = _useState10[0],
171
+ setExtraErrors = _useState10[1];
172
+ var formik = (0, _formik.useFormik)({
173
+ initialValues: initialFormData,
174
+ validateOnChange: revalidationEnabled,
175
+ validateOnBlur: revalidationEnabled,
176
+ validationSchema: yupSchema,
177
+ onSubmit: function () {
178
+ var _onSubmit = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(values) {
179
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
180
+ while (1) switch (_context2.prev = _context2.next) {
181
+ case 0:
182
+ setFormData(values);
183
+ _context2.next = 3;
184
+ return sleep(1000);
185
+ case 3:
186
+ setExtraErrors(["A server error occurred. Please try again later."]);
187
+ case 4:
188
+ case "end":
189
+ return _context2.stop();
190
+ }
191
+ }, _callee2);
192
+ }));
193
+ function onSubmit(_x2) {
194
+ return _onSubmit.apply(this, arguments);
195
+ }
196
+ return onSubmit;
197
+ }(),
198
+ onReset: function onReset() {
199
+ setFormData(initialFormData);
200
+ setExtraErrors([]);
201
+ }
202
+ });
203
+ var getFieldState = function getFieldState(fieldName) {
204
+ var fieldMeta = formik.getFieldMeta(fieldName);
205
+ if (fieldMeta.error) {
206
+ return {
207
+ status: "invalid",
208
+ errors: [fieldMeta.error]
209
+ };
210
+ } else if (formik.isSubmitting && fieldMeta.touched) {
211
+ return {
212
+ status: "validated"
213
+ };
214
+ } else {
215
+ return {
216
+ status: "default"
217
+ };
218
+ }
219
+ };
220
+ (0, _useFormikAutoFocusOnError.useFormikAutoFocusOnError)(formik);
221
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
222
+ className: (0, _satellitePrefixer["default"])(_templateObject8 || (_templateObject8 = (0, _taggedTemplateLiteral2["default"])(["@container w-full flex justify-center"]))),
223
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
224
+ className: (0, _satellitePrefixer["default"])(_templateObject9 || (_templateObject9 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-8 w-full @lg:w-1/2"]))),
225
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_Form.Form, {
226
+ onSubmit: ( /*#__PURE__*/function () {
227
+ var _ref3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(e) {
228
+ return _regenerator["default"].wrap(function _callee3$(_context3) {
229
+ while (1) switch (_context3.prev = _context3.next) {
230
+ case 0:
231
+ setRevalidationEnabled(true);
232
+ formik.handleSubmit(e);
233
+ // notice that you might want to hook your validations into Formik onSubmit handler (called just above)
234
+ // not directly here
235
+ case 2:
236
+ case "end":
237
+ return _context3.stop();
238
+ }
239
+ }, _callee3);
240
+ }));
241
+ return function (_x3) {
242
+ return _ref3.apply(this, arguments);
243
+ };
244
+ }()),
245
+ onChange: function onChange() {
246
+ return setExtraErrors([]);
247
+ },
248
+ onReset: function onReset(e) {
249
+ setRevalidationEnabled(false);
250
+ formik.handleReset(e);
251
+ },
252
+ className: (0, _satellitePrefixer["default"])(_templateObject10 || (_templateObject10 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col items-start gap-4 min-w-72"]))),
253
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Form.FormErrorMessage, {
254
+ extraErrors: extraErrors
255
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Field.Field, {
256
+ label: "Email",
257
+ labelFor: "email",
258
+ description: "Please enter a valid email address",
259
+ state: getFieldState("email"),
260
+ className: (0, _satellitePrefixer["default"])(_templateObject11 || (_templateObject11 = (0, _taggedTemplateLiteral2["default"])(["w-full"]))),
261
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Input.Input, _objectSpread({
262
+ id: "email",
263
+ placeholder: "Email",
264
+ required: true
265
+ }, formik.getFieldProps("email")))
266
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
267
+ className: (0, _satellitePrefixer["default"])(_templateObject12 || (_templateObject12 = (0, _taggedTemplateLiteral2["default"])(["flex gap-2"]))),
268
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Form.FormSubmit, {
269
+ variant: "primary",
270
+ "aria-label": "Submit",
271
+ loading: formik.isValidating || formik.isSubmitting,
272
+ children: "Submit"
273
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Form.FormReset, {
274
+ "aria-label": "Reset the form",
275
+ onClick: function onClick() {
276
+ return formik.resetForm();
277
+ },
278
+ children: "Reset"
279
+ })]
280
+ })]
281
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("hr", {
282
+ className: (0, _satellitePrefixer["default"])(_templateObject13 || (_templateObject13 = (0, _taggedTemplateLiteral2["default"])(["text-grey-500"])))
283
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("code", {
284
+ className: (0, _satellitePrefixer["default"])(_templateObject14 || (_templateObject14 = (0, _taggedTemplateLiteral2["default"])(["whitespace-pre"]))),
285
+ children: JSON.stringify(formData, null, 2)
286
+ })]
287
+ })
288
+ });
289
+ };