sellmate-design-system-react 9.0.0-beta.91 → 9.0.0-beta.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -13423,9 +13423,20 @@ var SystemButton = /* @__PURE__ */ react.forwardRef(function SystemButton2({
13423
13423
  }
13424
13424
  ),
13425
13425
  label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-semibold min-w-0 truncate", children: label }),
13426
- count != null && count > 0 && // 개수 오른쪽은 버튼 여백(alertButton.paddingX)만으로는 좁다 — 시안이 4px 을 더 준다.
13426
+ count != null && count > 0 && // 개수는 채운 배지로 단다 — 배경·글자색·치수는 xs deep 태그 토큰이 쥔다(시안).
13427
+ // 배지 색은 고정이다: 흰 면은 파랑, 어두운 면(dark·darker)은 노랑 바탕에 검은 글자.
13428
+ // 배지 오른쪽은 버튼 여백(alertButton.paddingX)만으로는 좁다 — 시안이 4px 을 더 준다.
13427
13429
  // 대응 토큰이 없어 디자인 값을 그대로 쓴다.
13428
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-md-bold me-[4px] shrink-0", style: { color: accentColor }, children: count.toLocaleString() })
13430
+ /* @__PURE__ */ jsxRuntime.jsx(
13431
+ STag,
13432
+ {
13433
+ size: "xs",
13434
+ deep: true,
13435
+ color: color === "light" ? "blue" : "yellow",
13436
+ label: count.toLocaleString(),
13437
+ className: "me-[4px] shrink-0"
13438
+ }
13439
+ )
13429
13440
  ]
13430
13441
  }
13431
13442
  );
@@ -14304,7 +14315,7 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
14304
14315
  items.findIndex((item4, index) => getItemValue(item4, index) === value)
14305
14316
  );
14306
14317
  const lastCompletedIndex = items.reduce(
14307
- (lastIndex, item4, index) => item4.completed === true ? index : lastIndex,
14318
+ (lastIndex2, item4, index) => item4.completed === true ? index : lastIndex2,
14308
14319
  -1
14309
14320
  );
14310
14321
  const resolvedClickableIndex = lastCompletedIndex + 1;
@@ -19403,13 +19414,21 @@ function SCalendar({
19403
19414
  }
19404
19415
  );
19405
19416
  }
19417
+
19418
+ // src/lib/mode-listbox.ts
19419
+ var MODE_LIST_HEIGHT = 240;
19420
+ var MODE_ITEM_HEIGHT = 28;
19421
+ var modeListItemClass = (selected, disabled) => cn(
19422
+ "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
19423
+ disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
19424
+ !disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
19425
+ !disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
19426
+ );
19406
19427
  var MODE_NOUN = {
19407
19428
  date: "\uB0A0\uC9DC",
19408
19429
  month: "\uC6D4",
19409
19430
  year: "\uC5F0\uB3C4"
19410
19431
  };
19411
- var DATEPICKER_MODE_LIST_HEIGHT = 240;
19412
- var DATEPICKER_MODE_ITEM_HEIGHT = 28;
19413
19432
  var YEAR_LIST_EDGE_BUFFER = 24;
19414
19433
  var YEAR_LIST_EXPAND_SIZE = 80;
19415
19434
  var MONTHS = Array.from({ length: 12 }, (_, i) => i + 1);
@@ -19460,7 +19479,7 @@ function YearWheel({ value, anchorYear, selectable, onCommit }) {
19460
19479
  if (!list) return;
19461
19480
  const index = anchorYearRef.current - rangeStartRef.current;
19462
19481
  syncingScrollRef.current = true;
19463
- list.scrollTop = index * DATEPICKER_MODE_ITEM_HEIGHT;
19482
+ list.scrollTop = index * MODE_ITEM_HEIGHT;
19464
19483
  requestAnimationFrame(() => {
19465
19484
  syncingScrollRef.current = false;
19466
19485
  });
@@ -19469,7 +19488,7 @@ function YearWheel({ value, anchorYear, selectable, onCommit }) {
19469
19488
  const list = listRef.current;
19470
19489
  if (!list) return;
19471
19490
  if (syncingScrollRef.current) return;
19472
- if (list.scrollTop < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
19491
+ if (list.scrollTop < MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
19473
19492
  const previousHeight = list.scrollHeight;
19474
19493
  setRange((current) => ({
19475
19494
  start: current.start - YEAR_LIST_EXPAND_SIZE,
@@ -19485,7 +19504,7 @@ function YearWheel({ value, anchorYear, selectable, onCommit }) {
19485
19504
  });
19486
19505
  return;
19487
19506
  }
19488
- if (list.scrollHeight - list.scrollTop - list.clientHeight < DATEPICKER_MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
19507
+ if (list.scrollHeight - list.scrollTop - list.clientHeight < MODE_ITEM_HEIGHT * YEAR_LIST_EDGE_BUFFER) {
19489
19508
  setRange((current) => ({
19490
19509
  start: current.start,
19491
19510
  end: current.end + YEAR_LIST_EXPAND_SIZE
@@ -19500,8 +19519,8 @@ function YearWheel({ value, anchorYear, selectable, onCommit }) {
19500
19519
  "aria-label": "year",
19501
19520
  className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
19502
19521
  style: {
19503
- paddingTop: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`,
19504
- paddingBottom: `calc((${DATEPICKER_MODE_LIST_HEIGHT}px - ${DATEPICKER_MODE_ITEM_HEIGHT}px) / 2)`
19522
+ paddingTop: `calc((${MODE_LIST_HEIGHT}px - ${MODE_ITEM_HEIGHT}px) / 2)`,
19523
+ paddingBottom: `calc((${MODE_LIST_HEIGHT}px - ${MODE_ITEM_HEIGHT}px) / 2)`
19505
19524
  },
19506
19525
  onScroll: handleScroll,
19507
19526
  children: years.map((year) => {
@@ -19514,12 +19533,7 @@ function YearWheel({ value, anchorYear, selectable, onCommit }) {
19514
19533
  role: "option",
19515
19534
  "aria-selected": selected,
19516
19535
  disabled,
19517
- className: cn(
19518
- "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
19519
- disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
19520
- !disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
19521
- !disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
19522
- ),
19536
+ className: modeListItemClass(selected, disabled),
19523
19537
  onClick: () => !disabled && onCommit(year),
19524
19538
  children: year
19525
19539
  },
@@ -19575,7 +19589,7 @@ function MonthWheel({ year, value, selectable, onCommit }) {
19575
19589
  if (!list) return;
19576
19590
  list.scrollTop = Math.max(
19577
19591
  0,
19578
- (initialValueRef.current - 1) * DATEPICKER_MODE_ITEM_HEIGHT - (list.clientHeight - DATEPICKER_MODE_ITEM_HEIGHT) / 2
19592
+ (initialValueRef.current - 1) * MODE_ITEM_HEIGHT - (list.clientHeight - MODE_ITEM_HEIGHT) / 2
19579
19593
  );
19580
19594
  }, []);
19581
19595
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -19595,12 +19609,7 @@ function MonthWheel({ year, value, selectable, onCommit }) {
19595
19609
  role: "option",
19596
19610
  "aria-selected": selected,
19597
19611
  disabled,
19598
- className: cn(
19599
- "flex w-full items-center justify-center gap-[var(--cmp-datepicker-mode-item-gap)] border-0 px-[var(--cmp-datepicker-mode-item-paddingX)] py-[var(--cmp-datepicker-mode-item-paddingY)] text-center font-base text-12 leading-[20px]",
19600
- disabled && "cursor-not-allowed bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-disabled)]",
19601
- !disabled && !selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-medium text-[color:var(--cmp-datepicker-mode-item-content-default)] hover:bg-[var(--cmp-datepicker-mode-item-bg-hover)] hover:text-[color:var(--cmp-datepicker-mode-item-content-hover)]",
19602
- !disabled && selected && "cursor-pointer bg-[var(--cmp-datepicker-mode-item-bg-default)] font-bold text-[color:var(--cmp-datepicker-mode-item-content-selected)]"
19603
- ),
19612
+ className: modeListItemClass(selected, disabled),
19604
19613
  onClick: () => !disabled && onCommit(month),
19605
19614
  children: [
19606
19615
  month,
@@ -28687,212 +28696,171 @@ function formatTimeDisplay(value, type) {
28687
28696
  const displayHour = hour % 12 === 0 ? 12 : hour % 12;
28688
28697
  return `${meridiem} ${padTimePart(displayHour)}:${padTimePart(minute)}`;
28689
28698
  }
28690
- var TIME_SELECTOR_WIDTH = 136;
28691
- var MERIDIEM_TIME_SELECTOR_WIDTH = 154;
28692
- function TimeSelector({
28699
+ function scrollSelectedIntoView(list, index, center) {
28700
+ const top = index * MODE_ITEM_HEIGHT;
28701
+ if (center) {
28702
+ list.scrollTop = Math.max(0, top - (list.clientHeight - MODE_ITEM_HEIGHT) / 2);
28703
+ return;
28704
+ }
28705
+ if (top < list.scrollTop) list.scrollTop = top;
28706
+ else if (top + MODE_ITEM_HEIGHT > list.scrollTop + list.clientHeight)
28707
+ list.scrollTop = top + MODE_ITEM_HEIGHT - list.clientHeight;
28708
+ }
28709
+ function lastIndex(arr, pred) {
28710
+ for (let i = arr.length - 1; i >= 0; i--) if (pred(arr[i], i)) return i;
28711
+ return -1;
28712
+ }
28713
+ function ListColumn({ ariaLabel, items }) {
28714
+ const listRef = react.useRef(null);
28715
+ const mountedRef = react.useRef(false);
28716
+ const selectedIndex = items.findIndex((item4) => item4.selected);
28717
+ const tabIndexTarget = selectedIndex >= 0 ? selectedIndex : items.findIndex((item4) => !item4.disabled);
28718
+ react.useLayoutEffect(() => {
28719
+ const list = listRef.current;
28720
+ if (!list || selectedIndex < 0) return;
28721
+ scrollSelectedIntoView(list, selectedIndex, !mountedRef.current);
28722
+ mountedRef.current = true;
28723
+ }, [selectedIndex]);
28724
+ const onKeyDown = (event) => {
28725
+ const buttons = [...listRef.current?.querySelectorAll("button") ?? []];
28726
+ const current = buttons.indexOf(document.activeElement);
28727
+ if (current < 0) return;
28728
+ const enabled = (item4, i) => !item4.disabled && i !== current;
28729
+ let next;
28730
+ if (event.key === "ArrowDown") next = items.findIndex((it, i) => i > current && enabled(it, i));
28731
+ else if (event.key === "ArrowUp")
28732
+ next = lastIndex(items, (it, i) => i < current && enabled(it, i));
28733
+ else if (event.key === "Home") next = items.findIndex((it) => !it.disabled);
28734
+ else if (event.key === "End") next = lastIndex(items, (it) => !it.disabled);
28735
+ else return;
28736
+ event.preventDefault();
28737
+ if (next < 0) return;
28738
+ buttons[next]?.focus({ preventScroll: true });
28739
+ if (listRef.current) scrollSelectedIntoView(listRef.current, next, false);
28740
+ };
28741
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-[var(--cmp-datepicker-mode-yearMonth-column-width)] min-w-0 overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]", children: /* @__PURE__ */ jsxRuntime.jsx(
28742
+ "div",
28743
+ {
28744
+ ref: listRef,
28745
+ role: "listbox",
28746
+ "aria-label": ariaLabel,
28747
+ tabIndex: -1,
28748
+ className: "h-full overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
28749
+ onKeyDown,
28750
+ children: items.map((item4, index) => /* @__PURE__ */ jsxRuntime.jsx(
28751
+ "button",
28752
+ {
28753
+ type: "button",
28754
+ role: "option",
28755
+ "aria-selected": item4.selected,
28756
+ disabled: item4.disabled,
28757
+ tabIndex: index === tabIndexTarget ? 0 : -1,
28758
+ className: cn(modeListItemClass(item4.selected, item4.disabled), "outline-offset-[-2px]"),
28759
+ onClick: () => !item4.disabled && item4.onSelect(),
28760
+ children: item4.label
28761
+ },
28762
+ item4.key
28763
+ ))
28764
+ }
28765
+ ) });
28766
+ }
28767
+ var HOURS_24 = Array.from({ length: 24 }, (_, i) => i);
28768
+ var HOURS_12 = [12, ...Array.from({ length: 11 }, (_, i) => i + 1)];
28769
+ function TimeListbox({
28693
28770
  value,
28694
28771
  showMeridiem,
28695
28772
  minuteStep,
28696
- onChange
28773
+ isDisabled,
28774
+ onChange,
28775
+ labelPrefix,
28776
+ elevated = true
28697
28777
  }) {
28698
- const parsed = react.useMemo(() => parseTimeValue(value), [value]);
28699
- const [hour, setHour] = react.useState(parsed.hour);
28700
- const [minute, setMinute] = react.useState(parsed.minute);
28701
- const [editingPart, setEditingPart] = react.useState(null);
28702
- const [inputDraft, setInputDraft] = react.useState({});
28778
+ const toState = (v) => v ? parseTimeValue(v) : null;
28779
+ const [time, setTime] = react.useState(() => toState(value));
28703
28780
  react.useEffect(() => {
28704
- setHour(parsed.hour);
28705
- setMinute(parsed.minute);
28706
- }, [parsed.hour, parsed.minute]);
28707
- const meridiem = hour >= 12 ? "PM" : "AM";
28708
- const displayHour = showMeridiem ? hour % 12 === 0 ? 12 : hour % 12 : hour;
28709
- const commit = (nextHour, nextMinute) => {
28710
- const h = clampTimePart(nextHour, 0, 23);
28711
- const m = clampTimePart(nextMinute, 0, 59);
28712
- setHour(h);
28713
- setMinute(m);
28714
- onChange(formatTimeValue(h, m));
28715
- };
28716
- const setMeridiem = (next) => {
28717
- if (next === meridiem) return;
28718
- commit(next === "AM" ? hour - 12 : hour + 12, minute);
28719
- };
28720
- const changeMinute = (delta) => {
28721
- const next = minute + delta;
28722
- if (next > 59) {
28723
- commit((hour + 1) % 24, next - 60);
28724
- return;
28725
- }
28726
- if (next < 0) {
28727
- commit((hour + 23) % 24, next + 60);
28728
- return;
28729
- }
28730
- commit(hour, next);
28731
- };
28732
- const changeHour = (delta) => commit((hour + delta + 24) % 24, minute);
28733
- const sanitizeInput = (next) => next.replace(/\D/g, "").slice(0, 2);
28734
- const beginEdit = (part, currentValue) => {
28735
- setEditingPart(part);
28736
- setInputDraft((prev) => ({ ...prev, [part]: String(currentValue).padStart(2, "0") }));
28737
- };
28738
- const commitHourDraft = (draft) => {
28739
- const clamped = clampTimePart(Number(draft), showMeridiem ? 1 : 0, showMeridiem ? 12 : 23);
28740
- const nextHour = showMeridiem ? meridiem === "PM" ? clamped === 12 ? 12 : clamped + 12 : clamped === 12 ? 0 : clamped : clamped;
28741
- commit(nextHour, minute);
28742
- return clamped;
28743
- };
28744
- const commitMinuteDraft = (draft) => {
28745
- const clamped = clampTimePart(Number(draft), 0, 59);
28746
- commit(hour, clamped);
28747
- return clamped;
28748
- };
28749
- const endEdit = (part) => {
28750
- const draft = inputDraft[part];
28751
- if (part === "hour" && draft != null && draft !== "") {
28752
- commitHourDraft(draft);
28753
- }
28754
- if (part === "minute" && draft != null && draft !== "") {
28755
- commitMinuteDraft(draft);
28756
- }
28757
- setEditingPart(null);
28758
- setInputDraft({});
28759
- };
28760
- const inputStyle = {
28761
- width: "var(--cmp-timepicker-selector-time-input-width)",
28762
- height: "var(--cmp-textinput-sm-height)",
28763
- borderRadius: "var(--cmp-textinput-sm-radius)",
28764
- border: "var(--cmp-textinput-borderWidth) solid var(--cmp-textinput-border-default)",
28765
- color: "var(--cmp-textinput-text-default)",
28766
- fontSize: 12,
28767
- lineHeight: "20px"
28781
+ setTime(toState(value));
28782
+ }, [value]);
28783
+ const step = Math.max(1, Math.floor(minuteStep));
28784
+ const minutes = Array.from({ length: Math.ceil(60 / step) }, (_, i) => i * step);
28785
+ const blocked = (h, m) => isDisabled?.(h * 60 + m) ?? false;
28786
+ const hourBlocked = (h) => minutes.every((m) => blocked(h, m));
28787
+ const commit = (hours, preferred, part) => {
28788
+ let next = blocked(preferred.hour, preferred.minute) ? null : preferred;
28789
+ for (const h of hours) {
28790
+ if (next) break;
28791
+ const m = minutes.find((mm) => !blocked(h, mm));
28792
+ if (m !== void 0) next = { hour: h, minute: m };
28793
+ }
28794
+ if (!next) return;
28795
+ setTime(next);
28796
+ onChange(formatTimeValue(next.hour, next.minute), part);
28768
28797
  };
28769
- const renderColumn = (type) => {
28770
- const isHour = type === "hour";
28771
- const val = isHour ? displayHour : minute;
28772
- const displayValue2 = editingPart === type ? inputDraft[type] ?? "" : String(val).padStart(2, "0");
28773
- return /* @__PURE__ */ jsxRuntime.jsxs(
28774
- "div",
28775
- {
28776
- className: "flex flex-col items-center justify-center",
28777
- style: { gap: "var(--cmp-timepicker-selector-time-column-gap)" },
28778
- children: [
28779
- /* @__PURE__ */ jsxRuntime.jsx(
28780
- SGhostButton,
28781
- {
28782
- icon: "chevronUp",
28783
- size: "xs",
28784
- ariaLabel: `${isHour ? "\uC2DC" : "\uBD84"} \uC99D\uAC00`,
28785
- onClick: () => isHour ? changeHour(1) : changeMinute(minuteStep)
28786
- }
28787
- ),
28788
- /* @__PURE__ */ jsxRuntime.jsx(
28789
- "input",
28790
- {
28791
- "aria-label": isHour ? "\uC2DC" : "\uBD84",
28792
- inputMode: "numeric",
28793
- value: displayValue2,
28794
- placeholder: "-",
28795
- onFocus: () => beginEdit(type, val),
28796
- onBlur: () => endEdit(type),
28797
- onChange: (event) => {
28798
- const draft = sanitizeInput(event.target.value);
28799
- setInputDraft((prev) => ({ ...prev, [type]: draft }));
28800
- if (draft === "") return;
28801
- const raw = Number(draft);
28802
- if (isHour) {
28803
- if (draft.length < 2) return;
28804
- const clamped2 = commitHourDraft(draft);
28805
- const displayDraft2 = raw === clamped2 ? draft : String(clamped2);
28806
- setInputDraft((prev) => ({ ...prev, [type]: displayDraft2 }));
28807
- return;
28808
- }
28809
- if (draft.length < 2) return;
28810
- const clamped = commitMinuteDraft(draft);
28811
- const displayDraft = raw === clamped ? draft : String(clamped);
28812
- setInputDraft((prev) => ({ ...prev, [type]: displayDraft }));
28813
- },
28814
- className: "box-border bg-white text-center outline-none",
28815
- style: inputStyle
28816
- }
28817
- ),
28818
- /* @__PURE__ */ jsxRuntime.jsx(
28819
- SGhostButton,
28820
- {
28821
- icon: "chevronDown",
28822
- size: "xs",
28823
- ariaLabel: `${isHour ? "\uC2DC" : "\uBD84"} \uAC10\uC18C`,
28824
- onClick: () => isHour ? changeHour(-1) : changeMinute(-minuteStep)
28825
- }
28826
- )
28827
- ]
28798
+ const hour = time?.hour;
28799
+ const minute = time?.minute ?? 0;
28800
+ const meridiem = hour === void 0 ? void 0 : hour >= 12 ? "PM" : "AM";
28801
+ const prefix = labelPrefix ? `${labelPrefix} ` : "";
28802
+ const meridiemItems = ["AM", "PM"].map((item4) => {
28803
+ const base = item4 === "AM" ? 0 : 12;
28804
+ const range = HOURS_24.slice(base, base + 12);
28805
+ return {
28806
+ key: item4,
28807
+ label: item4 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4",
28808
+ selected: meridiem === item4,
28809
+ disabled: range.every(hourBlocked),
28810
+ onSelect: () => {
28811
+ if (meridiem === item4) return;
28812
+ const h = hour === void 0 ? base : hour % 12 + base;
28813
+ commit(range, { hour: h, minute }, "meridiem");
28828
28814
  }
28829
- );
28830
- };
28815
+ };
28816
+ });
28817
+ const hourItems = showMeridiem ? HOURS_12.map((display) => {
28818
+ const h = display % 12 + (meridiem === "PM" ? 12 : 0);
28819
+ return {
28820
+ key: String(display),
28821
+ label: `${padTimePart(display)}\uC2DC`,
28822
+ selected: hour === h,
28823
+ disabled: hourBlocked(h),
28824
+ onSelect: () => commit([h], { hour: h, minute }, "hour")
28825
+ };
28826
+ }) : HOURS_24.map((h) => ({
28827
+ key: String(h),
28828
+ label: `${padTimePart(h)}\uC2DC`,
28829
+ selected: hour === h,
28830
+ disabled: hourBlocked(h),
28831
+ onSelect: () => commit([h], { hour: h, minute }, "hour")
28832
+ }));
28833
+ const minuteHour = hour ?? (meridiem === "PM" ? 12 : 0);
28834
+ const minuteItems = minutes.map((m) => ({
28835
+ key: String(m),
28836
+ label: `${padTimePart(m)}\uBD84`,
28837
+ selected: time != null && minute === m,
28838
+ disabled: blocked(minuteHour, m),
28839
+ onSelect: () => commit([minuteHour], { hour: minuteHour, minute: m }, "minute")
28840
+ }));
28841
+ const divider = /* @__PURE__ */ jsxRuntime.jsx(
28842
+ "div",
28843
+ {
28844
+ "aria-hidden": true,
28845
+ className: "w-[var(--border-width-1)] self-stretch bg-[var(--sys-color-divider-default)]"
28846
+ }
28847
+ );
28831
28848
  return /* @__PURE__ */ jsxRuntime.jsxs(
28832
28849
  "div",
28833
28850
  {
28834
- className: "flex flex-col items-stretch justify-center overflow-hidden",
28835
- style: {
28836
- background: "var(--cmp-timepicker-selector-bg)",
28837
- borderRadius: "var(--cmp-timepicker-selector-radius)",
28838
- boxShadow: "4px 8px 16px -4px rgba(34,34,34,0.1), 0 0 24px -6px rgba(34,34,34,0.12)"
28839
- },
28851
+ className: cn(
28852
+ "inline-flex gap-[var(--cmp-datepicker-mode-yearMonth-gap)] overflow-hidden bg-[var(--cmp-datepicker-mode-bg)]",
28853
+ elevated && "rounded-[var(--cmp-datepicker-mode-radius)] shadow-normal-sm"
28854
+ ),
28855
+ style: { height: MODE_LIST_HEIGHT },
28840
28856
  children: [
28841
- showMeridiem && /* @__PURE__ */ jsxRuntime.jsx(
28842
- "div",
28843
- {
28844
- className: "flex items-center justify-center",
28845
- style: {
28846
- padding: "var(--cmp-timepicker-selector-section-paddingY) var(--cmp-timepicker-selector-section-paddingX)"
28847
- },
28848
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "isolate flex", children: ["AM", "PM"].map((item4, index) => {
28849
- const selected = item4 === meridiem;
28850
- return /* @__PURE__ */ jsxRuntime.jsx(
28851
- "button",
28852
- {
28853
- type: "button",
28854
- onClick: () => setMeridiem(item4),
28855
- className: cn(
28856
- "box-border h-[var(--cmp-textinput-sm-height)] w-[61px] cursor-pointer border border-solid bg-white text-center text-[12px] font-medium leading-[20px]",
28857
- index === 0 ? "rounded-l-[var(--cmp-select-sm-radius)]" : "rounded-r-[var(--cmp-select-sm-radius)]",
28858
- index === 0 ? "-mr-px" : "",
28859
- selected ? "z-[1] border-[var(--cmp-timepicker-border-focus)] text-[var(--cmp-timepicker-border-focus)]" : "border-[var(--cmp-timepicker-border-default)] text-[var(--cmp-field-hint-color)]"
28860
- ),
28861
- children: item4 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4"
28862
- },
28863
- item4
28864
- );
28865
- }) })
28866
- }
28867
- ),
28868
- showMeridiem && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px w-full bg-[var(--sys-color-divider-default)]" }),
28869
- /* @__PURE__ */ jsxRuntime.jsxs(
28870
- "div",
28871
- {
28872
- className: "flex items-center justify-center",
28873
- style: {
28874
- gap: "var(--cmp-timepicker-selector-time-gap)",
28875
- padding: "var(--cmp-timepicker-selector-section-paddingY) var(--cmp-timepicker-selector-section-paddingX)"
28876
- },
28877
- children: [
28878
- renderColumn("hour"),
28879
- /* @__PURE__ */ jsxRuntime.jsx(
28880
- "span",
28881
- {
28882
- className: "text-center",
28883
- style: {
28884
- width: "var(--cmp-timepicker-selector-colon-size)",
28885
- color: "var(--cmp-field-hint-color)",
28886
- fontSize: "var(--cmp-timepicker-selector-colon-size)",
28887
- lineHeight: "var(--cmp-timepicker-selector-colon-size)"
28888
- },
28889
- children: ":"
28890
- }
28891
- ),
28892
- renderColumn("minute")
28893
- ]
28894
- }
28895
- )
28857
+ showMeridiem && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
28858
+ /* @__PURE__ */ jsxRuntime.jsx(ListColumn, { ariaLabel: `${prefix}\uC624\uC804/\uC624\uD6C4`, items: meridiemItems }),
28859
+ divider
28860
+ ] }),
28861
+ /* @__PURE__ */ jsxRuntime.jsx(ListColumn, { ariaLabel: `${prefix}\uC2DC`, items: hourItems }),
28862
+ divider,
28863
+ /* @__PURE__ */ jsxRuntime.jsx(ListColumn, { ariaLabel: `${prefix}\uBD84`, items: minuteItems })
28896
28864
  ]
28897
28865
  }
28898
28866
  );
@@ -28930,11 +28898,9 @@ function STimePicker({
28930
28898
  style
28931
28899
  }) {
28932
28900
  const portalContainer = usePortalContainer();
28933
- const triggerRef = react.useRef(null);
28934
28901
  const [open, setOpen] = react.useState(false);
28935
28902
  const triggerId = useFieldControlId();
28936
28903
  const triggerTextId = `${triggerId}-text`;
28937
- const [popoverAlignOffset, setPopoverAlignOffset] = react.useState(0);
28938
28904
  const [focused, setFocused] = react.useState(false);
28939
28905
  const [ruleError, setRuleError] = react.useState("");
28940
28906
  const dims = TIMEPICKER_SIZE_CONFIG[size] ?? TIMEPICKER_SIZE_CONFIG.sm;
@@ -28955,11 +28921,6 @@ function STimePicker({
28955
28921
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
28956
28922
  const commitOpen = (next) => {
28957
28923
  if (disabled) return;
28958
- if (next) {
28959
- const triggerWidth = triggerRef.current?.getBoundingClientRect().width ?? 0;
28960
- const selectorWidth = effectiveShowMeridiem ? MERIDIEM_TIME_SELECTOR_WIDTH : TIME_SELECTOR_WIDTH;
28961
- setPopoverAlignOffset(Math.max(0, (triggerWidth - selectorWidth) / 2));
28962
- }
28963
28924
  setOpen(next);
28964
28925
  onOpenChange?.(next);
28965
28926
  if (!next && rules && rules.length > 0) setRuleError(runRules(value, rules));
@@ -28998,7 +28959,6 @@ function STimePicker({
28998
28959
  /* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
28999
28960
  "div",
29000
28961
  {
29001
- ref: triggerRef,
29002
28962
  id: triggerId,
29003
28963
  role: "button",
29004
28964
  "aria-disabled": disabled,
@@ -29062,20 +29022,22 @@ function STimePicker({
29062
29022
  RPopover13__namespace.Content,
29063
29023
  {
29064
29024
  side: "bottom",
29065
- align: "start",
29025
+ align: "center",
29066
29026
  sideOffset: 4,
29067
- alignOffset: popoverAlignOffset,
29068
29027
  className: cn(
29069
29028
  "z-50 max-w-[var(--radix-popover-content-available-width)]",
29070
29029
  FLOATING_SLIDE_ANIM
29071
29030
  ),
29072
29031
  children: /* @__PURE__ */ jsxRuntime.jsx(
29073
- TimeSelector,
29032
+ TimeListbox,
29074
29033
  {
29075
29034
  value: normalized,
29076
29035
  showMeridiem: effectiveShowMeridiem,
29077
29036
  minuteStep,
29078
- onChange: commitValue
29037
+ onChange: (time, part) => {
29038
+ commitValue(time);
29039
+ if (part === "minute") commitOpen(false);
29040
+ }
29079
29041
  }
29080
29042
  )
29081
29043
  }
@@ -29105,7 +29067,6 @@ function formatTimeRangeDisplay(value, type) {
29105
29067
  if (value == null || value[0] === "" || value[1] === "") return "";
29106
29068
  return `${formatTimeDisplay(value[0], type)} ~ ${formatTimeDisplay(value[1], type)}`;
29107
29069
  }
29108
- var TIME_RANGE_SELECTOR_WIDTH = 345;
29109
29070
  var MIDDAY_FIELD_MIN_WIDTH = {
29110
29071
  sm: 178,
29111
29072
  md: 216
@@ -29114,6 +29075,10 @@ var MIDDAY_FIELD_MAX_WIDTH = {
29114
29075
  sm: "lg",
29115
29076
  md: "lg"
29116
29077
  };
29078
+ var toMinutes = (time) => {
29079
+ const { hour, minute } = parseTimeValue(time);
29080
+ return hour * 60 + minute;
29081
+ };
29117
29082
  function RangeTimeSelector({
29118
29083
  value,
29119
29084
  showMeridiem,
@@ -29121,233 +29086,32 @@ function RangeTimeSelector({
29121
29086
  rangeOrder,
29122
29087
  onChange
29123
29088
  }) {
29124
- const range = react.useMemo(() => value ?? ["00:00", "23:59"], [value]);
29125
- const [editingKey, setEditingKey] = react.useState(null);
29126
- const [inputDraft, setInputDraft] = react.useState({});
29127
- const autoAdjustedRef = react.useRef(null);
29128
- const getParts = (side) => parseTimeValue(side === "start" ? range[0] : range[1]);
29129
- const getMeridiem = (side) => getParts(side).hour >= 12 ? "PM" : "AM";
29130
- const getDisplayHour = (side) => {
29131
- const { hour } = getParts(side);
29132
- if (!showMeridiem) return hour;
29133
- const displayHour = hour % 12;
29134
- return displayHour === 0 ? 12 : displayHour;
29135
- };
29136
- const commit = (side, hour, minute, direction = "unknown") => {
29137
- const next = formatTimeValue(hour, minute);
29138
- onChange(
29139
- normalizeNextRange(side === "start" ? [next, range[1]] : [range[0], next], side, direction)
29140
- );
29141
- };
29142
- const getTimeMinutes2 = (time) => {
29143
- const { hour, minute } = parseTimeValue(time);
29144
- return hour * 60 + minute;
29145
- };
29146
- const normalizeNextRange = (nextRange, changedSide, direction) => {
29147
- if (rangeOrder === "allow-cross-day") return nextRange;
29148
- const [start, end] = nextRange;
29149
- const [currentStart, currentEnd] = range;
29150
- if (getTimeMinutes2(start) <= getTimeMinutes2(end)) {
29151
- const shouldKeepSynced = autoAdjustedRef.current?.side === changedSide && currentStart === currentEnd && start !== end && (direction === "unknown" || autoAdjustedRef.current.direction === direction);
29152
- if (shouldKeepSynced) {
29153
- return changedSide === "start" ? [start, start] : [end, end];
29154
- }
29155
- autoAdjustedRef.current = null;
29156
- return nextRange;
29157
- }
29158
- autoAdjustedRef.current = {
29159
- side: changedSide,
29160
- direction: changedSide === "start" ? "increase" : "decrease"
29161
- };
29162
- return changedSide === "start" ? [start, start] : [end, end];
29163
- };
29164
- const changeHour = (side, delta) => {
29165
- const { hour, minute } = getParts(side);
29166
- commit(side, (hour + delta + 24) % 24, minute, delta > 0 ? "increase" : "decrease");
29167
- };
29168
- const changeMinute = (side, delta) => {
29169
- const { hour, minute } = getParts(side);
29170
- const next = minute + delta;
29171
- if (next > 59) {
29172
- commit(side, (hour + 1) % 24, next - 60, delta > 0 ? "increase" : "decrease");
29089
+ const range = value ?? ["00:00", "23:59"];
29090
+ const strict = rangeOrder !== "allow-cross-day";
29091
+ const change = (side, time) => {
29092
+ if (side === "end") {
29093
+ onChange([range[0], time]);
29173
29094
  return;
29174
29095
  }
29175
- if (next < 0) {
29176
- commit(side, (hour + 23) % 24, next + 60, delta > 0 ? "increase" : "decrease");
29177
- return;
29178
- }
29179
- commit(side, hour, next, delta > 0 ? "increase" : "decrease");
29180
- };
29181
- const setMeridiem = (side, next) => {
29182
- const current = getMeridiem(side);
29183
- if (current === next) return;
29184
- const { hour, minute } = getParts(side);
29185
- commit(side, next === "AM" ? hour - 12 : hour + 12, minute);
29186
- };
29187
- const getEditingKey = (side, part) => `${side}-${part}`;
29188
- const sanitizeInput = (next) => next.replace(/\D/g, "").slice(0, 2);
29189
- const beginEdit = (side, part, currentValue) => {
29190
- const key = getEditingKey(side, part);
29191
- setEditingKey(key);
29192
- setInputDraft((prev) => ({ ...prev, [key]: String(currentValue).padStart(2, "0") }));
29193
- };
29194
- const commitHourDraft = (side, draft) => {
29195
- const clamped = clampTimePart(Number(draft), showMeridiem ? 1 : 0, showMeridiem ? 12 : 23);
29196
- const parts = getParts(side);
29197
- const meridiem = getMeridiem(side);
29198
- const nextHour = showMeridiem ? meridiem === "PM" ? clamped === 12 ? 12 : clamped + 12 : clamped === 12 ? 0 : clamped : clamped;
29199
- commit(side, nextHour, parts.minute);
29200
- return clamped;
29201
- };
29202
- const commitMinuteDraft = (side, draft) => {
29203
- const { hour } = getParts(side);
29204
- const clamped = clampTimePart(Number(draft), 0, 59);
29205
- commit(side, hour, clamped);
29206
- return clamped;
29207
- };
29208
- const endEdit = (side, part) => {
29209
- const key = getEditingKey(side, part);
29210
- const draft = inputDraft[key];
29211
- if (part === "hour" && draft != null && draft !== "") {
29212
- commitHourDraft(side, draft);
29213
- }
29214
- if (part === "minute" && draft != null && draft !== "") {
29215
- commitMinuteDraft(side, draft);
29216
- }
29217
- setEditingKey(null);
29218
- setInputDraft({});
29219
- };
29220
- const inputStyle = {
29221
- width: "var(--cmp-timepicker-selector-time-input-width)",
29222
- height: "var(--cmp-textinput-sm-height)",
29223
- borderRadius: "var(--cmp-textinput-sm-radius)",
29224
- border: "var(--cmp-textinput-borderWidth) solid var(--cmp-textinput-border-default)",
29225
- color: "var(--cmp-textinput-text-default)",
29226
- fontSize: 12,
29227
- lineHeight: "20px"
29228
- };
29229
- const renderColumn = (side, kind) => {
29230
- const isHour = kind === "hour";
29231
- const { minute } = getParts(side);
29232
- const val = isHour ? getDisplayHour(side) : minute;
29233
- const currentEditingKey = getEditingKey(side, kind);
29234
- const displayValue2 = editingKey === currentEditingKey ? inputDraft[currentEditingKey] ?? "" : String(val).padStart(2, "0");
29235
- return /* @__PURE__ */ jsxRuntime.jsxs(
29236
- "div",
29237
- {
29238
- className: "flex flex-col items-center justify-center",
29239
- style: { gap: "var(--cmp-timepicker-selector-time-column-gap)" },
29240
- children: [
29241
- /* @__PURE__ */ jsxRuntime.jsx(
29242
- SGhostButton,
29243
- {
29244
- icon: "chevronUp",
29245
- size: "xs",
29246
- ariaLabel: `${side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC"} ${isHour ? "\uC2DC" : "\uBD84"} \uC99D\uAC00`,
29247
- onClick: () => isHour ? changeHour(side, 1) : changeMinute(side, minuteStep)
29248
- }
29249
- ),
29250
- /* @__PURE__ */ jsxRuntime.jsx(
29251
- "input",
29252
- {
29253
- "aria-label": `${side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC"} ${isHour ? "\uC2DC" : "\uBD84"}`,
29254
- inputMode: "numeric",
29255
- value: displayValue2,
29256
- placeholder: "-",
29257
- onFocus: () => beginEdit(side, kind, val),
29258
- onBlur: () => endEdit(side, kind),
29259
- onChange: (event) => {
29260
- const draft = sanitizeInput(event.target.value);
29261
- setInputDraft((prev) => ({ ...prev, [currentEditingKey]: draft }));
29262
- if (draft === "") return;
29263
- const raw = Number(draft);
29264
- if (isHour) {
29265
- if (draft.length < 2) return;
29266
- const clamped2 = commitHourDraft(side, draft);
29267
- const displayDraft2 = raw === clamped2 ? draft : String(clamped2);
29268
- setInputDraft((prev) => ({ ...prev, [currentEditingKey]: displayDraft2 }));
29269
- return;
29270
- }
29271
- if (draft.length < 2) return;
29272
- const clamped = commitMinuteDraft(side, draft);
29273
- const displayDraft = raw === clamped ? draft : String(clamped);
29274
- setInputDraft((prev) => ({ ...prev, [currentEditingKey]: displayDraft }));
29275
- },
29276
- className: "box-border bg-white text-center outline-none",
29277
- style: inputStyle
29278
- }
29279
- ),
29280
- /* @__PURE__ */ jsxRuntime.jsx(
29281
- SGhostButton,
29282
- {
29283
- icon: "chevronDown",
29284
- size: "xs",
29285
- ariaLabel: `${side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC"} ${isHour ? "\uC2DC" : "\uBD84"} \uAC10\uC18C`,
29286
- onClick: () => isHour ? changeHour(side, -1) : changeMinute(side, -minuteStep)
29287
- }
29288
- )
29289
- ]
29290
- }
29291
- );
29096
+ onChange([time, strict && toMinutes(time) > toMinutes(range[1]) ? time : range[1]]);
29292
29097
  };
29293
29098
  const renderPanel = (side, title) => /* @__PURE__ */ jsxRuntime.jsxs(
29294
29099
  "div",
29295
29100
  {
29296
- className: "flex flex-col items-center justify-center",
29297
- style: { gap: "var(--cmp-timepicker-selector-range-section-gap)" },
29101
+ className: "flex flex-col items-center",
29102
+ style: { gap: "var(--cmp-timepicker-selector-range-heading-gap)" },
29298
29103
  children: [
29299
- /* @__PURE__ */ jsxRuntime.jsxs(
29300
- "div",
29301
- {
29302
- className: "flex flex-col items-center",
29303
- style: { gap: "var(--cmp-timepicker-selector-range-heading-gap)" },
29304
- children: [
29305
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-nowrap text-center text-[12px] font-bold leading-[20px] text-[var(--cmp-timepicker-selector-range-heading-color)]", children: title }),
29306
- showMeridiem && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "isolate flex", children: ["AM", "PM"].map((item4, index) => {
29307
- const selected = item4 === getMeridiem(side);
29308
- return /* @__PURE__ */ jsxRuntime.jsx(
29309
- "button",
29310
- {
29311
- type: "button",
29312
- onClick: () => setMeridiem(side, item4),
29313
- className: cn(
29314
- "box-border h-[var(--cmp-textinput-sm-height)] w-[61px] cursor-pointer border border-solid bg-white text-center text-[12px] font-medium leading-[20px]",
29315
- index === 0 ? "rounded-l-[var(--cmp-select-sm-radius)] -mr-px" : "rounded-r-[var(--cmp-select-sm-radius)]",
29316
- selected ? "z-[1] border-[var(--cmp-timepicker-border-focus)] text-[var(--cmp-timepicker-border-focus)]" : "border-[var(--cmp-timepicker-border-default)] text-[var(--cmp-field-hint-color)]"
29317
- ),
29318
- children: item4 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4"
29319
- },
29320
- item4
29321
- );
29322
- }) })
29323
- ]
29324
- }
29325
- ),
29326
- /* @__PURE__ */ jsxRuntime.jsxs(
29327
- "div",
29104
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-nowrap text-center text-[12px] font-bold leading-[20px] text-[var(--cmp-timepicker-selector-range-heading-color)]", children: title }),
29105
+ /* @__PURE__ */ jsxRuntime.jsx(
29106
+ TimeListbox,
29328
29107
  {
29329
- className: "flex items-center justify-center",
29330
- style: {
29331
- gap: "var(--cmp-timepicker-selector-time-gap)",
29332
- padding: "0 var(--cmp-timepicker-selector-section-paddingX)"
29333
- },
29334
- children: [
29335
- renderColumn(side, "hour"),
29336
- /* @__PURE__ */ jsxRuntime.jsx(
29337
- "span",
29338
- {
29339
- className: "text-center",
29340
- style: {
29341
- width: "var(--cmp-timepicker-selector-colon-size)",
29342
- color: "var(--cmp-field-hint-color)",
29343
- fontSize: "var(--cmp-timepicker-selector-colon-size)",
29344
- lineHeight: "var(--cmp-timepicker-selector-colon-size)"
29345
- },
29346
- children: ":"
29347
- }
29348
- ),
29349
- renderColumn(side, "minute")
29350
- ]
29108
+ value: side === "start" ? range[0] : range[1],
29109
+ showMeridiem,
29110
+ minuteStep,
29111
+ labelPrefix: side === "start" ? "\uC2DC\uC791" : "\uC885\uB8CC",
29112
+ elevated: false,
29113
+ isDisabled: strict && side === "end" ? (minutes) => minutes < toMinutes(range[0]) : void 0,
29114
+ onChange: (time) => change(side, time)
29351
29115
  }
29352
29116
  )
29353
29117
  ]
@@ -29406,11 +29170,9 @@ function STimeRangePicker({
29406
29170
  style
29407
29171
  }) {
29408
29172
  const portalContainer = usePortalContainer();
29409
- const triggerRef = react.useRef(null);
29410
29173
  const [open, setOpen] = react.useState(false);
29411
29174
  const triggerId = useFieldControlId();
29412
29175
  const triggerTextId = `${triggerId}-text`;
29413
- const [popoverAlignOffset, setPopoverAlignOffset] = react.useState(0);
29414
29176
  const [focused, setFocused] = react.useState(false);
29415
29177
  const [ruleError, setRuleError] = react.useState("");
29416
29178
  const dims = TIMEPICKER_SIZE_CONFIG[size] ?? TIMEPICKER_SIZE_CONFIG.sm;
@@ -29434,10 +29196,6 @@ function STimeRangePicker({
29434
29196
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
29435
29197
  const commitOpen = (next) => {
29436
29198
  if (disabled) return;
29437
- if (next) {
29438
- const triggerWidth = triggerRef.current?.getBoundingClientRect().width ?? 0;
29439
- setPopoverAlignOffset(Math.max(0, (triggerWidth - TIME_RANGE_SELECTOR_WIDTH) / 2));
29440
- }
29441
29199
  setOpen(next);
29442
29200
  onOpenChange?.(next);
29443
29201
  if (!next && rules && rules.length > 0) setRuleError(runRules(value, rules));
@@ -29476,7 +29234,6 @@ function STimeRangePicker({
29476
29234
  /* @__PURE__ */ jsxRuntime.jsx(RPopover13__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
29477
29235
  "div",
29478
29236
  {
29479
- ref: triggerRef,
29480
29237
  id: triggerId,
29481
29238
  role: "button",
29482
29239
  "aria-disabled": disabled,
@@ -29540,9 +29297,8 @@ function STimeRangePicker({
29540
29297
  RPopover13__namespace.Content,
29541
29298
  {
29542
29299
  side: "bottom",
29543
- align: "start",
29300
+ align: "center",
29544
29301
  sideOffset: 4,
29545
- alignOffset: popoverAlignOffset,
29546
29302
  className: cn(
29547
29303
  "z-50 max-w-[var(--radix-popover-content-available-width)]",
29548
29304
  FLOATING_SLIDE_ANIM