@sia.soul/sia-react-ui 0.1.39 → 0.1.41

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.
@@ -1991,11 +1991,12 @@ function DateRangePicker({
1991
1991
  const [currentValue, setCurrentValue] = useControllableState({ value: value === void 0 ? void 0 : Array.isArray(value) ? value : ["", ""], defaultValue, onChange });
1992
1992
  const [visible, setVisible] = useControllableState({ value: open, defaultValue: defaultOpen, onChange: onOpenChange });
1993
1993
  const [draftValue, setDraftValue] = (0, import_react7.useState)(currentValue);
1994
- const [activeIndex, setActiveIndex] = (0, import_react7.useState)(currentValue[0] && !currentValue[1] ? 1 : 0);
1994
+ const [activeIndex, setActiveIndex] = (0, import_react7.useState)(endpointDisabled[0] || currentValue[0] && !currentValue[1] ? 1 : 0);
1995
+ const [confirmedIndex, setConfirmedIndex] = (0, import_react7.useState)(null);
1996
+ const [presetSelected, setPresetSelected] = (0, import_react7.useState)(false);
1995
1997
  const [hoverDate, setHoverDate] = (0, import_react7.useState)("");
1996
1998
  const [viewMonth, setViewMonth] = (0, import_react7.useState)(() => startOfMonth(parseDate(dayFromValue(currentValue[0] || currentValue[1])) ?? /* @__PURE__ */ new Date()));
1997
1999
  const [endViewMonth, setEndViewMonth] = (0, import_react7.useState)(() => startOfMonth(parseDate(dayFromValue(currentValue[1])) ?? addMonths(parseDate(dayFromValue(currentValue[0])) ?? /* @__PURE__ */ new Date(), 1)));
1998
- const [compactDateTime, setCompactDateTime] = (0, import_react7.useState)(false);
1999
2000
  const showSecond = showSecondFrom(showTime);
2000
2001
  const defaultTime = defaultTimeFrom(showTime);
2001
2002
  const defaultEndTime = defaultTimeFrom(showTime, 1);
@@ -2006,51 +2007,46 @@ function DateRangePicker({
2006
2007
  const resolvedNeedConfirm = needConfirm ?? Boolean(showTime);
2007
2008
  const rangeDates = [dayFromValue(draftValue[0]), dayFromValue(draftValue[1])];
2008
2009
  const invalidDateTimeRange = Boolean(showTime && draftValue[0] && draftValue[1] && draftValue[0] > draftValue[1]);
2009
- (0, import_react7.useEffect)(() => {
2010
- if (!showTime || typeof document === "undefined") {
2011
- setCompactDateTime(false);
2012
- return void 0;
2013
- }
2014
- const updateLayout = () => {
2015
- const pairedPanelWidth = 2 * (280 + (showSecond ? 144 : 96) + 1) + 3;
2016
- setCompactDateTime(document.documentElement.clientWidth < pairedPanelWidth + 16);
2017
- };
2018
- updateLayout();
2019
- window.addEventListener("resize", updateLayout);
2020
- return () => window.removeEventListener("resize", updateLayout);
2021
- }, [showSecond, showTime]);
2022
2010
  (0, import_react7.useEffect)(() => {
2023
2011
  if (!visible) return void 0;
2024
2012
  const close = (event) => {
2025
2013
  const target = event.target;
2026
- if (!rootRef.current?.contains(target) && !popupRef.current?.contains(target)) setVisible(false);
2014
+ if (!rootRef.current?.contains(target) && !popupRef.current?.contains(target)) dismissPanel();
2027
2015
  };
2028
2016
  document.addEventListener("pointerdown", close);
2029
2017
  return () => document.removeEventListener("pointerdown", close);
2030
- }, [setVisible, visible]);
2031
- function changeOpen(next) {
2032
- if (next) {
2018
+ });
2019
+ function dismissPanel() {
2020
+ setVisible(false);
2021
+ }
2022
+ function changeOpen(next, endpoint) {
2023
+ if (next && !visible) {
2024
+ setConfirmedIndex(null);
2025
+ setPresetSelected(false);
2033
2026
  setDraftValue(currentValue);
2034
2027
  setTimes([timePart(currentValue[0], defaultTime), timePart(currentValue[1], defaultEndTime)]);
2035
- setActiveIndex(endpointDisabled[0] ? 1 : endpointDisabled[1] ? 0 : currentValue[0] && !currentValue[1] ? 1 : 0);
2028
+ setActiveIndex(endpointDisabled[0] ? 1 : endpointDisabled[1] ? 0 : endpoint ?? (currentValue[0] && !currentValue[1] ? 1 : 0));
2036
2029
  const nextStartMonth = startOfMonth(parseDate(dayFromValue(currentValue[0] || currentValue[1])) ?? /* @__PURE__ */ new Date());
2037
2030
  setViewMonth(nextStartMonth);
2038
2031
  setEndViewMonth(startOfMonth(parseDate(dayFromValue(currentValue[1])) ?? addMonths(nextStartMonth, 1)));
2039
2032
  }
2033
+ if (next && endpoint !== void 0 && !endpointDisabled[endpoint]) setActiveIndex(endpoint);
2040
2034
  setVisible(next);
2041
2035
  }
2042
- function isDisabled(day, index = activeIndex, pairedDateTime = false) {
2036
+ function isDisabled(day, index = activeIndex, dateTimeStep = false) {
2043
2037
  if (endpointDisabled[index]) return true;
2044
2038
  const minimum = minDate ?? props.min;
2045
2039
  const maximum = maxDate ?? props.max;
2046
2040
  if (minimum && day < String(minimum).slice(0, 10)) return true;
2047
2041
  if (maximum && day > String(maximum).slice(0, 10)) return true;
2048
2042
  const from = index === 1 ? rangeDates[0] : void 0;
2049
- if (pairedDateTime) {
2050
- const otherEndpoint = index === 0 ? rangeDates[1] : rangeDates[0];
2051
- if (index === 0 && otherEndpoint && day > otherEndpoint) return true;
2052
- if (index === 1 && otherEndpoint && day < otherEndpoint) return true;
2053
- if (otherEndpoint && maxRangeDays && Math.abs(daysBetween(otherEndpoint, day)) >= maxRangeDays) return true;
2043
+ if (dateTimeStep) {
2044
+ const otherIndex2 = index === 0 ? 1 : 0;
2045
+ const otherEndpoint = rangeDates[otherIndex2];
2046
+ if (otherEndpoint && (endpointDisabled[otherIndex2] || confirmedIndex === otherIndex2)) {
2047
+ if (index === 0 && day > otherEndpoint || index === 1 && day < otherEndpoint) return true;
2048
+ if (maxRangeDays && Math.abs(daysBetween(otherEndpoint, day)) >= maxRangeDays) return true;
2049
+ }
2054
2050
  } else if (from && maxRangeDays && Math.abs(daysBetween(from, day)) >= maxRangeDays) return true;
2055
2051
  return disabledDate?.(day, { from, type: "date" }) ?? false;
2056
2052
  }
@@ -2058,8 +2054,12 @@ function DateRangePicker({
2058
2054
  return showTime ? withTime(day, times[index], showSecond) : day;
2059
2055
  }
2060
2056
  function updateDraft(next) {
2057
+ setPresetSelected(false);
2061
2058
  setDraftValue(next);
2062
2059
  onCalendarChange?.(next);
2060
+ if (!showTime && isValidRange(next) && (next[0] !== currentValue[0] || next[1] !== currentValue[1])) {
2061
+ setCurrentValue(next);
2062
+ }
2063
2063
  }
2064
2064
  function selectDate(day) {
2065
2065
  if (isDisabled(day)) return;
@@ -2069,7 +2069,6 @@ function DateRangePicker({
2069
2069
  next[index] = buildRangeValue(day, index);
2070
2070
  updateDraft(next);
2071
2071
  if (!resolvedNeedConfirm && isValidRange(next)) {
2072
- setCurrentValue(next);
2073
2072
  changeOpen(false);
2074
2073
  }
2075
2074
  return;
@@ -2087,7 +2086,6 @@ function DateRangePicker({
2087
2086
  setActiveIndex(0);
2088
2087
  setHoverDate("");
2089
2088
  if (!resolvedNeedConfirm) {
2090
- setCurrentValue(ordered);
2091
2089
  changeOpen(false);
2092
2090
  }
2093
2091
  }
@@ -2097,16 +2095,7 @@ function DateRangePicker({
2097
2095
  nextValue[index] = buildRangeValue(day, index);
2098
2096
  updateDraft(nextValue);
2099
2097
  setHoverDate("");
2100
- if (!resolvedNeedConfirm && compactDateTime && index === 0) {
2101
- setActiveIndex(1);
2102
- setEndViewMonth(startOfMonth(parseDate(day) ?? /* @__PURE__ */ new Date()));
2103
- return;
2104
- }
2105
2098
  setActiveIndex(index);
2106
- if (!resolvedNeedConfirm && nextValue[0] && nextValue[1] && nextValue[0] <= nextValue[1]) {
2107
- setCurrentValue(nextValue);
2108
- changeOpen(false);
2109
- }
2110
2099
  }
2111
2100
  function changeTime(index, nextTime) {
2112
2101
  if (endpointDisabled[index]) return;
@@ -2142,11 +2131,16 @@ function DateRangePicker({
2142
2131
  }
2143
2132
  return true;
2144
2133
  }
2134
+ const otherIndex = activeIndex === 0 ? 1 : 0;
2135
+ const needsOtherConfirmation = Boolean(showTime && !presetSelected && !endpointDisabled[otherIndex] && confirmedIndex !== otherIndex);
2145
2136
  function confirm() {
2146
- if (compactDateTime && showTime && activeIndex === 0) {
2147
- if (!draftValue[0]) return;
2148
- setActiveIndex(1);
2149
- setEndViewMonth(startOfMonth(parseDate(dayFromValue(draftValue[1] || draftValue[0])) ?? /* @__PURE__ */ new Date()));
2137
+ if (needsOtherConfirmation) {
2138
+ if (!draftValue[activeIndex] && !allowEmpty[activeIndex]) return;
2139
+ setConfirmedIndex(activeIndex);
2140
+ setActiveIndex(otherIndex);
2141
+ const month = startOfMonth(parseDate(dayFromValue(draftValue[activeIndex])) ?? /* @__PURE__ */ new Date());
2142
+ if (otherIndex === 0) setViewMonth(month);
2143
+ else setEndViewMonth(month);
2150
2144
  setHoverDate("");
2151
2145
  return;
2152
2146
  }
@@ -2162,12 +2156,13 @@ function DateRangePicker({
2162
2156
  ];
2163
2157
  if (!isValidRange(next)) return;
2164
2158
  updateDraft(next);
2159
+ setConfirmedIndex(null);
2160
+ setPresetSelected(true);
2165
2161
  setTimes([timePart(next[0], defaultTime), timePart(next[1], defaultEndTime)]);
2166
2162
  const nextStartMonth = startOfMonth(parseDate(dayFromValue(next[0] || next[1])) ?? /* @__PURE__ */ new Date());
2167
2163
  setViewMonth(nextStartMonth);
2168
2164
  setEndViewMonth(startOfMonth(parseDate(dayFromValue(next[1])) ?? addMonths(nextStartMonth, 1)));
2169
- if (!resolvedNeedConfirm) {
2170
- setCurrentValue(next);
2165
+ if (!showTime && !resolvedNeedConfirm) {
2171
2166
  changeOpen(false);
2172
2167
  }
2173
2168
  }
@@ -2217,6 +2212,7 @@ function DateRangePicker({
2217
2212
  value: times[index],
2218
2213
  showSecond,
2219
2214
  ariaLabel: `${endpointLabel}\u65F6\u95F4`,
2215
+ disabledTime: endpointDisabled[index] ? () => true : void 0,
2220
2216
  onChange: (nextTime) => changeTime(index, nextTime)
2221
2217
  }
2222
2218
  )
@@ -2225,8 +2221,9 @@ function DateRangePicker({
2225
2221
  endpointLabel
2226
2222
  );
2227
2223
  }
2228
- const startFloating = useFloatingPlaceholder({ mode: placeholderMode, placeholder: placeholder[0], filled: Boolean(currentValue[0]), active: visible });
2229
- const endFloating = useFloatingPlaceholder({ mode: placeholderMode, placeholder: placeholder[1], filled: Boolean(currentValue[1]), active: visible });
2224
+ const displayValue = visible && allowEmpty.some(Boolean) ? draftValue : currentValue;
2225
+ const startFloating = useFloatingPlaceholder({ mode: placeholderMode, placeholder: placeholder[0], filled: Boolean(displayValue[0]), active: visible });
2226
+ const endFloating = useFloatingPlaceholder({ mode: placeholderMode, placeholder: placeholder[1], filled: Boolean(displayValue[1]), active: visible });
2230
2227
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { ref: rootRef, className: `sia-picker sia-picker-range-control sia-picker--${size} sia-picker--${status}${visible ? " is-open" : ""}${disabled ? " is-disabled" : ""} ${className}`.trim(), children: [
2231
2228
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2232
2229
  "button",
@@ -2242,66 +2239,68 @@ function DateRangePicker({
2242
2239
  "aria-describedby": props["aria-describedby"],
2243
2240
  "aria-errormessage": props["aria-errormessage"],
2244
2241
  disabled,
2245
- onClick: () => changeOpen(!visible),
2242
+ onClick: (event) => {
2243
+ const field = event.target.closest("[data-range-endpoint]");
2244
+ const endpoint = field?.dataset.rangeEndpoint;
2245
+ if (showTime && (endpoint === "0" || endpoint === "1")) {
2246
+ const index = Number(endpoint);
2247
+ if (!endpointDisabled[index]) changeOpen(true, index);
2248
+ } else if (visible) dismissPanel();
2249
+ else changeOpen(true);
2250
+ },
2246
2251
  children: [
2247
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: `sia-picker-range-control__field${startFloating.className}`, children: [
2248
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `sia-picker-range-control__value${currentValue[0] ? "" : " is-placeholder"}`, children: currentValue[0] ? formatValue(currentValue[0]) : placeholder[0] }),
2252
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { "data-range-endpoint": "0", className: `sia-picker-range-control__field${startFloating.className}${visible && activeIndex === 0 ? " is-active" : ""}`, children: [
2253
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `sia-picker-range-control__value${displayValue[0] ? "" : " is-placeholder"}`, children: displayValue[0] ? formatValue(displayValue[0]) : placeholder[0] }),
2249
2254
  startFloating.label
2250
2255
  ] }),
2251
2256
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sia-picker-range-control__separator", children: separator }),
2252
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: `sia-picker-range-control__field${endFloating.className}`, children: [
2253
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `sia-picker-range-control__value${currentValue[1] ? "" : " is-placeholder"}`, children: currentValue[1] ? formatValue(currentValue[1]) : placeholder[1] }),
2257
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { "data-range-endpoint": "1", className: `sia-picker-range-control__field${endFloating.className}${visible && activeIndex === 1 ? " is-active" : ""}`, children: [
2258
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: `sia-picker-range-control__value${displayValue[1] ? "" : " is-placeholder"}`, children: displayValue[1] ? formatValue(displayValue[1]) : placeholder[1] }),
2254
2259
  endFloating.label
2255
2260
  ] }),
2256
2261
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sia-picker__icon", "aria-hidden": "true", children: suffixIcon ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { name: "calendar", size: 16 }) })
2257
2262
  ]
2258
2263
  }
2259
2264
  ),
2260
- allowClear && (currentValue[0] || currentValue[1]) && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F\u8303\u56F4", onClick: clearValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
2261
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(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: [
2262
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "sia-date-panel__body", children: showTime ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "sia-date-panel__range-date-time", children: compactDateTime ? renderDateTimeGroup(activeIndex) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2263
- renderDateTimeGroup(0),
2264
- renderDateTimeGroup(1)
2265
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "sia-date-panel__range-calendars", children: [
2266
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "sia-date-panel__calendar", children: [
2267
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2268
- CalendarHeader,
2269
- {
2270
- month: viewMonth,
2271
- range: true,
2272
- onPreviousYear: () => setViewMonth(addMonths(viewMonth, -12)),
2273
- onPreviousMonth: () => setViewMonth(addMonths(viewMonth, -1))
2274
- }
2275
- ),
2276
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CalendarMonth, { month: viewMonth, range: rangeDates, previewEnd: activeIndex === 1 ? hoverDate : "", disabledDate: isDisabled, onSelect: selectDate, onHover: activeIndex === 1 ? setHoverDate : void 0 })
2277
- ] }),
2278
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "sia-date-panel__calendar", children: [
2279
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2280
- CalendarHeader,
2281
- {
2282
- month: addMonths(viewMonth, 1),
2283
- range: true,
2284
- onNextMonth: () => setViewMonth(addMonths(viewMonth, 1)),
2285
- onNextYear: () => setViewMonth(addMonths(viewMonth, 12))
2286
- }
2287
- ),
2288
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CalendarMonth, { month: addMonths(viewMonth, 1), range: rangeDates, previewEnd: activeIndex === 1 ? hoverDate : "", disabledDate: isDisabled, onSelect: selectDate, onHover: activeIndex === 1 ? setHoverDate : void 0 })
2265
+ allowClear && (displayValue[0] || displayValue[1]) && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F\u8303\u56F4", onClick: clearValue, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
2266
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(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-compact" : ""}${presets?.length ? " sia-date-panel--with-presets" : ""}`, role: "dialog", "aria-label": "\u65E5\u671F\u8303\u56F4\u9009\u62E9\u9762\u677F", children: [
2267
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "sia-date-panel__body", children: [
2268
+ presets?.length ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("aside", { className: "sia-date-panel__presets", "aria-label": "\u5FEB\u6377\u65E5\u671F\u8303\u56F4", children: presets.map((preset2, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: () => applyPreset(preset2), children: preset2.label }, index)) }) : null,
2269
+ showTime ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "sia-date-panel__range-date-time", children: renderDateTimeGroup(activeIndex) }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "sia-date-panel__range-calendars", children: [
2270
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "sia-date-panel__calendar", children: [
2271
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2272
+ CalendarHeader,
2273
+ {
2274
+ month: viewMonth,
2275
+ range: true,
2276
+ onPreviousYear: () => setViewMonth(addMonths(viewMonth, -12)),
2277
+ onPreviousMonth: () => setViewMonth(addMonths(viewMonth, -1))
2278
+ }
2279
+ ),
2280
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CalendarMonth, { month: viewMonth, range: rangeDates, previewEnd: activeIndex === 1 ? hoverDate : "", disabledDate: isDisabled, onSelect: selectDate, onHover: activeIndex === 1 ? setHoverDate : void 0 })
2281
+ ] }),
2282
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("section", { className: "sia-date-panel__calendar", children: [
2283
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2284
+ CalendarHeader,
2285
+ {
2286
+ month: addMonths(viewMonth, 1),
2287
+ range: true,
2288
+ onNextMonth: () => setViewMonth(addMonths(viewMonth, 1)),
2289
+ onNextYear: () => setViewMonth(addMonths(viewMonth, 12))
2290
+ }
2291
+ ),
2292
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CalendarMonth, { month: addMonths(viewMonth, 1), range: rangeDates, previewEnd: activeIndex === 1 ? hoverDate : "", disabledDate: isDisabled, onSelect: selectDate, onHover: activeIndex === 1 ? setHoverDate : void 0 })
2293
+ ] })
2289
2294
  ] })
2290
- ] }) }),
2295
+ ] }),
2291
2296
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2292
2297
  DatePanelFooter,
2293
2298
  {
2294
2299
  showToday: showToday && !presets?.length,
2295
- needConfirm: resolvedNeedConfirm || allowEmpty.some(Boolean),
2296
- disabledConfirm: compactDateTime && showTime && activeIndex === 0 ? !draftValue[0] : !isValidRange(draftValue),
2297
- confirmText: compactDateTime && showTime && activeIndex === 0 ? "\u4E0B\u4E00\u6B65" : "\u786E\u5B9A",
2300
+ needConfirm: Boolean(showTime) || resolvedNeedConfirm || allowEmpty.some(Boolean),
2301
+ disabledConfirm: needsOtherConfirmation ? !draftValue[activeIndex] && !allowEmpty[activeIndex] : !isValidRange(draftValue),
2298
2302
  extra: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2299
2303
  renderExtraFooter?.(),
2300
- presets?.map((preset2, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: () => applyPreset(preset2), children: preset2.label }, index)),
2301
- compactDateTime && showTime && activeIndex === 1 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: () => {
2302
- setActiveIndex(0);
2303
- setViewMonth(startOfMonth(parseDate(dayFromValue(draftValue[0])) ?? /* @__PURE__ */ new Date()));
2304
- }, children: "\u4E0A\u4E00\u6B65" }) : null,
2305
2304
  invalidDateTimeRange ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("small", { className: "sia-date-panel__range-error", children: "\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4" }) : maxRangeDays ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("small", { children: [
2306
2305
  "\u6700\u591A\u9009\u62E9 ",
2307
2306
  maxRangeDays,
@@ -2893,38 +2892,66 @@ var activeTooltipClose;
2893
2892
  function clampFloating(value, min, max) {
2894
2893
  return Math.min(Math.max(value, min), Math.max(min, max));
2895
2894
  }
2896
- function resolveFloatingPosition(trigger, overlay, placement) {
2895
+ function normalizeFloatingPlacement(placement) {
2896
+ const aliases = {
2897
+ topLeft: "top-start",
2898
+ topRight: "top-end",
2899
+ bottomLeft: "bottom-start",
2900
+ bottomRight: "bottom-end",
2901
+ leftTop: "left-start",
2902
+ leftBottom: "left-end",
2903
+ rightTop: "right-start",
2904
+ rightBottom: "right-end"
2905
+ };
2906
+ return aliases[placement] ?? placement;
2907
+ }
2908
+ function resolveFloatingPosition(trigger, overlay, placement, pointAtCenter, adjust) {
2897
2909
  const viewportWidth = document.documentElement.clientWidth;
2898
2910
  const viewportHeight = document.documentElement.clientHeight;
2899
- let resolvedPlacement = placement;
2900
- if (placement.startsWith("top") && trigger.top - overlay.height - FLOATING_GAP < FLOATING_VIEWPORT_PADDING && trigger.bottom + overlay.height + FLOATING_GAP <= viewportHeight - FLOATING_VIEWPORT_PADDING) {
2901
- resolvedPlacement = placement.replace("top", "bottom");
2902
- } else if (placement.startsWith("bottom") && trigger.bottom + overlay.height + FLOATING_GAP > viewportHeight - FLOATING_VIEWPORT_PADDING && trigger.top - overlay.height - FLOATING_GAP >= FLOATING_VIEWPORT_PADDING) {
2903
- resolvedPlacement = placement.replace("bottom", "top");
2904
- } else if (placement === "left" && trigger.left - overlay.width - FLOATING_GAP < FLOATING_VIEWPORT_PADDING && trigger.right + overlay.width + FLOATING_GAP <= viewportWidth - FLOATING_VIEWPORT_PADDING) {
2905
- resolvedPlacement = "right";
2906
- } else if (placement === "right" && trigger.right + overlay.width + FLOATING_GAP > viewportWidth - FLOATING_VIEWPORT_PADDING && trigger.left - overlay.width - FLOATING_GAP >= FLOATING_VIEWPORT_PADDING) {
2907
- resolvedPlacement = "left";
2908
- }
2909
- let top = trigger.top;
2910
- let left = trigger.left;
2911
- if (resolvedPlacement.startsWith("top") || resolvedPlacement.startsWith("bottom")) {
2912
- top = resolvedPlacement.startsWith("top") ? trigger.top - overlay.height - FLOATING_GAP : trigger.bottom + FLOATING_GAP;
2913
- left = resolvedPlacement.endsWith("-start") ? trigger.left : resolvedPlacement.endsWith("-end") ? trigger.right - overlay.width : trigger.left + (trigger.width - overlay.width) / 2;
2914
- } else {
2915
- top = trigger.top + (trigger.height - overlay.height) / 2;
2916
- left = resolvedPlacement === "left" ? trigger.left - overlay.width - FLOATING_GAP : trigger.right + FLOATING_GAP;
2917
- }
2918
- top = clampFloating(top, FLOATING_VIEWPORT_PADDING, viewportHeight - overlay.height - FLOATING_VIEWPORT_PADDING);
2919
- left = clampFloating(left, FLOATING_VIEWPORT_PADDING, viewportWidth - overlay.width - FLOATING_VIEWPORT_PADDING);
2920
- const result = { top, left, placement: resolvedPlacement };
2921
- if (resolvedPlacement.startsWith("top") || resolvedPlacement.startsWith("bottom")) {
2922
- result.arrowX = resolvedPlacement.endsWith("-start") ? clampFloating(FLOATING_ARROW_EDGE_OFFSET, 8, overlay.width - 16) : resolvedPlacement.endsWith("-end") ? clampFloating(overlay.width - FLOATING_ARROW_EDGE_OFFSET - 8, 8, overlay.width - 16) : clampFloating(trigger.left + trigger.width / 2 - left - 4, 8, overlay.width - 16);
2923
- } else {
2924
- result.arrowY = clampFloating(trigger.top + trigger.height / 2 - top - 4, 8, overlay.height - 16);
2911
+ let resolvedPlacement = normalizeFloatingPlacement(placement);
2912
+ const side = resolvedPlacement.split("-")[0];
2913
+ const available = { top: trigger.top, bottom: viewportHeight - trigger.bottom, left: trigger.left, right: viewportWidth - trigger.right };
2914
+ const opposite = { top: "bottom", bottom: "top", left: "right", right: "left" };
2915
+ const preferred = side;
2916
+ const other = opposite[preferred];
2917
+ const needed = (side === "top" || side === "bottom" ? overlay.height : overlay.width) + FLOATING_GAP + FLOATING_VIEWPORT_PADDING;
2918
+ if (adjust && available[preferred] < needed && available[other] > available[preferred]) {
2919
+ resolvedPlacement = resolvedPlacement.replace(preferred, other);
2920
+ }
2921
+ const vertical = resolvedPlacement.startsWith("top") || resolvedPlacement.startsWith("bottom");
2922
+ const start = resolvedPlacement.endsWith("-start");
2923
+ const end = resolvedPlacement.endsWith("-end");
2924
+ let top = vertical ? resolvedPlacement.startsWith("top") ? trigger.top - overlay.height - FLOATING_GAP : trigger.bottom + FLOATING_GAP : start ? trigger.top : end ? trigger.bottom - overlay.height : trigger.top + (trigger.height - overlay.height) / 2;
2925
+ let left = vertical ? start ? trigger.left : end ? trigger.right - overlay.width : trigger.left + (trigger.width - overlay.width) / 2 : resolvedPlacement.startsWith("left") ? trigger.left - overlay.width - FLOATING_GAP : trigger.right + FLOATING_GAP;
2926
+ if (adjust) {
2927
+ if (vertical) left = clampFloating(left, FLOATING_VIEWPORT_PADDING, viewportWidth - overlay.width - FLOATING_VIEWPORT_PADDING);
2928
+ else top = clampFloating(top, FLOATING_VIEWPORT_PADDING, viewportHeight - overlay.height - FLOATING_VIEWPORT_PADDING);
2925
2929
  }
2930
+ const result = { top, left, placement: resolvedPlacement };
2931
+ const size = vertical ? trigger.width : trigger.height;
2932
+ const anchorStart = vertical ? trigger.left : trigger.top;
2933
+ const edge = Math.min(size / 2, FLOATING_ARROW_EDGE_OFFSET + 4);
2934
+ const target = anchorStart + (pointAtCenter || !start && !end ? size / 2 : start ? edge : size - edge);
2935
+ if (vertical) result.arrowX = clampFloating(target - left - 4, 8, overlay.width - 16);
2936
+ else result.arrowY = clampFloating(target - top - 4, 8, overlay.height - 16);
2926
2937
  return result;
2927
2938
  }
2939
+ function isFloatingAnchorHidden(anchor, rect) {
2940
+ let left = 0, top = 0, right = document.documentElement.clientWidth, bottom = document.documentElement.clientHeight;
2941
+ for (let parent = anchor.parentElement; parent; parent = parent.parentElement) {
2942
+ const css = getComputedStyle(parent);
2943
+ const bounds = parent.getBoundingClientRect();
2944
+ if (/(auto|scroll|hidden|clip)/.test(css.overflowX)) {
2945
+ left = Math.max(left, bounds.left);
2946
+ right = Math.min(right, bounds.right);
2947
+ }
2948
+ if (/(auto|scroll|hidden|clip)/.test(css.overflowY)) {
2949
+ top = Math.max(top, bounds.top);
2950
+ bottom = Math.min(bottom, bounds.bottom);
2951
+ }
2952
+ }
2953
+ return rect.right <= left || rect.left >= right || rect.bottom <= top || rect.top >= bottom;
2954
+ }
2928
2955
  function Floating({
2929
2956
  children,
2930
2957
  content,
@@ -2935,6 +2962,7 @@ function Floating({
2935
2962
  mouseEnterDelay = 0.1,
2936
2963
  mouseLeaveDelay = 0.1,
2937
2964
  arrow = true,
2965
+ autoAdjustOverflow = true,
2938
2966
  color,
2939
2967
  className = "",
2940
2968
  overlayClassName = "",
@@ -2942,6 +2970,7 @@ function Floating({
2942
2970
  onOpenChange
2943
2971
  }) {
2944
2972
  const rootRef = (0, import_react13.useRef)(null);
2973
+ const triggerElementRef = (0, import_react13.useRef)(null);
2945
2974
  const overlayRef = (0, import_react13.useRef)(null);
2946
2975
  const enterTimer = (0, import_react13.useRef)();
2947
2976
  const leaveTimer = (0, import_react13.useRef)();
@@ -2993,28 +3022,42 @@ function Floating({
2993
3022
  setPosition(void 0);
2994
3023
  return;
2995
3024
  }
3025
+ const getAnchor = () => {
3026
+ const root = rootRef.current;
3027
+ const target = triggerElementRef.current;
3028
+ return target && root?.contains(target) ? target : root?.firstElementChild ?? root;
3029
+ };
2996
3030
  const update = () => {
2997
3031
  if (!rootRef.current || !overlayRef.current) return;
2998
- setPosition(resolveFloatingPosition(rootRef.current.getBoundingClientRect(), overlayRef.current.getBoundingClientRect(), placement));
3032
+ const anchor2 = getAnchor();
3033
+ if (anchor2) {
3034
+ const rect = anchor2.getBoundingClientRect();
3035
+ const next = resolveFloatingPosition(rect, overlayRef.current.getBoundingClientRect(), placement, typeof arrow === "object" && !!arrow.pointAtCenter, autoAdjustOverflow);
3036
+ next.hidden = isFloatingAnchorHidden(anchor2, rect);
3037
+ setPosition(next);
3038
+ }
2999
3039
  };
3000
3040
  update();
3001
3041
  window.addEventListener("resize", update);
3002
3042
  window.addEventListener("scroll", update, true);
3003
3043
  const observer = new ResizeObserver(update);
3004
3044
  if (rootRef.current) observer.observe(rootRef.current);
3045
+ const anchor = getAnchor();
3046
+ if (anchor) observer.observe(anchor);
3005
3047
  if (overlayRef.current) observer.observe(overlayRef.current);
3006
3048
  return () => {
3007
3049
  window.removeEventListener("resize", update);
3008
3050
  window.removeEventListener("scroll", update, true);
3009
3051
  observer.disconnect();
3010
3052
  };
3011
- }, [children, content, placement, visible]);
3053
+ }, [children, content, placement, visible, autoAdjustOverflow, typeof arrow === "object" && arrow.pointAtCenter]);
3012
3054
  (0, import_react13.useEffect)(() => () => {
3013
3055
  clearTimers();
3014
3056
  if (activeTooltipClose === closeSelfRef.current) activeTooltipClose = void 0;
3015
3057
  }, []);
3016
3058
  const child = (0, import_react13.cloneElement)(children, {
3017
3059
  ...triggers.includes("hover") ? { onMouseEnter: (event) => {
3060
+ triggerElementRef.current = event.currentTarget;
3018
3061
  children.props.onMouseEnter?.(event);
3019
3062
  show(mouseEnterDelay);
3020
3063
  }, onMouseLeave: (event) => {
@@ -3022,6 +3065,7 @@ function Floating({
3022
3065
  hide(mouseLeaveDelay);
3023
3066
  } } : {},
3024
3067
  ...triggers.includes("focus") ? { onFocus: (event) => {
3068
+ triggerElementRef.current = event.currentTarget;
3025
3069
  children.props.onFocus?.(event);
3026
3070
  show();
3027
3071
  }, onBlur: (event) => {
@@ -3029,6 +3073,7 @@ function Floating({
3029
3073
  hide();
3030
3074
  } } : {},
3031
3075
  ...triggers.includes("click") ? { onClick: (event) => {
3076
+ triggerElementRef.current = event.currentTarget;
3032
3077
  children.props.onClick?.(event);
3033
3078
  if (visible) closeNow();
3034
3079
  else openNow();
@@ -3043,14 +3088,14 @@ function Floating({
3043
3088
  id: contentId,
3044
3089
  role,
3045
3090
  "data-custom-color": color ? "" : void 0,
3046
- className: `sia-floating__overlay sia-floating__overlay--${position?.placement ?? placement} ${overlayClassName}`.trim(),
3091
+ className: `sia-floating__overlay sia-floating__overlay--${position?.placement ?? normalizeFloatingPlacement(placement)} ${overlayClassName}`.trim(),
3047
3092
  style: {
3048
3093
  "--sia-floating-color": color,
3049
3094
  "--sia-floating-arrow-x": position?.arrowX == null ? void 0 : `${position.arrowX}px`,
3050
3095
  "--sia-floating-arrow-y": position?.arrowY == null ? void 0 : `${position.arrowY}px`,
3051
3096
  top: position?.top ?? 0,
3052
3097
  left: position?.left ?? 0,
3053
- visibility: position ? "visible" : "hidden"
3098
+ visibility: position && !position.hidden ? "visible" : "hidden"
3054
3099
  },
3055
3100
  onMouseEnter: triggers.includes("hover") ? () => show() : void 0,
3056
3101
  onMouseLeave: triggers.includes("hover") ? () => hide(mouseLeaveDelay) : void 0,
@@ -1,4 +1,4 @@
1
- export { S as SelectDateRange, i as SelectDateRangeProps, j as SelectDateRangeValue } from './select-date-range-CtA-B8DB.cjs';
1
+ export { S as SelectDateRange, i as SelectDateRangeProps, j as SelectDateRangeValue } from './select-date-range-2galnCvZ.cjs';
2
2
  import 'react';
3
3
  import './shared-Bx4B28Wh.cjs';
4
4
  import './Select-YJbT-MF1.cjs';
@@ -1,4 +1,4 @@
1
- export { S as SelectDateRange, i as SelectDateRangeProps, j as SelectDateRangeValue } from './select-date-range-D9W_mmMq.js';
1
+ export { S as SelectDateRange, i as SelectDateRangeProps, j as SelectDateRangeValue } from './select-date-range-Dtj6XF9I.js';
2
2
  import 'react';
3
3
  import './shared-Bx4B28Wh.js';
4
4
  import './Select-CCrPqULn.js';
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SelectDateRange
3
- } from "./chunk-GLS4WVIZ.js";
4
- import "./chunk-LRGD2QDA.js";
3
+ } from "./chunk-LWVZEUGJ.js";
4
+ import "./chunk-3Q3S6CDZ.js";
5
5
  import "./chunk-XCVAVCIO.js";
6
6
  import "./chunk-IKAMZNCK.js";
7
7
  import "./chunk-H7IAG72O.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sia.soul/sia-react-ui",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "description": "Sia Design components and tokens for React",
5
5
  "publishConfig": {
6
6
  "access": "public",