@jobber/components 6.103.4-uncontroll-d4ef425.5 → 6.103.4-uncontroll-3a6b89f.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.
@@ -258,6 +258,9 @@ function useAutocomplete(props) {
258
258
  if (prevValueRef.current !== value) {
259
259
  prevValueRef.current = value;
260
260
  const currentValue = value;
261
+ // Mark this as a programmatic change, not user input
262
+ // This prevents onChange from being called when we sync from prop changes
263
+ lastInputWasUser.current = false;
261
264
  setInternalInputValue(currentValue ? getOptionLabel(currentValue) : "");
262
265
  }
263
266
  }, [value, inputValueProp, multiple, getOptionLabel]);
@@ -356,9 +359,8 @@ function useAutocomplete(props) {
356
359
  // This is only options
357
360
  const optionCount = renderable.reduce((count, item) => count + (item.kind === "option" ? 1 : 0), 0);
358
361
  const hasSelection = React.useMemo(() => {
359
- var _a;
360
362
  if (multiple) {
361
- const current = (_a = value) !== null && _a !== void 0 ? _a : [];
363
+ const current = value !== null && value !== void 0 ? value : [];
362
364
  return Array.isArray(current) && current.length > 0;
363
365
  }
364
366
  return value != null;
@@ -413,11 +415,15 @@ function useAutocomplete(props) {
413
415
  // In multiple mode, clearing the input should NOT clear the selection
414
416
  if (multiple)
415
417
  return;
416
- // For single-select, treat clearing input as clearing the selection
417
- if (hasSelection) {
418
+ // Only clear the selection if the user actually cleared the input
419
+ // (not from internal state sync when parent changes the value prop)
420
+ // This prevents calling onChange when we're syncing state from a controlled value prop,
421
+ // but still allows onChange to fire when the user deletes the input text
422
+ const currentlyHasSelection = value != null;
423
+ if (lastInputWasUser.current && currentlyHasSelection) {
418
424
  onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
419
425
  }
420
- }, [inputValue, multiple, hasSelection, setActiveIndex, onChange, open]);
426
+ }, [inputValue, multiple, setActiveIndex, onChange, open, value]);
421
427
  function selectOption(option) {
422
428
  var _a;
423
429
  if (multiple) {
@@ -256,6 +256,9 @@ function useAutocomplete(props) {
256
256
  if (prevValueRef.current !== value) {
257
257
  prevValueRef.current = value;
258
258
  const currentValue = value;
259
+ // Mark this as a programmatic change, not user input
260
+ // This prevents onChange from being called when we sync from prop changes
261
+ lastInputWasUser.current = false;
259
262
  setInternalInputValue(currentValue ? getOptionLabel(currentValue) : "");
260
263
  }
261
264
  }, [value, inputValueProp, multiple, getOptionLabel]);
@@ -354,9 +357,8 @@ function useAutocomplete(props) {
354
357
  // This is only options
355
358
  const optionCount = renderable.reduce((count, item) => count + (item.kind === "option" ? 1 : 0), 0);
356
359
  const hasSelection = useMemo(() => {
357
- var _a;
358
360
  if (multiple) {
359
- const current = (_a = value) !== null && _a !== void 0 ? _a : [];
361
+ const current = value !== null && value !== void 0 ? value : [];
360
362
  return Array.isArray(current) && current.length > 0;
361
363
  }
362
364
  return value != null;
@@ -411,11 +413,15 @@ function useAutocomplete(props) {
411
413
  // In multiple mode, clearing the input should NOT clear the selection
412
414
  if (multiple)
413
415
  return;
414
- // For single-select, treat clearing input as clearing the selection
415
- if (hasSelection) {
416
+ // Only clear the selection if the user actually cleared the input
417
+ // (not from internal state sync when parent changes the value prop)
418
+ // This prevents calling onChange when we're syncing state from a controlled value prop,
419
+ // but still allows onChange to fire when the user deletes the input text
420
+ const currentlyHasSelection = value != null;
421
+ if (lastInputWasUser.current && currentlyHasSelection) {
416
422
  onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
417
423
  }
418
- }, [inputValue, multiple, hasSelection, setActiveIndex, onChange, open]);
424
+ }, [inputValue, multiple, setActiveIndex, onChange, open, value]);
419
425
  function selectOption(option) {
420
426
  var _a;
421
427
  if (multiple) {
@@ -36,3 +36,20 @@ export declare function FreeFormWrapper({ initialValue, initialInputValue, onCha
36
36
  readonly inputEqualsOption?: (input: string, option: OptionLike) => boolean;
37
37
  readonly debounce?: number;
38
38
  }): React.JSX.Element;
39
+ export declare function UncontrolledWrapper<T extends OptionLike>({ defaultValue, menu, placeholder, }: {
40
+ readonly defaultValue?: T;
41
+ readonly menu: MenuItem<T>[];
42
+ readonly placeholder?: string;
43
+ }): React.JSX.Element;
44
+ export declare function SemiControlledWrapper<T extends OptionLike>({ initialValue, onChange, menu, placeholder, }: {
45
+ readonly initialValue?: T;
46
+ readonly onChange?: (v: T | undefined) => void;
47
+ readonly menu: MenuItem<T>[];
48
+ readonly placeholder?: string;
49
+ }): React.JSX.Element;
50
+ export declare function ControlledValueWrapper<T extends OptionLike>({ value, onChange, menu, placeholder, }: {
51
+ readonly value: T | undefined;
52
+ readonly onChange: (v: T | undefined) => void;
53
+ readonly menu: MenuItem<T>[];
54
+ readonly placeholder?: string;
55
+ }): React.JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "6.103.4-uncontroll-d4ef425.5+d4ef4259d",
3
+ "version": "6.103.4-uncontroll-3a6b89f.8+3a6b89f05",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -538,5 +538,5 @@
538
538
  "> 1%",
539
539
  "IE 10"
540
540
  ],
541
- "gitHead": "d4ef4259debb09593eabc29a42b18faa208329b8"
541
+ "gitHead": "3a6b89f051c7bf248c95263b514cd02722010dd7"
542
542
  }