@ioca/react 1.5.17 → 1.5.19

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/lib/cjs/components/editor/editor.js +4 -2
  2. package/lib/cjs/components/editor/editor.js.map +1 -1
  3. package/lib/cjs/components/input/input.js +3 -1
  4. package/lib/cjs/components/input/input.js.map +1 -1
  5. package/lib/cjs/components/input/textarea.js +1 -1
  6. package/lib/cjs/components/input/textarea.js.map +1 -1
  7. package/lib/cjs/components/message/index.js +3 -2
  8. package/lib/cjs/components/message/index.js.map +1 -1
  9. package/lib/cjs/components/message/message.js +93 -50
  10. package/lib/cjs/components/message/message.js.map +1 -1
  11. package/lib/cjs/components/modal/content.js +16 -8
  12. package/lib/cjs/components/modal/content.js.map +1 -1
  13. package/lib/cjs/components/modal/modal.js +60 -19
  14. package/lib/cjs/components/modal/modal.js.map +1 -1
  15. package/lib/cjs/components/modal/modalManager.js +83 -0
  16. package/lib/cjs/components/modal/modalManager.js.map +1 -0
  17. package/lib/cjs/components/picker/daterange/daterange.js +60 -0
  18. package/lib/cjs/components/picker/daterange/daterange.js.map +1 -0
  19. package/lib/cjs/components/picker/daterange/index.js +11 -0
  20. package/lib/cjs/components/picker/daterange/index.js.map +1 -0
  21. package/lib/cjs/components/picker/daterange/panel.js +55 -0
  22. package/lib/cjs/components/picker/daterange/panel.js.map +1 -0
  23. package/lib/cjs/components/picker/dates/dates.js +12 -4
  24. package/lib/cjs/components/picker/dates/dates.js.map +1 -1
  25. package/lib/cjs/components/picker/dates/index.js +6 -2
  26. package/lib/cjs/components/picker/dates/index.js.map +1 -1
  27. package/lib/cjs/components/picker/dates/panel.js +22 -9
  28. package/lib/cjs/components/picker/dates/panel.js.map +1 -1
  29. package/lib/cjs/components/picker/time/index.js +6 -2
  30. package/lib/cjs/components/picker/time/index.js.map +1 -1
  31. package/lib/cjs/components/popconfirm/popconfirm.js +2 -4
  32. package/lib/cjs/components/popconfirm/popconfirm.js.map +1 -1
  33. package/lib/cjs/index.js +10 -8
  34. package/lib/cjs/index.js.map +1 -1
  35. package/lib/cjs/js/hooks.js +5 -2
  36. package/lib/cjs/js/hooks.js.map +1 -1
  37. package/lib/css/colors.css +2 -2
  38. package/lib/css/index.css +1 -1
  39. package/lib/css/index.css.map +1 -1
  40. package/lib/css/input.css +17 -1
  41. package/lib/es/components/editor/editor.js +4 -2
  42. package/lib/es/components/editor/editor.js.map +1 -1
  43. package/lib/es/components/input/input.js +3 -1
  44. package/lib/es/components/input/input.js.map +1 -1
  45. package/lib/es/components/input/textarea.js +1 -1
  46. package/lib/es/components/input/textarea.js.map +1 -1
  47. package/lib/es/components/message/index.js +3 -3
  48. package/lib/es/components/message/index.js.map +1 -1
  49. package/lib/es/components/message/message.js +93 -51
  50. package/lib/es/components/message/message.js.map +1 -1
  51. package/lib/es/components/modal/content.js +18 -10
  52. package/lib/es/components/modal/content.js.map +1 -1
  53. package/lib/es/components/modal/modal.js +61 -20
  54. package/lib/es/components/modal/modal.js.map +1 -1
  55. package/lib/es/components/modal/modalManager.js +76 -0
  56. package/lib/es/components/modal/modalManager.js.map +1 -0
  57. package/lib/es/components/picker/daterange/daterange.js +50 -0
  58. package/lib/es/components/picker/daterange/daterange.js.map +1 -0
  59. package/lib/es/components/picker/daterange/index.js +6 -0
  60. package/lib/es/components/picker/daterange/index.js.map +1 -0
  61. package/lib/es/components/picker/daterange/panel.js +47 -0
  62. package/lib/es/components/picker/daterange/panel.js.map +1 -0
  63. package/lib/es/components/picker/dates/dates.js +12 -4
  64. package/lib/es/components/picker/dates/dates.js.map +1 -1
  65. package/lib/es/components/picker/dates/index.js +6 -2
  66. package/lib/es/components/picker/dates/index.js.map +1 -1
  67. package/lib/es/components/picker/dates/panel.js +22 -9
  68. package/lib/es/components/picker/dates/panel.js.map +1 -1
  69. package/lib/es/components/picker/time/index.js +6 -2
  70. package/lib/es/components/picker/time/index.js.map +1 -1
  71. package/lib/es/components/popconfirm/popconfirm.js +2 -4
  72. package/lib/es/components/popconfirm/popconfirm.js.map +1 -1
  73. package/lib/es/index.js +2 -1
  74. package/lib/es/index.js.map +1 -1
  75. package/lib/es/js/hooks.js +5 -2
  76. package/lib/es/js/hooks.js.map +1 -1
  77. package/lib/index.js +384 -104
  78. package/lib/types/components/input/type.d.ts +1 -0
  79. package/lib/types/components/message/index.d.ts +5 -3
  80. package/lib/types/components/message/message.d.ts +5 -4
  81. package/lib/types/components/message/type.d.ts +25 -12
  82. package/lib/types/components/picker/daterange/daterange.d.ts +6 -0
  83. package/lib/types/components/picker/daterange/index.d.ts +5 -0
  84. package/lib/types/components/picker/type.d.ts +11 -2
  85. package/lib/types/index.d.ts +2 -1
  86. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import classNames from 'classnames';
3
3
  import { debounce, uid, crush, throttle } from 'radash';
4
4
  import { useState, useRef, useEffect, useCallback, useMemo, Children, cloneElement, createElement, isValidElement, memo, Fragment as Fragment$1, useTransition, forwardRef, useLayoutEffect, useContext, createContext, useImperativeHandle } from 'react';
5
- import { SkipPreviousRound, CloseRound, MinusRound, PlusRound, InboxTwotone, UndoRound, RedoRound, FormatBoldRound, FormatItalicRound, FormatUnderlinedRound, StrikethroughSRound, ClearAllRound, PlayArrowRound, PauseRound, StopRound, VolumeDownRound, VolumeOffRound, FullscreenRound, FullscreenExitRound, FeedOutlined, AspectRatioRound, OpenInNewRound, FileDownloadOutlined, RotateRightRound, RotateLeftRound, KeyboardArrowLeftRound, KeyboardArrowRightRound, KeyboardDoubleArrowUpRound, SyncAltRound, VisibilityRound, VisibilityOffRound, MoreHorizRound, SearchRound, CheckRound, UnfoldMoreRound, CalendarMonthTwotone, AccessTimeRound, InfoOutlined, KeyboardArrowDownRound, MoveToInboxTwotone, OutboxTwotone, FilePresentOutlined, DriveFolderUploadOutlined } from '@ricons/material';
5
+ import { SkipPreviousRound, CloseRound, MinusRound, PlusRound, InboxTwotone, UndoRound, RedoRound, FormatBoldRound, FormatItalicRound, FormatUnderlinedRound, StrikethroughSRound, ClearAllRound, PlayArrowRound, PauseRound, StopRound, VolumeDownRound, VolumeOffRound, FullscreenRound, FullscreenExitRound, FeedOutlined, AspectRatioRound, OpenInNewRound, FileDownloadOutlined, RotateRightRound, RotateLeftRound, KeyboardArrowLeftRound, KeyboardArrowRightRound, KeyboardDoubleArrowUpRound, SyncAltRound, VisibilityRound, VisibilityOffRound, MoreHorizRound, SearchRound, CheckRound, UnfoldMoreRound, CalendarMonthTwotone, AccessTimeRound, KeyboardArrowDownRound, MoveToInboxTwotone, OutboxTwotone, FilePresentOutlined, DriveFolderUploadOutlined } from '@ricons/material';
6
6
  import { createRoot } from 'react-dom/client';
7
7
  import { getScrollbarSize, List as List$2 } from 'react-window';
8
8
  import { createPortal } from 'react-dom';
@@ -135,12 +135,15 @@ function useMouseUp(listener, options) {
135
135
  }
136
136
  function useKeydown(listener, options) {
137
137
  initEventsOnce();
138
+ const listenerRef = useRef(listener);
139
+ listenerRef.current = listener;
138
140
  useEffect(() => {
139
141
  if (options?.disabled)
140
142
  return;
141
- KeydownEvents.add(listener);
143
+ const handler = (e) => listenerRef.current(e);
144
+ KeydownEvents.add(handler);
142
145
  return () => {
143
- KeydownEvents.delete(listener);
146
+ KeydownEvents.delete(handler);
144
147
  };
145
148
  }, []);
146
149
  }
@@ -1785,7 +1788,7 @@ const List$1 = forwardRef((props, ref) => {
1785
1788
  });
1786
1789
  List$1.Item = Item$4;
1787
1790
 
1788
- const Content$2 = forwardRef((props, ref) => {
1791
+ const Content$3 = forwardRef((props, ref) => {
1789
1792
  const { arrow, arrowProps = {}, className, children, ...restProps } = props;
1790
1793
  const arrowCSS = useMemo(() => {
1791
1794
  let { left = 0, top = 0, pos } = arrowProps;
@@ -2297,7 +2300,7 @@ function Popup(props) {
2297
2300
  window.removeEventListener("scroll", onScrollOrResize, true);
2298
2301
  };
2299
2302
  }, [show]);
2300
- return (jsxs(Fragment, { children: [triggerNode, show && (jsx(Content$2, { ref: contentRef, arrow: arrow && trigger !== "contextmenu", style: {
2303
+ return (jsxs(Fragment, { children: [triggerNode, show && (jsx(Content$3, { ref: contentRef, arrow: arrow && trigger !== "contextmenu", style: {
2301
2304
  ...style,
2302
2305
  position: "fixed",
2303
2306
  }, className: className, ...contentTouch, trigger: triggerRef.current, children: content }))] }));
@@ -2703,6 +2706,7 @@ const Editor = (props) => {
2703
2706
  const [memtionKeyword, setMemtionKeyword] = useState("");
2704
2707
  const [memtionActiveIndex, setMemtionActiveIndex] = useState(0);
2705
2708
  const [activeMemtionIndex, setActiveMemtionIndex] = useState(-1);
2709
+ const activeMemtionIndexRef = useRef(-1);
2706
2710
  const memtionOptions = useMemo(() => {
2707
2711
  if (activeMemtionIndex < 0 || !memtion?.length)
2708
2712
  return [];
@@ -2838,6 +2842,7 @@ const Editor = (props) => {
2838
2842
  memtionTriggerRangeRef.current =
2839
2843
  selectionRef.current?.cloneRange() ?? null;
2840
2844
  pendingMemtionRef.current = true;
2845
+ activeMemtionIndexRef.current = matchedIndex;
2841
2846
  setActiveMemtionIndex(matchedIndex);
2842
2847
  }
2843
2848
  }
@@ -2887,8 +2892,8 @@ const Editor = (props) => {
2887
2892
  setEditorValue(nextValue);
2888
2893
  }
2889
2894
  rememberSelection();
2890
- if (activeMemtionIndex >= 0 && (pendingMemtionRef.current || memtionVisible)) {
2891
- const active = memtion?.[activeMemtionIndex];
2895
+ if (activeMemtionIndexRef.current >= 0 && (pendingMemtionRef.current || memtionVisible)) {
2896
+ const active = memtion?.[activeMemtionIndexRef.current];
2892
2897
  if (!active) {
2893
2898
  hideMemtion();
2894
2899
  return;
@@ -3261,14 +3266,21 @@ Form.useForm = useForm;
3261
3266
  Form.Field = Field;
3262
3267
  Form.useConfig = useConfig;
3263
3268
 
3264
- function Content$1(props) {
3269
+ const Content$1 = (props) => {
3265
3270
  const { title, footer, hideCloseButton, footerLeft, okButtonProps, cancelButtonProps, children, onOk, onClose, } = props;
3266
3271
  const showHeader = title || !hideCloseButton;
3272
+ const [loading, setLoading] = useState(false);
3267
3273
  const handleOk = async () => {
3268
- const ret = await onOk?.();
3269
- if (ret === false)
3270
- return;
3271
- onClose?.();
3274
+ setLoading(true);
3275
+ try {
3276
+ const ret = await onOk?.();
3277
+ if (ret === false)
3278
+ return;
3279
+ onClose?.();
3280
+ }
3281
+ finally {
3282
+ setLoading(false);
3283
+ }
3272
3284
  };
3273
3285
  const renderFooter = useMemo(() => {
3274
3286
  if (footer || footer === null)
@@ -3276,19 +3288,94 @@ function Content$1(props) {
3276
3288
  const propsOk = Object.assign({
3277
3289
  children: "确定",
3278
3290
  onClick: handleOk,
3279
- }, okButtonProps);
3291
+ }, okButtonProps, { loading });
3280
3292
  const propsCancel = Object.assign({
3281
3293
  secondary: true,
3282
3294
  children: "关闭",
3283
3295
  onClick: onClose,
3284
3296
  }, cancelButtonProps);
3285
3297
  return (jsxs(Fragment, { children: [footerLeft, jsx(Button, { ...propsOk }), jsx(Button, { ...propsCancel })] }));
3286
- }, [footer, okButtonProps, cancelButtonProps]);
3298
+ }, [footer, okButtonProps, cancelButtonProps, loading]);
3287
3299
  return (jsxs(Fragment, { children: [showHeader && (jsxs("header", { className: 'i-modal-header', children: [title && jsx("b", { children: title }), jsx(Helpericon, { active: !hideCloseButton, className: 'i-modal-close', onClick: onClose })] })), jsx("div", { className: 'i-modal-content', children: children }), jsx("footer", { className: 'i-modal-footer', children: renderFooter })] }));
3288
- }
3300
+ };
3301
+ var Content$2 = memo(Content$1);
3289
3302
 
3290
3303
  const ModalContext = createContext(false);
3291
3304
 
3305
+ const CONTAINER_ID = "i-modal-container";
3306
+ const BACKDROP_ID = "i-modal-backdrop";
3307
+ let containerEl = null;
3308
+ let backdropEl = null;
3309
+ const stack = [];
3310
+ const listeners = new Set();
3311
+ function ensureContainer() {
3312
+ if (containerEl)
3313
+ return containerEl;
3314
+ containerEl = document.createElement("div");
3315
+ containerEl.id = CONTAINER_ID;
3316
+ containerEl.className = "i-modal-container";
3317
+ document.body.append(containerEl);
3318
+ backdropEl = document.createElement("div");
3319
+ backdropEl.id = BACKDROP_ID;
3320
+ backdropEl.className = "i-modal-backdrop";
3321
+ containerEl.prepend(backdropEl);
3322
+ return containerEl;
3323
+ }
3324
+ function syncBackdrop() {
3325
+ if (!backdropEl)
3326
+ return;
3327
+ const show = stack.some((e) => e.visible && !e.hideBackdrop);
3328
+ backdropEl.classList.toggle("i-modal-backdrop-active", show);
3329
+ }
3330
+ function notify$1() {
3331
+ listeners.forEach((fn) => fn());
3332
+ }
3333
+ function register(entry) {
3334
+ ensureContainer();
3335
+ stack.push(entry);
3336
+ syncBackdrop();
3337
+ notify$1();
3338
+ return () => {
3339
+ const idx = stack.findIndex((e) => e.mid === entry.mid);
3340
+ if (idx !== -1)
3341
+ stack.splice(idx, 1);
3342
+ syncBackdrop();
3343
+ notify$1();
3344
+ if (stack.length === 0) {
3345
+ backdropEl?.remove();
3346
+ backdropEl = null;
3347
+ containerEl?.remove();
3348
+ containerEl = null;
3349
+ }
3350
+ };
3351
+ }
3352
+ function updateVisible(mid, visible) {
3353
+ const entry = stack.find((e) => e.mid === mid);
3354
+ if (entry) {
3355
+ entry.visible = visible;
3356
+ syncBackdrop();
3357
+ notify$1();
3358
+ }
3359
+ }
3360
+ function isTop(mid) {
3361
+ const top = getTopVisible();
3362
+ return top?.mid === mid;
3363
+ }
3364
+ function getTopVisible() {
3365
+ for (let i = stack.length - 1; i >= 0; i--) {
3366
+ if (stack[i].visible)
3367
+ return stack[i];
3368
+ }
3369
+ return undefined;
3370
+ }
3371
+ function getContainer() {
3372
+ return ensureContainer();
3373
+ }
3374
+ function subscribe(fn) {
3375
+ listeners.add(fn);
3376
+ return () => listeners.delete(fn);
3377
+ }
3378
+
3292
3379
  function useModal() {
3293
3380
  const ref = useRef(null);
3294
3381
  const handleOpen = (props) => {
@@ -3316,26 +3403,41 @@ function useModal() {
3316
3403
  };
3317
3404
  }
3318
3405
 
3406
+ let midCounter = 0;
3319
3407
  function Modal(props) {
3320
3408
  const { visible, title, footer, okButtonProps, cancelButtonProps, closable = true, hideBackdrop, backdropClosable = true, hideCloseButton, disableEsc, width, height, customized, fixed, hideShadow, children, style, className, keepDOM, footerLeft, onClick, onVisibleChange, onClose, onOk, ...restProps } = props;
3409
+ const midRef = useRef(`modal-${++midCounter}`);
3410
+ const mid = midRef.current;
3321
3411
  const [show, setShow] = useState(visible);
3322
3412
  const [active, setActive] = useState(false);
3323
3413
  const [bounced, setBounced] = useState(false);
3324
3414
  const [mounted, setMounted] = useState(false);
3415
+ const [top, setTop] = useState(false);
3325
3416
  const toggable = useRef(true);
3326
- const handleShow = async () => {
3417
+ const layerRef = useRef(null);
3418
+ const handleShow = useCallback(() => {
3327
3419
  if (!toggable.current)
3328
3420
  return;
3329
- (!keepDOM || !show) && setShow(true);
3421
+ if (!keepDOM || !show)
3422
+ setShow(true);
3330
3423
  toggable.current = false;
3331
- const timer = setTimeout(() => {
3424
+ updateVisible(mid, true);
3425
+ const raf = requestAnimationFrame(() => {
3426
+ if (!layerRef.current) {
3427
+ requestAnimationFrame(() => {
3428
+ setActive(true);
3429
+ onVisibleChange?.(true);
3430
+ toggable.current = true;
3431
+ });
3432
+ return;
3433
+ }
3332
3434
  setActive(true);
3333
3435
  onVisibleChange?.(true);
3334
3436
  toggable.current = true;
3335
- }, 64);
3336
- return () => clearTimeout(timer);
3337
- };
3338
- const handleHide = () => {
3437
+ });
3438
+ return () => cancelAnimationFrame(raf);
3439
+ }, [keepDOM, show, onVisibleChange]);
3440
+ const handleHide = useCallback(() => {
3339
3441
  if (!toggable.current)
3340
3442
  return;
3341
3443
  toggable.current = false;
@@ -3348,28 +3450,53 @@ function Modal(props) {
3348
3450
  return () => clearTimeout(timer);
3349
3451
  }
3350
3452
  setActive(false);
3453
+ updateVisible(mid, false);
3351
3454
  const timer = setTimeout(() => {
3352
- !keepDOM && setShow(false);
3455
+ if (!keepDOM)
3456
+ setShow(false);
3353
3457
  toggable.current = true;
3354
3458
  onVisibleChange?.(false);
3355
3459
  onClose?.();
3356
3460
  }, 240);
3357
3461
  return () => clearTimeout(timer);
3358
- };
3462
+ }, [closable, keepDOM, onClose, onVisibleChange]);
3359
3463
  const handleBackdropClick = () => {
3360
3464
  backdropClosable && handleHide();
3361
3465
  };
3362
- useKeydown((e) => {
3363
- if (e.code !== "Escape" || !visible)
3364
- return;
3365
- handleHide();
3366
- }, { disabled: disableEsc });
3466
+ useEffect(() => {
3467
+ const unsub = subscribe(() => {
3468
+ setTop(isTop(mid));
3469
+ });
3470
+ return unsub;
3471
+ }, []);
3472
+ useEffect(() => {
3473
+ const unregister = register({
3474
+ mid,
3475
+ visible: !!visible,
3476
+ hideBackdrop: !!hideBackdrop,
3477
+ closable: !!closable,
3478
+ });
3479
+ return unregister;
3480
+ }, []);
3367
3481
  useEffect(() => {
3368
3482
  visible ? handleShow() : handleHide();
3369
3483
  }, [visible]);
3484
+ useEffect(() => {
3485
+ if (!show)
3486
+ return;
3487
+ const raf = requestAnimationFrame(() => {
3488
+ setActive(top);
3489
+ });
3490
+ return () => cancelAnimationFrame(raf);
3491
+ }, [top]);
3370
3492
  useEffect(() => {
3371
3493
  setMounted(true);
3372
3494
  }, []);
3495
+ useKeydown((e) => {
3496
+ if (e.code !== "Escape" || !visible || !top)
3497
+ return;
3498
+ handleHide();
3499
+ }, { disabled: disableEsc });
3373
3500
  const handleClick = () => {
3374
3501
  if (typeof document === "undefined")
3375
3502
  return;
@@ -3377,12 +3504,12 @@ function Modal(props) {
3377
3504
  };
3378
3505
  if (!show || !mounted)
3379
3506
  return null;
3380
- return createPortal(jsx("div", { className: classNames("i-modal-container", {
3381
- "i-modal-backdrop": !hideBackdrop,
3382
- "i-modal-customized": customized,
3507
+ return createPortal(jsx("div", { ref: layerRef, className: classNames("i-modal-layer", {
3383
3508
  "i-modal-active": active,
3509
+ "i-modal-customized": customized,
3510
+ "i-modal-hide-backdrop": hideBackdrop,
3384
3511
  fixed,
3385
- }, className), style: style, onClick: handleBackdropClick, "aria-modal": 'true', inert: !active, children: jsx("div", { className: classNames("i-modal", {
3512
+ }, className), style: style, onClick: handleBackdropClick, children: jsx("div", { className: classNames("i-modal", {
3386
3513
  bounced,
3387
3514
  shadow: !hideShadow,
3388
3515
  }), style: {
@@ -3392,7 +3519,7 @@ function Modal(props) {
3392
3519
  e.stopPropagation();
3393
3520
  handleClick();
3394
3521
  onClick?.(e);
3395
- }, role: 'dialog', "aria-labelledby": title ? "modal-title" : undefined, ...restProps, children: jsxs(ModalContext.Provider, { value: true, children: [customized && children, !customized && (jsx(Content$1, { title: title, hideCloseButton: hideCloseButton, footer: footer, okButtonProps: okButtonProps, cancelButtonProps: cancelButtonProps, children: children, footerLeft: footerLeft, onOk: onOk, onClose: handleHide }))] }) }) }), document?.body ?? null);
3522
+ }, role: "dialog", "aria-modal": top, "data-mid": mid, ...restProps, children: jsxs(ModalContext.Provider, { value: true, children: [customized && children, !customized && (jsx(Content$2, { title: title, hideCloseButton: hideCloseButton, footer: footer, okButtonProps: okButtonProps, cancelButtonProps: cancelButtonProps, children: children, footerLeft: footerLeft, onOk: onOk, onClose: handleHide }))] }) }) }), getContainer());
3396
3523
  }
3397
3524
  Modal.useModal = useModal;
3398
3525
 
@@ -4258,7 +4385,7 @@ const Textarea = (props) => {
4258
4385
  onKeyDown: handleKeydown,
4259
4386
  ...restProps,
4260
4387
  };
4261
- return (jsx(InputContainer, { label: label, labelInline: labelInline, className: className, style: { width, ...style }, tip: message ?? tip, status: status, children: jsx("div", { className: classNames("i-input-item", {
4388
+ return (jsx(InputContainer, { label: label, labelInline: labelInline, className: classNames("i-textarea-label", className), style: { width, ...style }, tip: message ?? tip, status: status, children: jsx("div", { className: classNames("i-input-item", {
4262
4389
  [`i-input-${status}`]: status !== "normal",
4263
4390
  "i-input-borderless": !border,
4264
4391
  }), children: jsx("textarea", { ...inputProps }) }) }));
@@ -4317,11 +4444,13 @@ const Input = ((props) => {
4317
4444
  }, [type]);
4318
4445
  const clearable = clear && inputValue;
4319
4446
  const showHelper = type === "password" && !!inputValue;
4447
+ const isClearBtn = clearable && !showHelper;
4320
4448
  return (jsx(InputContainer, { label: label, labelInline: labelInline, className: className, style: { width, ...style }, tip: message ?? tip, status: status, required: required, children: jsxs("div", { className: classNames("i-input-item", {
4449
+ "i-input-clearable": clearable,
4321
4450
  [`i-input-${status}`]: status !== "normal",
4322
4451
  "i-input-borderless": !border,
4323
4452
  "i-input-underline": underline,
4324
- }), children: [prepend && jsx("div", { className: 'i-input-prepend', children: prepend }), jsx("input", { ...inputProps }), maxLength && inputValue?.length > 0 && (jsxs("span", { className: 'color-8 pr-4 font-sm', children: [inputValue.length, " / ", maxLength] })), jsx(Helpericon, { active: !!clearable || showHelper, icon: HelperIcon, onClick: handleHelperClick }), append && jsx("div", { className: 'i-input-append', children: append })] }) }));
4453
+ }), children: [prepend && jsx("div", { className: 'i-input-prepend', children: prepend }), jsx("input", { ...inputProps }), maxLength && inputValue?.length > 0 && (jsxs("span", { className: 'color-8 pr-4 font-sm', children: [inputValue.length, " / ", maxLength] })), jsx(Helpericon, { active: !!clearable || showHelper, icon: HelperIcon, className: classNames({ "i-helpericon-clear": isClearBtn }), onClick: handleHelperClick }), append && jsx("div", { className: 'i-input-append', children: append })] }) }));
4325
4454
  });
4326
4455
  Input.Textarea = Textarea;
4327
4456
  Input.Number = Number$1;
@@ -4332,13 +4461,13 @@ const AlignMap = {
4332
4461
  center: "center",
4333
4462
  right: "flex-end",
4334
4463
  };
4335
- const GlobalConfig = {
4464
+ const ContainerConfig = {
4465
+ align: "center",
4466
+ fromBottom: false,
4467
+ unshift: false,
4336
4468
  gap: 12,
4337
- };
4338
- const ItemDefaultConfig = {
4469
+ offset: "12px",
4339
4470
  duration: 3000,
4340
- closable: true,
4341
- active: false,
4342
4471
  };
4343
4472
  const handler = {
4344
4473
  oneInstance: null,
@@ -4355,12 +4484,12 @@ const heights = {
4355
4484
  center: [],
4356
4485
  right: [],
4357
4486
  };
4358
- const MessageItem = function ({ ref, active, content, top, className, style, onClick, }) {
4487
+ const MessageItem = function ({ ref, active, content, top, bottom, className, style, onClick, }) {
4359
4488
  return (jsx("div", { ref: ref, className: classNames("i-message", className, {
4360
4489
  "i-message-active": active,
4361
4490
  }), style: {
4362
4491
  ...style,
4363
- top,
4492
+ ...(bottom !== undefined ? { bottom } : { top }),
4364
4493
  }, onClick: onClick, children: content }));
4365
4494
  };
4366
4495
  function Messages() {
@@ -4377,26 +4506,32 @@ function Messages() {
4377
4506
  right: [],
4378
4507
  },
4379
4508
  });
4380
- const offsetTop = {
4381
- left: 0,
4382
- center: 0,
4383
- right: 0,
4384
- };
4385
4509
  useEffect(() => {
4386
4510
  Object.assign(handler, {
4387
4511
  callout: function (item) {
4388
4512
  const { align = "center", unshift, onShow } = item;
4389
- const size = queue[align][unshift ? "unshift" : "push"](item);
4513
+ queue[align][unshift ? "unshift" : "push"](item);
4390
4514
  state.items[align] = [...queue[align]];
4391
4515
  item.close = this.close.bind(item);
4392
- setTimeout(() => {
4516
+ // Pre-fill 0-height placeholder so heights stays index-aligned with queue
4517
+ if (unshift) {
4518
+ heights[align].unshift(0);
4519
+ }
4520
+ else {
4521
+ heights[align].push(0);
4522
+ }
4523
+ state.tops[align] = [...heights[align]];
4524
+ requestAnimationFrame(() => {
4393
4525
  const h = ref.current?.offsetHeight || 0;
4394
- queue[align][unshift ? 0 : size - 1].active = true;
4526
+ const idx = queue[align].findIndex((i) => i.id === item.id);
4527
+ if (idx < 0)
4528
+ return;
4529
+ queue[align][idx].active = true;
4395
4530
  state.items[align] = [...queue[align]];
4396
- heights[align][unshift ? "unshift" : "push"](h);
4531
+ heights[align][idx] = h;
4397
4532
  state.tops[align] = [...heights[align]];
4398
4533
  onShow?.();
4399
- }, 12);
4534
+ });
4400
4535
  if (item.duration !== 0) {
4401
4536
  item.timer = setTimeout(() => {
4402
4537
  this.close.call(item);
@@ -4423,36 +4558,65 @@ function Messages() {
4423
4558
  },
4424
4559
  });
4425
4560
  }, []);
4426
- const renderItems = (item, i) => {
4427
- if (!item)
4428
- return jsx(Fragment, {});
4429
- const { id, active, content, align = "center", className } = item;
4430
- offsetTop[align] += state.tops[align][i - 1] || 0;
4431
- const top = GlobalConfig.gap * i + offsetTop[align];
4432
- return (jsx(MessageItem, { ref: ref, active: active, content: content, top: top, className: className, style: { alignSelf: AlignMap[align] }, onClick: handler.close.bind(item) }, id));
4433
- };
4434
- return (jsxs("div", { className: 'i-messages', children: [state.items.left.map(renderItems), state.items.center.map(renderItems), state.items.right.map(renderItems)] }));
4561
+ const renderGroup = (align) => {
4562
+ const items = state.items[align];
4563
+ const tops = state.tops[align];
4564
+ const gap = ContainerConfig.gap;
4565
+ if (ContainerConfig.fromBottom) {
4566
+ // bottom-up: calculate bottom-edge positions
4567
+ let offset = 0;
4568
+ const bottoms = [];
4569
+ for (let i = items.length - 1; i >= 0; i--) {
4570
+ bottoms[i] = offset;
4571
+ offset += (tops[i] || 0) + gap;
4572
+ }
4573
+ return items.map((item, i) => {
4574
+ if (!item)
4575
+ return jsx(Fragment, {});
4576
+ const { id, active, content, className, style: itemStyle } = item;
4577
+ return (jsx(MessageItem, { ref: ref, active: active, content: content, bottom: bottoms[i], className: className, style: {
4578
+ ...itemStyle,
4579
+ alignSelf: AlignMap[align],
4580
+ }, onClick: handler.close.bind(item) }, id));
4581
+ });
4582
+ }
4583
+ // top-down (default)
4584
+ let offset = 0;
4585
+ return items.map((item, i) => {
4586
+ if (!item)
4587
+ return jsx(Fragment, {});
4588
+ const { id, active, content, className, style: itemStyle } = item;
4589
+ const top = offset;
4590
+ offset += (tops[i] || 0) + gap;
4591
+ return (jsx(MessageItem, { ref: ref, active: active, content: content, top: top, className: className, style: {
4592
+ ...itemStyle,
4593
+ alignSelf: AlignMap[align],
4594
+ }, onClick: handler.close.bind(item) }, id));
4595
+ });
4596
+ };
4597
+ return (jsxs("div", { className: "i-messages", style: {
4598
+ margin: ContainerConfig.offset,
4599
+ }, children: [renderGroup("left"), renderGroup("center"), renderGroup("right")] }));
4435
4600
  }
4436
4601
  function message(config) {
4437
- if (["string", "number"].includes(typeof config) ||
4438
- isValidElement(config)) {
4602
+ if (typeof config !== "object" || isValidElement(config)) {
4439
4603
  config = { content: config };
4440
4604
  }
4441
- config = Object.assign({ id: uid(7) }, ItemDefaultConfig, config);
4442
- handler.callout(config);
4605
+ const msg = {
4606
+ id: uid(7),
4607
+ active: false,
4608
+ align: ContainerConfig.align,
4609
+ duration: ContainerConfig.duration,
4610
+ closable: true,
4611
+ unshift: ContainerConfig.unshift,
4612
+ ...config,
4613
+ };
4614
+ handler.callout(msg);
4443
4615
  return {
4444
- instance: config,
4445
- close: handler.close.bind(config),
4616
+ instance: msg,
4617
+ close: handler.close.bind(msg),
4446
4618
  };
4447
4619
  }
4448
- function createContainer() {
4449
- if (typeof document === "undefined")
4450
- return null;
4451
- const container = document.createElement("div");
4452
- container.dataset.id = "messages";
4453
- document.body.append(container);
4454
- return container;
4455
- }
4456
4620
  message.error = (content) => {
4457
4621
  return message({
4458
4622
  content,
@@ -4495,17 +4659,27 @@ message.one = (config) => {
4495
4659
  handler.oneInstance = instance;
4496
4660
  }
4497
4661
  };
4498
- // 初始化消息容器
4499
- let container = null;
4500
- let root = null;
4501
- if (typeof window !== "undefined") {
4502
- container = createContainer();
4503
- if (container) {
4504
- root = createRoot(container);
4505
- root.render(jsx(Messages, {}));
4506
- }
4662
+ function MessageContainer({ align = "center", fromBottom = false, unshift = false, gap = 12, offset = "12px", duration = 3000, }) {
4663
+ ContainerConfig.align = align;
4664
+ ContainerConfig.fromBottom = fromBottom;
4665
+ ContainerConfig.unshift = unshift;
4666
+ ContainerConfig.gap = gap;
4667
+ ContainerConfig.offset = offset;
4668
+ ContainerConfig.duration = duration;
4669
+ return null;
4670
+ }
4671
+ // 默认 Portal 到 document.body(仅在客户端执行,避免 SSR 问题)
4672
+ if (typeof document !== "undefined") {
4673
+ import('react-dom/client').then(({ createRoot }) => {
4674
+ const container = document.createElement("div");
4675
+ container.dataset.id = "messages";
4676
+ document.body.append(container);
4677
+ createRoot(container).render(jsx(Messages, {}));
4678
+ });
4507
4679
  }
4508
4680
 
4681
+ const Message = Object.assign(message, { Container: MessageContainer });
4682
+
4509
4683
  const Page = (props) => {
4510
4684
  const { page, active, disabled, children, onChange } = props;
4511
4685
  const [loading, setLoading] = useState(false);
@@ -4772,7 +4946,7 @@ function ColorPicker(props) {
4772
4946
  }
4773
4947
 
4774
4948
  const Dates = (props) => {
4775
- const { value, month, weeks = ["一", "二", "三", "四", "五", "六", "日"], renderDate = (date) => date.date(), disabledDate, onDateClick, } = props;
4949
+ const { value, month, rangeEnd, hoverDate, weeks = ["一", "二", "三", "四", "五", "六", "日"], renderDate = (date) => date.date(), disabledDate, onDateClick, onDateHover, } = props;
4776
4950
  const today = dayjs();
4777
4951
  const dates = useMemo(() => {
4778
4952
  const dates = [];
@@ -4796,17 +4970,25 @@ const Dates = (props) => {
4796
4970
  return;
4797
4971
  onDateClick?.(date);
4798
4972
  };
4799
- return (jsxs(Fragment, { children: [jsx("div", { className: 'i-datepicker-weeks', children: weeks.map((week, i) => (jsx("span", { className: 'i-datepicker-week', children: week }, i))) }), jsx("div", { className: 'i-datepicker-dates', children: dates.map((date, i) => {
4800
- const active = date.isSame(value, "day");
4973
+ const handleMouseEnter = (date) => {
4974
+ if (disabledDate?.(date))
4975
+ return;
4976
+ onDateHover?.(date);
4977
+ };
4978
+ return (jsxs(Fragment, { children: [jsx("div", { className: 'i-datepicker-weeks', children: weeks.map((week, i) => (jsx("span", { className: 'i-datepicker-week', children: week }, i))) }), jsx("div", { className: 'i-datepicker-dates', onMouseLeave: () => onDateHover?.(null), children: dates.map((date, i) => {
4979
+ const active = date.isSame(value, "day") || (rangeEnd && date.isSame(rangeEnd, "day"));
4801
4980
  const isSameMonth = date.isSame(month, "month");
4802
4981
  const isToday = date.isSame(today, "day");
4803
4982
  const disabled = disabledDate?.(date);
4983
+ const isBetween = hoverDate && value && ((date.isAfter(value, "day") && date.isBefore(hoverDate, "day")) ||
4984
+ (date.isAfter(hoverDate, "day") && date.isBefore(value, "day")));
4804
4985
  return (jsx("div", { className: classNames("i-datepicker-item", {
4805
4986
  "i-datepicker-active": active,
4806
4987
  "i-datepicker-same-month": isSameMonth,
4807
4988
  "i-datepicker-today": isToday,
4808
4989
  "i-datepicker-disabled": disabled,
4809
- }), onClick: () => handleDateClick(date), children: renderDate(date) }, i));
4990
+ "i-daterange-between": isBetween,
4991
+ }), onMouseEnter: () => handleMouseEnter(date), onClick: () => handleDateClick(date), children: renderDate(date) }, i));
4810
4992
  }) })] }));
4811
4993
  };
4812
4994
 
@@ -4816,20 +4998,20 @@ const YearMonth = (props) => {
4816
4998
  return (jsxs("a", { className: 'i-datepicker-action', "data-ripple": true, onClick: onClick, children: [jsx("span", { children: renderYear?.(value.year()) }), unitYear, jsx("span", { children: renderMonth?.(value.month() + 1) }), unitMonth] }));
4817
4999
  };
4818
5000
  const Panel$1 = (props) => {
4819
- const { value, unitYear, unitMonth, renderDate, renderMonth = (m) => m, renderYear = (y) => y, disabledDate, onDateClick, } = props;
5001
+ const { value, month: controlledMonth, rangeEnd, hoverDate, onDateHover, onOperateMonth: onOperateMonthProp, unitYear, unitMonth, renderDate, renderMonth = (m) => m, renderYear = (y) => y, disabledDate, onDateClick, } = props;
4820
5002
  const [today, setToday] = useState(value);
4821
- const [month, setMonth] = useState(value || dayjs());
5003
+ const [month, setMonth] = useState(controlledMonth || value || dayjs());
4822
5004
  const [selectedYear, setSelectedYear] = useState(dayjs());
4823
5005
  const [years, setYears] = useState([]);
4824
5006
  const [selectable, setSelectable] = useState(false);
4825
5007
  const $years = useRef(null);
4826
- const handleOperateMonth = (next) => {
5008
+ const handleOperateMonth = onOperateMonthProp || ((next) => {
4827
5009
  setMonth((m) => m[next ? "add" : "subtract"](1, "month"));
4828
- };
5010
+ });
4829
5011
  const handleChangeDate = (date) => {
4830
5012
  if (date.isSame(today, "day"))
4831
5013
  return;
4832
- if (!date.isSame(month, "month")) {
5014
+ if (controlledMonth === undefined && !date.isSame(month, "month")) {
4833
5015
  setMonth(date);
4834
5016
  }
4835
5017
  setToday(date);
@@ -4853,27 +5035,40 @@ const Panel$1 = (props) => {
4853
5035
  }, [selectable, month]);
4854
5036
  useEffect(() => {
4855
5037
  setToday(value);
4856
- setMonth(value || dayjs());
4857
- }, [value]);
5038
+ if (controlledMonth === undefined) {
5039
+ setMonth(value || dayjs());
5040
+ }
5041
+ }, [value, controlledMonth]);
5042
+ useEffect(() => {
5043
+ const el = $years.current;
5044
+ if (!el)
5045
+ return;
5046
+ const onWheel = (e) => {
5047
+ e.preventDefault();
5048
+ getMoreYears(e);
5049
+ };
5050
+ el.addEventListener("wheel", onWheel, { passive: false });
5051
+ return () => el.removeEventListener("wheel", onWheel);
5052
+ }, []);
4858
5053
  return (jsxs("div", { className: 'i-datepicker', children: [jsxs("div", { className: 'i-datepicker-units', children: [jsx(YearMonth, { value: month, unitYear: unitYear, unitMonth: unitMonth, renderMonth: renderMonth, renderYear: renderYear, onClick: () => setSelectable(true) }), jsx("a", { className: 'ml-auto i-datepicker-action', "data-ripple": true, onClick: () => handleOperateMonth(false), children: jsx(Icon, { icon: jsx(KeyboardArrowLeftRound, {}) }) }), jsx("a", { className: 'i-datepicker-action', "data-ripple": true, onClick: () => handleOperateMonth(true), children: jsx(Icon, { icon: jsx(KeyboardArrowRightRound, {}) }) })] }), jsxs("div", { className: classNames("i-datepicker-ym", {
4859
5054
  "i-datepicker-active": selectable,
4860
5055
  }), children: [jsx(Helpericon, { active: true, className: 'i-datepicker-close', onClick: (e) => {
4861
5056
  e.stopPropagation();
4862
5057
  setSelectable(false);
4863
- } }), jsx("div", { ref: $years, className: 'i-datepicker-years', onWheel: getMoreYears, children: years.map((y) => (jsx("a", { className: classNames("i-datepicker-year", {
5058
+ } }), jsx("div", { ref: $years, className: 'i-datepicker-years', children: years.map((y) => (jsx("a", { className: classNames("i-datepicker-year", {
4864
5059
  "i-datepicker-active": y === selectedYear.year(),
4865
5060
  }), onClick: () => setSelectedYear((sy) => sy.year(y)), children: renderYear(y) }, y))) }), jsx("div", { className: 'i-datepicker-months', children: MONTHS.map((m) => {
4866
5061
  return (jsx("a", { className: classNames("i-datepicker-month", {
4867
5062
  "i-datepicker-active": m === month.month() + 1,
4868
5063
  }), onClick: () => handleChangeMonth(m), children: renderMonth(m) }, m));
4869
- }) })] }), jsx(Dates, { value: today, month: month, disabledDate: disabledDate, onDateClick: handleChangeDate, renderDate: renderDate })] }));
5064
+ }) })] }), jsx(Dates, { value: today, month: month, rangeEnd: rangeEnd, hoverDate: hoverDate, onDateHover: onDateHover, disabledDate: disabledDate, onDateClick: handleChangeDate, renderDate: renderDate })] }));
4870
5065
  };
4871
5066
 
4872
5067
  dayjs.extend(customParseFormat);
4873
5068
  const FORMATTYPES = ["YYYY-MM-DD", "YYYY-M-D", "YYYY/MM/DD", "YYYY/M/D"];
4874
5069
  const FORMAT$1 = "YYYY-MM-DD";
4875
5070
  const Datepicker = (props) => {
4876
- const { name, value, weeks, format = FORMAT$1, placeholder = props.format ?? FORMAT$1, className, renderDate, renderMonth, renderYear, popupProps, disabledDate, onDateClick, onChange, onBlur, ...restProps } = props;
5071
+ const { name, value, weeks, format = FORMAT$1, placeholder = props.format ?? FORMAT$1, className, renderDate, renderMonth, renderYear, popupProps, disabledDate, onDateClick, onChange, onBlur, clear, onClear: onClearProp, ...restProps } = props;
4877
5072
  const [inputValue, setInputValue] = useState(value);
4878
5073
  const [active, setActive] = useState(false);
4879
5074
  const dayJsValue = useMemo(() => {
@@ -4909,10 +5104,14 @@ const Datepicker = (props) => {
4909
5104
  popupProps?.onVisibleChange?.(v);
4910
5105
  setActive(v);
4911
5106
  };
5107
+ const handleClear = () => {
5108
+ setActive(false);
5109
+ onClearProp?.();
5110
+ };
4912
5111
  useEffect(() => {
4913
5112
  setInputValue(value);
4914
5113
  }, [value]);
4915
- return (jsx(Popup, { visible: active, trigger: 'click', position: 'bottom', arrow: false, align: 'start', onVisibleChange: handleVisibleChange, content: jsx(Panel$1, { value: dayJsValue, weeks: weeks, renderDate: renderDate, renderMonth: renderMonth, renderYear: renderYear, disabledDate: disabledDate, onDateClick: handleDateClick }), ...popupProps, children: jsx(Input, { value: inputValue, append: jsx(Icon, { icon: jsx(CalendarMonthTwotone, {}), className: 'i-datepicker-icon', size: '1em' }), placeholder: placeholder, onChange: handleChange, onBlur: handleBlur, onEnter: handleSetDate, className: classNames("i-datepicker-label", className), ...restProps }) }));
5114
+ return (jsx(Popup, { visible: active, trigger: 'click', position: 'bottom', arrow: false, align: 'start', onVisibleChange: handleVisibleChange, content: jsx(Panel$1, { value: dayJsValue, weeks: weeks, renderDate: renderDate, renderMonth: renderMonth, renderYear: renderYear, disabledDate: disabledDate, onDateClick: handleDateClick }), ...popupProps, children: jsx(Input, { value: inputValue, append: jsx(Icon, { icon: jsx(CalendarMonthTwotone, {}), className: 'i-datepicker-icon', size: '1em' }), placeholder: placeholder, clear: clear, onClear: handleClear, onChange: handleChange, onBlur: handleBlur, onEnter: handleSetDate, className: classNames("i-datepicker-label", className), ...restProps }) }));
4916
5115
  };
4917
5116
 
4918
5117
  function Items(props) {
@@ -5021,7 +5220,7 @@ function Panel(props) {
5021
5220
 
5022
5221
  const FORMAT = "hh:mm:ss";
5023
5222
  function TimePicker(props) {
5024
- const { name, value, format = FORMAT, periods, placeholder = props.format ?? FORMAT, className, renderItem, onChange, onBlur, popupProps, ...restProps } = props;
5223
+ const { name, value, format = FORMAT, periods, placeholder = props.format ?? FORMAT, className, renderItem, onChange, onBlur, popupProps, clear, onClear: onClearProp, ...restProps } = props;
5025
5224
  const [timeValue, setTimeValue] = useState(value);
5026
5225
  const [safeValue, setSafeValue] = useState(undefined);
5027
5226
  const [active, setActive] = useState(false);
@@ -5045,12 +5244,93 @@ function TimePicker(props) {
5045
5244
  popupProps?.onVisibleChange?.(v);
5046
5245
  setActive(v);
5047
5246
  };
5247
+ const handleClear = () => {
5248
+ setActive(false);
5249
+ onClearProp?.();
5250
+ };
5048
5251
  useEffect(() => {
5049
5252
  setTimeValue(value);
5050
5253
  }, [value]);
5051
- return (jsx(Popup, { visible: active, trigger: 'click', position: 'bottom', arrow: false, align: 'start', ...popupProps, onVisibleChange: handleVisibleChange, content: jsx(Panel, { value: timeValue, format: format, periods: periods, renderItem: renderItem, onChange: handleChange, onFallback: handleFallback }), children: jsx(Input, { value: timeValue, placeholder: placeholder, append: jsx(Icon, { icon: jsx(AccessTimeRound, {}), className: 'i-timepicker-icon', size: '1em' }), onChange: handleChange, onBlur: handleBlur, className: classNames("i-timepicker-label", className), ...restProps }) }));
5254
+ return (jsx(Popup, { visible: active, trigger: 'click', position: 'bottom', arrow: false, align: 'start', ...popupProps, onVisibleChange: handleVisibleChange, content: jsx(Panel, { value: timeValue, format: format, periods: periods, renderItem: renderItem, onChange: handleChange, onFallback: handleFallback }), children: jsx(Input, { value: timeValue, placeholder: placeholder, append: jsx(Icon, { icon: jsx(AccessTimeRound, {}), className: 'i-timepicker-icon', size: '1em' }), clear: clear, onClear: handleClear, onChange: handleChange, onBlur: handleBlur, className: classNames("i-timepicker-label", className), ...restProps }) }));
5052
5255
  }
5053
5256
 
5257
+ const DoublePanel = (props) => {
5258
+ const { value, weeks, unitYear, unitMonth, renderDate, renderMonth, renderYear, disabledDate, onSelected, } = props;
5259
+ const [baseMonth, setBaseMonth] = useState(value?.[0] || dayjs());
5260
+ const [startDate, setStartDate] = useState(value?.[0] || null);
5261
+ const [endDate, setEndDate] = useState(value?.[1] || null);
5262
+ const [selecting, setSelecting] = useState("start");
5263
+ const [hoverDate, setHoverDate] = useState(null);
5264
+ const nextMonth = useMemo(() => baseMonth.add(1, "month"), [baseMonth]);
5265
+ useEffect(() => {
5266
+ setStartDate(value?.[0] || null);
5267
+ setEndDate(value?.[1] || null);
5268
+ setBaseMonth(value?.[0] || dayjs());
5269
+ }, [value]);
5270
+ const handleDateClick = (date) => {
5271
+ if (selecting === "start") {
5272
+ setStartDate(date);
5273
+ setSelecting("end");
5274
+ }
5275
+ else {
5276
+ let start = startDate || date;
5277
+ let end = date;
5278
+ if (start.isAfter(end)) {
5279
+ [start, end] = [end, start];
5280
+ }
5281
+ setEndDate(end);
5282
+ setSelecting("start");
5283
+ onSelected?.([start, end]);
5284
+ }
5285
+ };
5286
+ const handleDateHover = (date) => {
5287
+ if (selecting === "end" && startDate) {
5288
+ setHoverDate(date);
5289
+ }
5290
+ };
5291
+ const handleOperateMonth = (next) => {
5292
+ setBaseMonth((m) => m[next ? "add" : "subtract"](1, "month"));
5293
+ };
5294
+ return (jsxs("div", { className: 'i-daterange-panel i-daterange-grids', children: [jsx("div", { className: 'i-daterange-col', children: jsx(Panel$1, { value: startDate, month: baseMonth, rangeEnd: endDate, hoverDate: hoverDate, onDateHover: handleDateHover, weeks: weeks, unitYear: unitYear, unitMonth: unitMonth, renderDate: renderDate, renderMonth: renderMonth, renderYear: renderYear, disabledDate: disabledDate, onDateClick: handleDateClick, onOperateMonth: handleOperateMonth }) }), jsx("div", { className: 'i-daterange-col', children: jsx(Panel$1, { value: startDate, month: nextMonth, rangeEnd: endDate, hoverDate: hoverDate, onDateHover: handleDateHover, weeks: weeks, unitYear: unitYear, unitMonth: unitMonth, renderDate: renderDate, renderMonth: renderMonth, renderYear: renderYear, disabledDate: disabledDate, onDateClick: handleDateClick, onOperateMonth: handleOperateMonth }) })] }));
5295
+ };
5296
+
5297
+ dayjs.extend(customParseFormat);
5298
+ const DateRange = (props) => {
5299
+ const { value, format = "YYYY-MM-DD", placeholder = "选择日期范围", className, disabledDate, onChange, clear, onClear: onClearProp, weeks, unitYear, unitMonth, renderDate, renderMonth, renderYear, ...restProps } = props;
5300
+ const [active, setActive] = useState(false);
5301
+ const inputValue = useMemo(() => {
5302
+ if (value?.[0] && value?.[1]) {
5303
+ return `${value[0]} ~ ${value[1]}`;
5304
+ }
5305
+ if (value?.[0]) {
5306
+ return `${value[0]} ~ `;
5307
+ }
5308
+ return "";
5309
+ }, [value]);
5310
+ const dayJsValue = useMemo(() => {
5311
+ const start = value?.[0] ? dayjs(value[0], format, true) : null;
5312
+ const end = value?.[1] ? dayjs(value[1], format, true) : null;
5313
+ if (start?.isValid() || end?.isValid()) {
5314
+ return [start?.isValid() ? start : null, end?.isValid() ? end : null];
5315
+ }
5316
+ return null;
5317
+ }, [value, format]);
5318
+ const handleSelected = (dates) => {
5319
+ const formatted = dates.map((d) => d.format(format));
5320
+ onChange?.([formatted[0], formatted[1]]);
5321
+ setActive(false);
5322
+ };
5323
+ const handleVisibleChange = (v) => {
5324
+ setActive(v);
5325
+ };
5326
+ const handleClear = () => {
5327
+ onChange?.([undefined, undefined]);
5328
+ setActive(false);
5329
+ onClearProp?.();
5330
+ };
5331
+ return (jsx(Popup, { visible: active, trigger: 'click', position: 'bottom', arrow: false, align: 'start', onVisibleChange: handleVisibleChange, content: jsx(DoublePanel, { value: dayJsValue, weeks: weeks, unitYear: unitYear, unitMonth: unitMonth, renderDate: renderDate, renderMonth: renderMonth, renderYear: renderYear, disabledDate: disabledDate, onSelected: handleSelected }), children: jsx(Input, { value: inputValue, placeholder: placeholder, readOnly: true, clear: clear, onClear: handleClear, append: jsx(Icon, { icon: jsx(CalendarMonthTwotone, {}), className: 'i-datepicker-icon', size: '1em' }), className: classNames("i-datepicker-label", className), ...restProps }) }));
5332
+ };
5333
+
5054
5334
  const defaultOk = {
5055
5335
  children: "确定",
5056
5336
  };
@@ -5059,7 +5339,7 @@ const defaultCancel = {
5059
5339
  flat: true,
5060
5340
  };
5061
5341
  const Popconfirm = (props) => {
5062
- const { trigger = "click", visible, icon = jsx(Icon, { icon: jsx(InfoOutlined, {}), className: "error", size: "1.2em" }), content, okButtonProps, cancelButtonProps, children, align, position = "top", offset = 12, extra, onOk, onClose, ...restProps } = props;
5342
+ const { trigger = "click", visible, icon, content, okButtonProps, cancelButtonProps, children, align, position = "top", offset = 12, extra, onOk, onClose, ...restProps } = props;
5063
5343
  const state = useReactive({
5064
5344
  loading: false,
5065
5345
  visible,
@@ -6531,4 +6811,4 @@ const useTheme = (props) => {
6531
6811
  };
6532
6812
  };
6533
6813
 
6534
- export { Affix, Badge, Button, Card, Checkbox, Collapse, ColorPicker, Datagrid, Datepicker as DatePicker, Description, Drawer, Dropdown, Editor, Flex, Form, Icon, MemoImage as Image, Input, List$1 as List, Loading, message as Message, Modal, Pagination, Popconfirm, Popup, Progress, Radio, Resizable, River, Scroll, Select, Step, Swiper, Tabs, Tag, Text, TimePicker, Tree, Upload, Video, usePreview, useTheme };
6814
+ export { Affix, Badge, Button, Card, Checkbox, Collapse, ColorPicker, Datagrid, Datepicker as DatePicker, DateRange, Description, Drawer, Dropdown, Editor, Flex, Form, Icon, MemoImage as Image, Input, List$1 as List, Loading, Message, Modal, Pagination, Popconfirm, Popup, Progress, Radio, Resizable, River, Scroll, Select, Step, Swiper, Tabs, Tag, Text, TimePicker, Tree, Upload, Video, usePreview, useTheme };