@choice-ui/react 1.5.6 → 1.5.8

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.
@@ -1,11 +1,12 @@
1
1
  import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
2
  import { Check } from "@choiceform/icons-react";
3
- import { Menus } from "../../../menus/dist/index.js";
4
- import React__default, { memo, useRef, useState, useMemo, useCallback, useEffect } from "react";
3
+ import { Dropdown as Dropdown2 } from "../../../dropdown/dist/index.js";
4
+ import { MenuTrigger } from "../../../menus/dist/index.js";
5
+ import React__default, { memo, useState, useMemo, useCallback } from "react";
5
6
  import { useEventCallback } from "usehooks-ts";
6
7
  import { generateTimeOptions, normalizeTimeValue, timeStringToDate } from "../utils/time.js";
7
8
  import { useMergedValue } from "../../../../shared/hooks/use-merged-value/use-merged-value.js";
8
- const TimeCalendar = memo(function TimeCalendar2(props) {
9
+ const TimeCalendarBase = memo(function TimeCalendar2(props) {
9
10
  const {
10
11
  value,
11
12
  defaultValue,
@@ -15,16 +16,21 @@ const TimeCalendar = memo(function TimeCalendar2(props) {
15
16
  className,
16
17
  children,
17
18
  readOnly = false,
19
+ open: controlledOpen,
20
+ onOpenChange,
21
+ closeOnSelect = true,
22
+ triggerRef,
23
+ triggerSelector,
18
24
  ...rest
19
25
  } = props;
20
- const scrollRef = useRef(null);
21
- const elementsRef = useRef([]);
22
- const customElementRef = useRef(null);
23
- const hasInitialScrolled = useRef(false);
24
- const lastSelectedIndexRef = useRef(null);
25
- const isInternalOperationRef = useRef(false);
26
- const [activeIndex, setActiveIndex] = useState(null);
27
- const [isScrolling, setIsScrolling] = useState(false);
26
+ const [internalOpen, setInternalOpen] = useState(false);
27
+ const isOpen = controlledOpen ?? internalOpen;
28
+ const handleOpenChange = useEventCallback((newOpen) => {
29
+ if (controlledOpen === void 0) {
30
+ setInternalOpen(newOpen);
31
+ }
32
+ onOpenChange == null ? void 0 : onOpenChange(newOpen);
33
+ });
28
34
  const [innerValue, setValue] = useMergedValue({
29
35
  value,
30
36
  defaultValue,
@@ -40,7 +46,7 @@ const TimeCalendar = memo(function TimeCalendar2(props) {
40
46
  const formatTo12Hour = useCallback((timeStr) => {
41
47
  const [hour, minute] = timeStr.split(":").map(Number);
42
48
  const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
43
- const ampm = hour < 12 ? "AM" : "PM";
49
+ const ampm = hour < 12 ? "am" : "pm";
44
50
  return `${displayHour}:${minute.toString().padStart(2, "0")} ${ampm}`;
45
51
  }, []);
46
52
  const customTimeOption = useMemo(() => {
@@ -67,222 +73,73 @@ const TimeCalendar = memo(function TimeCalendar2(props) {
67
73
  },
68
74
  [timeFormat]
69
75
  );
70
- const selectedIndex = useMemo(() => {
71
- if (!normalizedTimeString) return null;
72
- const index = timeOptions.findIndex((option) => option.value === normalizedTimeString);
73
- return index === -1 ? -1 : index;
74
- }, [normalizedTimeString, timeOptions]);
75
76
  const needsDivider = useMemo(() => {
76
77
  const is12Hour = timeFormat.toLowerCase().includes("a") || timeFormat === "12h";
77
78
  if (!is12Hour) return () => false;
78
79
  return (index) => {
79
- return index > 0 && timeOptions[index].label.includes("PM") && timeOptions[index - 1].label.includes("AM");
80
+ return index > 0 && timeOptions[index].label.toLowerCase().includes("pm") && timeOptions[index - 1].label.toLowerCase().includes("am");
80
81
  };
81
82
  }, [timeFormat, timeOptions]);
82
83
  const createPrefixElement = useCallback((isSelected) => {
83
84
  return isSelected ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx(Fragment, {});
84
85
  }, []);
85
- const scrollTimeoutRef = useRef(null);
86
- const mousePositionRef = useRef(null);
87
- const handleScroll = useEventCallback(() => {
88
- if (!isScrolling) {
89
- setIsScrolling(true);
90
- setActiveIndex(null);
91
- }
92
- if (scrollTimeoutRef.current) {
93
- clearTimeout(scrollTimeoutRef.current);
94
- }
95
- scrollTimeoutRef.current = setTimeout(() => {
96
- var _a;
97
- setIsScrolling(false);
98
- if (mousePositionRef.current) {
99
- const elementUnderMouse = document.elementFromPoint(
100
- mousePositionRef.current.x,
101
- mousePositionRef.current.y
102
- );
103
- if (customElementRef.current && (customElementRef.current === elementUnderMouse || customElementRef.current.contains(elementUnderMouse))) {
104
- setActiveIndex(-1);
105
- return;
106
- }
107
- const elements = elementsRef.current;
108
- for (let i = 0; i < elements.length; i++) {
109
- if (elements[i] && (elements[i] === elementUnderMouse || ((_a = elements[i]) == null ? void 0 : _a.contains(elementUnderMouse)))) {
110
- setActiveIndex(i);
111
- break;
112
- }
113
- }
114
- }
115
- }, 200);
116
- });
117
- const handleMouseMove = useEventCallback((event) => {
118
- mousePositionRef.current = { x: event.clientX, y: event.clientY };
119
- });
120
- useEffect(() => {
121
- return () => {
122
- if (scrollTimeoutRef.current) {
123
- clearTimeout(scrollTimeoutRef.current);
124
- }
125
- };
126
- }, []);
127
- useEffect(() => {
128
- var _a;
129
- if (selectedIndex === -1) {
130
- const customElement = customElementRef.current;
131
- if (!customElement || !scrollRef.current) {
132
- return;
133
- }
134
- const previousSelectedIndex2 = lastSelectedIndexRef.current;
135
- const isSelectedIndexChanged2 = previousSelectedIndex2 !== selectedIndex;
136
- lastSelectedIndexRef.current = selectedIndex;
137
- const shouldScroll2 = !hasInitialScrolled.current || // Initial scrolling
138
- isSelectedIndexChanged2 && !isInternalOperationRef.current;
139
- if (shouldScroll2) {
140
- const isInitialScroll = !hasInitialScrolled.current;
141
- if (isInitialScroll) {
142
- scrollRef.current.scrollTo({
143
- top: 0,
144
- behavior: "auto"
145
- });
146
- } else {
147
- customElement.scrollIntoView({
148
- block: "nearest",
149
- behavior: "smooth"
150
- });
151
- }
152
- if (!hasInitialScrolled.current) {
153
- hasInitialScrolled.current = true;
154
- }
155
- }
156
- if (isInternalOperationRef.current) {
157
- isInternalOperationRef.current = false;
158
- }
159
- return;
160
- }
161
- if (selectedIndex === null || !scrollRef.current || !elementsRef.current[selectedIndex]) {
162
- return;
163
- }
164
- const previousSelectedIndex = lastSelectedIndexRef.current;
165
- const isSelectedIndexChanged = previousSelectedIndex !== selectedIndex;
166
- lastSelectedIndexRef.current = selectedIndex;
167
- const shouldScroll = !hasInitialScrolled.current || // Initial scrolling
168
- isSelectedIndexChanged && !isInternalOperationRef.current;
169
- if (shouldScroll) {
170
- const isInitialScroll = !hasInitialScrolled.current;
171
- if (isInitialScroll) {
172
- (_a = elementsRef.current[selectedIndex]) == null ? void 0 : _a.scrollIntoView({
173
- block: "center",
174
- behavior: "auto"
175
- });
176
- } else {
177
- const container = scrollRef.current;
178
- const element = elementsRef.current[selectedIndex];
179
- if (container && element) {
180
- const containerRect = container.getBoundingClientRect();
181
- const elementRect = element.getBoundingClientRect();
182
- const margin = 8;
183
- const elementTop = elementRect.top - containerRect.top + container.scrollTop;
184
- const elementBottom = elementTop + elementRect.height;
185
- const visibleTop = container.scrollTop + margin;
186
- const visibleBottom = container.scrollTop + container.clientHeight - margin;
187
- let targetScrollTop = container.scrollTop;
188
- if (elementTop < visibleTop) {
189
- targetScrollTop = elementTop - margin;
190
- } else if (elementBottom > visibleBottom) {
191
- targetScrollTop = elementBottom - container.clientHeight + margin;
192
- }
193
- if (targetScrollTop !== container.scrollTop) {
194
- container.scrollTo({
195
- top: targetScrollTop
196
- });
197
- }
198
- }
199
- }
200
- if (!hasInitialScrolled.current) {
201
- hasInitialScrolled.current = true;
202
- }
203
- }
204
- if (isInternalOperationRef.current) {
205
- isInternalOperationRef.current = false;
206
- }
207
- }, [selectedIndex]);
208
86
  const handleTimeSelect = useEventCallback((timeValue) => {
209
87
  if (readOnly) return;
210
- isInternalOperationRef.current = true;
211
88
  const dateValue = timeStringToDate(timeValue);
212
89
  setValue(dateValue);
213
- });
214
- const handleMouseEnter = useEventCallback((index) => {
215
- if (isScrolling) {
216
- return;
90
+ if (closeOnSelect) {
91
+ handleOpenChange(false);
217
92
  }
218
- setActiveIndex(index);
219
- });
220
- const handleMouseLeave = useEventCallback(() => {
221
- setActiveIndex(null);
222
- });
223
- const handleClick = useEventCallback((timeValue) => {
224
- handleTimeSelect(timeValue);
225
93
  });
226
94
  return /* @__PURE__ */ jsxs(
227
- Menus,
95
+ Dropdown2,
228
96
  {
229
- ref: scrollRef,
230
- onScroll: handleScroll,
231
- onMouseLeave: handleMouseLeave,
232
- onMouseMove: handleMouseMove,
233
- className,
234
- "data-testid": "time-calendar-menu",
97
+ open: isOpen,
98
+ onOpenChange: handleOpenChange,
99
+ selection: true,
100
+ triggerRef,
101
+ triggerSelector,
235
102
  ...rest,
236
103
  children: [
237
- customTimeOption && /* @__PURE__ */ jsxs(Fragment, { children: [
238
- /* @__PURE__ */ jsx(
239
- Menus.Item,
240
- {
241
- ref: (node) => {
242
- customElementRef.current = node;
243
- },
244
- selected: selectedIndex === -1,
245
- active: !isScrolling && activeIndex === -1,
246
- onClick: () => handleClick(customTimeOption.value),
247
- onMouseEnter: () => handleMouseEnter(-1),
248
- prefixElement: createPrefixElement(selectedIndex === -1),
249
- variant: "highlight",
250
- "data-testid": "custom-time-item",
251
- children: renderTimeLabel(customTimeOption.label)
252
- }
253
- ),
254
- /* @__PURE__ */ jsx(Menus.Divider, { "data-testid": "custom-time-divider" })
255
- ] }),
256
- timeOptions.map((option, index) => {
257
- const isAmToPmTransition = needsDivider(index);
258
- const isItemSelected = selectedIndex === index;
259
- const isItemActive = !isScrolling && activeIndex === index;
260
- return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
261
- isAmToPmTransition && /* @__PURE__ */ jsx(Menus.Divider, { "data-testid": "ampm-divider" }),
104
+ children,
105
+ /* @__PURE__ */ jsxs(Dropdown2.Content, { className, children: [
106
+ customTimeOption && /* @__PURE__ */ jsxs(Fragment, { children: [
262
107
  /* @__PURE__ */ jsx(
263
- Menus.Item,
108
+ Dropdown2.Item,
264
109
  {
265
- ref: (node) => {
266
- elementsRef.current[index] = node;
267
- },
268
- selected: isItemSelected,
269
- active: isItemActive,
270
- onClick: () => handleClick(option.value),
271
- onMouseEnter: () => handleMouseEnter(index),
272
- prefixElement: createPrefixElement(isItemSelected),
273
- variant: "highlight",
274
- "data-testid": option.value,
275
- children: renderTimeLabel(option.label)
110
+ onMouseUp: () => handleTimeSelect(customTimeOption.value),
111
+ prefixElement: createPrefixElement(normalizedTimeString === customTimeOption.value),
112
+ "data-testid": "custom-time-item",
113
+ children: renderTimeLabel(customTimeOption.label)
276
114
  }
277
- )
278
- ] }, option.value);
279
- }),
280
- children
115
+ ),
116
+ /* @__PURE__ */ jsx(Dropdown2.Divider, { "data-testid": "custom-time-divider" })
117
+ ] }),
118
+ timeOptions.map((option, index) => {
119
+ const isAmToPmTransition = needsDivider(index);
120
+ const isSelected = normalizedTimeString === option.value;
121
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
122
+ isAmToPmTransition && /* @__PURE__ */ jsx(Dropdown2.Divider, { "data-testid": "ampm-divider" }),
123
+ /* @__PURE__ */ jsx(
124
+ Dropdown2.Item,
125
+ {
126
+ onMouseUp: () => handleTimeSelect(option.value),
127
+ prefixElement: createPrefixElement(isSelected),
128
+ "data-testid": option.value,
129
+ children: renderTimeLabel(option.label)
130
+ }
131
+ )
132
+ ] }, option.value);
133
+ })
134
+ ] })
281
135
  ]
282
136
  }
283
137
  );
284
138
  });
285
- TimeCalendar.displayName = "TimeCalendar";
139
+ TimeCalendarBase.displayName = "TimeCalendar";
140
+ const TimeCalendar = Object.assign(TimeCalendarBase, {
141
+ Trigger: MenuTrigger
142
+ });
286
143
  export {
287
144
  TimeCalendar
288
145
  };
@@ -241,7 +241,7 @@ const generateTimeOptions = (format2, step = 15) => {
241
241
  const minutes = i % 60;
242
242
  if (is12Hour) {
243
243
  const displayHour = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
244
- const ampm = hours < 12 ? "AM" : "PM";
244
+ const ampm = hours < 12 ? "am" : "pm";
245
245
  const value = `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
246
246
  const label = `${displayHour}:${minutes.toString().padStart(2, "0")} ${ampm}`;
247
247
  options.push({ value, label });
@@ -279,27 +279,52 @@ 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]);
282
321
  return /* @__PURE__ */ jsxs(FloatingNode, { id: nodeId, children: [
283
322
  !isCoordinateMode && !hasExternalTrigger && /* @__PURE__ */ jsx(
284
323
  Slot,
285
324
  {
286
325
  ref: refs.setReference,
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 })
326
+ ...slotProps,
327
+ children: slotChildren
303
328
  }
304
329
  ),
305
330
  /* @__PURE__ */ jsx(
@@ -279,27 +279,52 @@ const 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]);
282
321
  return /* @__PURE__ */ jsxs(FloatingNode, { id: nodeId, children: [
283
322
  !isCoordinateMode && !hasExternalTrigger && /* @__PURE__ */ jsx(
284
323
  Slot,
285
324
  {
286
325
  ref: refs.setReference,
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 })
326
+ ...slotProps,
327
+ children: slotChildren
303
328
  }
304
329
  ),
305
330
  /* @__PURE__ */ jsx(
@@ -1,13 +1,13 @@
1
1
  import { Button } from "../../button/dist/index.js";
2
- import React__default, { forwardRef, memo, useContext, createContext, useMemo, startTransition, useCallback, useRef, Children, isValidElement, Fragment as Fragment$1, useState, useEffect } from "react";
3
- import { jsx, Fragment, jsxs } from "react/jsx-runtime";
4
- import { Check, ChevronRightSmall, ChevronDownSmall, ChevronUpSmall } from "@choiceform/icons-react";
2
+ import React__default, { memo, forwardRef, useMemo, useContext, createContext, startTransition, useCallback, useRef, useState, useEffect, Children, isValidElement, Fragment as Fragment$1 } from "react";
3
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
4
+ import { ChevronDownSmall, Check, ChevronRightSmall, ChevronUpSmall } from "@choiceform/icons-react";
5
5
  import { Kbd } from "../../kbd/dist/index.js";
6
6
  import { flushSync } from "react-dom";
7
7
  import { SearchInput } from "../../search-input/dist/index.js";
8
8
  import { Slot } from "../../slot/dist/index.js";
9
- import { Input } from "../../input/dist/index.js";
10
9
  import { useEventCallback } from "usehooks-ts";
10
+ import { Input } from "../../input/dist/index.js";
11
11
  import { useListItem, useFloatingTree, useFloatingNodeId, useFloatingParentNodeId } from "@floating-ui/react";
12
12
  import { useIsomorphicLayoutEffect } from "../../../shared/hooks/use-isomorphic-layout-effect/use-isomorphic-layout-effect.js";
13
13
  import { tcv, tcx } from "../../../shared/utils/tcx/tcx.js";
@@ -638,24 +638,29 @@ var MenuTrigger = memo(
638
638
  isEmpty: empty,
639
639
  size: size2
640
640
  });
641
- const slotProps = enterForwardedProps ? {
642
- ...rest,
643
- active,
644
- selected,
645
- disabled,
646
- onClick: (e) => {
647
- e.stopPropagation();
648
- e.preventDefault();
649
- if (rest.onClick) {
650
- rest.onClick(e);
651
- }
641
+ const handleClick = useEventCallback((e) => {
642
+ var _a;
643
+ e.stopPropagation();
644
+ e.preventDefault();
645
+ (_a = rest.onClick) == null ? void 0 : _a.call(rest, e);
646
+ });
647
+ const slotProps = useMemo(() => {
648
+ if (enterForwardedProps) {
649
+ return {
650
+ ...rest,
651
+ active,
652
+ selected,
653
+ disabled,
654
+ onClick: handleClick
655
+ };
652
656
  }
653
- } : {
654
- ...rest,
655
- ...active !== void 0 ? { "data-active": active } : {},
656
- ...selected !== void 0 ? { "data-selected": selected } : {},
657
- ...disabled !== void 0 ? { "data-disabled": disabled } : {}
658
- };
657
+ return {
658
+ ...rest,
659
+ ...active !== void 0 ? { "data-active": active } : {},
660
+ ...selected !== void 0 ? { "data-selected": selected } : {},
661
+ ...disabled !== void 0 ? { "data-disabled": disabled } : {}
662
+ };
663
+ }, [enterForwardedProps, rest, active, selected, disabled, handleClick]);
659
664
  return asChild ? /* @__PURE__ */ jsx(
660
665
  Slot,
661
666
  {
@@ -717,7 +722,7 @@ var MenuValue = memo(({ children, ...rest }) => {
717
722
  });
718
723
  MenuValue.displayName = "MenuValue";
719
724
  var MenusBase = forwardRef((props, ref) => {
720
- const { children, className, matchTriggerWidth, variant, ...rest } = props;
725
+ const { children, className, matchTriggerWidth, variant = "default", ...rest } = props;
721
726
  const tv = MenusTv({ matchTriggerWidth, variant });
722
727
  const processChildren = (children2) => {
723
728
  return Children.map(children2, (child) => {
@@ -2,7 +2,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "../../../button/dist/index.js";
3
3
  import { Slot } from "../../../slot/dist/index.js";
4
4
  import { ChevronDownSmall } from "@choiceform/icons-react";
5
- import { memo, forwardRef } from "react";
5
+ import { memo, forwardRef, useMemo } from "react";
6
+ import { useEventCallback } from "usehooks-ts";
6
7
  import { MenuTriggerTv } from "../tv.js";
7
8
  import { tcx } from "../../../../shared/utils/tcx/tcx.js";
8
9
  const MenuTrigger = memo(
@@ -28,24 +29,29 @@ const MenuTrigger = memo(
28
29
  isEmpty: empty,
29
30
  size
30
31
  });
31
- const slotProps = enterForwardedProps ? {
32
- ...rest,
33
- active,
34
- selected,
35
- disabled,
36
- onClick: (e) => {
37
- e.stopPropagation();
38
- e.preventDefault();
39
- if (rest.onClick) {
40
- rest.onClick(e);
41
- }
32
+ const handleClick = useEventCallback((e) => {
33
+ var _a;
34
+ e.stopPropagation();
35
+ e.preventDefault();
36
+ (_a = rest.onClick) == null ? void 0 : _a.call(rest, e);
37
+ });
38
+ const slotProps = useMemo(() => {
39
+ if (enterForwardedProps) {
40
+ return {
41
+ ...rest,
42
+ active,
43
+ selected,
44
+ disabled,
45
+ onClick: handleClick
46
+ };
42
47
  }
43
- } : {
44
- ...rest,
45
- ...active !== void 0 ? { "data-active": active } : {},
46
- ...selected !== void 0 ? { "data-selected": selected } : {},
47
- ...disabled !== void 0 ? { "data-disabled": disabled } : {}
48
- };
48
+ return {
49
+ ...rest,
50
+ ...active !== void 0 ? { "data-active": active } : {},
51
+ ...selected !== void 0 ? { "data-selected": selected } : {},
52
+ ...disabled !== void 0 ? { "data-disabled": disabled } : {}
53
+ };
54
+ }, [enterForwardedProps, rest, active, selected, disabled, handleClick]);
49
55
  return asChild ? /* @__PURE__ */ jsx(
50
56
  Slot,
51
57
  {
@@ -11,7 +11,7 @@ import { MenuValue } from "./components/menu-value.js";
11
11
  import { MenusTv } from "./tv.js";
12
12
  import { tcx } from "../../../shared/utils/tcx/tcx.js";
13
13
  const MenusBase = forwardRef((props, ref) => {
14
- const { children, className, matchTriggerWidth, variant, ...rest } = props;
14
+ const { children, className, matchTriggerWidth, variant = "default", ...rest } = props;
15
15
  const tv = MenusTv({ matchTriggerWidth, variant });
16
16
  const processChildren = (children2) => {
17
17
  return Children.map(children2, (child) => {
@@ -740,6 +740,21 @@ var MultiSelectComponent = memo(
740
740
  chipVariant,
741
741
  valueDisabledMap
742
742
  ]);
743
+ const handleTouchStart = useEventCallback(() => {
744
+ setTouch(true);
745
+ });
746
+ const handlePointerMove = useEventCallback(({ pointerType }) => {
747
+ if (pointerType !== "touch") {
748
+ setTouch(false);
749
+ }
750
+ });
751
+ const slotProps = useMemo(() => {
752
+ return getReferenceProps({
753
+ disabled,
754
+ onTouchStart: handleTouchStart,
755
+ onPointerMove: handlePointerMove
756
+ });
757
+ }, [getReferenceProps, disabled, handleTouchStart, handlePointerMove]);
743
758
  if (!triggerElement || !contentElement) {
744
759
  console.error(
745
760
  "MultiSelect requires both MultiSelect.Trigger and MultiSelect.Content components as children"
@@ -751,17 +766,7 @@ var MultiSelectComponent = memo(
751
766
  Slot,
752
767
  {
753
768
  ref: refs.setReference,
754
- ...getReferenceProps({
755
- disabled,
756
- onTouchStart() {
757
- setTouch(true);
758
- },
759
- onPointerMove({ pointerType }) {
760
- if (pointerType !== "touch") {
761
- setTouch(false);
762
- }
763
- }
764
- }),
769
+ ...slotProps,
765
770
  children: enhancedTriggerElement
766
771
  }
767
772
  ),