@radix-ui/react-select 2.3.8 → 2.3.9-rc.1791245332176

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.js CHANGED
@@ -94,7 +94,6 @@ var import_react_slot = require("@radix-ui/react-slot");
94
94
  var import_react_use_callback_ref = require("@radix-ui/react-use-callback-ref");
95
95
  var import_react_use_controllable_state = require("@radix-ui/react-use-controllable-state");
96
96
  var import_react_use_layout_effect = require("@radix-ui/react-use-layout-effect");
97
- var import_react_use_previous = require("@radix-ui/react-use-previous");
98
97
  var import_react_visually_hidden = require("@radix-ui/react-visually-hidden");
99
98
  var import_aria_hidden = require("aria-hidden");
100
99
  var import_react_remove_scroll = require("react-remove-scroll");
@@ -155,6 +154,11 @@ function SelectProvider(props) {
155
154
  caller: SELECT_NAME
156
155
  });
157
156
  const triggerPointerDownPosRef = React.useRef(null);
157
+ const hasConsumerStoppedPropagationRef = React.useRef(false);
158
+ const [userInteractionCount, onUserInteraction] = React.useReducer(
159
+ (count) => count + 1,
160
+ 0
161
+ );
158
162
  const initialValueRef = React.useRef(value);
159
163
  React.useEffect(() => {
160
164
  const associatedForm = form ? trigger?.ownerDocument.getElementById(form) : trigger?.form;
@@ -189,6 +193,9 @@ function SelectProvider(props) {
189
193
  contentId,
190
194
  value,
191
195
  onValueChange: setValue,
196
+ hasConsumerStoppedPropagationRef,
197
+ userInteractionCount,
198
+ onUserInteraction,
192
199
  open,
193
200
  onOpenChange: setOpen,
194
201
  dir: direction,
@@ -246,6 +253,7 @@ var SelectTrigger = /* @__PURE__ */ React.forwardRef(
246
253
  const currentItem = enabledItems.find((item) => item.value === context.value);
247
254
  const nextItem = findNextItem(enabledItems, search, currentItem);
248
255
  if (nextItem !== void 0) {
256
+ context.onUserInteraction();
249
257
  context.onValueChange(nextItem.value);
250
258
  }
251
259
  });
@@ -297,7 +305,10 @@ var SelectTrigger = /* @__PURE__ */ React.forwardRef(
297
305
  onKeyDown: (0, import_primitive.composeEventHandlers)(triggerProps.onKeyDown, (event) => {
298
306
  const isTypingAhead = searchRef.current !== "";
299
307
  const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
300
- if (!isModifierKey && event.key.length === 1) handleTypeaheadSearch(event.key);
308
+ if (!isModifierKey && event.key.length === 1) {
309
+ context.hasConsumerStoppedPropagationRef.current = event.isPropagationStopped();
310
+ handleTypeaheadSearch(event.key);
311
+ }
301
312
  if (isTypingAhead && event.key === " ") return;
302
313
  if (OPEN_KEYS.includes(event.key)) {
303
314
  handleOpen();
@@ -904,10 +915,13 @@ var SelectItem = /* @__PURE__ */ React.forwardRef(
904
915
  const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, handleItemRefCallback);
905
916
  const textId = (0, import_react_id.useId)();
906
917
  const pointerTypeRef = React.useRef("touch");
907
- const handleSelect = /* @__PURE__ */ __name(() => {
918
+ function handleSelect(event) {
919
+ context.hasConsumerStoppedPropagationRef.current = event.isPropagationStopped();
920
+ context.onUserInteraction();
908
921
  context.onValueChange(value);
909
922
  context.onOpenChange(false);
910
- }, "handleSelect");
923
+ }
924
+ __name(handleSelect, "handleSelect");
911
925
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
912
926
  SelectItemContextProvider,
913
927
  {
@@ -941,20 +955,20 @@ var SelectItem = /* @__PURE__ */ React.forwardRef(
941
955
  ref: composedRefs,
942
956
  onFocus: (0, import_primitive.composeEventHandlers)(itemProps.onFocus, () => setIsFocused(true)),
943
957
  onBlur: (0, import_primitive.composeEventHandlers)(itemProps.onBlur, () => setIsFocused(false)),
944
- onClick: (0, import_primitive.composeEventHandlers)(itemProps.onClick, () => {
958
+ onClick: (0, import_primitive.composeEventHandlers)(itemProps.onClick, (event) => {
945
959
  if (disabled) {
946
960
  return;
947
961
  }
948
962
  if (pointerTypeRef.current !== "mouse") {
949
- handleSelect();
963
+ handleSelect(event);
950
964
  }
951
965
  }),
952
- onPointerUp: (0, import_primitive.composeEventHandlers)(itemProps.onPointerUp, () => {
966
+ onPointerUp: (0, import_primitive.composeEventHandlers)(itemProps.onPointerUp, (event) => {
953
967
  if (disabled) {
954
968
  return;
955
969
  }
956
970
  if (pointerTypeRef.current === "mouse") {
957
- handleSelect();
971
+ handleSelect(event);
958
972
  }
959
973
  }),
960
974
  onPointerDown: (0, import_primitive.composeEventHandlers)(itemProps.onPointerDown, (event) => {
@@ -982,7 +996,7 @@ var SelectItem = /* @__PURE__ */ React.forwardRef(
982
996
  return;
983
997
  }
984
998
  if (SELECTION_KEYS.includes(event.key)) {
985
- handleSelect();
999
+ handleSelect(event);
986
1000
  }
987
1001
  if (event.key === " ") {
988
1002
  event.preventDefault();
@@ -1171,12 +1185,23 @@ var SelectBubbleInput = /* @__PURE__ */ React.forwardRef(
1171
1185
  // blank line to reduce diff noise
1172
1186
  /* @__PURE__ */ __name(function SelectBubbleInput2({ __scopeSelect, ...props }, forwardedRef) {
1173
1187
  const context = useSelectContext(BUBBLE_INPUT_NAME, __scopeSelect);
1174
- const { value, onValueChange, required, disabled, name, autoComplete, form } = context;
1188
+ const {
1189
+ value,
1190
+ onValueChange,
1191
+ required,
1192
+ disabled,
1193
+ name,
1194
+ autoComplete,
1195
+ form,
1196
+ hasConsumerStoppedPropagationRef,
1197
+ userInteractionCount
1198
+ } = context;
1175
1199
  const { nativeOptions, nativeSelectKey } = context;
1176
1200
  const ref = React.useRef(null);
1177
1201
  const composedRefs = (0, import_react_compose_refs.useComposedRefs)(forwardedRef, ref);
1178
1202
  const selectValue = value ?? "";
1179
- const prevValue = (0, import_react_use_previous.usePrevious)(selectValue);
1203
+ const prevValueRef = React.useRef(selectValue);
1204
+ const prevUserInteractionCountRef = React.useRef(userInteractionCount);
1180
1205
  const hasEmptyValueOption = Array.from(nativeOptions).some(
1181
1206
  (option) => (option.props.value ?? "") === ""
1182
1207
  );
@@ -1189,12 +1214,17 @@ var SelectBubbleInput = /* @__PURE__ */ React.forwardRef(
1189
1214
  "value"
1190
1215
  );
1191
1216
  const setValue = descriptor.set;
1192
- if (prevValue !== selectValue && setValue) {
1193
- const event = new Event("change", { bubbles: true });
1217
+ const isUserInteraction = userInteractionCount !== prevUserInteractionCountRef.current;
1218
+ prevUserInteractionCountRef.current = userInteractionCount;
1219
+ const valueChanged = prevValueRef.current !== selectValue;
1220
+ prevValueRef.current = selectValue;
1221
+ const bubbles = isUserInteraction && !hasConsumerStoppedPropagationRef.current;
1222
+ if (valueChanged && setValue) {
1223
+ const event = new Event("change", { bubbles });
1194
1224
  setValue.call(select, selectValue);
1195
1225
  select.dispatchEvent(event);
1196
1226
  }
1197
- }, [prevValue, selectValue]);
1227
+ }, [hasConsumerStoppedPropagationRef, selectValue, userInteractionCount]);
1198
1228
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1199
1229
  import_react_primitive.Primitive.select,
1200
1230
  {
@@ -1235,11 +1265,13 @@ function useTypeaheadSearch(onSearchChange) {
1235
1265
  (key) => {
1236
1266
  const search = searchRef.current + key;
1237
1267
  handleSearchChange(search);
1238
- (/* @__PURE__ */ __name((function updateSearch(value) {
1268
+ function updateSearch(value) {
1239
1269
  searchRef.current = value;
1240
1270
  window.clearTimeout(timerRef.current);
1241
1271
  if (value !== "") timerRef.current = window.setTimeout(() => updateSearch(""), 1e3);
1242
- }), "updateSearch"))(search);
1272
+ }
1273
+ __name(updateSearch, "updateSearch");
1274
+ updateSearch(search);
1243
1275
  },
1244
1276
  [handleSearchChange]
1245
1277
  );