@wallarm-org/design-system 0.87.1 → 0.88.1-rc-fix-status-code-zero-value.1

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 (137) hide show
  1. package/dist/components/Alert/Alert.d.ts +1 -1
  2. package/dist/components/AnimatedBackground/pixel/module/celebration.d.ts +2 -2
  3. package/dist/components/AnimatedBackground/pixel/module/game-logic.d.ts +1 -1
  4. package/dist/components/AppShell/story-content/_storyLib.d.ts +1 -1
  5. package/dist/components/Badge/classes.d.ts +2 -2
  6. package/dist/components/Badge/constants.d.ts +26 -26
  7. package/dist/components/Banner/classes.d.ts +4 -4
  8. package/dist/components/Button/Button.d.ts +2 -2
  9. package/dist/components/ButtonBase/classes.d.ts +1 -1
  10. package/dist/components/Calendar/CalendarContext.d.ts +4 -4
  11. package/dist/components/Calendar/CalendarTrigger.d.ts +4 -12
  12. package/dist/components/Calendar/const.d.ts +2 -2
  13. package/dist/components/Checkbox/CheckboxGroup.d.ts +1 -1
  14. package/dist/components/Code/Code.d.ts +3 -3
  15. package/dist/components/CodeSnippet/CodeSnippetRoot.d.ts +5 -8
  16. package/dist/components/CodeSnippet/lib/httpFolds.d.ts +2 -2
  17. package/dist/components/Country/Country.d.ts +1 -1
  18. package/dist/components/Country/CountryFlag.d.ts +1 -1
  19. package/dist/components/Country/countries.d.ts +497 -497
  20. package/dist/components/DropdownMenu/classes.d.ts +1 -1
  21. package/dist/components/DropdownMenu/classes.js +1 -1
  22. package/dist/components/Field/Field.d.ts +1 -1
  23. package/dist/components/FilterInput/FilterInputField/FilterInputChip/classes.d.ts +1 -1
  24. package/dist/components/FilterInput/FilterInputField/FilterInputChip/segmentVariant.d.ts +3 -3
  25. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/FlatValueMenu.js +1 -0
  26. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/NestedValueMenuItem.js +1 -26
  27. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/ValueMenuItem.d.ts +2 -0
  28. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/ValueMenuItem.js +4 -3
  29. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/highlightMatch.d.ts +11 -0
  30. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/highlightMatch.js +28 -0
  31. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/useNestedValueMenuState.js +2 -2
  32. package/dist/components/FilterInput/FilterInputMenu/FilterInputValueMenu/valueOptionSearchText.d.ts +1 -1
  33. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/lib/valueResolution.d.ts +1 -1
  34. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useChipCascade.d.ts +1 -1
  35. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFilterInputAutocomplete.d.ts +2 -2
  36. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useMenuPositioning.d.ts +1 -1
  37. package/dist/components/FilterInput/hooks/useFilterInputExpression/buildChips.d.ts +1 -1
  38. package/dist/components/FilterInput/hooks/useFilterInputExpression/buildChips.js +1 -1
  39. package/dist/components/FilterInput/hooks/useFilterInputExpression/expression.d.ts +2 -2
  40. package/dist/components/FilterInput/hooks/useFilterInputExpression/useFilterInputExpression.d.ts +2 -2
  41. package/dist/components/FilterInput/hooks/useFilterInputPositioning.d.ts +1 -1
  42. package/dist/components/FilterInput/hooks/useFilterInputSelection/lib/serialize.d.ts +1 -1
  43. package/dist/components/FilterInput/lib/applyKnownFieldHelpers.d.ts +1 -1
  44. package/dist/components/FilterInput/lib/collapseValuesToLabels.d.ts +20 -18
  45. package/dist/components/FilterInput/lib/collapseValuesToLabels.js +12 -19
  46. package/dist/components/FilterInput/lib/conditions.d.ts +2 -2
  47. package/dist/components/FilterInput/lib/constants.d.ts +6 -3
  48. package/dist/components/FilterInput/lib/constants.js +1 -1
  49. package/dist/components/FilterInput/lib/index.d.ts +1 -1
  50. package/dist/components/FilterInput/lib/index.js +1 -1
  51. package/dist/components/FilterInput/lib/statusCode/createStatusCodeNormalizer.d.ts +3 -1
  52. package/dist/components/FilterInput/lib/statusCode/createStatusCodeNormalizer.js +2 -0
  53. package/dist/components/FilterInput/lib/statusCode/createStatusCodeSerializer.d.ts +3 -1
  54. package/dist/components/FilterInput/lib/statusCode/createStatusCodeSerializer.js +2 -0
  55. package/dist/components/FilterInput/lib/statusCode/createStatusCodeSuggestions.js +2 -2
  56. package/dist/components/FilterInput/lib/statusCode/createStatusCodeValidator.d.ts +4 -0
  57. package/dist/components/FilterInput/lib/statusCode/createStatusCodeValidator.js +2 -1
  58. package/dist/components/FilterInput/lib/statusCode/utils/constants.d.ts +6 -0
  59. package/dist/components/FilterInput/lib/statusCode/utils/constants.js +2 -1
  60. package/dist/components/FilterInput/lib/statusCode/utils/index.d.ts +1 -1
  61. package/dist/components/FilterInput/lib/statusCode/utils/index.js +1 -1
  62. package/dist/components/FilterInput/lib/statusCode/utils/makeMask.d.ts +3 -1
  63. package/dist/components/FilterInput/lib/statusCode/utils/makeMask.js +12 -1
  64. package/dist/components/FilterInput/lib/validation.d.ts +1 -1
  65. package/dist/components/Flex/Flex.d.ts +6 -6
  66. package/dist/components/Heading/Heading.d.ts +3 -3
  67. package/dist/components/InlineEdit/InlineEditSelect.d.ts +4 -4
  68. package/dist/components/Input/classes.d.ts +1 -1
  69. package/dist/components/InputGroup/InputGroup.d.ts +1 -1
  70. package/dist/components/InputGroup/InputGroupAddon.d.ts +2 -2
  71. package/dist/components/Ip/constants.d.ts +21 -21
  72. package/dist/components/Kbd/Kbd.d.ts +1 -1
  73. package/dist/components/Link/classes.d.ts +3 -3
  74. package/dist/components/Loader/Loader.d.ts +2 -2
  75. package/dist/components/Logo/classes.d.ts +1 -1
  76. package/dist/components/NumberInput/classes.d.ts +4 -4
  77. package/dist/components/NumericBadge/classes.d.ts +2 -2
  78. package/dist/components/OverflowTooltip/OverflowTooltip.d.ts +4 -8
  79. package/dist/components/OverflowTooltip/OverflowTooltipContent.d.ts +4 -7
  80. package/dist/components/Pagination/classes.d.ts +2 -2
  81. package/dist/components/ParameterPath/constants.d.ts +7 -7
  82. package/dist/components/Progress/classes.d.ts +2 -2
  83. package/dist/components/Progress/constants.d.ts +22 -22
  84. package/dist/components/Radio/RadioGroup.d.ts +1 -1
  85. package/dist/components/SegmentedControl/SegmentedControlSeparator.d.ts +1 -1
  86. package/dist/components/Select/Select.d.ts +4 -4
  87. package/dist/components/Select/SelectInput/SelectInputOverflowRenderer.d.ts +1 -1
  88. package/dist/components/Selection/Selection.d.ts +4 -4
  89. package/dist/components/Separator/Separator.d.ts +1 -1
  90. package/dist/components/SimpleCharts/BarList/classes.d.ts +3 -3
  91. package/dist/components/SimpleCharts/LineChart/constants.d.ts +2 -2
  92. package/dist/components/SimpleCharts/PieChart/classes.d.ts +2 -2
  93. package/dist/components/Skeleton/Skeleton.d.ts +1 -1
  94. package/dist/components/SplashScreen/classes.d.ts +4 -4
  95. package/dist/components/Stack/Stack.d.ts +5 -5
  96. package/dist/components/Table/EditableCell/EditableSelectCell.d.ts +28 -0
  97. package/dist/components/Table/EditableCell/EditableSelectCell.js +66 -0
  98. package/dist/components/Table/EditableCell/EditableTextCell.d.ts +22 -0
  99. package/dist/components/Table/EditableCell/EditableTextCell.js +78 -0
  100. package/dist/components/Table/EditableCell/classes.d.ts +11 -0
  101. package/dist/components/Table/EditableCell/classes.js +17 -0
  102. package/dist/components/Table/EditableCell/constants.d.ts +19 -0
  103. package/dist/components/Table/EditableCell/constants.js +4 -0
  104. package/dist/components/Table/EditableCell/index.d.ts +4 -0
  105. package/dist/components/Table/EditableCell/index.js +4 -0
  106. package/dist/components/Table/Table.d.ts +4 -4
  107. package/dist/components/Table/TableBody/TableBodyCell.d.ts +4 -4
  108. package/dist/components/Table/TableColumnMenu/TableColumnMenu.d.ts +4 -16
  109. package/dist/components/Table/TableHeadCell.d.ts +4 -4
  110. package/dist/components/Table/TableImperativeBridge.d.ts +4 -9
  111. package/dist/components/Table/TableMasterCellActions.d.ts +4 -4
  112. package/dist/components/Table/TableResizeHandler.d.ts +4 -4
  113. package/dist/components/Table/TableRow.d.ts +1 -1
  114. package/dist/components/Table/TableRowExpanded.d.ts +4 -4
  115. package/dist/components/Table/TableSettingsMenu/TableSettingsMenuItem.d.ts +4 -4
  116. package/dist/components/Table/TableSortHandler.d.ts +4 -4
  117. package/dist/components/Table/TableSortTrigger.d.ts +4 -19
  118. package/dist/components/Table/index.d.ts +1 -0
  119. package/dist/components/Table/index.js +1 -0
  120. package/dist/components/Table/lib/detectDataChange.d.ts +1 -1
  121. package/dist/components/Table/lib/isLastPinnedLeft.d.ts +2 -2
  122. package/dist/components/Tabs/classes.d.ts +1 -1
  123. package/dist/components/Text/Text.d.ts +5 -5
  124. package/dist/components/Textarea/classes.d.ts +2 -2
  125. package/dist/components/Toast/Toast.d.ts +4 -4
  126. package/dist/components/Toast/ToastClose.d.ts +4 -4
  127. package/dist/components/Toast/useToast.d.ts +4 -4
  128. package/dist/components/ToggleButton/ToggleButton.d.ts +1 -1
  129. package/dist/components/Tour/lib/waitForStepEvent.d.ts +1 -1
  130. package/dist/components/WallyIcon/classes.d.ts +1 -1
  131. package/dist/icons/SvgIcon.d.ts +1 -1
  132. package/dist/index.d.ts +1 -1
  133. package/dist/index.js +1 -1
  134. package/dist/metadata/components.json +627 -13
  135. package/dist/utils/hasNonTextEnd.d.ts +1 -1
  136. package/dist/utils/isIconOnly.d.ts +1 -1
  137. package/package.json +15 -17
@@ -1,6 +1,6 @@
1
1
  export declare const dropdownMenuClassNames: string;
2
2
  export declare const dropdownMenuItemVariants: (props?: ({
3
- variant?: "destructive" | "brand" | "default" | null | undefined;
3
+ variant?: "brand" | "default" | "destructive" | null | undefined;
4
4
  inset?: boolean | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export declare const dropdownMenuItemIndicatorClassName: string;
@@ -1,6 +1,6 @@
1
1
  import { cva } from "class-variance-authority";
2
2
  import { cn } from "../../utils/cn.js";
3
- const dropdownMenuClassNames = cn('flex flex-col gap-1 min-w-128', 'z-[calc(var(--drawer-positioner-z-index)+(var(--layer-index,0)*var(--drawer-level-ratio)))]', 'overflow-y-auto overflow-x-hidden outline-none', 'rounded-12 border border-border-primary-light bg-bg-surface-2 p-8 font-sans text-text-primary shadow-md outline-none', 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2');
3
+ const dropdownMenuClassNames = cn('flex flex-col gap-1 min-w-128', 'z-[calc(var(--drawer-positioner-z-index)+(var(--layer-index,0)*var(--drawer-level-ratio)))]', 'overflow-y-auto overflow-x-hidden outline-none overscroll-none [&_[data-part=viewport]]:overscroll-none', 'rounded-12 border border-border-primary-light bg-bg-surface-2 p-8 font-sans text-text-primary shadow-md outline-none', 'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2');
4
4
  const dropdownMenuItemVariants = cva([
5
5
  'flex items-center gap-8 rounded-6 px-8 py-6 text-sm',
6
6
  'relative cursor-pointer select-none outline-none transition-colors',
@@ -3,7 +3,7 @@ import { Field as ArkUiField } from '@ark-ui/react/field';
3
3
  import { type VariantProps } from 'class-variance-authority';
4
4
  import { type TestableProps } from '../../utils/testId';
5
5
  declare const fieldVariants: (props?: ({
6
- orientation?: "horizontal" | "vertical" | "responsive" | null | undefined;
6
+ orientation?: "horizontal" | "responsive" | "vertical" | null | undefined;
7
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
8
  type FieldNativeProps = Omit<HTMLAttributes<HTMLElement>, 'className'> & Omit<ArkUiField.RootProps, 'className'>;
9
9
  type FieldVariantsProps = VariantProps<typeof fieldVariants>;
@@ -16,7 +16,7 @@ export declare const emptyValueHitTarget = "min-w-[4px] self-stretch";
16
16
  export declare const editingValueMinWidth = "min-w-0";
17
17
  /** Segment text styles by variant */
18
18
  export declare const segmentTextVariants: (props?: ({
19
- variant?: "value" | "operator" | "attribute" | null | undefined;
19
+ variant?: "attribute" | "operator" | "value" | null | undefined;
20
20
  error?: boolean | null | undefined;
21
21
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
22
22
  /** Remove button styles — hidden by default, shown on chip hover or button focus.
@@ -1,7 +1,7 @@
1
1
  export declare const SEGMENT_VARIANT: {
2
- readonly attribute: "attribute";
3
- readonly operator: "operator";
4
- readonly value: "value";
2
+ readonly attribute: 'attribute';
3
+ readonly operator: 'operator';
4
+ readonly value: 'value';
5
5
  };
6
6
  export type SegmentVariant = (typeof SEGMENT_VARIANT)[keyof typeof SEGMENT_VARIANT];
7
7
  /** data-slot for the decorative ";" between paired triplets (non-interactive). */
@@ -62,6 +62,7 @@ const FlatValueMenu = ({ values, onSelect, onCommit, open = false, onOpenChange,
62
62
  isPending: pendingIds.has(String(option.value)),
63
63
  multiSelect: multiSelect,
64
64
  registerItem: registerItem,
65
+ highlight: filterText,
65
66
  onSelect: ()=>handleItemSelect({
66
67
  id: String(option.value),
67
68
  label: option.label,
@@ -5,32 +5,7 @@ import { Badge } from "../../../Badge/index.js";
5
5
  import { Checkmark } from "../../../Checkmark/index.js";
6
6
  import { DropdownMenuItem } from "../../../DropdownMenu/index.js";
7
7
  import { Text } from "../../../Text/index.js";
8
- const highlightMatch = (text, query)=>{
9
- const q = query?.trim().toLowerCase();
10
- if (!q) return text;
11
- const lower = text.toLowerCase();
12
- const parts = [];
13
- let cursor = 0;
14
- let key = 0;
15
- while(cursor < text.length){
16
- const at = lower.indexOf(q, cursor);
17
- if (-1 === at) {
18
- parts.push(/*#__PURE__*/ jsx("span", {
19
- children: text.slice(cursor)
20
- }, key++));
21
- break;
22
- }
23
- if (at > cursor) parts.push(/*#__PURE__*/ jsx("span", {
24
- children: text.slice(cursor, at)
25
- }, key++));
26
- parts.push(/*#__PURE__*/ jsx("mark", {
27
- className: "bg-transparent font-medium text-text-brand",
28
- children: text.slice(at, at + q.length)
29
- }, key++));
30
- cursor = at + q.length;
31
- }
32
- return parts;
33
- };
8
+ import { highlightMatch } from "./highlightMatch.js";
34
9
  const NestedValueMenuItem = ({ id, option, isGroup, checkedState, isPending, multiSelect, onSelect, onMouseEnter, onMouseLeave, registerRef, expanded, selectAll, highlight })=>{
35
10
  const isChecked = true === checkedState;
36
11
  const checkmark = multiSelect || !isGroup && checkedState ? /*#__PURE__*/ jsx(Checkmark, {
@@ -7,6 +7,8 @@ interface ValueMenuItemProps {
7
7
  multiSelect: boolean;
8
8
  onSelect: () => void;
9
9
  registerItem?: (id: string) => (el: HTMLElement | null) => void;
10
+ /** Active search query — matched substrings in label/description are emphasized. */
11
+ highlight?: string;
10
12
  }
11
13
  export declare const ValueMenuItem: FC<ValueMenuItemProps>;
12
14
  export {};
@@ -4,7 +4,8 @@ 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, registerItem })=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
7
+ import { highlightMatch } from "./highlightMatch.js";
8
+ const ValueMenuItem = ({ option, isChecked, isPending, multiSelect, onSelect, registerItem, highlight })=>/*#__PURE__*/ jsxs(DropdownMenuItem, {
8
9
  value: String(option.value),
9
10
  ref: registerItem?.(String(option.value)),
10
11
  onSelect: onSelect,
@@ -21,13 +22,13 @@ const ValueMenuItem = ({ option, isChecked, isPending, multiSelect, onSelect, re
21
22
  /*#__PURE__*/ jsx(Text, {
22
23
  size: "sm",
23
24
  truncate: true,
24
- children: option.label
25
+ children: highlightMatch(option.label, highlight)
25
26
  }),
26
27
  option.description && /*#__PURE__*/ jsx(Text, {
27
28
  size: "xs",
28
29
  color: "secondary",
29
30
  truncate: true,
30
- children: option.description
31
+ children: highlightMatch(option.description, highlight)
31
32
  })
32
33
  ]
33
34
  }),
@@ -0,0 +1,11 @@
1
+ import type { ReactNode } from 'react';
2
+ /**
3
+ * Wrap every case-insensitive occurrence of `query` in `text` with a brand-filled
4
+ * emphasis (orange background + light text — the same tokens DateInput uses for a
5
+ * focused segment), so a search match reads at a glance. Returns the raw string
6
+ * when there's no query (the common, non-search path) so nothing changes there.
7
+ *
8
+ * Shared by the flat (`ValueMenuItem`) and nested (`NestedValueMenuItem`) value
9
+ * menus so first- and second-level search highlights stay visually identical.
10
+ */
11
+ export declare const highlightMatch: (text: string, query?: string) => ReactNode;
@@ -0,0 +1,28 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ const highlightMatch = (text, query)=>{
3
+ const q = query?.trim().toLowerCase();
4
+ if (!q) return text;
5
+ const lower = text.toLowerCase();
6
+ const parts = [];
7
+ let cursor = 0;
8
+ let key = 0;
9
+ while(cursor < text.length){
10
+ const at = lower.indexOf(q, cursor);
11
+ if (-1 === at) {
12
+ parts.push(/*#__PURE__*/ jsx("span", {
13
+ children: text.slice(cursor)
14
+ }, key++));
15
+ break;
16
+ }
17
+ if (at > cursor) parts.push(/*#__PURE__*/ jsx("span", {
18
+ children: text.slice(cursor, at)
19
+ }, key++));
20
+ parts.push(/*#__PURE__*/ jsx("mark", {
21
+ className: "rounded-2 bg-bg-fill-brand font-medium text-text-primary-alt",
22
+ children: text.slice(at, at + q.length)
23
+ }, key++));
24
+ cursor = at + q.length;
25
+ }
26
+ return parts;
27
+ };
28
+ export { highlightMatch };
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
- import { collectLeaves } from "../../lib/index.js";
2
+ import { collapseValueOptions, collectLeaves } from "../../lib/index.js";
3
3
  import { useKeyboardNav } from "../hooks/useKeyboardNav.js";
4
4
  const SELECT_ALL_ID = '__filter_value_select_all__';
5
5
  const leafKeys = (option)=>collectLeaves(option.children).map((leaf)=>String(leaf.value));
@@ -279,7 +279,7 @@ const useNestedValueMenuState = ({ sections, allValues, open, multiSelect, initi
279
279
  }, [
280
280
  allValues
281
281
  ]);
282
- const buildingMultiValue = multiSelect && checkedValues.length > 0 ? checkedValues.map((v)=>labelByValue.get(String(v)) ?? String(v)).join(', ') : void 0;
282
+ const buildingMultiValue = multiSelect && checkedValues.length > 0 ? collapseValueOptions(allValues, checkedValues).map((token)=>'group' === token.kind ? token.label : labelByValue.get(String(token.value)) ?? String(token.value)).join(', ') : void 0;
283
283
  useEffect(()=>{
284
284
  onBuildingValueChange?.(buildingMultiValue);
285
285
  }, [
@@ -4,4 +4,4 @@ import type { ValueOption } from './FilterInputValueMenu';
4
4
  * its optional `description` (so a path fragment finds the row). Fed to
5
5
  * `filterAndSort`. The description entry is omitted when absent.
6
6
  */
7
- export declare const valueOptionSearchText: (option: Pick<ValueOption, "value" | "label" | "description">) => string[];
7
+ export declare const valueOptionSearchText: (option: Pick<ValueOption, 'value' | 'label' | 'description'>) => string[];
@@ -24,5 +24,5 @@ export declare const resolveDateRangeValue: (trimmed: string) => [string, string
24
24
  /** Validate and resolve a date value from text */
25
25
  export declare const resolveDateValue: (trimmed: string, editingChipId: string | null, conditions: Condition[]) => {
26
26
  error: boolean | undefined;
27
- dateOrigin: "relative" | "absolute" | undefined;
27
+ dateOrigin: 'relative' | 'absolute' | undefined;
28
28
  };
@@ -39,6 +39,6 @@ interface UseChipCascadeOptions {
39
39
  export declare const useChipCascade: ({ editing, chips, fields, conditionsRef, selectedField, selectedOperator, buildingMultiValue, upsertCondition, removeCondition, resetState, setInputText, setMenuState, setSelectedOperator, setBuildingMultiValue, }: UseChipCascadeOptions) => {
40
40
  switchEditSegment: (targetSegment: ChipSegment) => boolean;
41
41
  removeEditingChip: () => void;
42
- stepBackBuildingMenu: (current: "field" | "operator" | "value") => void;
42
+ stepBackBuildingMenu: (current: 'field' | 'operator' | 'value') => void;
43
43
  };
44
44
  export {};
@@ -22,7 +22,7 @@ export declare const useFilterInputAutocomplete: ({ fields, conditions, chips, u
22
22
  isBuilding: boolean;
23
23
  buildingChipData: import("../../FilterInputContext").BuildingChipData | null;
24
24
  menuPositioning: {
25
- placement: "bottom-start";
25
+ placement: 'bottom-start';
26
26
  gutter: number;
27
27
  getAnchorRect: () => {
28
28
  x: number;
@@ -55,7 +55,7 @@ export declare const useFilterInputAutocomplete: ({ fields, conditions, chips, u
55
55
  handleBuildingChipClick: (segment: ChipSegment, anchorEl: HTMLElement) => void;
56
56
  switchEditSegment: (targetSegment: ChipSegment) => boolean;
57
57
  removeEditingChip: () => void;
58
- handleConnectorChange: (connectorId: string, value: "and" | "or") => void;
58
+ handleConnectorChange: (connectorId: string, value: 'and' | 'or') => void;
59
59
  handleChipRemove: (chipId: string) => void;
60
60
  handleClear: () => void;
61
61
  handleKeyDown: (e: import("react").KeyboardEvent<HTMLInputElement>) => void;
@@ -32,7 +32,7 @@ interface UseMenuPositioningOptions {
32
32
  */
33
33
  export declare const useMenuPositioning: ({ containerRef, buildingChipRef, inputRef, isBuilding, insertIndex, chipsCount, isMenuOpen, }: UseMenuPositioningOptions) => {
34
34
  menuPositioning: {
35
- placement: "bottom-start";
35
+ placement: 'bottom-start';
36
36
  gutter: number;
37
37
  getAnchorRect: () => {
38
38
  x: number;
@@ -3,4 +3,4 @@ import type { Condition, FieldMetadata, FilterInputChipData } from '../../types'
3
3
  * Derive display chips from conditions + connectors.
4
4
  * When AND and OR are mixed, AND-groups of 2+ conditions get wrapped in parentheses.
5
5
  */
6
- export declare const buildChips: (conditions: Condition[], connectors: Array<"and" | "or">, fields: FieldMetadata[], error: boolean) => FilterInputChipData[];
6
+ export declare const buildChips: (conditions: Condition[], connectors: Array<'and' | 'or'>, fields: FieldMetadata[], error: boolean) => FilterInputChipData[];
@@ -70,7 +70,7 @@ const buildDateChip = (baseChip, condition, chipError)=>{
70
70
  const buildMultiValueChip = (baseChip, condition, field, fields, chipError)=>{
71
71
  const values = condition.value;
72
72
  const invalidIndices = field ? getInvalidValueIndices(field, values) : [];
73
- const valueParts = field && 0 === invalidIndices.length ? collapseValues(field, values).map((token)=>'group' === token.kind ? null != token.count ? `${token.label} (${token.count})` : token.label : resolveValueLabel(token.value, field, fields) ?? String(token.value)) : values.map((v)=>resolveValueLabel(v, field, fields) ?? String(v));
73
+ const valueParts = field && 0 === invalidIndices.length ? collapseValues(field, values).map((token)=>'group' === token.kind ? token.label : resolveValueLabel(token.value, field, fields) ?? String(token.value)) : values.map((v)=>resolveValueLabel(v, field, fields) ?? String(v));
74
74
  return {
75
75
  ...baseChip,
76
76
  value: valueParts.join(MULTI_VALUE_SEPARATOR),
@@ -7,7 +7,7 @@ import type { Condition, ExprNode, FieldMetadata } from '../../types';
7
7
  * Pass `fields` to expand paired conditions into two AND-joined conditions
8
8
  * (the serialization contract). Omit it to keep paired conditions intact.
9
9
  */
10
- export declare const buildExpression: (rawConditions: Condition[], rawConnectors: Array<"and" | "or">, fields?: FieldMetadata[]) => ExprNode | null;
10
+ export declare const buildExpression: (rawConditions: Condition[], rawConnectors: Array<'and' | 'or'>, fields?: FieldMetadata[]) => ExprNode | null;
11
11
  /**
12
12
  * Flatten a (possibly nested) ExprNode back to flat conditions + connectors.
13
13
  * Walks the tree depth-first; between siblings inserts the parent's operator.
@@ -17,5 +17,5 @@ export declare const buildExpression: (rawConditions: Condition[], rawConnectors
17
17
  */
18
18
  export declare const expressionToConditions: (expr: ExprNode | null, fields?: FieldMetadata[]) => {
19
19
  conditions: Condition[];
20
- connectors: Array<"and" | "or">;
20
+ connectors: Array<'and' | 'or'>;
21
21
  };
@@ -10,11 +10,11 @@ export declare const useFilterInputExpression: ({ fields, value, onChange, error
10
10
  conditions: Condition[];
11
11
  connectors: ("and" | "or")[];
12
12
  chips: import("../..").FilterInputChipData[];
13
- upsertCondition: (field: FieldMetadata, operator: FilterOperator | undefined, val: string | number | boolean | null | Array<string | number | boolean>, editingChipId?: string | null, atIndex?: number, error?: ChipErrorSegment, dateOrigin?: "relative" | "absolute", side?: 0 | 1) => void;
13
+ upsertCondition: (field: FieldMetadata, operator: FilterOperator | undefined, val: string | number | boolean | null | Array<string | number | boolean>, editingChipId?: string | null, atIndex?: number, error?: ChipErrorSegment, dateOrigin?: 'relative' | 'absolute', side?: 0 | 1) => void;
14
14
  removeCondition: (chipId: string) => void;
15
15
  removeConditionAtIndex: (idx: number) => void;
16
16
  clearAll: () => void;
17
17
  replaceExpression: (expr: ExprNode | null) => void;
18
- setConnectorValue: (connectorId: string, value: "and" | "or") => void;
18
+ setConnectorValue: (connectorId: string, value: 'and' | 'or') => void;
19
19
  };
20
20
  export {};
@@ -18,7 +18,7 @@ interface UseFilterInputPositioningProps {
18
18
  * @param deps - extra values that force positioning recalculation (e.g. insertIndex)
19
19
  */
20
20
  export declare const useFilterInputPositioning: ({ anchorRef, containerRef, getAnchorBounds, gutter }: UseFilterInputPositioningProps, deps?: unknown[]) => {
21
- placement: "bottom-start";
21
+ placement: 'bottom-start';
22
22
  gutter: number;
23
23
  getAnchorRect: () => {
24
24
  x: number;
@@ -1,3 +1,3 @@
1
1
  import type { Condition } from '../../../types';
2
2
  /** Serialize selected (drag) or all conditions into a text string */
3
- export declare const serializeSelectedOrAll: (conditions: Condition[], connectors: Array<"and" | "or">, chipRegistry: Map<string, HTMLElement>) => string;
3
+ export declare const serializeSelectedOrAll: (conditions: Condition[], connectors: Array<'and' | 'or'>, chipRegistry: Map<string, HTMLElement>) => string;
@@ -22,4 +22,4 @@ export declare const applyKnownFieldHelpers: (fields: FieldMetadata[]) => FieldM
22
22
  * undefined for unknown names. For consumers that hold their own expression
23
23
  * shape but want the same transform as FilterInput's `serializeValue`.
24
24
  */
25
- export declare const getKnownFieldSerializer: (fieldName: string) => NonNullable<FieldMetadata["serializeValue"]> | undefined;
25
+ export declare const getKnownFieldSerializer: (fieldName: string) => NonNullable<FieldMetadata['serializeValue']> | undefined;
@@ -1,32 +1,34 @@
1
- import type { FieldMetadata } from '../types';
1
+ import type { FieldMetadata, FieldValueOption } from '../types';
2
2
  /**
3
- * A display token for a multi-value chip. A `group` token stands in for a
4
- * **submenu** parent category (e.g. "SQL injection"): `count` present means a
5
- * partial selection ("SQL injection (4)"), `count` absent means every sub-value
6
- * is selected ("SQL injection"). A `leaf` token is a single committed value.
3
+ * A display token for a multi-value chip. A `group` token stands in for a group
4
+ * whose every descendant leaf is selected (e.g. "SQL injection", or a whole
5
+ * top-level section like "Input-based attacks") it renders as just the group
6
+ * label. A `leaf` token is a single committed value. Partial group selections
7
+ * are never a group token: they expand to their individual `leaf` tokens.
7
8
  */
8
9
  export type CollapseToken = {
9
10
  kind: 'group';
10
11
  label: string;
11
- count?: number;
12
12
  } | {
13
13
  kind: 'leaf';
14
14
  value: string | number | boolean;
15
15
  };
16
16
  /**
17
- * Collapse a committed leaf-value array into display tokens, folding a submenu
18
- * parent category into a single group token. Display-only: the stored
19
- * `Condition.value` array is never mutated and always holds leaf values.
17
+ * Collapse a leaf-value array into display tokens, folding a **fully selected**
18
+ * group into a single group token. Display-only: the underlying value array is
19
+ * never mutated and always holds leaf values.
20
20
  *
21
- * For a field with no nested groups this returns one leaf token per value in
22
- * the original committed order (identical to the previous flat behavior). For a
23
- * nested field it walks the config in declaration order:
24
- * - **Top-level groups are section headers** (no checkbox) — never collapsed;
25
- * we recurse so their direct leaves render individually.
26
- * - **Nested groups are submenu categories** any selection collapses to a
27
- * single group token: fully selected just the label; partially selected
28
- * label + selected-leaf `count`.
21
+ * Walks the config in declaration order:
22
+ * - A group with **every** descendant leaf selected collapses to a single group
23
+ * token (its label) this applies at any depth, so both a submenu category
24
+ * ("SQL injection") and a whole top-level section ("Input-based attacks")
25
+ * collapse the same way.
26
+ * - A **partially** selected group is not collapsed: we recurse into it so its
27
+ * selected leaves render individually, while any nested fully-selected
28
+ * subgroup still folds to its own label.
29
29
  *
30
- * Committed values absent from the config (freeform) trail in committed order.
30
+ * Values absent from the config (freeform) trail in original committed order.
31
31
  */
32
+ export declare const collapseValueOptions: (options: FieldValueOption[] | undefined, values: Array<string | number | boolean>) => CollapseToken[];
33
+ /** {@link collapseValueOptions} keyed off a field's own value config. */
32
34
  export declare const collapseValues: (field: FieldMetadata, values: Array<string | number | boolean>) => CollapseToken[];
@@ -1,6 +1,5 @@
1
1
  import { collectLeaves, isValueGroup } from "./fields.js";
2
- const collapseValues = (field, values)=>{
3
- const options = field.values;
2
+ const collapseValueOptions = (options, values)=>{
4
3
  const hasGroups = options?.some(isValueGroup) ?? false;
5
4
  if (!options || !hasGroups) return values.map((value)=>({
6
5
  kind: 'leaf',
@@ -9,25 +8,18 @@ const collapseValues = (field, values)=>{
9
8
  const committed = new Set(values.map(String));
10
9
  const consumed = new Set();
11
10
  const tokens = [];
12
- const walk = (opts, depth)=>{
11
+ const walk = (opts)=>{
13
12
  for (const option of opts)if (isValueGroup(option)) {
14
- if (0 === depth) {
15
- walk(option.children, depth + 1);
16
- continue;
17
- }
18
13
  const leafKeys = collectLeaves(option.children).map((leaf)=>String(leaf.value));
19
14
  const selected = leafKeys.filter((key)=>committed.has(key));
20
15
  if (0 === selected.length) continue;
21
- const isFull = selected.length === leafKeys.length;
22
- tokens.push(isFull ? {
23
- kind: 'group',
24
- label: option.label
25
- } : {
26
- kind: 'group',
27
- label: option.label,
28
- count: selected.length
29
- });
30
- for (const key of selected)consumed.add(key);
16
+ if (selected.length === leafKeys.length) {
17
+ tokens.push({
18
+ kind: 'group',
19
+ label: option.label
20
+ });
21
+ for (const key of selected)consumed.add(key);
22
+ } else walk(option.children);
31
23
  } else if (null != option.value) {
32
24
  const key = String(option.value);
33
25
  if (committed.has(key) && !consumed.has(key)) {
@@ -39,7 +31,7 @@ const collapseValues = (field, values)=>{
39
31
  }
40
32
  }
41
33
  };
42
- walk(options, 0);
34
+ walk(options);
43
35
  for (const value of values){
44
36
  const key = String(value);
45
37
  if (!consumed.has(key)) {
@@ -52,4 +44,5 @@ const collapseValues = (field, values)=>{
52
44
  }
53
45
  return tokens;
54
46
  };
55
- export { collapseValues };
47
+ const collapseValues = (field, values)=>collapseValueOptions(field.values, values);
48
+ export { collapseValueOptions, collapseValues };
@@ -2,13 +2,13 @@ import type { ChipErrorSegment, Condition, FilterInputChipData, FilterOperator }
2
2
  /** Map a chip ID (e.g. "chip-2") back to condition index */
3
3
  export declare const chipIdToConditionIndex: (chipId: string) => number | null;
4
4
  /** A filter value is empty when null/undefined, '', or an empty array. */
5
- export declare const isEmptyFilterValue: (value: Condition["value"] | undefined) => boolean;
5
+ export declare const isEmptyFilterValue: (value: Condition['value'] | undefined) => boolean;
6
6
  /**
7
7
  * Error segment for an incomplete triplet, or `undefined` when complete:
8
8
  * missing operator → whole triplet (`true`); value-bearing operator with an
9
9
  * empty value → the value segment; no-value operator ("is set") → complete.
10
10
  */
11
- export declare const incompleteTripletError: (operator: FilterOperator | null | undefined, value: Condition["value"] | undefined) => ChipErrorSegment | undefined;
11
+ export declare const incompleteTripletError: (operator: FilterOperator | null | undefined, value: Condition['value'] | undefined) => ChipErrorSegment | undefined;
12
12
  /**
13
13
  * Convert a condition-level insert index to a position in the chips array.
14
14
  * When `afterConnector` is true, split AFTER the connector preceding the target chip.
@@ -12,9 +12,12 @@ export declare const QUERY_BAR_SELECTOR = "[data-slot=\"filter-input\"]";
12
12
  /** Gap between the dropdown and the field border in the empty/initial state. */
13
13
  export declare const MENU_BASE_GUTTER = 4;
14
14
  /** Extra vertical offset added to the anchor's bottom when the dropdown is
15
- * anchored to a chip / input total visual gap becomes
16
- * MENU_BASE_GUTTER + MENU_CHIP_GUTTER_OFFSET (12). */
17
- export declare const MENU_CHIP_GUTTER_OFFSET = 8;
15
+ * anchored to a chip / input. A building chip (h-22) sits 10px inset from the
16
+ * field's bottom edge (measured: 8px py + 2px top-biased placement), so this
17
+ * offset cancels that inset — the visual gap below the field border stays =
18
+ * MENU_BASE_GUTTER in every state, matching the empty/field-anchored first
19
+ * level. Value verified live in Storybook, not derived from nominal sizes. */
20
+ export declare const MENU_CHIP_GUTTER_OFFSET = 10;
18
21
  /** Labels for non-chip filter chip variants (connectors, brackets). */
19
22
  export declare const VARIANT_LABELS: Partial<Record<FilterInputChipVariant, string>>;
20
23
  /** Raw operator symbols shown on the right side of menus. */
@@ -10,7 +10,7 @@ const CHIP_ID_PATTERN = /^chip-(\d+)$/;
10
10
  const CONNECTOR_ID_PATTERN = /^connector-(\d+)$/;
11
11
  const QUERY_BAR_SELECTOR = '[data-slot="filter-input"]';
12
12
  const MENU_BASE_GUTTER = 4;
13
- const MENU_CHIP_GUTTER_OFFSET = 8;
13
+ const MENU_CHIP_GUTTER_OFFSET = 10;
14
14
  const VARIANT_LABELS = {
15
15
  and: 'AND',
16
16
  or: 'OR',
@@ -5,7 +5,7 @@ export { applyFieldValueTransforms } from './applyFieldValueTransforms';
5
5
  export { applyKnownFieldHelpers, getKnownFieldSerializer } from './applyKnownFieldHelpers';
6
6
  export { buildFieldMenuSections, type FieldMenuSection } from './buildFieldMenuSections';
7
7
  export { buildValueMenuSections, type ValueMenuRow, type ValueMenuSection, } from './buildValueMenuSections';
8
- export { type CollapseToken, collapseValues } from './collapseValuesToLabels';
8
+ export { type CollapseToken, collapseValueOptions, collapseValues, } from './collapseValuesToLabels';
9
9
  export { chipIdToConditionIndex, findChipSplitIndex, incompleteTripletError, isEmptyFilterValue, } from './conditions';
10
10
  export { CONNECTOR_ID_PATTERN, MENU_BASE_GUTTER, MENU_CHIP_GUTTER_OFFSET, NO_VALUE_OPERATORS, OPERATOR_LABELS, OPERATOR_LABELS_BY_TYPE, OPERATOR_SYMBOLS, OPERATORS_BY_TYPE, QUERY_BAR_SELECTOR, VARIANT_LABELS, } from './constants';
11
11
  export { COUNTRY_OPTIONS } from './country';
@@ -4,7 +4,7 @@ export { applyFieldValueTransforms } from "./applyFieldValueTransforms.js";
4
4
  export { applyKnownFieldHelpers, getKnownFieldSerializer } from "./applyKnownFieldHelpers.js";
5
5
  export { buildFieldMenuSections } from "./buildFieldMenuSections.js";
6
6
  export { buildValueMenuSections } from "./buildValueMenuSections.js";
7
- export { collapseValues } from "./collapseValuesToLabels.js";
7
+ export { collapseValueOptions, collapseValues } from "./collapseValuesToLabels.js";
8
8
  export { chipIdToConditionIndex, findChipSplitIndex, incompleteTripletError, isEmptyFilterValue } from "./conditions.js";
9
9
  export { CONNECTOR_ID_PATTERN, MENU_BASE_GUTTER, MENU_CHIP_GUTTER_OFFSET, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, OPERATOR_LABELS, OPERATOR_LABELS_BY_TYPE, OPERATOR_SYMBOLS, QUERY_BAR_SELECTOR, VARIANT_LABELS } from "./constants.js";
10
10
  export { COUNTRY_OPTIONS } from "./country/index.js";
@@ -5,6 +5,8 @@
5
5
  * - "22" → "22X"
6
6
  * - "2x" → "2XX"
7
7
  * - "222", "4XX", "40X" → unchanged (already 3 chars)
8
- * Leaves anything unrecognised alone so `validate` can still flag it.
8
+ * Leaves anything unrecognised alone so `validate` can still flag it. The
9
+ * `NO_RESPONSE_CODE` sentinel (`"0"`) is a concrete value, not a partial class,
10
+ * so it is passed through as-is rather than padded to `"0XX"`.
9
11
  */
10
12
  export declare const createStatusCodeNormalizer: () => ((value: string | number | boolean) => string | number | boolean);
@@ -1,6 +1,8 @@
1
+ import { NO_RESPONSE_CODE } from "./utils/constants.js";
1
2
  const createStatusCodeNormalizer = ()=>(value)=>{
2
3
  if ('string' != typeof value && 'number' != typeof value) return value;
3
4
  const s = String(value).toUpperCase();
5
+ if (s === NO_RESPONSE_CODE) return s;
4
6
  if (!/^\d[0-9X]{0,2}$/.test(s)) return value;
5
7
  if (1 === s.length) return `${s}XX`;
6
8
  if (2 === s.length) return `${s}X`;
@@ -11,6 +11,8 @@
11
11
  *
12
12
  * Anything that isn't a status-code-shaped string (e.g. a number, boolean,
13
13
  * or freeform text) is returned unchanged so invalid committed values still
14
- * surface in the backend payload for the parser to reject.
14
+ * surface in the backend payload for the parser to reject. The
15
+ * `NO_RESPONSE_CODE` sentinel (`"0"`) carries no mask placeholder, so it is
16
+ * passed through verbatim.
15
17
  */
16
18
  export declare const createStatusCodeSerializer: () => ((value: string | number | boolean) => string | number | boolean);
@@ -1,5 +1,7 @@
1
+ import { NO_RESPONSE_CODE } from "./utils/constants.js";
1
2
  const createStatusCodeSerializer = ()=>(value)=>{
2
3
  if ('string' != typeof value) return value;
4
+ if (value === NO_RESPONSE_CODE) return value;
3
5
  if (!/^\d[\dX]{0,2}$/i.test(value)) return value;
4
6
  return value.replace(/X+$/i, '');
5
7
  };
@@ -1,6 +1,6 @@
1
- import { MASK_ROOTS, canonicalizeStatusCodeInput, makeMask } from "./utils/index.js";
1
+ import { MASK_ROOTS, NO_RESPONSE_CODE, canonicalizeStatusCodeInput, makeMask } from "./utils/index.js";
2
2
  const createStatusCodeSuggestions = ()=>{
3
- const resolveSelected = (selectedValues)=>(selectedValues ?? []).map((v)=>String(v)).filter((s)=>/^\d[\dX]{0,2}$/.test(s) && MASK_ROOTS.includes(s.charAt(0))).map((s)=>makeMask(s));
3
+ const resolveSelected = (selectedValues)=>(selectedValues ?? []).map((v)=>String(v)).filter((s)=>s === NO_RESPONSE_CODE || /^\d[\dX]{0,2}$/.test(s) && MASK_ROOTS.includes(s.charAt(0))).map((s)=>makeMask(s));
4
4
  return (inputText, context)=>{
5
5
  const norm = inputText.trim();
6
6
  const selected = resolveSelected(context?.selectedValues);
@@ -6,6 +6,10 @@
6
6
  * - `dX` (narrowed mask like `40X`)
7
7
  * - `dd` (concrete code like `401`)
8
8
  *
9
+ * The `NO_RESPONSE_CODE` sentinel (`status_code=0`, published by the backend
10
+ * for attacks with no HTTP response) is also accepted even though it carries no
11
+ * HTTP class.
12
+ *
9
13
  * Returns `true` when the value is invalid, matching the
10
14
  * `FieldMetadata.validate` contract.
11
15
  */
@@ -1,6 +1,7 @@
1
- import { MASK_ROOTS, STATUS_CODE_LENGTH } from "./utils/index.js";
1
+ import { MASK_ROOTS, NO_RESPONSE_CODE, STATUS_CODE_LENGTH } from "./utils/index.js";
2
2
  const createStatusCodeValidator = ()=>(value)=>{
3
3
  const s = String(value);
4
+ if (s === NO_RESPONSE_CODE) return false;
4
5
  if (s.length !== STATUS_CODE_LENGTH) return true;
5
6
  if (!MASK_ROOTS.includes(s.charAt(0))) return true;
6
7
  return !/^(XX|\dX|\d\d)$/.test(s.slice(1));
@@ -11,3 +11,9 @@ export declare const MASK_ROOTS: readonly string[];
11
11
  export declare const STATUS_CODE_LENGTH = 3;
12
12
  /** Placeholder character used inside masks (e.g. the `X` in `4XX`). */
13
13
  export declare const MASK_PLACEHOLDER = "X";
14
+ /** The "no HTTP response captured" sentinel. The backend publishes
15
+ * `status_code=0` for attacks it never got a response for; it is a legitimate,
16
+ * filterable concrete value that sits outside the `1XX–5XX` HTTP classes, so
17
+ * the mask helpers treat it as a valid, neutrally-badged code rather than an
18
+ * incomplete class or an error. */
19
+ export declare const NO_RESPONSE_CODE = "0";
@@ -7,4 +7,5 @@ const MASK_ROOTS = [
7
7
  ];
8
8
  const STATUS_CODE_LENGTH = 3;
9
9
  const MASK_PLACEHOLDER = 'X';
10
- export { MASK_PLACEHOLDER, MASK_ROOTS, STATUS_CODE_LENGTH };
10
+ const NO_RESPONSE_CODE = '0';
11
+ export { MASK_PLACEHOLDER, MASK_ROOTS, NO_RESPONSE_CODE, STATUS_CODE_LENGTH };
@@ -1,3 +1,3 @@
1
1
  export { canonicalizeStatusCodeInput } from './canonicalize';
2
- export { MASK_PLACEHOLDER, MASK_ROOTS, STATUS_CODE_LENGTH } from './constants';
2
+ export { MASK_PLACEHOLDER, MASK_ROOTS, NO_RESPONSE_CODE, STATUS_CODE_LENGTH } from './constants';
3
3
  export { makeMask } from './makeMask';