@pushwoosh/dumb-components 1.1.141 → 1.1.142

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,12 +1,14 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useId, useMemo, useRef, useState } from 'react';
3
- import { DEFAULT_DEBOUNCE_MS, FieldInput, FieldShell, defaultGetKey, useActiveIndex, useDropdownItems, useListNavigation, useShellMouseDown } from '../shared/dropdownField';
3
+ import { DEFAULT_DEBOUNCE_MS, FieldInput, FieldShell, defaultGetKey, useActiveIndex, useDropdownItems, useFieldOpenEffects, useListNavigation, useShellMouseDown } from '../shared/dropdownField';
4
4
  function FreeCombobox({
5
5
  items,
6
6
  loadItems,
7
7
  debounceMs = DEFAULT_DEBOUNCE_MS,
8
8
  value,
9
9
  onChange,
10
+ onClose,
11
+ autoFocus,
10
12
  getLabel: getLabelProp,
11
13
  filter,
12
14
  renderItem,
@@ -58,6 +60,13 @@ function FreeCombobox({
58
60
  onEscape: close
59
61
  });
60
62
  const onShellMouseDown = useShellMouseDown(inputRef, isOpen, open);
63
+ useFieldOpenEffects({
64
+ isOpen,
65
+ open,
66
+ onClose,
67
+ autoFocus,
68
+ inputRef
69
+ });
61
70
  const dropdownItems = useMemo(() => filteredItems.map((item, idx) => {
62
71
  const selected = getLabel(item) === value;
63
72
  const state = {
@@ -122,6 +131,8 @@ function SelectCombobox({
122
131
  debounceMs = DEFAULT_DEBOUNCE_MS,
123
132
  value,
124
133
  onChange,
134
+ onClose,
135
+ autoFocus,
125
136
  getLabel,
126
137
  getKey: getKeyProp,
127
138
  filter,
@@ -190,6 +201,13 @@ function SelectCombobox({
190
201
  onEscape: close
191
202
  });
192
203
  const onShellMouseDown = useShellMouseDown(inputRef, isOpen, open);
204
+ useFieldOpenEffects({
205
+ isOpen,
206
+ open,
207
+ onClose,
208
+ autoFocus,
209
+ inputRef
210
+ });
193
211
  const dropdownItems = useMemo(() => filteredItems.map((item, idx) => {
194
212
  const key = getKey(item);
195
213
  const selected = key === selectedKey;
@@ -13,6 +13,8 @@ type CommonProps<T> = {
13
13
  filter?: (item: T, query: string) => boolean;
14
14
  renderItem?: (item: T, state: ItemState) => ReactNode;
15
15
  renderEmpty?: (query: string) => ReactNode;
16
+ onClose?: () => void;
17
+ autoFocus?: boolean;
16
18
  placeholder?: string;
17
19
  disabled?: boolean;
18
20
  loading?: boolean;
@@ -1,3 +1,3 @@
1
1
  import { type ReactElement } from 'react';
2
2
  import { type ComboboxMultiProps } from './types';
3
- export declare function ComboboxMulti<T>({ items, loadItems, debounceMs, value, onChange, getLabel, getKey: getKeyProp, filter, renderItem, renderEmpty, creatable, onCreate, canCreate, renderCreateLabel, maxValues, placeholder, disabled, loading, clearable, autosize, $isErrored, width, minWidth, }: ComboboxMultiProps<T>): ReactElement;
3
+ export declare function ComboboxMulti<T>({ items, loadItems, debounceMs, value, onChange, onClose, autoFocus, getLabel, getKey: getKeyProp, filter, renderItem, renderEmpty, creatable, onCreate, canCreate, renderCreateLabel, maxValues, placeholder, disabled, loading, clearable, autosize, $isErrored, width, minWidth, }: ComboboxMultiProps<T>): ReactElement;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useId, useMemo, useRef, useState } from 'react';
3
3
  import { Chip } from '../Chip';
4
- import { DEFAULT_DEBOUNCE_MS, FieldInput, FieldShell, defaultGetKey, useActiveIndex, useDropdownItems, useListNavigation, useShellMouseDown } from '../shared/dropdownField';
4
+ import { DEFAULT_DEBOUNCE_MS, FieldInput, FieldShell, defaultGetKey, useActiveIndex, useDropdownItems, useFieldOpenEffects, useListNavigation, useShellMouseDown } from '../shared/dropdownField';
5
5
  function defaultCanCreate(query, items, getLabel) {
6
6
  const trimmed = query.trim();
7
7
  if (!trimmed) return false;
@@ -14,6 +14,8 @@ export function ComboboxMulti({
14
14
  debounceMs = DEFAULT_DEBOUNCE_MS,
15
15
  value,
16
16
  onChange,
17
+ onClose,
18
+ autoFocus,
17
19
  getLabel,
18
20
  getKey: getKeyProp,
19
21
  filter,
@@ -107,6 +109,13 @@ export function ComboboxMulti({
107
109
  onBackspaceEmpty: () => onChange(value.slice(0, -1))
108
110
  });
109
111
  const onShellMouseDown = useShellMouseDown(inputRef, isOpen, open);
112
+ useFieldOpenEffects({
113
+ isOpen,
114
+ open,
115
+ onClose,
116
+ autoFocus,
117
+ inputRef
118
+ });
110
119
  const toggleOpen = useCallback(() => {
111
120
  if (isOpen) {
112
121
  var _inputRef$current2;
@@ -13,6 +13,8 @@ type CreatableProp<T> = [T] extends [string] ? {
13
13
  export type ComboboxMultiProps<T> = ItemsSource<T> & GetKeyProp<T> & CreatableProp<T> & {
14
14
  value: T[];
15
15
  onChange: (value: T[]) => void;
16
+ onClose?: () => void;
17
+ autoFocus?: boolean;
16
18
  getLabel: (item: T) => string;
17
19
  filter?: (item: T, query: string) => boolean;
18
20
  renderItem?: (item: T, state: ItemState) => ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "1.1.141",
3
+ "version": "1.1.142",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -33,6 +33,7 @@ export function FieldShell({
33
33
  const {
34
34
  setReference,
35
35
  setFloating,
36
+ floatingRef,
36
37
  floatingStyles
37
38
  } = useDropdownPosition({
38
39
  isOpen: dropdownOpen,
@@ -44,6 +45,15 @@ export function FieldShell({
44
45
  isOpen: !!dropdownOpen,
45
46
  onClose
46
47
  });
48
+ const onShellBlur = event => {
49
+ var _floatingRef$current;
50
+ if (!isOpen) return;
51
+ const next = event.relatedTarget;
52
+ if (!next) return;
53
+ if (event.currentTarget.contains(next)) return;
54
+ if ((_floatingRef$current = floatingRef.current) !== null && _floatingRef$current !== void 0 && _floatingRef$current.contains(next)) return;
55
+ onClose === null || onClose === void 0 || onClose();
56
+ };
47
57
  return _jsxs(_Fragment, {
48
58
  children: [_jsxs(Shell, {
49
59
  ref: setReference,
@@ -56,6 +66,7 @@ export function FieldShell({
56
66
  "$autosize": autosize,
57
67
  "$tightLeft": tightLeft,
58
68
  onMouseDown: onShellMouseDown,
69
+ onBlur: onShellBlur,
59
70
  children: [_jsx(ShellInner, {
60
71
  children: children
61
72
  }), _jsxs(Indicators, {
@@ -6,6 +6,7 @@ export { useDebouncedValue } from './useDebouncedValue';
6
6
  export { useAsyncItems } from './useAsyncItems';
7
7
  export { useDropdownItems } from './useDropdownItems';
8
8
  export { useActiveIndex } from './useActiveIndex';
9
+ export { useFieldOpenEffects } from './useFieldOpenEffects';
9
10
  export { useListNavigation } from './useListNavigation';
10
11
  export { defaultGetKey, defaultLabelFilter, useShellMouseDown } from './shared';
11
12
  export { DEFAULT_DEBOUNCE_MS } from './constants';
@@ -6,6 +6,7 @@ export { useDebouncedValue } from './useDebouncedValue';
6
6
  export { useAsyncItems } from './useAsyncItems';
7
7
  export { useDropdownItems } from './useDropdownItems';
8
8
  export { useActiveIndex } from './useActiveIndex';
9
+ export { useFieldOpenEffects } from './useFieldOpenEffects';
9
10
  export { useListNavigation } from './useListNavigation';
10
11
  export { defaultGetKey, defaultLabelFilter, useShellMouseDown } from './shared';
11
12
  export { DEFAULT_DEBOUNCE_MS } from './constants';
@@ -5,6 +5,7 @@ type Args = {
5
5
  export declare function useDropdownPosition({ isOpen, onClickOutside }: Args): {
6
6
  setReference: (node: import("@floating-ui/react-dom").ReferenceType | null) => void;
7
7
  setFloating: (node: HTMLElement | null) => void;
8
+ floatingRef: import("react").MutableRefObject<HTMLElement | null>;
8
9
  floatingStyles: import("react").CSSProperties;
9
10
  };
10
11
  export {};
@@ -35,6 +35,7 @@ export function useDropdownPosition({
35
35
  return {
36
36
  setReference: refs.setReference,
37
37
  setFloating: refs.setFloating,
38
+ floatingRef: refs.floating,
38
39
  floatingStyles
39
40
  };
40
41
  }
@@ -0,0 +1,10 @@
1
+ import { type RefObject } from 'react';
2
+ type Args = {
3
+ isOpen: boolean;
4
+ open: () => void;
5
+ onClose?: () => void;
6
+ autoFocus?: boolean;
7
+ inputRef: RefObject<HTMLInputElement>;
8
+ };
9
+ export declare function useFieldOpenEffects({ isOpen, open, onClose, autoFocus, inputRef, }: Args): void;
10
+ export {};
@@ -0,0 +1,25 @@
1
+ import { useEffect, useRef } from 'react';
2
+ export function useFieldOpenEffects({
3
+ isOpen,
4
+ open,
5
+ onClose,
6
+ autoFocus,
7
+ inputRef
8
+ }) {
9
+ const onCloseRef = useRef(onClose);
10
+ onCloseRef.current = onClose;
11
+ const wasOpenRef = useRef(isOpen);
12
+ useEffect(() => {
13
+ var _onCloseRef$current;
14
+ if (wasOpenRef.current && !isOpen) (_onCloseRef$current = onCloseRef.current) === null || _onCloseRef$current === void 0 || _onCloseRef$current.call(onCloseRef);
15
+ wasOpenRef.current = isOpen;
16
+ }, [isOpen]);
17
+ const didAutoFocusRef = useRef(false);
18
+ useEffect(() => {
19
+ var _inputRef$current;
20
+ if (!autoFocus || didAutoFocusRef.current) return;
21
+ didAutoFocusRef.current = true;
22
+ (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
23
+ open();
24
+ }, [autoFocus, open, inputRef]);
25
+ }