@choice-ui/react 1.6.1 → 1.6.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.
Files changed (40) hide show
  1. package/dist/components/calendar/dist/index.d.ts +5 -12
  2. package/dist/components/calendar/dist/index.js +223 -122
  3. package/dist/components/dialog/dist/index.d.ts +2 -1
  4. package/dist/components/dialog/dist/index.js +5 -1
  5. package/dist/components/dialog/src/dialog.d.ts +2 -1
  6. package/dist/components/dialog/src/dialog.js +5 -1
  7. package/dist/components/dropdown/dist/index.js +16 -41
  8. package/dist/components/list/dist/index.d.ts +8 -3
  9. package/dist/components/list/src/components/list-content.d.ts +3 -2
  10. package/dist/components/list/src/components/list-content.js +2 -2
  11. package/dist/components/list/src/components/list-item.d.ts +3 -0
  12. package/dist/components/list/src/list.d.ts +2 -1
  13. package/dist/components/list/src/list.js +4 -2
  14. package/dist/components/md-render/src/tv.js +1 -1
  15. package/dist/components/menus/dist/index.js +20 -25
  16. package/dist/components/modal/dist/index.d.ts +2 -1
  17. package/dist/components/modal/dist/index.js +2 -2
  18. package/dist/components/modal/src/modal.d.ts +2 -1
  19. package/dist/components/modal/src/modal.js +2 -2
  20. package/dist/components/multi-select/dist/index.js +11 -16
  21. package/dist/components/popover/dist/index.d.ts +11 -10
  22. package/dist/components/popover/dist/index.js +5 -1
  23. package/dist/components/popover/src/popover.d.ts +2 -1
  24. package/dist/components/popover/src/popover.js +5 -1
  25. package/dist/components/scroll-area/dist/index.d.ts +6 -1
  26. package/dist/components/scroll-area/dist/index.js +2 -2
  27. package/dist/components/scroll-area/src/components/scroll-area-content.d.ts +4 -1
  28. package/dist/components/scroll-area/src/components/scroll-area-content.js +2 -2
  29. package/dist/components/scroll-area/src/scroll-area.d.ts +1 -1
  30. package/dist/components/select/dist/index.js +15 -47
  31. package/dist/components/slot/dist/index.d.ts +10 -6
  32. package/dist/components/slot/dist/index.js +51 -45
  33. package/dist/components/tooltip/dist/index.js +2 -7
  34. package/dist/components/virtual-select/dist/index.d.ts +48 -0
  35. package/dist/styles/components.css +220 -193
  36. package/dist/styles/markdown.css +362 -360
  37. package/package.json +1 -1
  38. package/dist/styles/preflight.css +0 -97
  39. package/dist/styles/stories.css +0 -5
  40. package/dist/styles/theme.css +0 -597
@@ -1,8 +1,6 @@
1
1
  import { default as React__default } from 'react';
2
2
  import { Locale, Quarter as Quarter$1, Day, isSameDay, isSameMonth, isSameYear, addMonths, startOfMonth, endOfMonth, startOfWeek, endOfWeek } from 'date-fns';
3
3
  import { TextFieldProps } from '../../text-field/src';
4
- import { DropdownProps } from '../../dropdown/src';
5
- import { MenuTrigger } from '../../menus/src';
6
4
  import { TZDate } from '@date-fns/tz';
7
5
  import { Locale as Locale$1 } from 'date-fns/locale';
8
6
  import { PressMoveProps } from '../../../../../shared/src';
@@ -569,21 +567,16 @@ interface DateRangeInputProps extends Omit<TextFieldProps, "value" | "onChange"
569
567
  }
570
568
  declare const DateRangeInput: (props: DateRangeInputProps) => react_jsx_runtime.JSX.Element;
571
569
 
572
- interface TimeCalendarComponentType extends React__default.MemoExoticComponent<React__default.FC<TimeCalendarProps>> {
573
- Trigger: typeof MenuTrigger;
574
- }
575
- interface TimeCalendarProps extends BaseTimeProps, StepProps, Pick<DropdownProps, "offset" | "placement" | "matchTriggerWidth" | "variant" | "readOnly"> {
570
+ interface TimeCalendarProps extends BaseTimeProps, StepProps {
576
571
  children?: React__default.ReactNode;
572
+ /** Custom class name */
577
573
  className?: string;
574
+ /** Hour step, default 1 hour */
578
575
  hourStep?: number;
576
+ /** Minute step, default 15 minutes */
579
577
  minuteStep?: number;
580
- open?: boolean;
581
- onOpenChange?: (open: boolean) => void;
582
- closeOnSelect?: boolean;
583
- triggerRef?: React__default.RefObject<HTMLElement>;
584
- triggerSelector?: string;
585
578
  }
586
- declare const TimeCalendar: TimeCalendarComponentType;
579
+ declare const TimeCalendar: React__default.NamedExoticComponent<TimeCalendarProps>;
587
580
 
588
581
  interface TimeInputProps extends Omit<TextFieldProps, "value" | "onChange" | "format" | "defaultValue" | "step">, BaseTimeProps, StepProps, TimeInteractionProps {
589
582
  prefixElement?: React__default.ReactNode;
@@ -10,8 +10,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
10
10
  import { IconButton } from "../../icon-button/dist/index.js";
11
11
  import { FieldTypeDate, Undo, ChevronUpSmall, ChevronLeftSmall, ChevronDownSmall, ChevronRightSmall, Check, Clock } from "@choiceform/icons-react";
12
12
  import { TextField } from "../../text-field/dist/index.js";
13
- import { Dropdown as Dropdown2 } from "../../dropdown/dist/index.js";
14
- import { MenuTrigger } from "../../menus/dist/index.js";
13
+ import { Menus } from "../../menus/dist/index.js";
15
14
  import { tcx, tcv } from "../../../shared/utils/tcx/tcx.js";
16
15
  import { useMergedValue } from "../../../shared/hooks/use-merged-value/use-merged-value.js";
17
16
  import { useModifierKeys } from "../../../shared/hooks/use-modifier-keys/use-modifier-keys.js";
@@ -1222,71 +1221,54 @@ function parseCompositeFormat(input, format10, locale) {
1222
1221
  }
1223
1222
  }
1224
1223
  function removeWeekdayFromFormat(format10) {
1225
- return format10.replace(/\s*[eEic]{1,4}\s*/g, "").replace(/MMM(?!M)/g, "M月").replace(/\s+/g, " ").replace(/\s*([,,、])\s*/g, "$1").trim();
1224
+ return format10.replace(/\s*[eEic]{1,4}\s*/g, "").replace(/\s+/g, " ").replace(/\s*([,,、])\s*/g, "$1").trim();
1226
1225
  }
1227
1226
  function removeWeekdayFromInput(input, locale) {
1228
1227
  try {
1229
- const { longNames, shortNames } = generateWeekdayNames2(locale);
1230
- let result = input;
1231
- if (longNames.length > 0) {
1232
- const sortedLongNames = longNames.sort((a, b) => b.length - a.length);
1233
- const longPattern = new RegExp(`\\s*(${sortedLongNames.join("|")})\\s*`, "gi");
1234
- result = result.replace(longPattern, " ");
1235
- }
1236
- if (shortNames.length > 0) {
1237
- const sortedShortNames = shortNames.sort((a, b) => b.length - a.length);
1238
- const singleCharNames = sortedShortNames.filter((name) => name.length === 1);
1239
- const multiCharNames = sortedShortNames.filter((name) => name.length > 1);
1240
- if (multiCharNames.length > 0) {
1241
- const multiPattern = new RegExp(`\\s*(${multiCharNames.join("|")})\\s*`, "gi");
1242
- result = result.replace(multiPattern, " ");
1243
- }
1244
- if (singleCharNames.length > 0) {
1245
- const singlePattern = new RegExp(
1246
- `([((「【])(${singleCharNames.join("|")})([))」】])`,
1247
- "gi"
1248
- );
1249
- result = result.replace(singlePattern, "$1$3");
1250
- }
1228
+ const weekdayNames = generateWeekdayNames2(locale);
1229
+ if (weekdayNames.length === 0) {
1230
+ return input;
1251
1231
  }
1252
- return result.replace(/\s+/g, " ").trim();
1232
+ const sortedNames = weekdayNames.sort((a, b) => b.length - a.length);
1233
+ const pattern = new RegExp(`\\s*(${sortedNames.join("|")})\\s*`, "gi");
1234
+ return input.replace(pattern, "").replace(/\s+/g, " ").trim();
1253
1235
  } catch {
1254
1236
  return input.replace(/\s*(星期[一二三四五六日天]|周[一二三四五六日天])\s*/g, "").replace(/\s+/g, " ").trim();
1255
1237
  }
1256
1238
  }
1257
1239
  function generateWeekdayNames2(locale) {
1258
- const longNames = [];
1259
- const shortNames = [];
1240
+ const names = [];
1260
1241
  try {
1261
1242
  const baseDate = new Date(2024, 0, 7);
1262
1243
  for (let i = 0; i < 7; i++) {
1263
1244
  const currentDate = new Date(baseDate);
1264
1245
  currentDate.setDate(baseDate.getDate() + i);
1265
1246
  const fullName = format(currentDate, "eeee", { locale });
1266
- if (fullName && fullName !== "eeee" && !fullName.includes("e")) {
1267
- longNames.push(fullName);
1247
+ if (fullName && fullName !== "eeee") {
1248
+ names.push(fullName);
1268
1249
  }
1269
1250
  const shortName = format(currentDate, "eee", { locale });
1270
- if (shortName && shortName !== "eee" && shortName !== fullName && !shortName.includes("e")) {
1271
- shortNames.push(shortName);
1251
+ if (shortName && shortName !== "eee" && shortName !== fullName) {
1252
+ names.push(shortName);
1253
+ }
1254
+ const veryShortName = format(currentDate, "ee", { locale });
1255
+ if (veryShortName && veryShortName !== "ee" && veryShortName !== shortName && veryShortName !== fullName) {
1256
+ names.push(veryShortName);
1272
1257
  }
1273
1258
  const localeKey = getLocaleKey(locale);
1274
- if (localeKey === "zh" && fullName) {
1275
- const weekFormat = fullName.replace("星期", "周");
1259
+ if (localeKey === "zh") {
1260
+ const weekFormat = format(currentDate, "eeee", { locale }).replace("星期", "周");
1276
1261
  if (weekFormat !== fullName) {
1277
- shortNames.push(weekFormat);
1262
+ names.push(weekFormat);
1278
1263
  }
1279
1264
  }
1280
1265
  }
1281
- const filterNames = (names) => [...new Set(names)].filter(
1282
- (name) => name && name.length > 0 && !/^\d+$/.test(name) && name !== "Invalid Date"
1266
+ return [...new Set(names)].filter(
1267
+ (name) => name && name.length > 0 && !name.includes("e") && // 过滤掉格式化失败的情况
1268
+ name !== "Invalid Date"
1283
1269
  );
1284
- return {
1285
- longNames: filterNames(longNames),
1286
- shortNames: filterNames(shortNames)
1287
- };
1288
1270
  } catch {
1289
- return { longNames: [], shortNames: [] };
1271
+ return [];
1290
1272
  }
1291
1273
  }
1292
1274
  function parseInvalidFormattedDate(input, targetFormat, locale) {
@@ -1733,7 +1715,7 @@ var generateTimeOptions = (format10, step = 15) => {
1733
1715
  const minutes = i % 60;
1734
1716
  if (is12Hour) {
1735
1717
  const displayHour = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
1736
- const ampm = hours < 12 ? "am" : "pm";
1718
+ const ampm = hours < 12 ? "AM" : "PM";
1737
1719
  const value = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
1738
1720
  const label = `${displayHour}:${minutes.toString().padStart(2, "0")} ${ampm}`;
1739
1721
  options.push({ value, label });
@@ -3052,7 +3034,7 @@ var DateInput = forwardRef((props, ref) => {
3052
3034
  );
3053
3035
  });
3054
3036
  DateInput.displayName = "DateInput";
3055
- var TimeCalendarBase = memo(function TimeCalendar(props) {
3037
+ var TimeCalendar = memo(function TimeCalendar2(props) {
3056
3038
  const {
3057
3039
  value,
3058
3040
  defaultValue,
@@ -3062,25 +3044,16 @@ var TimeCalendarBase = memo(function TimeCalendar(props) {
3062
3044
  className,
3063
3045
  children,
3064
3046
  readOnly = false,
3065
- open: controlledOpen,
3066
- onOpenChange,
3067
- closeOnSelect = true,
3068
- triggerRef,
3069
- triggerSelector,
3070
- offset,
3071
- placement,
3072
- matchTriggerWidth,
3073
- variant,
3074
3047
  ...rest
3075
3048
  } = props;
3076
- const [internalOpen, setInternalOpen] = useState(false);
3077
- const isOpen = controlledOpen ?? internalOpen;
3078
- const handleOpenChange = useEventCallback((newOpen) => {
3079
- if (controlledOpen === void 0) {
3080
- setInternalOpen(newOpen);
3081
- }
3082
- onOpenChange == null ? void 0 : onOpenChange(newOpen);
3083
- });
3049
+ const scrollRef = useRef(null);
3050
+ const elementsRef = useRef([]);
3051
+ const customElementRef = useRef(null);
3052
+ const hasInitialScrolled = useRef(false);
3053
+ const lastSelectedIndexRef = useRef(null);
3054
+ const isInternalOperationRef = useRef(false);
3055
+ const [activeIndex, setActiveIndex] = useState(null);
3056
+ const [isScrolling, setIsScrolling] = useState(false);
3084
3057
  const [innerValue, setValue] = useMergedValue({
3085
3058
  value,
3086
3059
  defaultValue,
@@ -3096,7 +3069,7 @@ var TimeCalendarBase = memo(function TimeCalendar(props) {
3096
3069
  const formatTo12Hour = useCallback((timeStr) => {
3097
3070
  const [hour, minute] = timeStr.split(":").map(Number);
3098
3071
  const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
3099
- const ampm = hour < 12 ? "am" : "pm";
3072
+ const ampm = hour < 12 ? "AM" : "PM";
3100
3073
  return `${displayHour}:${minute.toString().padStart(2, "0")} ${ampm}`;
3101
3074
  }, []);
3102
3075
  const customTimeOption = useMemo(() => {
@@ -3123,95 +3096,222 @@ var TimeCalendarBase = memo(function TimeCalendar(props) {
3123
3096
  },
3124
3097
  [timeFormat]
3125
3098
  );
3099
+ const selectedIndex = useMemo(() => {
3100
+ if (!normalizedTimeString) return null;
3101
+ const index = timeOptions.findIndex((option) => option.value === normalizedTimeString);
3102
+ return index === -1 ? -1 : index;
3103
+ }, [normalizedTimeString, timeOptions]);
3126
3104
  const needsDivider = useMemo(() => {
3127
3105
  const is12Hour = timeFormat.toLowerCase().includes("a") || timeFormat === "12h";
3128
3106
  if (!is12Hour) return () => false;
3129
3107
  return (index) => {
3130
- return index > 0 && timeOptions[index].label.toLowerCase().includes("pm") && timeOptions[index - 1].label.toLowerCase().includes("am");
3108
+ return index > 0 && timeOptions[index].label.includes("PM") && timeOptions[index - 1].label.includes("AM");
3131
3109
  };
3132
3110
  }, [timeFormat, timeOptions]);
3133
3111
  const createPrefixElement = useCallback((isSelected) => {
3134
3112
  return isSelected ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(Fragment, {});
3135
3113
  }, []);
3114
+ const scrollTimeoutRef = useRef(null);
3115
+ const mousePositionRef = useRef(null);
3116
+ const handleScroll = useEventCallback(() => {
3117
+ if (!isScrolling) {
3118
+ setIsScrolling(true);
3119
+ setActiveIndex(null);
3120
+ }
3121
+ if (scrollTimeoutRef.current) {
3122
+ clearTimeout(scrollTimeoutRef.current);
3123
+ }
3124
+ scrollTimeoutRef.current = setTimeout(() => {
3125
+ var _a;
3126
+ setIsScrolling(false);
3127
+ if (mousePositionRef.current) {
3128
+ const elementUnderMouse = document.elementFromPoint(
3129
+ mousePositionRef.current.x,
3130
+ mousePositionRef.current.y
3131
+ );
3132
+ if (customElementRef.current && (customElementRef.current === elementUnderMouse || customElementRef.current.contains(elementUnderMouse))) {
3133
+ setActiveIndex(-1);
3134
+ return;
3135
+ }
3136
+ const elements = elementsRef.current;
3137
+ for (let i = 0; i < elements.length; i++) {
3138
+ if (elements[i] && (elements[i] === elementUnderMouse || ((_a = elements[i]) == null ? void 0 : _a.contains(elementUnderMouse)))) {
3139
+ setActiveIndex(i);
3140
+ break;
3141
+ }
3142
+ }
3143
+ }
3144
+ }, 200);
3145
+ });
3146
+ const handleMouseMove = useEventCallback((event) => {
3147
+ mousePositionRef.current = { x: event.clientX, y: event.clientY };
3148
+ });
3136
3149
  useEffect(() => {
3137
- if (!isOpen || !normalizedTimeString) return;
3138
- let attempts = 0;
3139
- const maxAttempts = 10;
3140
- const scrollToSelected = () => {
3141
- const selectedItem = document.querySelector(
3142
- `[data-testid="${normalizedTimeString}"]`
3143
- );
3144
- if (selectedItem) {
3145
- selectedItem.scrollIntoView({ block: "center" });
3146
- } else if (attempts < maxAttempts) {
3147
- attempts++;
3148
- requestAnimationFrame(scrollToSelected);
3150
+ return () => {
3151
+ if (scrollTimeoutRef.current) {
3152
+ clearTimeout(scrollTimeoutRef.current);
3149
3153
  }
3150
3154
  };
3151
- requestAnimationFrame(scrollToSelected);
3152
- }, [isOpen, normalizedTimeString]);
3155
+ }, []);
3156
+ useEffect(() => {
3157
+ var _a;
3158
+ if (selectedIndex === -1) {
3159
+ const customElement = customElementRef.current;
3160
+ if (!customElement || !scrollRef.current) {
3161
+ return;
3162
+ }
3163
+ const previousSelectedIndex2 = lastSelectedIndexRef.current;
3164
+ const isSelectedIndexChanged2 = previousSelectedIndex2 !== selectedIndex;
3165
+ lastSelectedIndexRef.current = selectedIndex;
3166
+ const shouldScroll2 = !hasInitialScrolled.current || // Initial scrolling
3167
+ isSelectedIndexChanged2 && !isInternalOperationRef.current;
3168
+ if (shouldScroll2) {
3169
+ const isInitialScroll = !hasInitialScrolled.current;
3170
+ if (isInitialScroll) {
3171
+ scrollRef.current.scrollTo({
3172
+ top: 0,
3173
+ behavior: "auto"
3174
+ });
3175
+ } else {
3176
+ customElement.scrollIntoView({
3177
+ block: "nearest",
3178
+ behavior: "smooth"
3179
+ });
3180
+ }
3181
+ if (!hasInitialScrolled.current) {
3182
+ hasInitialScrolled.current = true;
3183
+ }
3184
+ }
3185
+ if (isInternalOperationRef.current) {
3186
+ isInternalOperationRef.current = false;
3187
+ }
3188
+ return;
3189
+ }
3190
+ if (selectedIndex === null || !scrollRef.current || !elementsRef.current[selectedIndex]) {
3191
+ return;
3192
+ }
3193
+ const previousSelectedIndex = lastSelectedIndexRef.current;
3194
+ const isSelectedIndexChanged = previousSelectedIndex !== selectedIndex;
3195
+ lastSelectedIndexRef.current = selectedIndex;
3196
+ const shouldScroll = !hasInitialScrolled.current || // Initial scrolling
3197
+ isSelectedIndexChanged && !isInternalOperationRef.current;
3198
+ if (shouldScroll) {
3199
+ const isInitialScroll = !hasInitialScrolled.current;
3200
+ if (isInitialScroll) {
3201
+ (_a = elementsRef.current[selectedIndex]) == null ? void 0 : _a.scrollIntoView({
3202
+ block: "center",
3203
+ behavior: "auto"
3204
+ });
3205
+ } else {
3206
+ const container = scrollRef.current;
3207
+ const element = elementsRef.current[selectedIndex];
3208
+ if (container && element) {
3209
+ const containerRect = container.getBoundingClientRect();
3210
+ const elementRect = element.getBoundingClientRect();
3211
+ const margin = 8;
3212
+ const elementTop = elementRect.top - containerRect.top + container.scrollTop;
3213
+ const elementBottom = elementTop + elementRect.height;
3214
+ const visibleTop = container.scrollTop + margin;
3215
+ const visibleBottom = container.scrollTop + container.clientHeight - margin;
3216
+ let targetScrollTop = container.scrollTop;
3217
+ if (elementTop < visibleTop) {
3218
+ targetScrollTop = elementTop - margin;
3219
+ } else if (elementBottom > visibleBottom) {
3220
+ targetScrollTop = elementBottom - container.clientHeight + margin;
3221
+ }
3222
+ if (targetScrollTop !== container.scrollTop) {
3223
+ container.scrollTo({
3224
+ top: targetScrollTop
3225
+ });
3226
+ }
3227
+ }
3228
+ }
3229
+ if (!hasInitialScrolled.current) {
3230
+ hasInitialScrolled.current = true;
3231
+ }
3232
+ }
3233
+ if (isInternalOperationRef.current) {
3234
+ isInternalOperationRef.current = false;
3235
+ }
3236
+ }, [selectedIndex]);
3153
3237
  const handleTimeSelect = useEventCallback((timeValue) => {
3154
3238
  if (readOnly) return;
3239
+ isInternalOperationRef.current = true;
3155
3240
  const dateValue = timeStringToDate(timeValue);
3156
3241
  setValue(dateValue);
3157
- if (closeOnSelect) {
3158
- handleOpenChange(false);
3242
+ });
3243
+ const handleMouseEnter = useEventCallback((index) => {
3244
+ if (isScrolling) {
3245
+ return;
3159
3246
  }
3247
+ setActiveIndex(index);
3248
+ });
3249
+ const handleMouseLeave = useEventCallback(() => {
3250
+ setActiveIndex(null);
3251
+ });
3252
+ const handleClick = useEventCallback((timeValue) => {
3253
+ handleTimeSelect(timeValue);
3160
3254
  });
3161
3255
  return /* @__PURE__ */ jsxs(
3162
- Dropdown2,
3256
+ Menus,
3163
3257
  {
3164
- open: isOpen,
3165
- onOpenChange: handleOpenChange,
3166
- selection: true,
3167
- triggerRef,
3168
- triggerSelector,
3169
- offset,
3170
- placement,
3171
- matchTriggerWidth,
3172
- variant,
3173
- readOnly,
3258
+ ref: scrollRef,
3259
+ onScroll: handleScroll,
3260
+ onMouseLeave: handleMouseLeave,
3261
+ onMouseMove: handleMouseMove,
3262
+ className,
3263
+ "data-testid": "time-calendar-menu",
3174
3264
  ...rest,
3175
3265
  children: [
3176
- children,
3177
- /* @__PURE__ */ jsxs(Dropdown2.Content, { className, children: [
3178
- customTimeOption && /* @__PURE__ */ jsxs(Fragment, { children: [
3266
+ customTimeOption && /* @__PURE__ */ jsxs(Fragment, { children: [
3267
+ /* @__PURE__ */ jsx(
3268
+ Menus.Item,
3269
+ {
3270
+ ref: (node) => {
3271
+ customElementRef.current = node;
3272
+ },
3273
+ selected: selectedIndex === -1,
3274
+ active: !isScrolling && activeIndex === -1,
3275
+ onClick: () => handleClick(customTimeOption.value),
3276
+ onMouseEnter: () => handleMouseEnter(-1),
3277
+ prefixElement: createPrefixElement(selectedIndex === -1),
3278
+ variant: "highlight",
3279
+ "data-testid": "custom-time-item",
3280
+ children: renderTimeLabel(customTimeOption.label)
3281
+ }
3282
+ ),
3283
+ /* @__PURE__ */ jsx(Menus.Divider, { "data-testid": "custom-time-divider" })
3284
+ ] }),
3285
+ timeOptions.map((option, index) => {
3286
+ const isAmToPmTransition = needsDivider(index);
3287
+ const isItemSelected = selectedIndex === index;
3288
+ const isItemActive = !isScrolling && activeIndex === index;
3289
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
3290
+ isAmToPmTransition && /* @__PURE__ */ jsx(Menus.Divider, { "data-testid": "ampm-divider" }),
3179
3291
  /* @__PURE__ */ jsx(
3180
- Dropdown2.Item,
3292
+ Menus.Item,
3181
3293
  {
3182
- onMouseUp: () => handleTimeSelect(customTimeOption.value),
3183
- prefixElement: createPrefixElement(normalizedTimeString === customTimeOption.value),
3184
- "data-testid": "custom-time-item",
3185
- children: renderTimeLabel(customTimeOption.label)
3294
+ ref: (node) => {
3295
+ elementsRef.current[index] = node;
3296
+ },
3297
+ selected: isItemSelected,
3298
+ active: isItemActive,
3299
+ onClick: () => handleClick(option.value),
3300
+ onMouseEnter: () => handleMouseEnter(index),
3301
+ prefixElement: createPrefixElement(isItemSelected),
3302
+ variant: "highlight",
3303
+ "data-testid": option.value,
3304
+ children: renderTimeLabel(option.label)
3186
3305
  }
3187
- ),
3188
- /* @__PURE__ */ jsx(Dropdown2.Divider, { "data-testid": "custom-time-divider" })
3189
- ] }),
3190
- timeOptions.map((option, index) => {
3191
- const isAmToPmTransition = needsDivider(index);
3192
- const isSelected = normalizedTimeString === option.value;
3193
- return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
3194
- isAmToPmTransition && /* @__PURE__ */ jsx(Dropdown2.Divider, { "data-testid": "ampm-divider" }),
3195
- /* @__PURE__ */ jsx(
3196
- Dropdown2.Item,
3197
- {
3198
- onMouseUp: () => handleTimeSelect(option.value),
3199
- prefixElement: createPrefixElement(isSelected),
3200
- "data-testid": option.value,
3201
- children: renderTimeLabel(option.label)
3202
- }
3203
- )
3204
- ] }, option.value);
3205
- })
3206
- ] })
3306
+ )
3307
+ ] }, option.value);
3308
+ }),
3309
+ children
3207
3310
  ]
3208
3311
  }
3209
3312
  );
3210
3313
  });
3211
- TimeCalendarBase.displayName = "TimeCalendar";
3212
- Object.assign(TimeCalendarBase, {
3213
- Trigger: MenuTrigger
3214
- });
3314
+ TimeCalendar.displayName = "TimeCalendar";
3215
3315
  function useTimeInput(props) {
3216
3316
  const {
3217
3317
  value,
@@ -4429,6 +4529,7 @@ export {
4429
4529
  LOCALE_MAP,
4430
4530
  MonthCalendar,
4431
4531
  QuarterCalendar,
4532
+ TimeCalendar,
4432
4533
  TimeInput,
4433
4534
  YearCalendar,
4434
4535
  calculateWeekNumbers,
@@ -13,8 +13,9 @@ declare const DialogTrigger: react.MemoExoticComponent<react.ForwardRefExoticCom
13
13
 
14
14
  type DialogPosition = "left-top" | "center-top" | "right-top" | "left-center" | "center" | "right-center" | "left-bottom" | "center-bottom" | "right-bottom";
15
15
 
16
- interface DialogProps {
16
+ interface DialogProps extends Omit<react__default.HTMLAttributes<HTMLElement>, "title"> {
17
17
  afterOpenChange?: (isOpen: boolean) => void;
18
+ as?: react__default.ElementType;
18
19
  children?: react__default.ReactNode;
19
20
  className?: string;
20
21
  closeOnEscape?: boolean;
@@ -645,6 +645,7 @@ var dragDialogTv = tcv({
645
645
  });
646
646
  var PORTAL_ROOT_ID = "floating-modal-root";
647
647
  var DialogComponent = memo(function DialogComponent2({
648
+ as,
648
649
  className,
649
650
  children,
650
651
  closeOnEscape = true,
@@ -667,7 +668,8 @@ var DialogComponent = memo(function DialogComponent2({
667
668
  rememberSize = false,
668
669
  focusManagerProps = { initialFocus: 1 },
669
670
  transitionStylesProps,
670
- root
671
+ root,
672
+ ...restProps
671
673
  }) {
672
674
  const dialogRef = useRef(null);
673
675
  const contentRef = useRef(null);
@@ -829,9 +831,11 @@ var DialogComponent = memo(function DialogComponent2({
829
831
  floating.refs.setFloating(node);
830
832
  }
831
833
  },
834
+ as,
832
835
  style: getStyleWithDefaults,
833
836
  className: tcx(style.dialog(), className),
834
837
  ...floating.getFloatingProps(),
838
+ ...restProps,
835
839
  "aria-labelledby": titleId,
836
840
  "aria-describedby": descriptionId,
837
841
  role: "dialog",
@@ -3,8 +3,9 @@ import { FloatingFocusManagerProps, UseTransitionStylesProps } from '@floating-u
3
3
  import { default as React } from 'react';
4
4
  import { DialogHeader, DialogTrigger } from './components';
5
5
  import { DialogPosition } from './types';
6
- export interface DialogProps {
6
+ export interface DialogProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
7
7
  afterOpenChange?: (isOpen: boolean) => void;
8
+ as?: React.ElementType;
8
9
  children?: React.ReactNode;
9
10
  className?: string;
10
11
  closeOnEscape?: boolean;
@@ -14,6 +14,7 @@ import { findChildByType } from "../../../shared/utils/assertion.js";
14
14
  import { tcx } from "../../../shared/utils/tcx/tcx.js";
15
15
  const PORTAL_ROOT_ID = "floating-modal-root";
16
16
  const DialogComponent = memo(function DialogComponent2({
17
+ as,
17
18
  className,
18
19
  children,
19
20
  closeOnEscape = true,
@@ -36,7 +37,8 @@ const DialogComponent = memo(function DialogComponent2({
36
37
  rememberSize = false,
37
38
  focusManagerProps = { initialFocus: 1 },
38
39
  transitionStylesProps,
39
- root
40
+ root,
41
+ ...restProps
40
42
  }) {
41
43
  const dialogRef = useRef(null);
42
44
  const contentRef = useRef(null);
@@ -198,9 +200,11 @@ const DialogComponent = memo(function DialogComponent2({
198
200
  floating.refs.setFloating(node);
199
201
  }
200
202
  },
203
+ as,
201
204
  style: getStyleWithDefaults,
202
205
  className: tcx(style.dialog(), className),
203
206
  ...floating.getFloatingProps(),
207
+ ...restProps,
204
208
  "aria-labelledby": titleId,
205
209
  "aria-describedby": descriptionId,
206
210
  role: "dialog",
@@ -279,52 +279,27 @@ var DropdownComponent = memo(function DropdownComponent2(props) {
279
279
  }),
280
280
  [activeIndex, getItemProps, handleClose, isControlledOpen, readOnly, selection, variant]
281
281
  );
282
- const parentActiveIndex = parent == null ? void 0 : parent.activeIndex;
283
- const parentGetItemProps = parent == null ? void 0 : parent.getItemProps;
284
- const slotProps = useMemo(() => {
285
- const referenceProps = getReferenceProps(
286
- parentGetItemProps ? parentGetItemProps({
287
- onFocus: handleFocus
288
- }) : {}
289
- );
290
- return {
291
- tabIndex: !isNested ? void 0 : parentActiveIndex === item.index ? 0 : -1,
292
- role: isNested ? "menuitem" : void 0,
293
- "data-open": isControlledOpen ? "" : void 0,
294
- "data-nested": isNested ? "" : void 0,
295
- "data-focus-inside": hasFocusInside ? "" : void 0,
296
- onTouchStart: handleTouchStart,
297
- onPointerMove: handlePointerMove,
298
- "aria-haspopup": "menu",
299
- "aria-expanded": isControlledOpen,
300
- "aria-controls": menuId,
301
- ...referenceProps
302
- };
303
- }, [
304
- isNested,
305
- parentActiveIndex,
306
- parentGetItemProps,
307
- item.index,
308
- isControlledOpen,
309
- hasFocusInside,
310
- handleTouchStart,
311
- handlePointerMove,
312
- menuId,
313
- getReferenceProps,
314
- handleFocus
315
- ]);
316
- const slotChildren = useMemo(() => {
317
- const element = isNested ? subTriggerElement : triggerElement;
318
- if (!element) return null;
319
- return cloneElement(element, { active: isControlledOpen });
320
- }, [isNested, subTriggerElement, triggerElement, isControlledOpen]);
321
282
  return /* @__PURE__ */ jsxs(FloatingNode, { id: nodeId, children: [
322
283
  !isCoordinateMode && !hasExternalTrigger && /* @__PURE__ */ jsx(
323
284
  Slot,
324
285
  {
325
286
  ref: refs.setReference,
326
- ...slotProps,
327
- children: slotChildren
287
+ tabIndex: !isNested ? void 0 : (parent == null ? void 0 : parent.activeIndex) === item.index ? 0 : -1,
288
+ role: isNested ? "menuitem" : void 0,
289
+ "data-open": isControlledOpen ? "" : void 0,
290
+ "data-nested": isNested ? "" : void 0,
291
+ "data-focus-inside": hasFocusInside ? "" : void 0,
292
+ onTouchStart: handleTouchStart,
293
+ onPointerMove: handlePointerMove,
294
+ "aria-haspopup": "menu",
295
+ "aria-expanded": isControlledOpen,
296
+ "aria-controls": menuId,
297
+ ...getReferenceProps(
298
+ parent ? parent.getItemProps({
299
+ onFocus: handleFocus
300
+ }) : {}
301
+ ),
302
+ children: isNested ? subTriggerElement && cloneElement(subTriggerElement, { active: isControlledOpen }) : triggerElement && cloneElement(triggerElement, { active: isControlledOpen })
328
303
  }
329
304
  ),
330
305
  /* @__PURE__ */ jsx(