@wallarm-org/design-system 0.29.1 → 0.29.2-rc-feature-AS-882.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 (63) hide show
  1. package/dist/components/FilterInput/FilterInput.js +4 -2
  2. package/dist/components/FilterInput/FilterInputContext/types.d.ts +6 -0
  3. package/dist/components/FilterInput/FilterInputContext/useFilterInputContextValue.d.ts +3 -0
  4. package/dist/components/FilterInput/FilterInputContext/useFilterInputContextValue.js +7 -1
  5. package/dist/components/FilterInput/FilterInputErrors/FilterInputErrors.js +5 -9
  6. package/dist/components/FilterInput/FilterInputErrors/parseFilterInputErrors.js +3 -2
  7. package/dist/components/FilterInput/FilterInputField/FilterInputChip/FilterInputChip.d.ts +2 -1
  8. package/dist/components/FilterInput/FilterInputField/FilterInputChip/FilterInputChip.js +15 -14
  9. package/dist/components/FilterInput/FilterInputField/FilterInputChip/Segment.d.ts +1 -2
  10. package/dist/components/FilterInput/FilterInputField/FilterInputChip/Segment.js +18 -9
  11. package/dist/components/FilterInput/FilterInputField/FilterInputChip/index.d.ts +1 -0
  12. package/dist/components/FilterInput/FilterInputField/FilterInputChip/index.js +2 -1
  13. package/dist/components/FilterInput/FilterInputField/FilterInputChip/segmentVariant.d.ts +6 -0
  14. package/dist/components/FilterInput/FilterInputField/FilterInputChip/segmentVariant.js +6 -0
  15. package/dist/components/FilterInput/FilterInputField/FilterInputConnectorChip/FilterInputConnectorChip.js +1 -0
  16. package/dist/components/FilterInput/FilterInputField/FilterInputField.js +3 -2
  17. package/dist/components/FilterInput/FilterInputMenu/FilterInputDateValueMenu/FilterInputDateValueMenu.js +1 -0
  18. package/dist/components/FilterInput/FilterInputMenu/FilterInputFieldMenu/FieldMenuSections.d.ts +3 -0
  19. package/dist/components/FilterInput/FilterInputMenu/FilterInputFieldMenu/FieldMenuSections.js +7 -3
  20. package/dist/components/FilterInput/FilterInputMenu/FilterInputFieldMenu/FilterInputFieldMenu.js +9 -4
  21. package/dist/components/FilterInput/FilterInputMenu/FilterInputMenu.d.ts +1 -1
  22. package/dist/components/FilterInput/FilterInputMenu/FilterInputMenu.js +3 -2
  23. package/dist/components/FilterInput/FilterInputMenu/FilterInputOperatorMenu.js +3 -1
  24. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/FilterInputValueMenu.js +4 -2
  25. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/ValueMenuItem.d.ts +1 -0
  26. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/ValueMenuItem.js +2 -1
  27. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/useValueMenuState.d.ts +1 -0
  28. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/useValueMenuState.js +8 -3
  29. package/dist/components/FilterInput/FilterInputMenu/hooks/useKeyboardNav.d.ts +1 -0
  30. package/dist/components/FilterInput/FilterInputMenu/hooks/useKeyboardNav.js +9 -7
  31. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useBlurCommit.d.ts +33 -0
  32. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useBlurCommit.js +42 -0
  33. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useChipActions.d.ts +27 -0
  34. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useChipActions.js +55 -0
  35. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useChipEditing.d.ts +5 -5
  36. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useChipEditing.js +7 -6
  37. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFilterInputAutocomplete.d.ts +6 -3
  38. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFilterInputAutocomplete.js +54 -87
  39. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFocusManagement.d.ts +9 -2
  40. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFocusManagement.js +33 -8
  41. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useMenuFlow.d.ts +3 -3
  42. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useMenuFlow.js +12 -11
  43. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useResetState.d.ts +42 -0
  44. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useResetState.js +41 -0
  45. package/dist/components/FilterInput/hooks/useFilterInputExpression/buildChips.js +7 -8
  46. package/dist/components/FilterInput/hooks/useFilterInputExpression/useFilterInputExpression.d.ts +1 -0
  47. package/dist/components/FilterInput/hooks/useFilterInputExpression/useFilterInputExpression.js +11 -0
  48. package/dist/components/FilterInput/hooks/useFilterInputSelection/useFilterInputSelection.d.ts +5 -2
  49. package/dist/components/FilterInput/hooks/useFilterInputSelection/useFilterInputSelection.js +4 -2
  50. package/dist/components/FilterInput/hooks/useFilterInputSelection/useSelectionClipboard.d.ts +9 -2
  51. package/dist/components/FilterInput/hooks/useFilterInputSelection/useSelectionClipboard.js +9 -5
  52. package/dist/components/FilterInput/hooks/useFilterInputSelection/useSelectionKeyboard.d.ts +2 -1
  53. package/dist/components/FilterInput/hooks/useFilterInputSelection/useSelectionKeyboard.js +3 -2
  54. package/dist/components/FilterInput/lib/dom.d.ts +9 -1
  55. package/dist/components/FilterInput/lib/dom.js +1 -1
  56. package/dist/components/FilterInput/lib/fields.d.ts +9 -0
  57. package/dist/components/FilterInput/lib/fields.js +6 -1
  58. package/dist/components/FilterInput/lib/index.d.ts +1 -1
  59. package/dist/components/FilterInput/lib/index.js +2 -2
  60. package/dist/components/FilterInput/lib/menuFilterText.js +2 -1
  61. package/dist/components/FilterInput/types.d.ts +6 -0
  62. package/dist/metadata/components.json +2 -2
  63. package/package.json +1 -1
@@ -19,7 +19,7 @@ const FilterInput = ({ fields: rawFields = [], value, onChange, placeholder = 'T
19
19
  const fields = useMemo(()=>applyKnownFieldHelpers(rawFields), [
20
20
  rawFields
21
21
  ]);
22
- const { conditions, connectors, chips, upsertCondition, removeCondition, removeConditionAtIndex, clearAll, setConnectorValue } = useFilterInputExpression({
22
+ const { conditions, connectors, chips, upsertCondition, removeCondition, removeConditionAtIndex, clearAll, replaceExpression, setConnectorValue } = useFilterInputExpression({
23
23
  fields,
24
24
  value,
25
25
  onChange,
@@ -48,7 +48,8 @@ const FilterInput = ({ fields: rawFields = [], value, onChange, placeholder = 'T
48
48
  clearAll,
49
49
  setInputText: autocomplete.setInputText,
50
50
  closeMenu: autocomplete.closeAutocompleteMenu,
51
- onChange
51
+ replaceExpression,
52
+ resetAutocompleteState: autocomplete.handleMenuDiscard
52
53
  });
53
54
  const contextValue = useFilterInputContextValue({
54
55
  chips,
@@ -84,6 +85,7 @@ const FilterInput = ({ fields: rawFields = [], value, onChange, placeholder = 'T
84
85
  return /*#__PURE__*/ jsxs("div", {
85
86
  ref: containerRef,
86
87
  className: cn('group/filter-input relative flex w-full flex-col gap-4', className),
88
+ tabIndex: -1,
87
89
  onFocus: autocomplete.handleFocus,
88
90
  onBlur: autocomplete.handleBlur,
89
91
  onClick: allSelected ? clearSelection : void 0,
@@ -39,4 +39,10 @@ export interface FilterInputContextValue {
39
39
  closeAutocompleteMenu: () => void;
40
40
  /** Register/unregister a chip DOM element for selection tracking */
41
41
  registerChipRef: (id: string, el: HTMLElement | null) => void;
42
+ /** Direct ref to the attribute segment <input> — attached by Segment when editing. */
43
+ segmentAttributeInputRef: RefObject<HTMLInputElement | null>;
44
+ /** Direct ref to the operator segment <input> — attached by Segment when editing. */
45
+ segmentOperatorInputRef: RefObject<HTMLInputElement | null>;
46
+ /** Direct ref to the value segment <input> — attached by Segment when editing. */
47
+ segmentValueInputRef: RefObject<HTMLInputElement | null>;
42
48
  }
@@ -25,6 +25,9 @@ interface AutocompleteForContext {
25
25
  handleCustomAttributeCommit: (customText: string) => void;
26
26
  menuRef: RefObject<HTMLDivElement | null>;
27
27
  closeAutocompleteMenu: () => void;
28
+ segmentAttributeInputRef: RefObject<HTMLInputElement | null>;
29
+ segmentOperatorInputRef: RefObject<HTMLInputElement | null>;
30
+ segmentValueInputRef: RefObject<HTMLInputElement | null>;
28
31
  }
29
32
  interface UseFilterInputContextValueOptions {
30
33
  chips: FilterInputChipData[];
@@ -28,7 +28,10 @@ const useFilterInputContextValue = ({ chips, autocomplete, buildingChipRef, inpu
28
28
  onCustomAttributeCommit: autocomplete.handleCustomAttributeCommit,
29
29
  menuRef: autocomplete.menuRef,
30
30
  closeAutocompleteMenu: autocomplete.closeAutocompleteMenu,
31
- registerChipRef
31
+ registerChipRef,
32
+ segmentAttributeInputRef: autocomplete.segmentAttributeInputRef,
33
+ segmentOperatorInputRef: autocomplete.segmentOperatorInputRef,
34
+ segmentValueInputRef: autocomplete.segmentValueInputRef
32
35
  }), [
33
36
  chips,
34
37
  autocomplete.buildingChipData,
@@ -53,6 +56,9 @@ const useFilterInputContextValue = ({ chips, autocomplete, buildingChipRef, inpu
53
56
  autocomplete.handleCustomAttributeCommit,
54
57
  autocomplete.menuRef,
55
58
  autocomplete.closeAutocompleteMenu,
59
+ autocomplete.segmentAttributeInputRef,
60
+ autocomplete.segmentOperatorInputRef,
61
+ autocomplete.segmentValueInputRef,
56
62
  registerChipRef,
57
63
  buildingChipRef,
58
64
  inputRef,
@@ -1,7 +1,6 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Alert } from "../../Alert/Alert.js";
3
3
  import { AlertContent } from "../../Alert/AlertContent.js";
4
- import { AlertDescription } from "../../Alert/AlertDescription.js";
5
4
  import { AlertIcon } from "../../Alert/AlertIcon.js";
6
5
  import { AlertTitle } from "../../Alert/AlertTitle.js";
7
6
  const FilterInputErrors = ({ errors })=>{
@@ -16,14 +15,11 @@ const FilterInputErrors = ({ errors })=>{
16
15
  /*#__PURE__*/ jsx(AlertTitle, {
17
16
  children: title
18
17
  }),
19
- /*#__PURE__*/ jsx(AlertDescription, {
20
- lineClamp: 0,
21
- children: /*#__PURE__*/ jsx("ul", {
22
- className: "list-disc ms-[21px]",
23
- children: errors.map((err, idx)=>/*#__PURE__*/ jsx("li", {
24
- children: err
25
- }, idx))
26
- })
18
+ /*#__PURE__*/ jsx("ul", {
19
+ className: "list-disc ms-[21px] text-sm text-text-secondary",
20
+ children: errors.map((err, idx)=>/*#__PURE__*/ jsx("li", {
21
+ children: err
22
+ }, idx))
27
23
  })
28
24
  ]
29
25
  })
@@ -1,3 +1,4 @@
1
+ import { SEGMENT_VARIANT } from "../FilterInputField/FilterInputChip/index.js";
1
2
  import { isValidFieldValue } from "../hooks/useFilterInputAutocomplete/valueCommitHelpers.js";
2
3
  import { getFieldValues, hasStaticAllowlist } from "../lib/index.js";
3
4
  const parseFilterInputErrors = (conditions, fields)=>{
@@ -7,10 +8,10 @@ const parseFilterInputErrors = (conditions, fields)=>{
7
8
  const field = fields.find((f)=>f.name === condition.field);
8
9
  const label = field?.label || condition.field;
9
10
  switch(condition.error){
10
- case 'attribute':
11
+ case SEGMENT_VARIANT.attribute:
11
12
  errors.push(`Unknown field ${condition.field}`);
12
13
  break;
13
- case 'value':
14
+ case SEGMENT_VARIANT.value:
14
15
  if (field?.validate) {
15
16
  const values = Array.isArray(condition.value) ? condition.value : [
16
17
  condition.value
@@ -1,6 +1,7 @@
1
1
  import type { FC, HTMLAttributes, Ref } from 'react';
2
2
  import type { ChipErrorSegment } from '../../types';
3
- export type ChipSegment = 'attribute' | 'operator' | 'value';
3
+ import { type SegmentVariant } from './segmentVariant';
4
+ export type ChipSegment = SegmentVariant;
4
5
  export interface FilterInputChipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
5
6
  ref?: Ref<HTMLDivElement>;
6
7
  chipId?: string;
@@ -6,6 +6,7 @@ import { chipVariants } from "./classes.js";
6
6
  import { useEditingContext } from "./context/EditingContext.js";
7
7
  import { FilterInputRemoveButton } from "./FilterInputRemoveButton.js";
8
8
  import { Segment } from "./Segment.js";
9
+ import { SEGMENT_VARIANT } from "./segmentVariant.js";
9
10
  const FilterInputChip = ({ ref, chipId, attribute, operator, value, error = false, valueParts, valueSeparator, errorValueIndices, building = false, disabled = false, onRemove, onSegmentClick, className, ...props })=>{
10
11
  const interactive = !building && !disabled;
11
12
  const hasError = !!error;
@@ -17,7 +18,7 @@ const FilterInputChip = ({ ref, chipId, attribute, operator, value, error = fals
17
18
  if (!onSegmentClick) return;
18
19
  if (activeSegment === segment) return;
19
20
  e.stopPropagation();
20
- const anchorEl = 'attribute' === segment ? internalRef.current : e.currentTarget;
21
+ const anchorEl = segment === SEGMENT_VARIANT.attribute ? internalRef.current : e.currentTarget;
21
22
  if (!anchorEl) return;
22
23
  onSegmentClick(segment, anchorEl.getBoundingClientRect());
23
24
  }, [
@@ -49,29 +50,29 @@ const FilterInputChip = ({ ref, chipId, attribute, operator, value, error = fals
49
50
  ...props,
50
51
  children: [
51
52
  /*#__PURE__*/ jsx(Segment, {
52
- variant: "attribute",
53
+ variant: SEGMENT_VARIANT.attribute,
53
54
  className: "shrink-0",
54
- error: true === error || 'attribute' === error,
55
- onClick: interactive ? (e)=>handleSegmentClick('attribute', e) : void 0,
56
- ...segmentEditProps('attribute'),
55
+ error: true === error || error === SEGMENT_VARIANT.attribute,
56
+ onClick: interactive ? (e)=>handleSegmentClick(SEGMENT_VARIANT.attribute, e) : void 0,
57
+ ...segmentEditProps(SEGMENT_VARIANT.attribute),
57
58
  children: attribute
58
59
  }),
59
- (operator || 'operator' === activeSegment) && /*#__PURE__*/ jsx(Segment, {
60
- variant: "operator",
60
+ (operator || activeSegment === SEGMENT_VARIANT.operator) && /*#__PURE__*/ jsx(Segment, {
61
+ variant: SEGMENT_VARIANT.operator,
61
62
  className: "shrink-0",
62
- onClick: interactive ? (e)=>handleSegmentClick('operator', e) : void 0,
63
- ...segmentEditProps('operator'),
63
+ onClick: interactive ? (e)=>handleSegmentClick(SEGMENT_VARIANT.operator, e) : void 0,
64
+ ...segmentEditProps(SEGMENT_VARIANT.operator),
64
65
  children: operator ?? ''
65
66
  }),
66
- (value || 'value' === activeSegment) && /*#__PURE__*/ jsx(Segment, {
67
- variant: "value",
67
+ (value || activeSegment === SEGMENT_VARIANT.value) && /*#__PURE__*/ jsx(Segment, {
68
+ variant: SEGMENT_VARIANT.value,
68
69
  className: "min-w-0",
69
- error: 'value' !== activeSegment && (true === error || 'value' === error),
70
+ error: activeSegment !== SEGMENT_VARIANT.value && (true === error || error === SEGMENT_VARIANT.value),
70
71
  valueParts: valueParts,
71
72
  valueSeparator: valueSeparator,
72
73
  errorValueIndices: errorValueIndices,
73
- onClick: interactive ? (e)=>handleSegmentClick('value', e) : void 0,
74
- ...segmentEditProps('value'),
74
+ onClick: interactive ? (e)=>handleSegmentClick(SEGMENT_VARIANT.value, e) : void 0,
75
+ ...segmentEditProps(SEGMENT_VARIANT.value),
75
76
  children: value ?? ''
76
77
  }),
77
78
  building && /*#__PURE__*/ jsx(ChipSearchInput, {}),
@@ -1,5 +1,5 @@
1
1
  import type { FC, FocusEvent, HTMLAttributes, KeyboardEvent } from 'react';
2
- type SegmentVariant = 'attribute' | 'operator' | 'value';
2
+ import { type SegmentVariant } from './segmentVariant';
3
3
  export type SegmentProps = HTMLAttributes<HTMLDivElement> & {
4
4
  variant: SegmentVariant;
5
5
  children: string;
@@ -17,4 +17,3 @@ export type SegmentProps = HTMLAttributes<HTMLDivElement> & {
17
17
  errorValueIndices?: number[];
18
18
  };
19
19
  export declare const Segment: FC<SegmentProps>;
20
- export {};
@@ -1,14 +1,18 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useEffect, useRef } from "react";
2
+ import { useCallback, useContext, useEffect, useRef } from "react";
3
3
  import { cn } from "../../../../utils/cn.js";
4
+ import { FilterInputContext } from "../../FilterInputContext/FilterInputContext.js";
4
5
  import { segmentContainer, segmentTextVariants } from "./classes.js";
5
6
  import { CHAR_WIDTH_PX } from "./constants.js";
6
7
  import { MultiValueSegment } from "./MultiValueSegment.js";
7
8
  import { useSizerWidth } from "./model/useSizerWidth.js";
9
+ import { SEGMENT_VARIANT } from "./segmentVariant.js";
8
10
  const Segment = ({ variant, children, className, error, editing, editText, onEditChange, onEditKeyDown, onEditBlur, valueParts, valueSeparator = ', ', errorValueIndices, ...props })=>{
9
11
  const textRef = useRef(null);
10
12
  const inputRef = useRef(null);
11
13
  const sizerRef = useRef(null);
14
+ const filterInputContext = useContext(FilterInputContext);
15
+ const segmentInputRef = variant === SEGMENT_VARIANT.attribute ? filterInputContext?.segmentAttributeInputRef : variant === SEGMENT_VARIANT.operator ? filterInputContext?.segmentOperatorInputRef : variant === SEGMENT_VARIANT.value ? filterInputContext?.segmentValueInputRef : null;
12
16
  const lastTextWidthRef = useRef(0);
13
17
  useEffect(()=>{
14
18
  if (editing) return;
@@ -20,17 +24,16 @@ const Segment = ({ variant, children, className, error, editing, editText, onEdi
20
24
  ]);
21
25
  useEffect(()=>{
22
26
  if (!editing) return;
23
- let outer = 0;
24
- let inner = 0;
25
- outer = requestAnimationFrame(()=>{
26
- inner = requestAnimationFrame(()=>{
27
+ let innerFrame = 0;
28
+ const outerFrame = requestAnimationFrame(()=>{
29
+ innerFrame = requestAnimationFrame(()=>{
27
30
  inputRef.current?.focus();
28
31
  inputRef.current?.select();
29
32
  });
30
33
  });
31
34
  return ()=>{
32
- cancelAnimationFrame(outer);
33
- cancelAnimationFrame(inner);
35
+ cancelAnimationFrame(outerFrame);
36
+ cancelAnimationFrame(innerFrame);
34
37
  };
35
38
  }, [
36
39
  editing
@@ -39,8 +42,14 @@ const Segment = ({ variant, children, className, error, editing, editText, onEdi
39
42
  sizerRef,
40
43
  text: editText ?? ''
41
44
  });
45
+ const setInputRef = useCallback((node)=>{
46
+ inputRef.current = node;
47
+ if (segmentInputRef) segmentInputRef.current = node;
48
+ }, [
49
+ segmentInputRef
50
+ ]);
42
51
  const isInteractive = !!props.onClick;
43
- const hasMultiValueErrors = 'value' === variant && !!valueParts && !!errorValueIndices && errorValueIndices.length > 0 && !editing;
52
+ const hasMultiValueErrors = variant === SEGMENT_VARIANT.value && !!valueParts && !!errorValueIndices && errorValueIndices.length > 0 && !editing;
44
53
  if (hasMultiValueErrors) return /*#__PURE__*/ jsx(MultiValueSegment, {
45
54
  valueParts: valueParts,
46
55
  valueSeparator: valueSeparator,
@@ -59,7 +68,7 @@ const Segment = ({ variant, children, className, error, editing, editText, onEdi
59
68
  children: editing ? /*#__PURE__*/ jsxs(Fragment, {
60
69
  children: [
61
70
  /*#__PURE__*/ jsx("input", {
62
- ref: inputRef,
71
+ ref: setInputRef,
63
72
  size: 1,
64
73
  value: editText ?? '',
65
74
  onChange: (e)=>onEditChange?.(e.target.value),
@@ -3,3 +3,4 @@ export { type EditingContextValue, EditingProvider, useEditingContext, } from '.
3
3
  export { type ChipSegment, FilterInputChip, type FilterInputChipProps } from './FilterInputChip';
4
4
  export { FilterInputRemoveButton } from './FilterInputRemoveButton';
5
5
  export { Segment, type SegmentProps } from './Segment';
6
+ export { SEGMENT_VARIANT, type SegmentVariant } from './segmentVariant';
@@ -3,4 +3,5 @@ import { EditingProvider, useEditingContext } from "./context/EditingContext.js"
3
3
  import { FilterInputChip } from "./FilterInputChip.js";
4
4
  import { FilterInputRemoveButton } from "./FilterInputRemoveButton.js";
5
5
  import { Segment } from "./Segment.js";
6
- export { EditingProvider, FilterInputChip, FilterInputConnectorChip, FilterInputRemoveButton, Segment, useEditingContext };
6
+ import { SEGMENT_VARIANT } from "./segmentVariant.js";
7
+ export { EditingProvider, FilterInputChip, FilterInputConnectorChip, FilterInputRemoveButton, SEGMENT_VARIANT, Segment, useEditingContext };
@@ -0,0 +1,6 @@
1
+ export declare const SEGMENT_VARIANT: {
2
+ readonly attribute: "attribute";
3
+ readonly operator: "operator";
4
+ readonly value: "value";
5
+ };
6
+ export type SegmentVariant = (typeof SEGMENT_VARIANT)[keyof typeof SEGMENT_VARIANT];
@@ -0,0 +1,6 @@
1
+ const SEGMENT_VARIANT = {
2
+ attribute: 'attribute',
3
+ operator: 'operator',
4
+ value: 'value'
5
+ };
6
+ export { SEGMENT_VARIANT };
@@ -56,6 +56,7 @@ const FilterInputConnectorChip = ({ chipId, variant, onChange, className })=>{
56
56
  }),
57
57
  /*#__PURE__*/ jsxs(DropdownMenuContent, {
58
58
  className: "w-auto min-w-64",
59
+ "data-filter-input-menu": "true",
59
60
  children: [
60
61
  /*#__PURE__*/ jsxs(DropdownMenuItem, {
61
62
  value: "and",
@@ -9,6 +9,7 @@ import { ChipsWithGaps, TrailingGap } from "./ChipsWithGaps.js";
9
9
  import { ACTIONS_PADDING, COLLAPSED_MAX_HEIGHT, filterInputContainerVariants, filterInputInnerVariants } from "./classes.js";
10
10
  import { EditingProvider } from "./FilterInputChip/context/EditingContext.js";
11
11
  import { FilterInputChip } from "./FilterInputChip/FilterInputChip.js";
12
+ import { SEGMENT_VARIANT } from "./FilterInputChip/segmentVariant.js";
12
13
  import { FilterInputFieldActions } from "./FilterInputFieldActions.js";
13
14
  import { FilterInputSearch } from "./FilterInputSearch.js";
14
15
  import { useChipsSplitting } from "./hooks/useChipsSplitting.js";
@@ -31,12 +32,12 @@ const FilterInputField = ({ className, ...props })=>{
31
32
  return;
32
33
  }
33
34
  if ('Enter' === e.key && !e.defaultPrevented) {
34
- if ('value' === editingSegment) {
35
+ if (editingSegment === SEGMENT_VARIANT.value) {
35
36
  e.preventDefault();
36
37
  onCustomValueCommit(segmentFilterText);
37
38
  return;
38
39
  }
39
- if ('attribute' === editingSegment) {
40
+ if (editingSegment === SEGMENT_VARIANT.attribute) {
40
41
  e.preventDefault();
41
42
  onCustomAttributeCommit(segmentFilterText);
42
43
  return;
@@ -51,6 +51,7 @@ const FilterInputDateValueMenu = ({ open, onSelect, onRangeSelect, onOpenChange,
51
51
  children: /*#__PURE__*/ jsx(DropdownMenuContent, {
52
52
  ref: menuRef,
53
53
  className: cn('w-fit', className),
54
+ "data-filter-input-menu": "true",
54
55
  onKeyDown: (e)=>{
55
56
  if ('Escape' === e.key) {
56
57
  e.preventDefault();
@@ -4,16 +4,19 @@ interface RecentSectionProps {
4
4
  conditions: Condition[];
5
5
  fields: FieldMetadata[];
6
6
  onSelect: (field: FieldMetadata) => void;
7
+ registerItem: (id: string) => (el: HTMLElement | null) => void;
7
8
  }
8
9
  export declare const RecentSection: FC<RecentSectionProps>;
9
10
  interface SuggestionsSectionProps {
10
11
  fields: FieldMetadata[];
11
12
  onSelect: (field: FieldMetadata) => void;
13
+ registerItem: (id: string) => (el: HTMLElement | null) => void;
12
14
  }
13
15
  export declare const SuggestionsSection: FC<SuggestionsSectionProps>;
14
16
  interface OperatorsSectionProps {
15
17
  onSelectAnd?: () => void;
16
18
  onSelectOr?: () => void;
19
+ registerItem: (id: string) => (el: HTMLElement | null) => void;
17
20
  }
18
21
  export declare const OperatorsSection: FC<OperatorsSectionProps>;
19
22
  export {};
@@ -2,7 +2,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { CirclePlus } from "../../../../icons/CirclePlus.js";
3
3
  import { CircleSlash } from "../../../../icons/CircleSlash.js";
4
4
  import { DropdownMenuGroup, DropdownMenuItem, DropdownMenuItemIcon, DropdownMenuItemText, DropdownMenuLabel, DropdownMenuSeparator } from "../../../DropdownMenu/index.js";
5
- const RecentSection = ({ conditions, fields, onSelect })=>/*#__PURE__*/ jsxs(Fragment, {
5
+ const RecentSection = ({ conditions, fields, onSelect, registerItem })=>/*#__PURE__*/ jsxs(Fragment, {
6
6
  children: [
7
7
  /*#__PURE__*/ jsx(DropdownMenuLabel, {
8
8
  children: "Recent"
@@ -15,6 +15,7 @@ const RecentSection = ({ conditions, fields, onSelect })=>/*#__PURE__*/ jsxs(Fra
15
15
  const value = String(condition.value);
16
16
  return /*#__PURE__*/ jsx(DropdownMenuItem, {
17
17
  value: `recent-${index}`,
18
+ ref: registerItem(`recent-${index}`),
18
19
  onSelect: ()=>{
19
20
  if (fieldMeta) onSelect(fieldMeta);
20
21
  },
@@ -42,7 +43,7 @@ const RecentSection = ({ conditions, fields, onSelect })=>/*#__PURE__*/ jsxs(Fra
42
43
  ]
43
44
  });
44
45
  RecentSection.displayName = 'RecentSection';
45
- const SuggestionsSection = ({ fields, onSelect })=>/*#__PURE__*/ jsxs(Fragment, {
46
+ const SuggestionsSection = ({ fields, onSelect, registerItem })=>/*#__PURE__*/ jsxs(Fragment, {
46
47
  children: [
47
48
  /*#__PURE__*/ jsx(DropdownMenuLabel, {
48
49
  children: "Suggestions"
@@ -50,6 +51,7 @@ const SuggestionsSection = ({ fields, onSelect })=>/*#__PURE__*/ jsxs(Fragment,
50
51
  /*#__PURE__*/ jsx(DropdownMenuGroup, {
51
52
  children: fields.map((field, index)=>/*#__PURE__*/ jsx(DropdownMenuItem, {
52
53
  value: `suggested-${index}`,
54
+ ref: registerItem(`suggested-${index}`),
53
55
  onSelect: ()=>onSelect(field),
54
56
  children: /*#__PURE__*/ jsxs("span", {
55
57
  className: "flex gap-2 items-center text-sm",
@@ -74,11 +76,12 @@ const SuggestionsSection = ({ fields, onSelect })=>/*#__PURE__*/ jsxs(Fragment,
74
76
  ]
75
77
  });
76
78
  SuggestionsSection.displayName = 'SuggestionsSection';
77
- const OperatorsSection = ({ onSelectAnd, onSelectOr })=>/*#__PURE__*/ jsxs(Fragment, {
79
+ const OperatorsSection = ({ onSelectAnd, onSelectOr, registerItem })=>/*#__PURE__*/ jsxs(Fragment, {
78
80
  children: [
79
81
  /*#__PURE__*/ jsx(DropdownMenuSeparator, {}),
80
82
  onSelectAnd && /*#__PURE__*/ jsxs(DropdownMenuItem, {
81
83
  value: "and",
84
+ ref: registerItem('and'),
82
85
  onSelect: ()=>onSelectAnd(),
83
86
  children: [
84
87
  /*#__PURE__*/ jsx(DropdownMenuItemIcon, {
@@ -91,6 +94,7 @@ const OperatorsSection = ({ onSelectAnd, onSelectOr })=>/*#__PURE__*/ jsxs(Fragm
91
94
  }),
92
95
  onSelectOr && /*#__PURE__*/ jsxs(DropdownMenuItem, {
93
96
  value: "or",
97
+ ref: registerItem('or'),
94
98
  onSelect: ()=>onSelectOr(),
95
99
  children: [
96
100
  /*#__PURE__*/ jsx(DropdownMenuItemIcon, {
@@ -87,7 +87,7 @@ const FilterInputFieldMenu = ({ fields, filterText = '', onSelect, open = false,
87
87
  } else if ('and' === data.type) onSelectAnd?.();
88
88
  else if ('or' === data.type) onSelectOr?.();
89
89
  };
90
- const { highlightedValue, onHighlightChange } = useKeyboardNav({
90
+ const { highlightedValue, onHighlightChange, registerItem } = useKeyboardNav({
91
91
  items: flatItems,
92
92
  open,
93
93
  onSelect: handleItemSelect,
@@ -109,19 +109,23 @@ const FilterInputFieldMenu = ({ fields, filterText = '', onSelect, open = false,
109
109
  ref: menuRef,
110
110
  className: cn('w-[300px] max-h-[430px]', className),
111
111
  "data-slot": "filter-input-field-menu",
112
+ "data-filter-input-menu": "true",
112
113
  children: [
113
114
  !filterText && showRecent && /*#__PURE__*/ jsx(RecentSection, {
114
115
  conditions: limitedRecentConditions,
115
116
  fields: fields,
116
- onSelect: onSelect
117
+ onSelect: onSelect,
118
+ registerItem: registerItem
117
119
  }),
118
120
  !filterText && showSuggestions && !showRecent && /*#__PURE__*/ jsx(SuggestionsSection, {
119
121
  fields: suggestedFields,
120
- onSelect: onSelect
122
+ onSelect: onSelect,
123
+ registerItem: registerItem
121
124
  }),
122
125
  filteredFields.length > 0 ? /*#__PURE__*/ jsx(DropdownMenuGroup, {
123
126
  children: filteredFields.map((field)=>/*#__PURE__*/ jsx(DropdownMenuItem, {
124
127
  value: `field-${field.name}`,
128
+ ref: registerItem(`field-${field.name}`),
125
129
  onSelect: ()=>onSelect(field),
126
130
  children: /*#__PURE__*/ jsx(DropdownMenuItemText, {
127
131
  children: field.label
@@ -130,7 +134,8 @@ const FilterInputFieldMenu = ({ fields, filterText = '', onSelect, open = false,
130
134
  }) : /*#__PURE__*/ jsx(MenuEmptyState, {}),
131
135
  !filterText && (onSelectAnd || onSelectOr) && /*#__PURE__*/ jsx(OperatorsSection, {
132
136
  onSelectAnd: onSelectAnd,
133
- onSelectOr: onSelectOr
137
+ onSelectOr: onSelectOr,
138
+ registerItem: registerItem
134
139
  }),
135
140
  /*#__PURE__*/ jsxs(DropdownMenuFooter, {
136
141
  children: [
@@ -1,5 +1,5 @@
1
1
  import { type FC, type RefObject } from 'react';
2
- import type { ChipSegment } from '../FilterInputField/FilterInputChip';
2
+ import { type ChipSegment } from '../FilterInputField/FilterInputChip';
3
3
  import type { FieldMetadata, FilterOperator, MenuState } from '../types';
4
4
  export interface FilterInputAutocompleteState {
5
5
  inputText: string;
@@ -1,5 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
+ import { SEGMENT_VARIANT } from "../FilterInputField/FilterInputChip/index.js";
3
4
  import { getCurrentValueTokenText, getFieldValues, getValueFilterText, isBetweenOperator, isMultiSelectOperator } from "../lib/index.js";
4
5
  import { FilterInputDateValueMenu } from "./FilterInputDateValueMenu/index.js";
5
6
  import { FilterInputFieldMenu } from "./FilterInputFieldMenu/index.js";
@@ -7,8 +8,8 @@ import { FilterInputOperatorMenu } from "./FilterInputOperatorMenu.js";
7
8
  import { FilterInputValueMenu } from "./FilterInputValueMenu/index.js";
8
9
  const FilterInputMenu = ({ fields, autocomplete })=>{
9
10
  const { inputText, menuState, selectedField, selectedOperator, menuPositioning, editingMultiValues, editingSingleValue, editingDateRange, inputRef, menuRef, handleFieldSelect, handleOperatorSelect, handleValueSelect, handleMultiCommit, handleRangeSelect, handleMenuClose, handleMenuDiscard, handleBuildingValueChange, handleMultiSelectToggle, segmentMenuFilterText, editingSegment, blurCommitRef } = autocomplete;
10
- const fieldFilterText = 'attribute' === editingSegment ? segmentMenuFilterText : inputText;
11
- const operatorFilterText = 'operator' === editingSegment ? segmentMenuFilterText : inputText;
11
+ const fieldFilterText = editingSegment === SEGMENT_VARIANT.attribute ? segmentMenuFilterText : inputText;
12
+ const operatorFilterText = editingSegment === SEGMENT_VARIANT.operator ? segmentMenuFilterText : inputText;
12
13
  const currentTokenText = getCurrentValueTokenText(editingSegment, inputText, segmentMenuFilterText, selectedOperator);
13
14
  const selectedContext = useMemo(()=>({
14
15
  selectedValues: [
@@ -36,7 +36,7 @@ const FilterInputOperatorMenu = ({ fieldType, operators, onSelect, open = false,
36
36
  filteredGroups,
37
37
  fieldType
38
38
  ]);
39
- const { highlightedValue, onHighlightChange } = useKeyboardNav({
39
+ const { highlightedValue, onHighlightChange, registerItem } = useKeyboardNav({
40
40
  items: flatItems,
41
41
  open,
42
42
  onSelect: (item)=>onSelect(item.value),
@@ -56,12 +56,14 @@ const FilterInputOperatorMenu = ({ fieldType, operators, onSelect, open = false,
56
56
  children: /*#__PURE__*/ jsxs(DropdownMenuContent, {
57
57
  ref: menuRef,
58
58
  className: cn('w-256 max-h-[430px]', className),
59
+ "data-filter-input-menu": "true",
59
60
  children: [
60
61
  filteredGroups.length > 0 ? filteredGroups.map((group, groupIdx)=>/*#__PURE__*/ jsxs(Fragment, {
61
62
  children: [
62
63
  /*#__PURE__*/ jsx(DropdownMenuGroup, {
63
64
  children: group.map((operator)=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
64
65
  value: operator,
66
+ ref: registerItem(operator),
65
67
  onSelect: ()=>onSelect(operator),
66
68
  children: [
67
69
  /*#__PURE__*/ jsx(DropdownMenuItemText, {
@@ -16,7 +16,7 @@ const FilterInputValueMenu = ({ values, onSelect, onCommit, open = false, onOpen
16
16
  values,
17
17
  filterText
18
18
  ]);
19
- const { selectedValues, checkedValues, highlightedValue, onHighlightChange, pendingIds, handleItemSelect } = useValueMenuState({
19
+ const { selectedValues, checkedValues, highlightedValue, onHighlightChange, pendingIds, registerItem, handleItemSelect } = useValueMenuState({
20
20
  values: filteredValues,
21
21
  open,
22
22
  multiSelect,
@@ -54,13 +54,15 @@ const FilterInputValueMenu = ({ values, onSelect, onCommit, open = false, onOpen
54
54
  ref: menuRef,
55
55
  className: cn(widthClass, 'max-h-[430px]', className),
56
56
  style: widthStyle,
57
+ "data-filter-input-menu": "true",
57
58
  children: [
58
59
  displayValues.length > 0 ? /*#__PURE__*/ jsx(DropdownMenuGroup, {
59
60
  children: displayValues.map((option)=>/*#__PURE__*/ jsx(ValueMenuItem, {
60
61
  option: option,
61
- isChecked: selectedValues.includes(option.value),
62
+ isChecked: selectedValues.some((v)=>String(v) === String(option.value)),
62
63
  isPending: pendingIds.has(String(option.value)),
63
64
  multiSelect: multiSelect,
65
+ registerItem: registerItem,
64
66
  onSelect: ()=>handleItemSelect({
65
67
  id: String(option.value),
66
68
  label: option.label,
@@ -6,6 +6,7 @@ interface ValueMenuItemProps {
6
6
  isPending: boolean;
7
7
  multiSelect: boolean;
8
8
  onSelect: () => void;
9
+ registerItem?: (id: string) => (el: HTMLElement | null) => void;
9
10
  }
10
11
  export declare const ValueMenuItem: FC<ValueMenuItemProps>;
11
12
  export {};
@@ -4,8 +4,9 @@ import { Badge } from "../../../Badge/index.js";
4
4
  import { Checkmark } from "../../../Checkmark/index.js";
5
5
  import { DropdownMenuItem } from "../../../DropdownMenu/index.js";
6
6
  import { Text } from "../../../Text/index.js";
7
- const ValueMenuItem = ({ option, isChecked, isPending, multiSelect, onSelect })=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
7
+ const ValueMenuItem = ({ option, isChecked, isPending, multiSelect, onSelect, registerItem })=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
8
8
  value: String(option.value),
9
+ ref: registerItem?.(String(option.value)),
9
10
  onSelect: onSelect,
10
11
  className: isPending ? 'bg-states-primary-hover' : void 0,
11
12
  children: [
@@ -31,6 +31,7 @@ export declare const useValueMenuState: ({ values, open, multiSelect, initialVal
31
31
  highlightedValue: string | null;
32
32
  }) => void;
33
33
  pendingIds: Set<string>;
34
+ registerItem: (id: string) => (el: HTMLElement | null) => void;
34
35
  commitChecked: () => boolean;
35
36
  handleItemSelect: (item: FilterInputDropdownItem) => void;
36
37
  };
@@ -24,10 +24,14 @@ const useValueMenuState = ({ values, open, multiSelect, initialValues, highlight
24
24
  open
25
25
  ]);
26
26
  const toggleValue = (val)=>{
27
- setCheckedValues((prev)=>prev.includes(val) ? prev.filter((v)=>v !== val) : [
27
+ setCheckedValues((prev)=>{
28
+ const key = String(val);
29
+ const exists = prev.some((v)=>String(v) === key);
30
+ return exists ? prev.filter((v)=>String(v) !== key) : [
28
31
  ...prev,
29
32
  val
30
- ]);
33
+ ];
34
+ });
31
35
  };
32
36
  const onCommitRef = useRef(onCommit);
33
37
  onCommitRef.current = onCommit;
@@ -68,7 +72,7 @@ const useValueMenuState = ({ values, open, multiSelect, initialValues, highlight
68
72
  if (multiSelect) commitChecked();
69
73
  onOpenChange?.(false);
70
74
  };
71
- const { highlightedValue, onHighlightChange, pendingIds } = useKeyboardNav({
75
+ const { highlightedValue, onHighlightChange, pendingIds, registerItem } = useKeyboardNav({
72
76
  items: flatItems,
73
77
  open,
74
78
  onSelect: handleItemSelect,
@@ -94,6 +98,7 @@ const useValueMenuState = ({ values, open, multiSelect, initialValues, highlight
94
98
  highlightedValue,
95
99
  onHighlightChange,
96
100
  pendingIds,
101
+ registerItem,
97
102
  commitChecked,
98
103
  handleItemSelect
99
104
  };
@@ -32,5 +32,6 @@ export declare const useKeyboardNav: ({ items, open, onSelect, onClose, onArrowR
32
32
  highlightedValue: string | null;
33
33
  }) => void;
34
34
  pendingIds: Set<string>;
35
+ registerItem: (id: string) => (el: HTMLElement | null) => void;
35
36
  };
36
37
  export {};