@wallarm-org/design-system 1.6.2 → 1.8.0

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 (31) hide show
  1. package/dist/components/EmptyState/EmptyState.js +14 -10
  2. package/dist/components/EmptyState/EmptyStateContext.d.ts +3 -0
  3. package/dist/components/EmptyState/EmptyStateContext.js +5 -0
  4. package/dist/components/EmptyState/EmptyStateIllustration.js +2 -1
  5. package/dist/components/EmptyState/EmptyStateMessage.js +6 -1
  6. package/dist/components/EmptyState/EmptyStateTitle.js +6 -1
  7. package/dist/components/EmptyState/classes.d.ts +27 -0
  8. package/dist/components/EmptyState/classes.js +27 -4
  9. package/dist/components/FilterInput/FilterInputField/ChipsWithGaps.js +2 -0
  10. package/dist/components/FilterInput/FilterInputField/FilterInputChip/FilterInputChip.d.ts +5 -0
  11. package/dist/components/FilterInput/FilterInputField/FilterInputChip/FilterInputChip.js +12 -1
  12. package/dist/components/FilterInput/FilterInputField/FilterInputChip/Segment.d.ts +6 -0
  13. package/dist/components/FilterInput/FilterInputField/FilterInputChip/Segment.js +10 -3
  14. package/dist/components/FilterInput/FilterInputField/FilterInputChip/applyEditCaret.d.ts +1 -0
  15. package/dist/components/FilterInput/FilterInputField/FilterInputChip/applyEditCaret.js +10 -0
  16. package/dist/components/FilterInput/FilterInputField/FilterInputChip/index.d.ts +1 -0
  17. package/dist/components/FilterInput/FilterInputField/FilterInputChip/index.js +1 -0
  18. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFilterInputAutocomplete.js +4 -1
  19. package/dist/components/FilterInput/hooks/useFilterInputAutocomplete/useFocusManagement.js +16 -5
  20. package/dist/components/FilterInput/hooks/useFilterInputExpression/buildChips.js +6 -0
  21. package/dist/components/FilterInput/types.d.ts +16 -0
  22. package/dist/icons/Shapes.d.ts +3 -0
  23. package/dist/icons/Shapes.js +12 -0
  24. package/dist/icons/index.d.ts +1 -0
  25. package/dist/icons/index.js +1 -0
  26. package/dist/metadata/components.json +1141 -633
  27. package/dist/theme/Pixel.stories.tsx +9 -1
  28. package/dist/theme/index.css +1 -0
  29. package/dist/theme/semantic.css +28 -0
  30. package/dist/theme/utilities/empty-state-medallion.css +18 -0
  31. package/package.json +1 -1
@@ -2,18 +2,22 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { TestIdProvider } from "../../utils/testId.js";
4
4
  import { emptyStateVariants } from "./classes.js";
5
+ import { EmptyStateProvider } from "./EmptyStateContext.js";
5
6
  const EmptyState = ({ ref, type = 'collection-empty', className, children, 'data-testid': testId, ...props })=>/*#__PURE__*/ jsx(TestIdProvider, {
6
7
  value: testId,
7
- children: /*#__PURE__*/ jsx("div", {
8
- ...props,
9
- ref: ref,
10
- role: "status",
11
- "data-slot": "empty-state",
12
- "data-testid": testId,
13
- className: cn(emptyStateVariants({
14
- type
15
- }), className),
16
- children: children
8
+ children: /*#__PURE__*/ jsx(EmptyStateProvider, {
9
+ value: type,
10
+ children: /*#__PURE__*/ jsx("div", {
11
+ ...props,
12
+ ref: ref,
13
+ role: "status",
14
+ "data-slot": "empty-state",
15
+ "data-testid": testId,
16
+ className: cn(emptyStateVariants({
17
+ type
18
+ }), className),
19
+ children: children
20
+ })
17
21
  })
18
22
  });
19
23
  EmptyState.displayName = 'EmptyState';
@@ -0,0 +1,3 @@
1
+ import type { EmptyStateType } from './classes';
2
+ export declare const EmptyStateProvider: import("react").Provider<EmptyStateType>;
3
+ export declare const useEmptyStateType: () => EmptyStateType;
@@ -0,0 +1,5 @@
1
+ import { createContext, useContext } from "react";
2
+ const EmptyStateContext = /*#__PURE__*/ createContext('collection-empty');
3
+ const EmptyStateProvider = EmptyStateContext.Provider;
4
+ const useEmptyStateType = ()=>useContext(EmptyStateContext);
5
+ export { EmptyStateProvider, useEmptyStateType };
@@ -1,6 +1,7 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { useTestId } from "../../utils/testId.js";
4
+ import { emptyStateIllustrationVariants } from "./classes.js";
4
5
  const EmptyStateIllustration = ({ ref, className, children, ...props })=>{
5
6
  const testId = useTestId('illustration');
6
7
  return /*#__PURE__*/ jsx("div", {
@@ -8,7 +9,7 @@ const EmptyStateIllustration = ({ ref, className, children, ...props })=>{
8
9
  ref: ref,
9
10
  "data-slot": "empty-state-illustration",
10
11
  "data-testid": testId,
11
- className: cn('text-text-secondary p-8 border border-border-primary bg-bg-light-primary rounded-full w-36 h-36 flex items-center justify-center', className),
12
+ className: cn(emptyStateIllustrationVariants(), className),
12
13
  children: children
13
14
  });
14
15
  };
@@ -1,14 +1,19 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { useTestId } from "../../utils/testId.js";
4
+ import { emptyStateMessageVariants } from "./classes.js";
5
+ import { useEmptyStateType } from "./EmptyStateContext.js";
4
6
  const EmptyStateMessage = ({ ref, className, children, ...props })=>{
5
7
  const testId = useTestId('message');
8
+ const type = useEmptyStateType();
6
9
  return /*#__PURE__*/ jsx("div", {
7
10
  ...props,
8
11
  ref: ref,
9
12
  "data-slot": "empty-state-message",
10
13
  "data-testid": testId,
11
- className: cn('flex flex-col items-center gap-8', className),
14
+ className: cn(emptyStateMessageVariants({
15
+ type
16
+ }), className),
12
17
  children: children
13
18
  });
14
19
  };
@@ -1,14 +1,19 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { useTestId } from "../../utils/testId.js";
4
+ import { emptyStateTitleVariants } from "./classes.js";
5
+ import { useEmptyStateType } from "./EmptyStateContext.js";
4
6
  const EmptyStateTitle = ({ ref, className, children, ...props })=>{
5
7
  const testId = useTestId('title');
8
+ const type = useEmptyStateType();
6
9
  return /*#__PURE__*/ jsx("p", {
7
10
  ...props,
8
11
  ref: ref,
9
12
  "data-testid": testId,
10
13
  "data-slot": "empty-state-title",
11
- className: cn('font-pixel text-base leading-base text-text-primary text-center break-words', className),
14
+ className: cn(emptyStateTitleVariants({
15
+ type
16
+ }), className),
12
17
  children: children
13
18
  });
14
19
  };
@@ -2,3 +2,30 @@ export type EmptyStateType = 'collection-empty' | 'no-results';
2
2
  export declare const emptyStateVariants: (props?: ({
3
3
  type?: "collection-empty" | "no-results" | null | undefined;
4
4
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
5
+ /**
6
+ * The medallion: a 36px raised tile holding a 20px glyph, which with `p-8` fills
7
+ * the content box exactly — the hairline is an inset ring in the shadow list,
8
+ * not a real border, so it doesn't eat into the padding. `text-xl` sets the
9
+ * 20px em box, so an icon left at its default `size='inherit'` lands on spec
10
+ * without every call site restating a size.
11
+ *
12
+ * The Figma master's placeholder is 16px at 10px padding, but every applied
13
+ * instance and the medallion spec sheet itself use 20px at 8px — the file is
14
+ * inconsistent here, and the 20/8 pairing is the one that fills the tile.
15
+ *
16
+ * There is deliberately no unframed variant — the spec never shows a bare glyph,
17
+ * at either scale, so an illustration always carries the tile.
18
+ *
19
+ * `rounded-[15px]` is off the radius scale on purpose: it's the value Figma
20
+ * reports for this node, and fitting a superellipse to the rendered outline
21
+ * agrees — a plain circular corner at r=14.5 matches to 0.29px, and r=15 to
22
+ * 0.35px, while the nearest token (16) is off by 0.73px. There is no corner
23
+ * smoothing on this shape, so no `corner-shape` is needed.
24
+ */
25
+ export declare const emptyStateIllustrationVariants: (props?: import("class-variance-authority/types").ClassProp | undefined) => string;
26
+ export declare const emptyStateMessageVariants: (props?: ({
27
+ type?: "collection-empty" | "no-results" | null | undefined;
28
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
29
+ export declare const emptyStateTitleVariants: (props?: ({
30
+ type?: "collection-empty" | "no-results" | null | undefined;
31
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
@@ -1,13 +1,36 @@
1
1
  import { cva } from "class-variance-authority";
2
- const emptyStateVariants = cva('flex flex-col items-center text-center gap-16 m-[0_auto]', {
2
+ const emptyStateVariants = cva('flex flex-col items-center text-center m-[0_auto]', {
3
3
  variants: {
4
4
  type: {
5
- 'collection-empty': 'max-w-[560px] min-w-[256px]',
6
- 'no-results': 'w-[240px] py-16'
5
+ 'collection-empty': 'gap-16 py-24 max-w-[560px] min-w-[256px]',
6
+ 'no-results': 'gap-8 py-8 w-[240px]'
7
7
  }
8
8
  },
9
9
  defaultVariants: {
10
10
  type: 'collection-empty'
11
11
  }
12
12
  });
13
- export { emptyStateVariants };
13
+ const emptyStateIllustrationVariants = cva('empty-state-medallion flex items-center justify-center shrink-0 size-36 rounded-[15px] p-8 text-xl text-icon-secondary');
14
+ const emptyStateMessageVariants = cva('flex flex-col items-center', {
15
+ variants: {
16
+ type: {
17
+ 'collection-empty': 'gap-8',
18
+ 'no-results': 'gap-4'
19
+ }
20
+ },
21
+ defaultVariants: {
22
+ type: 'collection-empty'
23
+ }
24
+ });
25
+ const emptyStateTitleVariants = cva('text-center break-words', {
26
+ variants: {
27
+ type: {
28
+ 'collection-empty': 'font-pixel text-base leading-base text-text-primary',
29
+ 'no-results': 'font-sans-display text-sm font-medium text-text-secondary'
30
+ }
31
+ },
32
+ defaultVariants: {
33
+ type: 'collection-empty'
34
+ }
35
+ });
36
+ export { emptyStateIllustrationVariants, emptyStateMessageVariants, emptyStateTitleVariants, emptyStateVariants };
@@ -30,6 +30,8 @@ const ChipsWithGaps = ({ chips, hideLeadingGap, hideTrailingGap, onChipClick, on
30
30
  valueSeparator: chip.valueSeparator,
31
31
  errorValueIndices: chip.errorValueIndices,
32
32
  disabled: chip.disabled,
33
+ valueMaxWidth: chip.valueMaxWidth,
34
+ caretMode: chip.caretMode,
33
35
  pair: chip.pair,
34
36
  onRemove: chip.disabled ? void 0 : ()=>onChipRemove(chip.id),
35
37
  onSegmentClick: chip.disabled ? void 0 : (segment, anchorEl)=>onChipClick(chip.id, segment, anchorEl),
@@ -20,6 +20,11 @@ export interface FilterInputChipProps extends Omit<HTMLAttributes<HTMLDivElement
20
20
  building?: boolean;
21
21
  /** When true, the chip cannot be edited or removed (dimmed appearance) */
22
22
  disabled?: boolean;
23
+ /** Caps the applied value segment at this width (px), truncating with an
24
+ * ellipsis; lifts the chip's default max-width so it grows to fit (AS-1064). */
25
+ valueMaxWidth?: number;
26
+ /** `'end'` places the caret at the end on value inline-edit; omit to select all (AS-1064). */
27
+ caretMode?: 'end';
23
28
  /** Second paired triplet (two-step fields). The paired attribute is fixed. */
24
29
  pair?: FilterInputChipData['pair'];
25
30
  onRemove?: () => void;
@@ -9,7 +9,7 @@ import { FilterInputRemoveButton } from "./FilterInputRemoveButton.js";
9
9
  import { PairSeparator } from "./PairSeparator.js";
10
10
  import { Segment } from "./Segment.js";
11
11
  import { SEGMENT_VARIANT } from "./segmentVariant.js";
12
- const FilterInputChip = ({ ref, chipId, attribute, attributeDescription, operator, value, error = false, valueParts, valueSeparator, errorValueIndices, building = false, disabled = false, pair, onRemove, onSegmentClick, onPairSegmentClick, className, ...props })=>{
12
+ const FilterInputChip = ({ ref, chipId, attribute, attributeDescription, operator, value, error = false, valueParts, valueSeparator, errorValueIndices, building = false, disabled = false, valueMaxWidth, caretMode, pair, onRemove, onSegmentClick, onPairSegmentClick, className, style, ...props })=>{
13
13
  const interactive = !disabled;
14
14
  const internalRef = useRef(null);
15
15
  const editing = useEditingContext();
@@ -75,6 +75,10 @@ const FilterInputChip = ({ ref, chipId, attribute, attributeDescription, operato
75
75
  disabled,
76
76
  building
77
77
  }), pair ? 'max-w-[380px]' : 'max-w-[320px]', className),
78
+ style: valueMaxWidth && !pair ? {
79
+ maxWidth: 'none',
80
+ ...style
81
+ } : style,
78
82
  "data-slot": "filter-input-condition-chip",
79
83
  ...building && {
80
84
  'data-building': ''
@@ -104,10 +108,17 @@ const FilterInputChip = ({ ref, chipId, attribute, attributeDescription, operato
104
108
  (value || baseActiveSegment === SEGMENT_VARIANT.value || !pair && effectiveError === SEGMENT_VARIANT.value) && /*#__PURE__*/ jsx(Segment, {
105
109
  variant: SEGMENT_VARIANT.value,
106
110
  className: value || pair ? pair ? 'max-w-[90px] shrink-0' : 'min-w-0' : emptyValueHitTarget,
111
+ ...valueMaxWidth && value && !pair && {
112
+ style: {
113
+ maxWidth: valueMaxWidth
114
+ }
115
+ },
107
116
  error: baseActiveSegment !== SEGMENT_VARIANT.value && (true === effectiveError || effectiveError === SEGMENT_VARIANT.value),
108
117
  valueParts: valueParts,
109
118
  valueSeparator: valueSeparator,
110
119
  errorValueIndices: errorValueIndices,
120
+ caretMode: caretMode,
121
+ valueMaxWidth: valueMaxWidth,
111
122
  onClick: interactive ? (e)=>handleSegmentClick(SEGMENT_VARIANT.value, e) : void 0,
112
123
  onMouseDown: interactive && building ? handleSegmentMouseDown : void 0,
113
124
  ...segmentEditProps(SEGMENT_VARIANT.value),
@@ -18,5 +18,11 @@ export type SegmentProps = HTMLAttributes<HTMLDivElement> & {
18
18
  valueSeparator?: string;
19
19
  /** Indices of invalid values in valueParts */
20
20
  errorValueIndices?: number[];
21
+ /** `'end'` places the caret at the end on edit; omit for default select-all (AS-1064). */
22
+ caretMode?: 'end';
23
+ /** Caps the edit input's width (px) to match the applied value cap, so the
24
+ * segment keeps the same width entering/leaving edit instead of snapping to
25
+ * the default MAX_INPUT_WIDTH. Value variant only (AS-1064). */
26
+ valueMaxWidth?: number;
21
27
  };
22
28
  export declare const Segment: FC<SegmentProps>;
@@ -2,12 +2,13 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useContext, useEffect, useRef } from "react";
3
3
  import { cn } from "../../../../utils/cn.js";
4
4
  import { FilterInputContext } from "../../FilterInputContext/FilterInputContext.js";
5
+ import { applyEditCaret } from "./applyEditCaret.js";
5
6
  import { editingValueMinWidth, segmentContainer, segmentTextVariants } from "./classes.js";
6
7
  import { CHAR_WIDTH_PX } from "./constants.js";
7
8
  import { MultiValueSegment } from "./MultiValueSegment.js";
8
9
  import { useSizerWidth } from "./model/useSizerWidth.js";
9
10
  import { SEGMENT_VARIANT } from "./segmentVariant.js";
10
- const Segment = ({ ref, variant, children, className, error, editing, editText, onEditChange, onEditKeyDown, onEditBlur, valueParts, valueSeparator = ', ', errorValueIndices, ...props })=>{
11
+ const Segment = ({ ref, variant, children, className, error, editing, editText, onEditChange, onEditKeyDown, onEditBlur, valueParts, valueSeparator = ', ', errorValueIndices, caretMode, valueMaxWidth, ...props })=>{
11
12
  const textRef = useRef(null);
12
13
  const inputRef = useRef(null);
13
14
  const sizerRef = useRef(null);
@@ -28,7 +29,7 @@ const Segment = ({ ref, variant, children, className, error, editing, editText,
28
29
  const outerFrame = requestAnimationFrame(()=>{
29
30
  innerFrame = requestAnimationFrame(()=>{
30
31
  inputRef.current?.focus();
31
- inputRef.current?.select();
32
+ applyEditCaret(inputRef.current);
32
33
  });
33
34
  });
34
35
  return ()=>{
@@ -40,7 +41,10 @@ const Segment = ({ ref, variant, children, className, error, editing, editText,
40
41
  ]);
41
42
  const inputWidth = useSizerWidth({
42
43
  sizerRef,
43
- text: editText ?? ''
44
+ text: editText ?? '',
45
+ ...variant === SEGMENT_VARIANT.value && valueMaxWidth && {
46
+ maxWidth: valueMaxWidth
47
+ }
44
48
  });
45
49
  const setInputRef = useCallback((node)=>{
46
50
  inputRef.current = node;
@@ -76,6 +80,9 @@ const Segment = ({ ref, variant, children, className, error, editing, editText,
76
80
  onKeyDown: onEditKeyDown,
77
81
  onBlur: onEditBlur,
78
82
  "aria-label": `Filter ${variant}`,
83
+ ...'end' === caretMode && {
84
+ 'data-caret-mode': 'end'
85
+ },
79
86
  className: cn(segmentTextVariants({
80
87
  variant,
81
88
  error
@@ -0,0 +1 @@
1
+ export declare const applyEditCaret: (input: HTMLInputElement | null) => void;
@@ -0,0 +1,10 @@
1
+ const applyEditCaret = (input)=>{
2
+ if (!input) return;
3
+ if ('end' === input.dataset.caretMode) {
4
+ const end = input.value.length;
5
+ input.setSelectionRange(end, end);
6
+ return;
7
+ }
8
+ input.select();
9
+ };
10
+ export { applyEditCaret };
@@ -1,4 +1,5 @@
1
1
  export { type ConnectorVariant, FilterInputConnectorChip, type FilterInputConnectorChipProps, } from '../FilterInputConnectorChip';
2
+ export { applyEditCaret } from './applyEditCaret';
2
3
  export { type EditingContextValue, EditingProvider, useEditingContext, } from './context/EditingContext';
3
4
  export { type ChipSegment, FilterInputChip, type FilterInputChipProps, type PairSegment, } from './FilterInputChip';
4
5
  export { FilterInputRemoveButton } from './FilterInputRemoveButton';
@@ -1,4 +1,5 @@
1
1
  export { FilterInputConnectorChip } from "../FilterInputConnectorChip/index.js";
2
+ export { applyEditCaret } from "./applyEditCaret.js";
2
3
  export { EditingProvider, useEditingContext } from "./context/EditingContext.js";
3
4
  export { FilterInputChip } from "./FilterInputChip.js";
4
5
  export { FilterInputRemoveButton } from "./FilterInputRemoveButton.js";
@@ -1,6 +1,7 @@
1
1
  import { useCallback } from "react";
2
2
  import { SEGMENT_VARIANT } from "../../FilterInputField/FilterInputChip/index.js";
3
3
  import { useDateRange } from "../../FilterInputMenu/FilterInputDateValueMenu/hooks.js";
4
+ import { isMultiSelectOperator } from "../../lib/index.js";
4
5
  import { deriveAutocompleteValues } from "./lib/index.js";
5
6
  import { useAutocompleteState } from "./useAutocompleteState.js";
6
7
  import { useBlurCommit } from "./useBlurCommit.js";
@@ -218,6 +219,8 @@ const useFilterInputAutocomplete = ({ fields, conditions, chips, upsertCondition
218
219
  buildingBase,
219
220
  editingSide: editing.editingSide
220
221
  });
222
+ const isMultiValueValueEdit = null != editing.editingChipId && editing.editingSegment === SEGMENT_VARIANT.value && null != selectedOperator && isMultiSelectOperator(selectedOperator);
223
+ const liveSegmentFilterText = isMultiValueValueEdit && null != buildingMultiValue && '' === editing.segmentMenuFilterText ? buildingMultiValue : editing.segmentFilterText;
221
224
  return {
222
225
  inputText,
223
226
  menuState,
@@ -260,7 +263,7 @@ const useFilterInputAutocomplete = ({ fields, conditions, chips, upsertCondition
260
263
  editingChipId: editing.editingChipId,
261
264
  editingSegment: editing.editingSegment,
262
265
  editingSide: editing.editingSide,
263
- segmentFilterText: editing.segmentFilterText,
266
+ segmentFilterText: liveSegmentFilterText,
264
267
  segmentMenuFilterText: editing.segmentMenuFilterText,
265
268
  handleSegmentFilterChange,
266
269
  cancelSegmentEdit,
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useMemo, useRef } from "react";
2
- import { SEGMENT_VARIANT } from "../../FilterInputField/FilterInputChip/index.js";
2
+ import { SEGMENT_VARIANT, applyEditCaret } from "../../FilterInputField/FilterInputChip/index.js";
3
3
  import { isMenuRelated, nextBuildingMenu } from "../../lib/index.js";
4
4
  const useFocusManagement = ({ menuState, isFocused, conditionsLength, inputText, selectedField, selectedOperator, containerRef, inputRef, editingSegment, segmentAttributeInputRef, segmentOperatorInputRef, segmentValueInputRef, blurCommitRef, commitBuildingOnBlur, hasIncompleteBuilding, setIsFocused, setMenuState, resetMenuAnchor, resetState })=>{
5
5
  const handleFocus = useCallback((e)=>{
@@ -12,12 +12,19 @@ const useFocusManagement = ({ menuState, isFocused, conditionsLength, inputText,
12
12
  const handleBlur = useCallback((e)=>{
13
13
  if (handlingBlurRef.current) return;
14
14
  const related = e.relatedTarget;
15
- if (containerRef.current?.contains(related)) return;
16
15
  if (isMenuRelated(related)) return;
16
+ if (null != related && (related === segmentAttributeInputRef.current || related === segmentOperatorInputRef.current || related === segmentValueInputRef.current)) return;
17
17
  handlingBlurRef.current = true;
18
18
  try {
19
+ const focusStaysInside = !!containerRef.current?.contains(related);
20
+ if ((null != editingSegment || !focusStaysInside) && blurCommitRef.current?.()) {
21
+ setIsFocused(false);
22
+ related?.focus();
23
+ return;
24
+ }
25
+ if (focusStaysInside) return;
19
26
  setIsFocused(false);
20
- const committed = blurCommitRef.current?.() || commitBuildingOnBlur();
27
+ const committed = commitBuildingOnBlur();
21
28
  if (!committed) if (hasIncompleteBuilding()) setMenuState('closed');
22
29
  else resetState();
23
30
  related?.focus();
@@ -33,7 +40,11 @@ const useFocusManagement = ({ menuState, isFocused, conditionsLength, inputText,
33
40
  resetState,
34
41
  setIsFocused,
35
42
  setMenuState,
36
- inputRef
43
+ inputRef,
44
+ editingSegment,
45
+ segmentAttributeInputRef,
46
+ segmentOperatorInputRef,
47
+ segmentValueInputRef
37
48
  ]);
38
49
  const prevFocusedRef = useRef(false);
39
50
  useEffect(()=>{
@@ -87,7 +98,7 @@ const useFocusManagement = ({ menuState, isFocused, conditionsLength, inputText,
87
98
  if (!dest) return;
88
99
  if (document.activeElement === dest) return;
89
100
  dest.focus();
90
- if (editingSegment) dest.select();
101
+ if (editingSegment) applyEditCaret(dest);
91
102
  });
92
103
  });
93
104
  return ()=>{
@@ -39,6 +39,12 @@ const buildBaseChip = (i, condition, field)=>({
39
39
  ...field?.description && {
40
40
  attributeDescription: field.description
41
41
  },
42
+ ...field?.valueMaxWidth && {
43
+ valueMaxWidth: field.valueMaxWidth
44
+ },
45
+ ...field?.caretMode && {
46
+ caretMode: field.caretMode
47
+ },
42
48
  operator: condition.operator ? getOperatorLabel(condition.operator, field?.type || DEFAULT_FIELD_TYPE) : void 0,
43
49
  ...condition.disabled && {
44
50
  disabled: true
@@ -38,6 +38,10 @@ export interface FilterInputChipData {
38
38
  errorValueIndices?: number[];
39
39
  /** When true, the chip cannot be edited or removed */
40
40
  disabled?: boolean;
41
+ /** Applied value-segment width cap in px (see FieldMetadata.valueMaxWidth). */
42
+ valueMaxWidth?: number;
43
+ /** Caret placement on value inline-edit (see FieldMetadata.caretMode). */
44
+ caretMode?: 'end';
41
45
  /** Second paired triplet (display) for two-step fields. */
42
46
  pair?: {
43
47
  attribute: string;
@@ -199,6 +203,18 @@ export interface FieldMetadata {
199
203
  * set it while an async options fetch is in flight.
200
204
  */
201
205
  loadingOptions?: boolean;
206
+ /**
207
+ * Caps the applied value segment at this width in px: a longer value truncates
208
+ * with a trailing ellipsis while the full value is preserved for matching. When
209
+ * set, the chip's default max-width is lifted so it grows to fit the wider value.
210
+ * Omit to keep the chip's default cap. (AS-1064: long parameter-path expressions.)
211
+ */
212
+ valueMaxWidth?: number;
213
+ /**
214
+ * `'end'` places the caret at the end of the value on inline-edit (natural for
215
+ * long values); omit to select the whole value so typing replaces it. (AS-1064)
216
+ */
217
+ caretMode?: 'end';
202
218
  }
203
219
  /**
204
220
  * A labeled group of filter fields for the field-selection menu, referenced by
@@ -0,0 +1,3 @@
1
+ import type { FC } from 'react';
2
+ import { type SvgIconProps } from './SvgIcon';
3
+ export declare const Shapes: FC<SvgIconProps>;
@@ -0,0 +1,12 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { SvgIcon } from "./SvgIcon.js";
3
+ const Shapes = (props)=>/*#__PURE__*/ jsx(SvgIcon, {
4
+ ...props,
5
+ viewBox: "0 0 24 24",
6
+ children: /*#__PURE__*/ jsx("path", {
7
+ d: "M9 13C10.105 13 11 13.895 11 15V20C11 21.105 10.105 22 9 22H4C2.895 22 2 21.105 2 20V15C2 13.895 2.895 13 4 13H9ZM17.5 13C19.985 13 22 15.015 22 17.5C22 19.985 19.985 22 17.5 22C15.015 22 13 19.985 13 17.5C13 15.015 15.015 13 17.5 13ZM4 20H9V15H4V20ZM17.5 15C16.119 15 15 16.119 15 17.5C15 18.881 16.119 20 17.5 20C18.881 20 20 18.881 20 17.5C20 16.119 18.881 15 17.5 15ZM12.169 1.647C12.314 1.661 12.457 1.692 12.594 1.742L12.794 1.83L12.981 1.943C13.161 2.068 13.315 2.226 13.435 2.41C13.438 2.416 13.443 2.422 13.446 2.428L17.148 8.371C17.287 8.584 17.377 8.824 17.41 9.075L17.422 9.19L17.425 9.307C17.424 9.577 17.358 9.843 17.233 10.084C17.09 10.359 16.875 10.59 16.61 10.751C16.346 10.912 16.041 10.999 15.731 11H8.3V10.999C8.005 11.006 7.713 10.937 7.453 10.797C7.178 10.648 6.948 10.425 6.791 10.154C6.634 9.883 6.555 9.573 6.562 9.26C6.57 8.946 6.664 8.641 6.834 8.378L10.554 2.467L10.555 2.469C10.695 2.233 10.889 2.034 11.123 1.891C11.373 1.738 11.658 1.651 11.95 1.641L12.169 1.647ZM8.806 9H15.184L12.011 3.905L8.806 9Z",
8
+ fill: "currentColor"
9
+ })
10
+ });
11
+ Shapes.displayName = 'ShapesIcon';
12
+ export { Shapes };
@@ -438,6 +438,7 @@ export { Ses } from './Ses';
438
438
  export { SesNeutral } from './SesNeutral';
439
439
  export { Settings } from './Settings';
440
440
  export { Settings2 } from './Settings2';
441
+ export { Shapes } from './Shapes';
441
442
  export { Share } from './Share';
442
443
  export { Sheet } from './Sheet';
443
444
  export { Shield } from './Shield';
@@ -438,6 +438,7 @@ export { Ses } from "./Ses.js";
438
438
  export { SesNeutral } from "./SesNeutral.js";
439
439
  export { Settings } from "./Settings.js";
440
440
  export { Settings2 } from "./Settings2.js";
441
+ export { Shapes } from "./Shapes.js";
441
442
  export { Share } from "./Share.js";
442
443
  export { Sheet } from "./Sheet.js";
443
444
  export { Shield } from "./Shield.js";