rsuite 6.1.3 → 6.2.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 (47) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/Timeline/styles/index.css +11 -0
  3. package/Timeline/styles/index.scss +13 -0
  4. package/Uploader/styles/index.css +3 -0
  5. package/Uploader/styles/index.scss +3 -0
  6. package/cjs/AutoComplete/AutoComplete.d.ts +2 -0
  7. package/cjs/AutoComplete/AutoComplete.js +3 -1
  8. package/cjs/CheckTree/utils.js +2 -1
  9. package/cjs/Form/Form.d.ts +37 -0
  10. package/cjs/Form/Form.js +16 -1
  11. package/cjs/Form/hooks/useFormValidate.d.ts +2 -0
  12. package/cjs/Form/hooks/useFormValidate.js +117 -1
  13. package/cjs/Form/index.d.ts +1 -0
  14. package/cjs/Form/resolvers.d.ts +59 -0
  15. package/cjs/Form/resolvers.js +4 -0
  16. package/cjs/Timeline/Timeline.d.ts +5 -0
  17. package/cjs/Timeline/Timeline.js +13 -6
  18. package/cjs/Tree/hooks/useFlattenTree.js +5 -8
  19. package/cjs/Uploader/Uploader.d.ts +2 -0
  20. package/cjs/Uploader/Uploader.js +48 -2
  21. package/cjs/internals/Picker/PickerIndicator.js +13 -11
  22. package/cjs/toaster/toaster.js +38 -3
  23. package/dist/rsuite-no-reset.css +14 -0
  24. package/dist/rsuite-no-reset.min.css +1 -1
  25. package/dist/rsuite.css +14 -0
  26. package/dist/rsuite.js +9 -9
  27. package/dist/rsuite.min.css +1 -1
  28. package/dist/rsuite.min.js +1 -1
  29. package/dist/rsuite.min.js.map +1 -1
  30. package/esm/AutoComplete/AutoComplete.d.ts +2 -0
  31. package/esm/AutoComplete/AutoComplete.js +3 -1
  32. package/esm/CheckTree/utils.js +2 -1
  33. package/esm/Form/Form.d.ts +37 -0
  34. package/esm/Form/Form.js +16 -1
  35. package/esm/Form/hooks/useFormValidate.d.ts +2 -0
  36. package/esm/Form/hooks/useFormValidate.js +117 -1
  37. package/esm/Form/index.d.ts +1 -0
  38. package/esm/Form/resolvers.d.ts +59 -0
  39. package/esm/Form/resolvers.js +2 -0
  40. package/esm/Timeline/Timeline.d.ts +5 -0
  41. package/esm/Timeline/Timeline.js +13 -6
  42. package/esm/Tree/hooks/useFlattenTree.js +5 -8
  43. package/esm/Uploader/Uploader.d.ts +2 -0
  44. package/esm/Uploader/Uploader.js +48 -2
  45. package/esm/internals/Picker/PickerIndicator.js +13 -11
  46. package/esm/toaster/toaster.js +38 -3
  47. package/package.json +1 -1
@@ -132,6 +132,7 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
132
132
  onError,
133
133
  onProgress,
134
134
  onReupload,
135
+ onCompletion,
135
136
  ...rest
136
137
  } = propsWithDefaults;
137
138
  const {
@@ -143,6 +144,11 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
143
144
  const rootRef = (0, _react.useRef)(null);
144
145
  const xhrs = (0, _react.useRef)({});
145
146
  const trigger = (0, _react.useRef)(null);
147
+ const uploadingCount = (0, _react.useRef)(0);
148
+ const uploadResults = (0, _react.useRef)({
149
+ completed: [],
150
+ failed: []
151
+ });
146
152
  const [fileList, dispatch] = useFileList(fileListProp || defaultFileList);
147
153
  (0, _react.useEffect)(() => {
148
154
  if (typeof fileListProp !== 'undefined') {
@@ -182,7 +188,16 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
182
188
  };
183
189
  updateFileStatus(nextFile);
184
190
  onSuccess?.(response, nextFile, event, xhr);
185
- }, [onSuccess, updateFileStatus]);
191
+ uploadingCount.current--;
192
+ uploadResults.current.completed.push(nextFile);
193
+ if (uploadingCount.current === 0) {
194
+ onCompletion?.(uploadResults.current.completed, uploadResults.current.failed);
195
+ uploadResults.current = {
196
+ completed: [],
197
+ failed: []
198
+ };
199
+ }
200
+ }, [onCompletion, onSuccess, updateFileStatus]);
186
201
 
187
202
  /**
188
203
  * Callback for file upload error.
@@ -198,7 +213,16 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
198
213
  };
199
214
  updateFileStatus(nextFile);
200
215
  onError?.(status, nextFile, event, xhr);
201
- }, [onError, updateFileStatus]);
216
+ uploadingCount.current--;
217
+ uploadResults.current.failed.push(nextFile);
218
+ if (uploadingCount.current === 0) {
219
+ onCompletion?.(uploadResults.current.completed, uploadResults.current.failed);
220
+ uploadResults.current = {
221
+ completed: [],
222
+ failed: []
223
+ };
224
+ }
225
+ }, [onCompletion, onError, updateFileStatus]);
202
226
 
203
227
  /**
204
228
  * Callback for file upload progress update.
@@ -252,9 +276,19 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
252
276
  fileList.current.forEach(file => {
253
277
  const checkState = shouldUpload?.(file);
254
278
  if (checkState instanceof Promise) {
279
+ uploadingCount.current++;
255
280
  checkState.then(res => {
256
281
  if (res) {
257
282
  handleUploadFile(file);
283
+ } else {
284
+ uploadingCount.current--;
285
+ if (uploadingCount.current === 0) {
286
+ onCompletion?.(uploadResults.current.completed, uploadResults.current.failed);
287
+ uploadResults.current = {
288
+ completed: [],
289
+ failed: []
290
+ };
291
+ }
258
292
  }
259
293
  });
260
294
  return;
@@ -262,6 +296,7 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
262
296
  return;
263
297
  }
264
298
  if (file.status === 'inited') {
299
+ uploadingCount.current++;
265
300
  handleUploadFile(file);
266
301
  }
267
302
  });
@@ -308,6 +343,15 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
308
343
  const nextFileList = fileList.current.filter(f => f.fileKey !== fileKey);
309
344
  if (xhrs.current?.[file.fileKey]?.readyState !== 4) {
310
345
  xhrs.current[file.fileKey]?.abort();
346
+ uploadingCount.current--;
347
+ uploadResults.current.failed.push(file);
348
+ if (uploadingCount.current === 0) {
349
+ onCompletion?.(uploadResults.current.completed, uploadResults.current.failed);
350
+ uploadResults.current = {
351
+ completed: [],
352
+ failed: []
353
+ };
354
+ }
311
355
  }
312
356
  dispatch({
313
357
  type: 'remove',
@@ -318,6 +362,7 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
318
362
  cleanInputValue();
319
363
  });
320
364
  const handleReupload = (0, _hooks.useEventCallback)(file => {
365
+ uploadingCount.current++;
321
366
  autoUpload && handleUploadFile(file);
322
367
  onReupload?.(file);
323
368
  });
@@ -325,6 +370,7 @@ const Uploader = (0, _utils.forwardRef)((props, ref) => {
325
370
  // public API
326
371
  const start = (0, _react.useCallback)(file => {
327
372
  if (file) {
373
+ uploadingCount.current++;
328
374
  handleUploadFile(file);
329
375
  return;
330
376
  }
@@ -36,21 +36,23 @@ const PickerIndicator = ({
36
36
  size: size === 'xs' ? 'xs' : 'sm'
37
37
  });
38
38
  }
39
- if (showCleanButton && !disabled) {
40
- return /*#__PURE__*/_react.default.createElement(_CloseButton.default, {
41
- className: prefix('clean'),
42
- tabIndex: -1,
43
- locale: {
44
- closeLabel: clear
45
- },
46
- onClick: onClose
47
- });
48
- }
49
- return caretAs && /*#__PURE__*/_react.default.createElement(_Icon.default, {
39
+ const caret = caretAs && /*#__PURE__*/_react.default.createElement(_Icon.default, {
50
40
  as: caretAs,
51
41
  className: prefix('caret-icon'),
52
42
  "data-testid": "caret"
53
43
  });
44
+ const cleanButton = showCleanButton && !disabled && /*#__PURE__*/_react.default.createElement(_CloseButton.default, {
45
+ className: prefix('clean'),
46
+ tabIndex: -1,
47
+ locale: {
48
+ closeLabel: clear
49
+ },
50
+ onClick: onClose
51
+ });
52
+ if (caret && cleanButton) {
53
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, caret, cleanButton);
54
+ }
55
+ return cleanButton || caret || null;
54
56
  };
55
57
  const props = Component === _InputGroup.default.Addon ? {
56
58
  disabled
@@ -5,9 +5,17 @@ exports.__esModule = true;
5
5
  exports.default = void 0;
6
6
  var _ToastContainer = _interopRequireWildcard(require("./ToastContainer"));
7
7
  var _symbols = require("../internals/symbols");
8
+ var _utils = require("../internals/utils");
8
9
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
9
10
  const containers = new Map();
10
11
 
12
+ /**
13
+ * Track in-progress container creation promises keyed by `${containerId}_${placement}`.
14
+ * This prevents duplicate containers from being created when `push` is called multiple
15
+ * times synchronously (e.g. inside a loop) before the first container has mounted.
16
+ */
17
+ const pendingContainerPromises = new Map();
18
+
11
19
  /**
12
20
  * Create a container instance.
13
21
  * @param placement
@@ -15,7 +23,9 @@ const containers = new Map();
15
23
  */
16
24
  async function createContainer(placement, props) {
17
25
  const [container, containerId] = await _ToastContainer.default.getInstance(props);
18
- containers.set(`${containerId}_${placement}`, container);
26
+ const key = `${containerId}_${placement}`;
27
+ containers.set(key, container);
28
+ pendingContainerPromises.delete(key);
19
29
  return container;
20
30
  }
21
31
 
@@ -35,12 +45,37 @@ toaster.push = (message, options = {}) => {
35
45
  ...restOptions
36
46
  } = options;
37
47
  const containerElement = typeof container === 'function' ? container() : container;
38
- const containerElementId = containerElement ? containerElement[_symbols.RSUITE_TOASTER_ID] : null;
39
- if (containerElementId) {
48
+ if (containerElement) {
49
+ // Pre-assign the container ID so subsequent synchronous calls can find it
50
+ // before the async container creation has completed.
51
+ if (!containerElement[_symbols.RSUITE_TOASTER_ID]) {
52
+ containerElement[_symbols.RSUITE_TOASTER_ID] = (0, _utils.guid)();
53
+ }
54
+ const containerElementId = containerElement[_symbols.RSUITE_TOASTER_ID];
55
+ const key = `${containerElementId}_${placement}`;
40
56
  const existedContainer = getContainer(containerElementId, placement);
41
57
  if (existedContainer) {
42
58
  return existedContainer.current?.push(message, restOptions);
43
59
  }
60
+
61
+ // A container creation for this placement may already be in progress (e.g. when `push`
62
+ // is called multiple times synchronously in a loop). Reuse that promise instead of
63
+ // creating a second container.
64
+ const pendingPromise = pendingContainerPromises.get(key);
65
+ if (pendingPromise) {
66
+ return pendingPromise.then(ref => ref.current?.push(message, restOptions));
67
+ }
68
+ const newOptions = {
69
+ ...options,
70
+ container: containerElement,
71
+ placement
72
+ };
73
+ const containerPromise = createContainer(placement, newOptions);
74
+
75
+ // Register the pending promise before any async work begins so that subsequent
76
+ // synchronous `push` calls for the same placement chain onto it.
77
+ pendingContainerPromises.set(key, containerPromise);
78
+ return containerPromise.then(ref => ref.current?.push(message, restOptions));
44
79
  }
45
80
  const newOptions = {
46
81
  ...options,
@@ -14642,6 +14642,17 @@ blockquote.rs-text{
14642
14642
  height:auto;
14643
14643
  min-height:var(--rs-time-line-tail-min-height);
14644
14644
  }
14645
+ .rs-timeline-reverse.rs-timeline-endless .rs-timeline-item:first-child .rs-timeline-item-tail{
14646
+ top:0;
14647
+ bottom:0;
14648
+ height:auto;
14649
+ }
14650
+
14651
+ .rs-timeline-reverse.rs-timeline-endless .rs-timeline-item:last-child .rs-timeline-item-tail{
14652
+ height:calc(var(--rs-time-line-dot-center-gap) + var(--rs-time-line-dot-side-length));
14653
+ min-height:0;
14654
+ }
14655
+
14645
14656
  .rs-timeline-item:only-child .rs-timeline-item-tail{
14646
14657
  display:none;
14647
14658
  }
@@ -15351,6 +15362,7 @@ blockquote.rs-text{
15351
15362
  text-overflow:ellipsis;
15352
15363
  white-space:nowrap;
15353
15364
  flex:1 1 auto;
15365
+ min-width:0;
15354
15366
  }
15355
15367
  .rs-uploader[data-list-type=text] .rs-uploader-file-item-size{
15356
15368
  flex:0 0 auto;
@@ -15397,6 +15409,7 @@ blockquote.rs-text{
15397
15409
  .rs-uploader[data-list-type=picture]{
15398
15410
  display:inline-flex;
15399
15411
  flex-direction:row;
15412
+ flex-wrap:wrap;
15400
15413
  gap:var(--rs-uploader-item-spacing);
15401
15414
  }
15402
15415
  .rs-uploader[data-list-type=picture] .rs-uploader-trigger-btn{
@@ -15431,6 +15444,7 @@ blockquote.rs-text{
15431
15444
  }
15432
15445
  .rs-uploader[data-list-type=picture] .rs-uploader-file-items{
15433
15446
  display:inline-flex;
15447
+ flex-wrap:wrap;
15434
15448
  gap:var(--rs-uploader-item-spacing);
15435
15449
  }
15436
15450
  .rs-uploader[data-list-type=picture] .rs-uploader-file-item{