@sia.soul/sia-react-ui 0.1.0 → 0.1.2

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.
@@ -9,4 +9,3 @@ Ant Design Icons is licensed under the MIT License.
9
9
  - Project: https://github.com/ant-design/ant-design-icons
10
10
  - Copyright: Ant Design Team
11
11
  - License: https://github.com/ant-design/ant-design-icons/blob/master/LICENSE
12
-
@@ -49,14 +49,15 @@ function withTime(date, time, showSecond = false) {
49
49
  const [hour = "00", minute = "00", second = "00"] = time.split(":");
50
50
  return `${date} ${hour}:${minute}${showSecond ? `:${second}` : ""}`;
51
51
  }
52
- function normalizeDateValue(value, showTime) {
52
+ function normalizeDateValue(value, showTime, index = 0) {
53
53
  if (!value) return "";
54
54
  const date = parseDate(value);
55
55
  if (!date) return value;
56
56
  const day = dateKey(date);
57
57
  if (!showTime) return day;
58
58
  const config = typeof showTime === "object" ? showTime : {};
59
- return withTime(day, timePart(value, config.defaultValue ?? "00:00:00"), Boolean(config.showSecond));
59
+ const fallback = typeof config.defaultValue === "string" ? config.defaultValue : config.defaultValue?.[index] ?? "00:00:00";
60
+ return withTime(day, timePart(value, fallback), Boolean(config.showSecond));
60
61
  }
61
62
  var WEEKDAYS = ["\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u65E5"];
62
63
  function CalendarMonth({
@@ -256,8 +257,9 @@ function placeholderFor(picker, showTime, multiple) {
256
257
  function showSecondFrom(showTime) {
257
258
  return Boolean(typeof showTime === "object" && showTime.showSecond);
258
259
  }
259
- function defaultTimeFrom(showTime) {
260
- return typeof showTime === "object" ? showTime.defaultValue ?? "00:00:00" : "00:00:00";
260
+ function defaultTimeFrom(showTime, index = 0) {
261
+ const value = typeof showTime === "object" ? showTime.defaultValue : void 0;
262
+ return typeof value === "string" ? value : value?.[index] ?? "00:00:00";
261
263
  }
262
264
  function resolvePreset(value) {
263
265
  return typeof value === "function" ? value() : value;
@@ -288,6 +290,8 @@ function DatePicker({
288
290
  onChange,
289
291
  onOpenChange,
290
292
  placeholder,
293
+ formatValue = (value2) => value2,
294
+ renderExtraFooter,
291
295
  ...props
292
296
  }) {
293
297
  const id = useId();
@@ -353,6 +357,8 @@ function DatePicker({
353
357
  }
354
358
  }
355
359
  function commitDraft() {
360
+ const values = Array.isArray(draftValue) ? draftValue : [draftValue];
361
+ if (values.some((value2) => !value2 || isDisabled(dayFromValue(value2)))) return;
356
362
  setCurrentValue(draftValue);
357
363
  changeOpen(false);
358
364
  }
@@ -362,7 +368,7 @@ function DatePicker({
362
368
  setDraftValue(empty);
363
369
  setCurrentValue(empty);
364
370
  }
365
- const display = Array.isArray(currentValue) ? currentValue.join("\u3001") : currentValue;
371
+ const display = Array.isArray(currentValue) ? currentValue.map(formatValue).join("\u3001") : currentValue ? formatValue(currentValue) : "";
366
372
  const triggerLabel = props["aria-label"] ?? (typeof placeholder === "string" ? placeholder : "\u65E5\u671F\u9009\u62E9\u5668");
367
373
  return /* @__PURE__ */ jsxs2("span", { ref: rootRef, className: `sia-picker sia-picker--${size} sia-picker--${status}${visible ? " is-open" : ""}${disabled ? " is-disabled" : ""} ${className}`.trim(), children: [
368
374
  /* @__PURE__ */ jsxs2(
@@ -388,15 +394,16 @@ function DatePicker({
388
394
  },
389
395
  children: [
390
396
  /* @__PURE__ */ jsx2("span", { className: `sia-picker__value${display ? "" : " is-placeholder"}`, children: display || placeholder || placeholderFor(picker, showTime, multiple) }),
391
- allowClear && display && !disabled ? /* @__PURE__ */ jsx2("span", { role: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F", onClick: clearValue, children: /* @__PURE__ */ jsx2(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
392
397
  /* @__PURE__ */ jsx2("span", { className: "sia-picker__icon", "aria-hidden": "true", children: suffixIcon ?? /* @__PURE__ */ jsx2(Icon, { name: "calendar", size: 16 }) })
393
398
  ]
394
399
  }
395
400
  ),
401
+ allowClear && display && !disabled ? /* @__PURE__ */ jsx2("button", { type: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F", onClick: clearValue, children: /* @__PURE__ */ jsx2(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
396
402
  /* @__PURE__ */ jsxs2(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: visible, className: `sia-date-panel${showTime ? " sia-date-panel--with-time" : ""}${presets?.length ? " sia-date-panel--with-presets" : ""}`, role: "dialog", "aria-label": "\u65E5\u671F\u9009\u62E9\u9762\u677F", children: [
397
403
  /* @__PURE__ */ jsxs2("div", { className: "sia-date-panel__body", children: [
398
404
  presets?.length ? /* @__PURE__ */ jsx2("aside", { className: "sia-date-panel__presets", children: presets.map((preset, index) => /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => {
399
405
  const next = resolvePreset(preset.value);
406
+ if (!next || isDisabled(dayFromValue(next))) return;
400
407
  setDraftValue(next);
401
408
  if (!resolvedNeedConfirm) {
402
409
  setCurrentValue(next);
@@ -424,6 +431,7 @@ function DatePicker({
424
431
  /* @__PURE__ */ jsx2(
425
432
  DatePanelFooter,
426
433
  {
434
+ extra: renderExtraFooter?.(),
427
435
  showToday,
428
436
  needConfirm: resolvedNeedConfirm,
429
437
  disabledConfirm: Array.isArray(draftValue) ? draftValue.length === 0 : !draftValue,
@@ -441,6 +449,8 @@ function DateRangePicker({
441
449
  separator = "\u2192",
442
450
  presets,
443
451
  maxRangeDays,
452
+ allowEmpty = [false, false],
453
+ endpointDisabled = [false, false],
444
454
  size = "medium",
445
455
  status = "default",
446
456
  allowClear = true,
@@ -458,6 +468,8 @@ function DateRangePicker({
458
468
  onCalendarChange,
459
469
  onChange,
460
470
  onOpenChange,
471
+ formatValue = (value2) => value2,
472
+ renderExtraFooter,
461
473
  ...props
462
474
  }) {
463
475
  const id = useId();
@@ -473,9 +485,10 @@ function DateRangePicker({
473
485
  const [compactDateTime, setCompactDateTime] = useState(false);
474
486
  const showSecond = showSecondFrom(showTime);
475
487
  const defaultTime = defaultTimeFrom(showTime);
488
+ const defaultEndTime = defaultTimeFrom(showTime, 1);
476
489
  const [times, setTimes] = useState([
477
490
  timePart(currentValue[0], defaultTime),
478
- timePart(currentValue[1], defaultTime)
491
+ timePart(currentValue[1], defaultEndTime)
479
492
  ]);
480
493
  const resolvedNeedConfirm = needConfirm ?? Boolean(showTime);
481
494
  const rangeDates = [dayFromValue(draftValue[0]), dayFromValue(draftValue[1])];
@@ -505,8 +518,8 @@ function DateRangePicker({
505
518
  function changeOpen(next) {
506
519
  if (next) {
507
520
  setDraftValue(currentValue);
508
- setTimes([timePart(currentValue[0], defaultTime), timePart(currentValue[1], defaultTime)]);
509
- setActiveIndex(currentValue[0] && !currentValue[1] ? 1 : 0);
521
+ setTimes([timePart(currentValue[0], defaultTime), timePart(currentValue[1], defaultEndTime)]);
522
+ setActiveIndex(endpointDisabled[0] ? 1 : endpointDisabled[1] ? 0 : currentValue[0] && !currentValue[1] ? 1 : 0);
510
523
  const nextStartMonth = startOfMonth(parseDate(dayFromValue(currentValue[0] || currentValue[1])) ?? /* @__PURE__ */ new Date());
511
524
  setViewMonth(nextStartMonth);
512
525
  setEndViewMonth(startOfMonth(parseDate(dayFromValue(currentValue[1])) ?? addMonths(nextStartMonth, 1)));
@@ -514,6 +527,7 @@ function DateRangePicker({
514
527
  setVisible(next);
515
528
  }
516
529
  function isDisabled(day, index = activeIndex, pairedDateTime = false) {
530
+ if (endpointDisabled[index]) return true;
517
531
  const minimum = minDate ?? props.min;
518
532
  const maximum = maxDate ?? props.max;
519
533
  if (minimum && day < String(minimum).slice(0, 10)) return true;
@@ -536,6 +550,17 @@ function DateRangePicker({
536
550
  }
537
551
  function selectDate(day) {
538
552
  if (isDisabled(day)) return;
553
+ if (endpointDisabled.some(Boolean)) {
554
+ const index = endpointDisabled[0] ? 1 : 0;
555
+ const next = [...draftValue];
556
+ next[index] = buildRangeValue(day, index);
557
+ updateDraft(next);
558
+ if (!resolvedNeedConfirm && isValidRange(next)) {
559
+ setCurrentValue(next);
560
+ changeOpen(false);
561
+ }
562
+ return;
563
+ }
539
564
  if (activeIndex === 0 || !rangeDates[0] || rangeDates[1]) {
540
565
  const next = [buildRangeValue(day, 0), ""];
541
566
  updateDraft(next);
@@ -571,6 +596,7 @@ function DateRangePicker({
571
596
  }
572
597
  }
573
598
  function changeTime(index, nextTime) {
599
+ if (endpointDisabled[index]) return;
574
600
  const nextTimes = [...times];
575
601
  nextTimes[index] = nextTime;
576
602
  setTimes(nextTimes);
@@ -581,6 +607,28 @@ function DateRangePicker({
581
607
  updateDraft(nextValue);
582
608
  }
583
609
  }
610
+ function isValidRange(next) {
611
+ if (!next.some(Boolean)) return false;
612
+ for (const index of [0, 1]) {
613
+ if (!next[index]) {
614
+ if (!allowEmpty[index]) return false;
615
+ else continue;
616
+ }
617
+ if (endpointDisabled[index]) {
618
+ if (next[index] !== currentValue[index]) return false;
619
+ else continue;
620
+ }
621
+ const day = dayFromValue(next[index]);
622
+ if (!day) return false;
623
+ if (minDate && day < minDate.slice(0, 10) || maxDate && day > maxDate.slice(0, 10)) return false;
624
+ if (disabledDate?.(day, { from: index === 1 ? dayFromValue(next[0]) || void 0 : void 0, type: "date" })) return false;
625
+ }
626
+ if (next[0] && next[1]) {
627
+ if (next[0] > next[1]) return false;
628
+ if (maxRangeDays && Math.abs(daysBetween(dayFromValue(next[0]), dayFromValue(next[1]))) >= maxRangeDays) return false;
629
+ }
630
+ return true;
631
+ }
584
632
  function confirm() {
585
633
  if (compactDateTime && showTime && activeIndex === 0) {
586
634
  if (!draftValue[0]) return;
@@ -589,7 +637,7 @@ function DateRangePicker({
589
637
  setHoverDate("");
590
638
  return;
591
639
  }
592
- if (!draftValue[0] || !draftValue[1] || invalidDateTimeRange) return;
640
+ if (!isValidRange(draftValue)) return;
593
641
  setCurrentValue(draftValue);
594
642
  changeOpen(false);
595
643
  }
@@ -597,10 +645,11 @@ function DateRangePicker({
597
645
  const raw = resolveRangePreset(preset.value);
598
646
  const next = [
599
647
  normalizeDateValue(raw[0], showTime),
600
- normalizeDateValue(raw[1], showTime)
648
+ normalizeDateValue(raw[1], showTime, 1)
601
649
  ];
650
+ if (!isValidRange(next)) return;
602
651
  updateDraft(next);
603
- setTimes([timePart(next[0], defaultTime), timePart(next[1], defaultTime)]);
652
+ setTimes([timePart(next[0], defaultTime), timePart(next[1], defaultEndTime)]);
604
653
  const nextStartMonth = startOfMonth(parseDate(dayFromValue(next[0] || next[1])) ?? /* @__PURE__ */ new Date());
605
654
  setViewMonth(nextStartMonth);
606
655
  setEndViewMonth(startOfMonth(parseDate(dayFromValue(next[1])) ?? addMonths(nextStartMonth, 1)));
@@ -611,7 +660,7 @@ function DateRangePicker({
611
660
  }
612
661
  function clearValue(event) {
613
662
  event.stopPropagation();
614
- const empty = ["", ""];
663
+ const empty = [endpointDisabled[0] ? currentValue[0] : "", endpointDisabled[1] ? currentValue[1] : ""];
615
664
  updateDraft(empty);
616
665
  setCurrentValue(empty);
617
666
  setActiveIndex(0);
@@ -680,14 +729,14 @@ function DateRangePicker({
680
729
  disabled,
681
730
  onClick: () => changeOpen(!visible),
682
731
  children: [
683
- /* @__PURE__ */ jsx2("span", { className: `sia-picker-range-control__value${currentValue[0] ? "" : " is-placeholder"}`, children: currentValue[0] || placeholder[0] }),
732
+ /* @__PURE__ */ jsx2("span", { className: `sia-picker-range-control__value${currentValue[0] ? "" : " is-placeholder"}`, children: currentValue[0] ? formatValue(currentValue[0]) : placeholder[0] }),
684
733
  /* @__PURE__ */ jsx2("span", { className: "sia-picker-range-control__separator", children: separator }),
685
- /* @__PURE__ */ jsx2("span", { className: `sia-picker-range-control__value${currentValue[1] ? "" : " is-placeholder"}`, children: currentValue[1] || placeholder[1] }),
686
- allowClear && (currentValue[0] || currentValue[1]) && !disabled ? /* @__PURE__ */ jsx2("span", { role: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F\u8303\u56F4", onClick: clearValue, children: /* @__PURE__ */ jsx2(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
734
+ /* @__PURE__ */ jsx2("span", { className: `sia-picker-range-control__value${currentValue[1] ? "" : " is-placeholder"}`, children: currentValue[1] ? formatValue(currentValue[1]) : placeholder[1] }),
687
735
  /* @__PURE__ */ jsx2("span", { className: "sia-picker__icon", "aria-hidden": "true", children: suffixIcon ?? /* @__PURE__ */ jsx2(Icon, { name: "calendar", size: 16 }) })
688
736
  ]
689
737
  }
690
738
  ),
739
+ allowClear && (currentValue[0] || currentValue[1]) && !disabled ? /* @__PURE__ */ jsx2("button", { type: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F\u8303\u56F4", onClick: clearValue, children: /* @__PURE__ */ jsx2(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
691
740
  /* @__PURE__ */ jsxs2(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: visible, className: `sia-date-panel sia-date-panel--range${showTime ? ` sia-date-panel--with-time sia-date-panel--range-time-${compactDateTime ? "compact" : "paired"}` : ""}${presets?.length ? " sia-date-panel--with-presets" : ""}`, role: "dialog", "aria-label": "\u65E5\u671F\u8303\u56F4\u9009\u62E9\u9762\u677F", children: [
692
741
  /* @__PURE__ */ jsx2("div", { className: "sia-date-panel__body", children: showTime ? /* @__PURE__ */ jsx2("div", { className: "sia-date-panel__range-date-time", children: compactDateTime ? renderDateTimeGroup(activeIndex) : /* @__PURE__ */ jsxs2(Fragment, { children: [
693
742
  renderDateTimeGroup(0),
@@ -722,10 +771,11 @@ function DateRangePicker({
722
771
  DatePanelFooter,
723
772
  {
724
773
  showToday: showToday && !presets?.length,
725
- needConfirm: resolvedNeedConfirm,
726
- disabledConfirm: compactDateTime && showTime && activeIndex === 0 ? !draftValue[0] : !draftValue[0] || !draftValue[1] || invalidDateTimeRange,
774
+ needConfirm: resolvedNeedConfirm || allowEmpty.some(Boolean),
775
+ disabledConfirm: compactDateTime && showTime && activeIndex === 0 ? !draftValue[0] : !isValidRange(draftValue),
727
776
  confirmText: compactDateTime && showTime && activeIndex === 0 ? "\u4E0B\u4E00\u6B65" : "\u786E\u5B9A",
728
777
  extra: /* @__PURE__ */ jsxs2(Fragment, { children: [
778
+ renderExtraFooter?.(),
729
779
  presets?.map((preset, index) => /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => applyPreset(preset), children: preset.label }, index)),
730
780
  compactDateTime && showTime && activeIndex === 1 ? /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => {
731
781
  setActiveIndex(0);
@@ -740,10 +740,10 @@ function Tree({
740
740
  },
741
741
  children: (() => {
742
742
  const content = /* @__PURE__ */ jsxs5("span", { className: "sia-tree__context-content", children: [
743
- hasChildren ? /* @__PURE__ */ jsx5("button", { type: "button", className: "sia-tree__switcher", style: { width: normalizedSwitcherWidth, flexBasis: normalizedSwitcherWidth }, disabled: node.disabled, onClick: (event) => {
743
+ hasChildren ? /* @__PURE__ */ jsx5("button", { type: "button", className: "sia-tree__switcher", "aria-label": open ? "\u6536\u8D77\u8282\u70B9" : "\u5C55\u5F00\u8282\u70B9", "aria-expanded": open, style: { width: normalizedSwitcherWidth, flexBasis: normalizedSwitcherWidth }, disabled: node.disabled, onClick: (event) => {
744
744
  event.stopPropagation();
745
745
  void toggleExpand(node);
746
- }, children: nodeLoading ? /* @__PURE__ */ jsx5(Icon, { name: "loader", className: "sia-spin-icon", size: 13 }) : /* @__PURE__ */ jsx5(Icon, { name: open ? "chevron-down" : "chevron-right", size: 13 }) }) : /* @__PURE__ */ jsx5("span", { className: "sia-tree__switcher", style: { width: normalizedSwitcherWidth, flexBasis: normalizedSwitcherWidth }, "aria-hidden": "true" }),
746
+ }, children: nodeLoading ? /* @__PURE__ */ jsx5(Icon, { name: "loader", className: "sia-spin-icon", size: 13 }) : /* @__PURE__ */ jsx5(Icon, { name: open ? "chevron-down" : "chevron-right", size: 13 }) }) : /* @__PURE__ */ jsx5("span", { className: "sia-tree__switcher", "aria-label": open ? "\u6536\u8D77\u8282\u70B9" : "\u5C55\u5F00\u8282\u70B9", "aria-expanded": open, style: { width: normalizedSwitcherWidth, flexBasis: normalizedSwitcherWidth }, "aria-hidden": "true" }),
747
747
  checkable || node.checkable ? /* @__PURE__ */ jsx5("span", { onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsx5(Checkbox2, { checked: isChecked, disabled: node.disabled || node.disableCheckbox, onChange: () => check(node) }) }) : null,
748
748
  node.prefix ? /* @__PURE__ */ jsx5("span", { className: "sia-tree__prefix", onClick: (event) => event.stopPropagation(), children: node.prefix }) : null,
749
749
  showIcon ? /* @__PURE__ */ jsx5("span", { className: "sia-tree__icon", children: node.icon ?? /* @__PURE__ */ jsx5(Icon, { name: hasChildren ? "folder" : "file", size: 15 }) }) : null,
@@ -1541,6 +1541,7 @@ var ModalRoot = forwardRef2(function Modal({
1541
1541
  onOk,
1542
1542
  onCancel,
1543
1543
  onOpenChange,
1544
+ afterOpenChange,
1544
1545
  className = "",
1545
1546
  style,
1546
1547
  ...props
@@ -1550,6 +1551,14 @@ var ModalRoot = forwardRef2(function Modal({
1550
1551
  const [submitting, setSubmitting] = useState6(false);
1551
1552
  const [rendered, setRendered] = useState6(open);
1552
1553
  const [closing, setClosing] = useState6(false);
1554
+ const afterOpenChangeRef = useRef7(afterOpenChange);
1555
+ afterOpenChangeRef.current = afterOpenChange;
1556
+ const submitLock = useRef7(false);
1557
+ useEffect6(() => {
1558
+ if (!open || !rendered) return void 0;
1559
+ const timer = window.setTimeout(() => afterOpenChangeRef.current?.(true), MODAL_MOTION_DURATION);
1560
+ return () => window.clearTimeout(timer);
1561
+ }, [open, rendered]);
1553
1562
  useEffect6(() => {
1554
1563
  if (open) {
1555
1564
  setRendered(true);
@@ -1561,6 +1570,7 @@ var ModalRoot = forwardRef2(function Modal({
1561
1570
  const timer = window.setTimeout(() => {
1562
1571
  setRendered(false);
1563
1572
  setClosing(false);
1573
+ afterOpenChangeRef.current?.(false);
1564
1574
  }, MODAL_MOTION_DURATION);
1565
1575
  return () => window.clearTimeout(timer);
1566
1576
  }, [open, rendered]);
@@ -1575,8 +1585,11 @@ var ModalRoot = forwardRef2(function Modal({
1575
1585
  onOpenChange?.(false);
1576
1586
  }
1577
1587
  async function handleOk() {
1588
+ if (submitLock.current || confirmLoading) return;
1589
+ submitLock.current = true;
1578
1590
  if (!onOk) {
1579
1591
  onOpenChange?.(false);
1592
+ submitLock.current = false;
1580
1593
  return;
1581
1594
  }
1582
1595
  try {
@@ -1591,6 +1604,7 @@ var ModalRoot = forwardRef2(function Modal({
1591
1604
  } catch {
1592
1605
  return;
1593
1606
  } finally {
1607
+ submitLock.current = false;
1594
1608
  setSubmitting(false);
1595
1609
  }
1596
1610
  }
@@ -930,6 +930,8 @@ interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, "title" | "onS
930
930
  onOk?: () => ModalActionResult;
931
931
  onCancel?: () => void;
932
932
  onOpenChange?: (open: boolean) => void;
933
+ /** 动画完成后触发,适用于聚焦内容和释放外部挂载点。 */
934
+ afterOpenChange?: (open: boolean) => void;
933
935
  }
934
936
  interface ModalOpenConfig extends Omit<ModalProps, "open"> {
935
937
  }
@@ -930,6 +930,8 @@ interface ModalProps extends Omit<HTMLAttributes<HTMLDivElement>, "title" | "onS
930
930
  onOk?: () => ModalActionResult;
931
931
  onCancel?: () => void;
932
932
  onOpenChange?: (open: boolean) => void;
933
+ /** 动画完成后触发,适用于聚焦内容和释放外部挂载点。 */
934
+ afterOpenChange?: (open: boolean) => void;
933
935
  }
934
936
  interface ModalOpenConfig extends Omit<ModalProps, "open"> {
935
937
  }
package/dist/core.cjs CHANGED
@@ -2710,6 +2710,7 @@ var ModalRoot = (0, import_react16.forwardRef)(function Modal({
2710
2710
  onOk,
2711
2711
  onCancel,
2712
2712
  onOpenChange,
2713
+ afterOpenChange,
2713
2714
  className = "",
2714
2715
  style,
2715
2716
  ...props
@@ -2719,6 +2720,14 @@ var ModalRoot = (0, import_react16.forwardRef)(function Modal({
2719
2720
  const [submitting, setSubmitting] = (0, import_react16.useState)(false);
2720
2721
  const [rendered, setRendered] = (0, import_react16.useState)(open);
2721
2722
  const [closing, setClosing] = (0, import_react16.useState)(false);
2723
+ const afterOpenChangeRef = (0, import_react16.useRef)(afterOpenChange);
2724
+ afterOpenChangeRef.current = afterOpenChange;
2725
+ const submitLock = (0, import_react16.useRef)(false);
2726
+ (0, import_react16.useEffect)(() => {
2727
+ if (!open || !rendered) return void 0;
2728
+ const timer = window.setTimeout(() => afterOpenChangeRef.current?.(true), MODAL_MOTION_DURATION);
2729
+ return () => window.clearTimeout(timer);
2730
+ }, [open, rendered]);
2722
2731
  (0, import_react16.useEffect)(() => {
2723
2732
  if (open) {
2724
2733
  setRendered(true);
@@ -2730,6 +2739,7 @@ var ModalRoot = (0, import_react16.forwardRef)(function Modal({
2730
2739
  const timer = window.setTimeout(() => {
2731
2740
  setRendered(false);
2732
2741
  setClosing(false);
2742
+ afterOpenChangeRef.current?.(false);
2733
2743
  }, MODAL_MOTION_DURATION);
2734
2744
  return () => window.clearTimeout(timer);
2735
2745
  }, [open, rendered]);
@@ -2744,8 +2754,11 @@ var ModalRoot = (0, import_react16.forwardRef)(function Modal({
2744
2754
  onOpenChange?.(false);
2745
2755
  }
2746
2756
  async function handleOk() {
2757
+ if (submitLock.current || confirmLoading) return;
2758
+ submitLock.current = true;
2747
2759
  if (!onOk) {
2748
2760
  onOpenChange?.(false);
2761
+ submitLock.current = false;
2749
2762
  return;
2750
2763
  }
2751
2764
  try {
@@ -2760,6 +2773,7 @@ var ModalRoot = (0, import_react16.forwardRef)(function Modal({
2760
2773
  } catch {
2761
2774
  return;
2762
2775
  } finally {
2776
+ submitLock.current = false;
2763
2777
  setSubmitting(false);
2764
2778
  }
2765
2779
  }
package/dist/core.css CHANGED
@@ -3915,6 +3915,17 @@
3915
3915
  .sia-space-compact--vertical > *:not(:first-child) {
3916
3916
  margin-top: -1px;
3917
3917
  }
3918
+ .sia-space-compact--horizontal > *:not(:first-child) :is(.sia-input, .sia-input-control, .sia-select, .sia-tree-select__trigger, .sia-picker, .sia-input-number) {
3919
+ border-top-left-radius: 0;
3920
+ border-bottom-left-radius: 0;
3921
+ }
3922
+ .sia-space-compact--horizontal > *:not(:last-child) :is(.sia-input, .sia-input-control, .sia-select, .sia-tree-select__trigger, .sia-picker, .sia-input-number) {
3923
+ border-top-right-radius: 0;
3924
+ border-bottom-right-radius: 0;
3925
+ }
3926
+ .sia-space-compact > *:focus-within {
3927
+ z-index: 1;
3928
+ }
3918
3929
  .sia-row {
3919
3930
  --sia-grid-gutter-x: 0px;
3920
3931
  --sia-grid-gutter-y: 0px;
@@ -5674,10 +5685,20 @@
5674
5685
  font-size: 12px;
5675
5686
  }
5676
5687
  .sia-tree-select__clear {
5688
+ position: absolute;
5689
+ right: 30px;
5690
+ top: 50%;
5691
+ transform: translateY(-50%);
5677
5692
  display: none;
5693
+ align-items: center;
5694
+ padding: 2px;
5695
+ border: 0;
5696
+ background: var(--sia-color-surface);
5678
5697
  color: var(--sia-color-text-secondary);
5698
+ cursor: pointer;
5679
5699
  }
5680
- .sia-tree-select__trigger:hover .sia-tree-select__clear {
5700
+ .sia-tree-select:hover .sia-tree-select__clear,
5701
+ .sia-tree-select:focus-within .sia-tree-select__clear {
5681
5702
  display: inline-flex;
5682
5703
  }
5683
5704
  .sia-tree-select__dropdown {
@@ -8382,6 +8403,115 @@ button.sia-treemap__tile:focus-visible,
8382
8403
  transition-duration: .01ms;
8383
8404
  }
8384
8405
  }
8406
+ .sia-input-select {
8407
+ min-width: 0;
8408
+ }
8409
+ .sia-input-select__suffix,
8410
+ .sia-selection-panel__actions {
8411
+ display: flex;
8412
+ align-items: center;
8413
+ gap: 4px;
8414
+ }
8415
+ .sia-input-select__suffix .sia-button {
8416
+ padding: 0 3px;
8417
+ min-width: 18px;
8418
+ }
8419
+ .sia-input-select__popup {
8420
+ z-index: 1100;
8421
+ width: max(240px, var(--sia-popup-anchor-width));
8422
+ max-width: calc(100vw - 24px);
8423
+ padding: 8px;
8424
+ background: var(--sia-color-bg, white);
8425
+ border: 1px solid var(--sia-color-border, #ddd);
8426
+ border-radius: 6px;
8427
+ box-shadow: 0 6px 24px #0002;
8428
+ }
8429
+ .sia-selection-panel {
8430
+ min-width: 0;
8431
+ display: grid;
8432
+ gap: 8px;
8433
+ }
8434
+ .sia-selection-panel__actions {
8435
+ margin-bottom: 4px;
8436
+ flex-wrap: wrap;
8437
+ font-size: 12px;
8438
+ }
8439
+ .sia-selection-panel__actions > span {
8440
+ margin-left: auto;
8441
+ color: var(--sia-color-text-secondary, #777);
8442
+ }
8443
+ .sia-selection-panel__list {
8444
+ overflow: auto;
8445
+ outline-offset: 1px;
8446
+ }
8447
+ .sia-selection-panel__row {
8448
+ display: grid;
8449
+ gap: 4px;
8450
+ }
8451
+ .sia-selection-panel__group {
8452
+ display: flex;
8453
+ align-items: center;
8454
+ font-size: 12px;
8455
+ font-weight: 600;
8456
+ color: var(--sia-color-text-secondary, #777);
8457
+ padding: 0 6px;
8458
+ }
8459
+ .sia-selection-panel__option {
8460
+ width: 100%;
8461
+ height: 100%;
8462
+ display: flex;
8463
+ align-items: center;
8464
+ gap: 6px;
8465
+ border: 0;
8466
+ background: transparent;
8467
+ border-radius: 4px;
8468
+ padding: 4px 8px;
8469
+ text-align: left;
8470
+ color: inherit;
8471
+ cursor: pointer;
8472
+ min-width: 0;
8473
+ font: inherit;
8474
+ }
8475
+ .sia-selection-panel__option:hover,
8476
+ .sia-selection-panel__option.is-active {
8477
+ background: var(--sia-color-fill-secondary, #f2f5f8);
8478
+ }
8479
+ .sia-selection-panel__option[aria-selected=true] {
8480
+ background: var(--sia-color-primary-bg, #eaf4ff);
8481
+ color: var(--sia-color-primary, #1677ff);
8482
+ }
8483
+ .sia-selection-panel__option[aria-disabled=true] {
8484
+ opacity: .45;
8485
+ cursor: not-allowed;
8486
+ }
8487
+ .sia-selection-panel__check {
8488
+ width: 14px;
8489
+ height: 14px;
8490
+ flex-shrink: 0;
8491
+ border: 1px solid currentColor;
8492
+ border-radius: 3px;
8493
+ line-height: 12px;
8494
+ text-align: center;
8495
+ }
8496
+ .sia-selection-panel__text {
8497
+ overflow: hidden;
8498
+ white-space: nowrap;
8499
+ text-overflow: ellipsis;
8500
+ }
8501
+ .sia-selection-panel__text small {
8502
+ display: block;
8503
+ opacity: .65;
8504
+ font-size: 11px;
8505
+ }
8506
+ .sia-selection-panel__divider {
8507
+ align-self: center;
8508
+ border-top: 1px solid var(--sia-color-border, #ddd);
8509
+ }
8510
+ .sia-selection-panel__empty {
8511
+ padding: 16px;
8512
+ text-align: center;
8513
+ color: var(--sia-color-text-secondary, #777);
8514
+ }
8385
8515
 
8386
8516
  /* src/breadcrumb.css */
8387
8517
  .sia-breadcrumb {
package/dist/core.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- export { e as Breadcrumb, f as BreadcrumbItem, g as BreadcrumbProps, h as Button, i as ButtonProps, j as ButtonSize, k as ButtonVariant, m as Card, n as CardAccent, o as CardProps, s as Collapse, t as CollapseItem, u as CollapseKey, v as CollapseProps, G as FilledIconName, H as FloatButton, I as FloatButtonBackTopProps, J as FloatButtonGroupProps, K as FloatButtonProps, L as FloatButtonShape, Q as Icon, R as IconName, S as IconProps, T as IconVariant, Z as Input, _ as InputProps, a5 as MessageConfig, a6 as MessageHandle, a7 as MessageKey, a8 as MessageType, a9 as Modal, aa as ModalActionResult, ab as ModalOpenConfig, ac as ModalProps, ad as ModalType, a as OverlayApiHandle, al as Progress, am as ProgressProps, an as ProgressStatus, aq as Segmented, ar as SegmentedOption, as as SegmentedProps, at as SegmentedValue, aA as TabItem, aB as Tabs, aD as TabsOrientation, aE as TabsPosition, aF as TabsProps, aG as TabsType, aH as Tag, aI as TagProps, aJ as TagStatus, aK as TagVariant, aY as Typography, aZ as TypographyLinkProps, a_ as TypographyProps, a$ as TypographyTitleProps, b0 as TypographyType, b1 as Upload, b2 as UploadChangeInfo, b3 as UploadDraggerProps, b4 as UploadFile, b5 as UploadFileStatus, b6 as UploadProps, b7 as UploadRequestOptions, bb as message } from './core-DRICIs2n.cjs';
1
+ export { e as Breadcrumb, f as BreadcrumbItem, g as BreadcrumbProps, h as Button, i as ButtonProps, j as ButtonSize, k as ButtonVariant, m as Card, n as CardAccent, o as CardProps, s as Collapse, t as CollapseItem, u as CollapseKey, v as CollapseProps, G as FilledIconName, H as FloatButton, I as FloatButtonBackTopProps, J as FloatButtonGroupProps, K as FloatButtonProps, L as FloatButtonShape, Q as Icon, R as IconName, S as IconProps, T as IconVariant, Z as Input, _ as InputProps, a5 as MessageConfig, a6 as MessageHandle, a7 as MessageKey, a8 as MessageType, a9 as Modal, aa as ModalActionResult, ab as ModalOpenConfig, ac as ModalProps, ad as ModalType, a as OverlayApiHandle, al as Progress, am as ProgressProps, an as ProgressStatus, aq as Segmented, ar as SegmentedOption, as as SegmentedProps, at as SegmentedValue, aA as TabItem, aB as Tabs, aD as TabsOrientation, aE as TabsPosition, aF as TabsProps, aG as TabsType, aH as Tag, aI as TagProps, aJ as TagStatus, aK as TagVariant, aY as Typography, aZ as TypographyLinkProps, a_ as TypographyProps, a$ as TypographyTitleProps, b0 as TypographyType, b1 as Upload, b2 as UploadChangeInfo, b3 as UploadDraggerProps, b4 as UploadFile, b5 as UploadFileStatus, b6 as UploadProps, b7 as UploadRequestOptions, bb as message } from './core-De2pRX5w.cjs';
2
2
  export { S as Select, d as SelectOption, e as SelectProps, f as SelectValue } from './Select-CJJ5LQap.cjs';
3
3
  import 'react';
package/dist/core.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { e as Breadcrumb, f as BreadcrumbItem, g as BreadcrumbProps, h as Button, i as ButtonProps, j as ButtonSize, k as ButtonVariant, m as Card, n as CardAccent, o as CardProps, s as Collapse, t as CollapseItem, u as CollapseKey, v as CollapseProps, G as FilledIconName, H as FloatButton, I as FloatButtonBackTopProps, J as FloatButtonGroupProps, K as FloatButtonProps, L as FloatButtonShape, Q as Icon, R as IconName, S as IconProps, T as IconVariant, Z as Input, _ as InputProps, a5 as MessageConfig, a6 as MessageHandle, a7 as MessageKey, a8 as MessageType, a9 as Modal, aa as ModalActionResult, ab as ModalOpenConfig, ac as ModalProps, ad as ModalType, a as OverlayApiHandle, al as Progress, am as ProgressProps, an as ProgressStatus, aq as Segmented, ar as SegmentedOption, as as SegmentedProps, at as SegmentedValue, aA as TabItem, aB as Tabs, aD as TabsOrientation, aE as TabsPosition, aF as TabsProps, aG as TabsType, aH as Tag, aI as TagProps, aJ as TagStatus, aK as TagVariant, aY as Typography, aZ as TypographyLinkProps, a_ as TypographyProps, a$ as TypographyTitleProps, b0 as TypographyType, b1 as Upload, b2 as UploadChangeInfo, b3 as UploadDraggerProps, b4 as UploadFile, b5 as UploadFileStatus, b6 as UploadProps, b7 as UploadRequestOptions, bb as message } from './core-BeiAQiDY.js';
1
+ export { e as Breadcrumb, f as BreadcrumbItem, g as BreadcrumbProps, h as Button, i as ButtonProps, j as ButtonSize, k as ButtonVariant, m as Card, n as CardAccent, o as CardProps, s as Collapse, t as CollapseItem, u as CollapseKey, v as CollapseProps, G as FilledIconName, H as FloatButton, I as FloatButtonBackTopProps, J as FloatButtonGroupProps, K as FloatButtonProps, L as FloatButtonShape, Q as Icon, R as IconName, S as IconProps, T as IconVariant, Z as Input, _ as InputProps, a5 as MessageConfig, a6 as MessageHandle, a7 as MessageKey, a8 as MessageType, a9 as Modal, aa as ModalActionResult, ab as ModalOpenConfig, ac as ModalProps, ad as ModalType, a as OverlayApiHandle, al as Progress, am as ProgressProps, an as ProgressStatus, aq as Segmented, ar as SegmentedOption, as as SegmentedProps, at as SegmentedValue, aA as TabItem, aB as Tabs, aD as TabsOrientation, aE as TabsPosition, aF as TabsProps, aG as TabsType, aH as Tag, aI as TagProps, aJ as TagStatus, aK as TagVariant, aY as Typography, aZ as TypographyLinkProps, a_ as TypographyProps, a$ as TypographyTitleProps, b0 as TypographyType, b1 as Upload, b2 as UploadChangeInfo, b3 as UploadDraggerProps, b4 as UploadFile, b5 as UploadFileStatus, b6 as UploadProps, b7 as UploadRequestOptions, bb as message } from './core-DFYheaoJ.js';
2
2
  export { S as Select, d as SelectOption, e as SelectProps, f as SelectValue } from './Select-CJJ5LQap.js';
3
3
  import 'react';
package/dist/core.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  Typography,
11
11
  Upload,
12
12
  message
13
- } from "./chunk-ULEGTKXR.js";
13
+ } from "./chunk-ZPYGBMBH.js";
14
14
  import "./chunk-NZAT2RUM.js";
15
15
  import {
16
16
  Input,