@steroidsjs/core 3.0.67 → 3.0.69

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/actions/list.d.ts CHANGED
@@ -110,8 +110,10 @@ export declare const LIST_TOGGLE_ITEM = "@list/toggle_item";
110
110
  export declare const LIST_TOGGLE_ALL = "@list/toggle_all";
111
111
  export declare const LIST_SET_LAYOUT = "@list/set_layout";
112
112
  export declare const LIST_CHANGE_ACTION = "@list/change_action";
113
- export declare const httpFetchHandler: (list: IList, query: any, { http }: {
113
+ export declare const LIST_SELECT_ITEM = "@list/select_item";
114
+ export declare const httpFetchHandler: (list: IList, query: any, { http, httpCancelToken }: {
114
115
  http: any;
116
+ httpCancelToken: any;
115
117
  }) => any;
116
118
  export declare const localFetchHandler: (list: IList, query: Record<string, unknown>) => {
117
119
  items: any[];
@@ -192,3 +194,8 @@ export declare const toggleAll: (listId: any) => {
192
194
  listId: any;
193
195
  type: string;
194
196
  };
197
+ export declare const selectItem: (listId: any, itemId: any) => {
198
+ listId: any;
199
+ itemId: any;
200
+ type: string;
201
+ };
package/actions/list.js CHANGED
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
16
  exports.__esModule = true;
17
- exports.toggleAll = exports.toggleItem = exports.deleteItem = exports.update = exports.add = exports.listDestroy = exports.listRefresh = exports.listLazyFetch = exports.listFetch = exports.listChangeAction = exports.listSetLayout = exports.listSetItems = exports.listInit = exports.localFetchHandler = exports.httpFetchHandler = exports.LIST_CHANGE_ACTION = exports.LIST_SET_LAYOUT = exports.LIST_TOGGLE_ALL = exports.LIST_TOGGLE_ITEM = exports.LIST_DESTROY = exports.LIST_ITEM_DELETE = exports.LIST_ITEM_UPDATE = exports.LIST_ITEM_ADD = exports.LIST_AFTER_FETCH = exports.LIST_BEFORE_FETCH = exports.LIST_SET_ITEMS = exports.LIST_INIT = void 0;
17
+ exports.selectItem = exports.toggleAll = exports.toggleItem = exports.deleteItem = exports.update = exports.add = exports.listDestroy = exports.listRefresh = exports.listLazyFetch = exports.listFetch = exports.listChangeAction = exports.listSetLayout = exports.listSetItems = exports.listInit = exports.localFetchHandler = exports.httpFetchHandler = exports.LIST_SELECT_ITEM = exports.LIST_CHANGE_ACTION = exports.LIST_SET_LAYOUT = exports.LIST_TOGGLE_ALL = exports.LIST_TOGGLE_ITEM = exports.LIST_DESTROY = exports.LIST_ITEM_DELETE = exports.LIST_ITEM_UPDATE = exports.LIST_ITEM_ADD = exports.LIST_AFTER_FETCH = exports.LIST_BEFORE_FETCH = exports.LIST_SET_ITEMS = exports.LIST_INIT = void 0;
18
18
  var get_1 = __importDefault(require("lodash-es/get"));
19
19
  var isArray_1 = __importDefault(require("lodash-es/isArray"));
20
20
  var isEmpty_1 = __importDefault(require("lodash-es/isEmpty"));
@@ -23,6 +23,7 @@ var trimStart_1 = __importDefault(require("lodash-es/trimStart"));
23
23
  var isFunction_1 = __importDefault(require("lodash-es/isFunction"));
24
24
  var isEqual_1 = __importDefault(require("lodash-es/isEqual"));
25
25
  var isNil_1 = __importDefault(require("lodash-es/isNil"));
26
+ var axios_1 = __importDefault(require("axios"));
26
27
  var form_1 = require("../reducers/form");
27
28
  var form_2 = require("../actions/form");
28
29
  var data_1 = require("../utils/data");
@@ -38,6 +39,7 @@ exports.LIST_TOGGLE_ITEM = '@list/toggle_item';
38
39
  exports.LIST_TOGGLE_ALL = '@list/toggle_all';
39
40
  exports.LIST_SET_LAYOUT = '@list/set_layout';
40
41
  exports.LIST_CHANGE_ACTION = '@list/change_action';
42
+ exports.LIST_SELECT_ITEM = '@list/select_item';
41
43
  //const STORAGE_LAYOUT_KEY_PREFIX = 'listLayout_';
42
44
  var lazyTimers = {};
43
45
  var createList = function (listId, props) { return ({
@@ -61,18 +63,22 @@ var createList = function (listId, props) { return ({
61
63
  layoutAttribute: (0, get_1["default"])(props, '_layout.attribute') || null
62
64
  }); };
63
65
  var httpFetchHandler = function (list, query, _a) {
64
- var http = _a.http;
66
+ var http = _a.http, httpCancelToken = _a.httpCancelToken;
65
67
  var url = list.action;
66
68
  if (list.scope) {
67
69
  url
68
70
  += (url.indexOf('?') !== -1 ? '&' : '?') + 'scope=' + list.scope.join(',');
69
71
  }
70
72
  return http
71
- .send(list.actionMethod, url || window.location.pathname, query)
73
+ .send(list.actionMethod, url || window.location.pathname, query, {
74
+ cancelToken: httpCancelToken
75
+ })
72
76
  .then(function (response) { return response.data; })["catch"](function (error) {
73
77
  if (typeof list.onError === 'function') {
74
78
  list.onError(error);
75
79
  }
80
+ // rethrow чтобы внешняя логика могла отловить отмену/ошибку
81
+ throw error;
76
82
  });
77
83
  };
78
84
  exports.httpFetchHandler = httpFetchHandler;
@@ -149,31 +155,7 @@ var listChangeAction = function (listId, action) { return ({
149
155
  action: action
150
156
  }); };
151
157
  exports.listChangeAction = listChangeAction;
152
- /*export const initSSR = (listId, props) => (dispatch, getState, {http, clientStorage}) => {
153
- const state = getState()
154
- const stateList = _get(state, ['list', 'lists', listId]);
155
- const list = {
156
- ...createList(listId, props, clientStorage),
157
- ...stateList
158
- };
159
- if ((!list.action && list.action !== '') || list.items) {
160
- if (!stateList) {
161
- return dispatch({
162
- ...list,
163
- type: LIST_INIT
164
- });
165
- }
166
- return;
167
- }
168
- const onFetch = list.onFetch || httpFetchHandler;
169
- return dispatch(
170
- onFetch(list, VALUES, http).then(data => ({
171
- ...list,
172
- ...data,
173
- type: LIST_INIT
174
- }))
175
- );
176
- };*/
158
+ var _cancelSourceByList = new Map();
177
159
  /**
178
160
  * Update query values and send request
179
161
  * @param listId
@@ -205,9 +187,24 @@ var listFetch = function (listId, query) {
205
187
  type: exports.LIST_BEFORE_FETCH
206
188
  });
207
189
  }
190
+ // Axios cancel logic: cancel previous request for this listId
191
+ var prevSource = _cancelSourceByList.get(listId);
192
+ if (prevSource) {
193
+ // отменяем предыдущий активный запрос (если он ещё выполняется)
194
+ try {
195
+ prevSource.cancel('Cancelled by new request');
196
+ }
197
+ catch (e) {
198
+ /* ignore */
199
+ }
200
+ }
201
+ var cancelSource = axios_1["default"].CancelToken.source();
202
+ _cancelSourceByList.set(listId, cancelSource);
208
203
  // Send request
209
- toDispatch.push(Promise.resolve(onFetch(list, formValues, components)).then(function (data) {
204
+ toDispatch.push(Promise.resolve(onFetch(list, formValues, __assign(__assign({}, components), { httpCancelToken: cancelSource.token }))).then(function (data) {
210
205
  var _a;
206
+ // cleanup: текущий источник уже отработал
207
+ _cancelSourceByList["delete"](listId);
211
208
  // Skip on empty
212
209
  if (!data) {
213
210
  return [];
@@ -230,7 +227,6 @@ var listFetch = function (listId, query) {
230
227
  var totalPages = Math.ceil(((list === null || list === void 0 ? void 0 : list.total) || 0) / (pageSize || 1));
231
228
  var hasNextPage = (_a = data === null || data === void 0 ? void 0 : data.hasNextPage) !== null && _a !== void 0 ? _a : (page !== totalPages || null);
232
229
  return [
233
- // Check has errors
234
230
  (0, form_2.formSetErrors)(list.formId, data.errors || null),
235
231
  {
236
232
  items: items,
@@ -244,6 +240,16 @@ var listFetch = function (listId, query) {
244
240
  type: exports.LIST_AFTER_FETCH
245
241
  },
246
242
  ];
243
+ })["catch"](function (err) {
244
+ // Если это отмена через axios, просто игнорируем
245
+ _cancelSourceByList["delete"](listId);
246
+ // Если нужно — можно выставить ошибку формы или диспатчить событие
247
+ if (!axios_1["default"].isCancel(err)) {
248
+ // передаём ошибку дальше — если нужна стандартная обработка
249
+ throw err;
250
+ }
251
+ // при отмене просто возвращаем пустой массив действий
252
+ return [];
247
253
  }));
248
254
  return dispatch(toDispatch);
249
255
  };
@@ -318,6 +324,12 @@ var toggleAll = function (listId) { return ({
318
324
  type: exports.LIST_TOGGLE_ALL
319
325
  }); };
320
326
  exports.toggleAll = toggleAll;
327
+ var selectItem = function (listId, itemId) { return ({
328
+ listId: listId,
329
+ itemId: itemId,
330
+ type: exports.LIST_SELECT_ITEM
331
+ }); };
332
+ exports.selectItem = selectItem;
321
333
  // TODO local storage save?
322
334
  /*export const setLayoutName = (listId, layoutName) => (
323
335
  dispatch,
@@ -3278,6 +3278,14 @@
3278
3278
  "type": "string",
3279
3279
  "example": "items"
3280
3280
  },
3281
+ {
3282
+ "name": "hasCloseOnSelect",
3283
+ "decorators": [],
3284
+ "description": "Нужно ли закрывать выпадающий список после выбора элемента",
3285
+ "required": false,
3286
+ "type": "boolean",
3287
+ "example": "true"
3288
+ },
3281
3289
  {
3282
3290
  "name": "inputValue",
3283
3291
  "decorators": [],
@@ -13795,6 +13803,15 @@
13795
13803
  "example": "items",
13796
13804
  "defaultValue": null
13797
13805
  },
13806
+ {
13807
+ "name": "hasCloseOnSelect",
13808
+ "decorators": [],
13809
+ "description": "Нужно ли закрывать выпадающий список после выбора элемента",
13810
+ "required": false,
13811
+ "type": "boolean",
13812
+ "example": "true",
13813
+ "defaultValue": null
13814
+ },
13798
13815
  {
13799
13816
  "name": "hint",
13800
13817
  "decorators": [],
@@ -15626,6 +15643,15 @@
15626
15643
  "example": "items",
15627
15644
  "defaultValue": null
15628
15645
  },
15646
+ {
15647
+ "name": "hasCloseOnSelect",
15648
+ "decorators": [],
15649
+ "description": "Нужно ли закрывать выпадающий список после выбора элемента",
15650
+ "required": false,
15651
+ "type": "boolean",
15652
+ "example": "true",
15653
+ "defaultValue": null
15654
+ },
15629
15655
  {
15630
15656
  "name": "hint",
15631
15657
  "decorators": [],
@@ -16182,6 +16208,15 @@
16182
16208
  "example": "items",
16183
16209
  "defaultValue": null
16184
16210
  },
16211
+ {
16212
+ "name": "hasCloseOnSelect",
16213
+ "decorators": [],
16214
+ "description": "Нужно ли закрывать выпадающий список после выбора элемента",
16215
+ "required": false,
16216
+ "type": "boolean",
16217
+ "example": "true",
16218
+ "defaultValue": null
16219
+ },
16185
16220
  {
16186
16221
  "name": "hasIconExpandOnly",
16187
16222
  "decorators": [],
@@ -19188,6 +19223,15 @@
19188
19223
  "example": "items",
19189
19224
  "defaultValue": null
19190
19225
  },
19226
+ {
19227
+ "name": "hasCloseOnSelect",
19228
+ "decorators": [],
19229
+ "description": "Нужно ли закрывать выпадающий список после выбора элемента",
19230
+ "required": false,
19231
+ "type": "boolean",
19232
+ "example": "true",
19233
+ "defaultValue": null
19234
+ },
19191
19235
  {
19192
19236
  "name": "hint",
19193
19237
  "decorators": [],
@@ -19657,6 +19701,14 @@
19657
19701
  "type": "string",
19658
19702
  "example": "items"
19659
19703
  },
19704
+ {
19705
+ "name": "hasCloseOnSelect",
19706
+ "decorators": [],
19707
+ "description": "Нужно ли закрывать выпадающий список после выбора элемента",
19708
+ "required": false,
19709
+ "type": "boolean",
19710
+ "example": "true"
19711
+ },
19660
19712
  {
19661
19713
  "name": "hint",
19662
19714
  "decorators": [],
package/en.json CHANGED
@@ -986,6 +986,7 @@
986
986
  "Значение страницы по умолчанию.": "",
987
987
  "Логическое значение, указывающее, можно ли загрузить еще элементы для списка при скролле.": "",
988
988
  " Ref autocomplete поиска": "",
989
+ "Нужно ли закрывать выпадающий список после выбора элемента": "",
989
990
  "Подключение бесконечного скролла": "",
990
991
  "Флаг определяет необходимо ли передавать query параметры в URL": "",
991
992
  "Дополнительный свойства для view части компонента": "",
@@ -54,6 +54,11 @@ export interface IDataSelectConfig {
54
54
  * Ref autocomplete поиска
55
55
  */
56
56
  autoCompleteInputRef?: MutableRefObject<HTMLInputElement>;
57
+ /**
58
+ * Нужно ли закрывать выпадающий список после выбора элемента
59
+ * @example true
60
+ */
61
+ hasCloseOnSelect?: boolean;
57
62
  }
58
63
  export interface IDataSelectResult {
59
64
  isOpened: boolean;
@@ -128,11 +128,13 @@ function useDataSelect(config) {
128
128
  else if (selectedIds.length === 1 && selectedIds[0] === id_1) {
129
129
  setSelectedIdsInternal([]);
130
130
  }
131
- setIsFocused(false);
132
- setIsOpened(false);
131
+ if (config.hasCloseOnSelect) {
132
+ setIsFocused(false);
133
+ setIsOpened(false);
134
+ }
133
135
  }
134
136
  }
135
- }, [config.multiple, selectedIds]);
137
+ }, [config.hasCloseOnSelect, config.multiple, selectedIds]);
136
138
  var setSelectedAll = (0, react_1.useCallback)(function () {
137
139
  var itemsIds = flattenedItems.map(function (item) { return item.id; });
138
140
  setSelectedIds(itemsIds);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steroidsjs/core",
3
- "version": "3.0.67",
3
+ "version": "3.0.69",
4
4
  "description": "",
5
5
  "author": "Vladimir Kozhin <hello@kozhindev.com>",
6
6
  "repository": {
package/reducers/list.js CHANGED
@@ -129,6 +129,10 @@ var reducerMap = (_a = {},
129
129
  }
130
130
  return [];
131
131
  },
132
+ _a[list_1.LIST_SELECT_ITEM] = function (state, action) {
133
+ var _a;
134
+ return (__assign(__assign({}, state), { selectedIds: __assign(__assign({}, state.selectedIds), (_a = {}, _a[action.listId] = action.itemId ? [action.itemId] : [], _a)) }));
135
+ },
132
136
  _a[list_1.LIST_SET_LAYOUT] = function (state, action) {
133
137
  var _a;
134
138
  return (__assign(__assign({}, state), { lists: __assign(__assign({}, state.lists), (_a = {}, _a[action.listId] = __assign(__assign({}, state.lists[action.listId]), { layoutName: action.layoutName }), _a)) }));
@@ -132,7 +132,8 @@ function DropDownField(props) {
132
132
  items: items,
133
133
  sourceItems: sourceItems,
134
134
  inputValue: props.input.value,
135
- autoCompleteInputRef: autoCompleteInputForwardedRef
135
+ autoCompleteInputRef: autoCompleteInputForwardedRef,
136
+ hasCloseOnSelect: props.hasCloseOnSelect
136
137
  }), isOpened = _d.isOpened, setIsOpened = _d.setIsOpened, setIsFocused = _d.setIsFocused, hoveredId = _d.hoveredId, setHoveredId = _d.setHoveredId, selectedIds = _d.selectedIds, setSelectedIds = _d.setSelectedIds, selectedItems = _d.selectedItems, setSelectedAll = _d.setSelectedAll, isSelectedAll = _d.isSelectedAll;
137
138
  var onOpen = (0, react_1.useCallback)(function () {
138
139
  setQuery('');
@@ -259,6 +260,7 @@ DropDownField.defaultProps = {
259
260
  multiple: false,
260
261
  isSearchAutoFocus: true,
261
262
  itemToSelectAll: false,
262
- isFetchOnClose: false
263
+ isFetchOnClose: false,
264
+ hasCloseOnSelect: true
263
265
  };
264
266
  exports["default"] = (0, fieldWrapper_1["default"])(enums_1.FieldEnum.DROPDOWN_FIELD, DropDownField);