@wallarm-org/design-system 0.28.0-rc-feature-WDS-96-update-data-input-component.6 → 0.28.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.
- package/dist/components/DateInput/DateInput.js +2 -5
- package/dist/components/DateInput/DateInputInternal.js +4 -6
- package/dist/components/DateInput/types.d.ts +0 -3
- package/dist/components/DateRangeInput/DateRangeContext/DateRangeProvider.js +17 -9
- package/dist/components/DateRangeInput/DateRangeContext/types.d.ts +0 -2
- package/dist/components/DateRangeInput/DateRangeGroup.js +1 -1
- package/dist/components/DateRangeInput/DateRangeInputInternal.js +15 -33
- package/dist/components/DateRangeInput/DateRangeSegment.js +1 -6
- package/dist/components/DateRangeInput/DateRangeSegmentGroup.js +12 -4
- package/dist/components/DateRangeInput/DateRangeSeparator.d.ts +1 -2
- package/dist/components/DateRangeInput/DateRangeSeparator.js +5 -2
- package/dist/components/DateRangeInput/types.d.ts +0 -3
- package/dist/components/FilterInput/FilterInput.d.ts +14 -0
- package/dist/components/FilterInput/FilterInput.js +5 -1
- package/dist/components/FilterInput/index.d.ts +1 -1
- package/dist/components/FilterInput/index.js +2 -2
- package/dist/components/FilterInput/lib/applyFieldValueTransforms.d.ts +11 -0
- package/dist/components/FilterInput/lib/applyFieldValueTransforms.js +43 -0
- package/dist/components/FilterInput/lib/applyKnownFieldHelpers.d.ts +21 -0
- package/dist/components/FilterInput/lib/applyKnownFieldHelpers.js +29 -0
- package/dist/components/FilterInput/lib/index.d.ts +3 -1
- package/dist/components/FilterInput/lib/index.js +4 -2
- package/dist/components/FilterInput/lib/serializeExpression.d.ts +12 -2
- package/dist/components/FilterInput/lib/serializeExpression.js +5 -2
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSerializer.d.ts +16 -0
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSerializer.js +6 -0
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSuggestions.d.ts +5 -4
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeSuggestions.js +5 -6
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeValidator.d.ts +1 -8
- package/dist/components/FilterInput/lib/statusCode/createStatusCodeValidator.js +3 -3
- package/dist/components/FilterInput/lib/statusCode/index.d.ts +1 -1
- package/dist/components/FilterInput/lib/statusCode/index.js +2 -1
- package/dist/components/FilterInput/lib/statusCode/utils/canonicalize.d.ts +2 -2
- package/dist/components/FilterInput/lib/statusCode/utils/canonicalize.js +3 -3
- package/dist/components/FilterInput/lib/statusCode/utils/constants.d.ts +7 -3
- package/dist/components/FilterInput/lib/statusCode/utils/constants.js +3 -3
- package/dist/components/FilterInput/lib/statusCode/utils/index.d.ts +1 -3
- package/dist/components/FilterInput/lib/statusCode/utils/index.js +2 -3
- package/dist/components/FilterInput/types.d.ts +9 -0
- package/dist/components/InputGroup/InputGroup.d.ts +1 -6
- package/dist/components/InputGroup/InputGroup.js +3 -19
- package/dist/components/InputGroup/index.d.ts +1 -1
- package/dist/components/SimpleCharts/BarList/BarList.d.ts +16 -0
- package/dist/components/SimpleCharts/BarList/BarList.figma.d.ts +1 -0
- package/dist/components/SimpleCharts/BarList/BarList.figma.js +74 -0
- package/dist/components/SimpleCharts/BarList/BarList.js +38 -0
- package/dist/components/SimpleCharts/BarList/BarListBar.d.ts +14 -0
- package/dist/components/SimpleCharts/BarList/BarListBar.js +29 -0
- package/dist/components/SimpleCharts/BarList/BarListContext.d.ts +12 -0
- package/dist/components/SimpleCharts/BarList/BarListContext.js +4 -0
- package/dist/components/SimpleCharts/BarList/BarListItem.d.ts +12 -0
- package/dist/components/SimpleCharts/BarList/BarListItem.js +66 -0
- package/dist/components/SimpleCharts/BarList/BarListLabel.d.ts +5 -0
- package/dist/components/SimpleCharts/BarList/BarListLabel.js +16 -0
- package/dist/components/SimpleCharts/BarList/BarListPercent.d.ts +7 -0
- package/dist/components/SimpleCharts/BarList/BarListPercent.js +21 -0
- package/dist/components/SimpleCharts/BarList/BarListSkeleton.d.ts +8 -0
- package/dist/components/SimpleCharts/BarList/BarListSkeleton.js +36 -0
- package/dist/components/SimpleCharts/BarList/BarListValue.d.ts +5 -0
- package/dist/components/SimpleCharts/BarList/BarListValue.js +16 -0
- package/dist/components/SimpleCharts/BarList/classes.d.ts +25 -0
- package/dist/components/SimpleCharts/BarList/classes.js +44 -0
- package/dist/components/SimpleCharts/BarList/index.d.ts +7 -0
- package/dist/components/SimpleCharts/BarList/index.js +8 -0
- package/dist/components/SimpleCharts/Chart/Chart.d.ts +6 -0
- package/dist/components/SimpleCharts/Chart/Chart.figma.d.ts +1 -0
- package/dist/components/SimpleCharts/Chart/Chart.figma.js +41 -0
- package/dist/components/SimpleCharts/Chart/Chart.js +17 -0
- package/dist/components/SimpleCharts/Chart/ChartActions.d.ts +10 -0
- package/dist/components/SimpleCharts/Chart/ChartActions.js +18 -0
- package/dist/components/SimpleCharts/Chart/ChartEmpty.d.ts +5 -0
- package/dist/components/SimpleCharts/Chart/ChartEmpty.js +22 -0
- package/dist/components/SimpleCharts/Chart/ChartHeader.d.ts +5 -0
- package/dist/components/SimpleCharts/Chart/ChartHeader.js +16 -0
- package/dist/components/SimpleCharts/Chart/ChartTitle.d.ts +5 -0
- package/dist/components/SimpleCharts/Chart/ChartTitle.js +22 -0
- package/dist/components/SimpleCharts/Chart/classes.d.ts +6 -0
- package/dist/components/SimpleCharts/Chart/classes.js +16 -0
- package/dist/components/SimpleCharts/Chart/index.d.ts +5 -0
- package/dist/components/SimpleCharts/Chart/index.js +6 -0
- package/dist/components/SimpleCharts/index.d.ts +2 -0
- package/dist/components/SimpleCharts/index.js +3 -0
- package/dist/components/SimpleCharts/types.d.ts +9 -0
- package/dist/components/TemporalCore/TemporalClear.js +0 -1
- package/dist/components/TemporalCore/TemporalSegment.js +2 -7
- package/dist/components/TemporalCore/TimeDropdown.js +1 -1
- package/dist/components/TemporalCore/index.d.ts +0 -1
- package/dist/components/TemporalCore/index.js +1 -2
- package/dist/components/TemporalCore/utils.d.ts +0 -8
- package/dist/components/TemporalCore/utils.js +1 -6
- package/dist/components/TimeInput/TimeInput.js +3 -7
- package/dist/metadata/components.json +3569 -282
- package/package.json +1 -1
- package/dist/components/FilterInput/lib/statusCode/utils/maskRoots.d.ts +0 -4
- package/dist/components/FilterInput/lib/statusCode/utils/maskRoots.js +0 -3
- package/dist/components/FilterInput/lib/statusCode/utils/types.d.ts +0 -8
- package/dist/components/FilterInput/stories/mockStatusCodes.d.ts +0 -6
- package/dist/components/FilterInput/stories/mockStatusCodes.js +0 -20
- /package/dist/components/{FilterInput/lib/statusCode/utils → SimpleCharts}/types.js +0 -0
|
@@ -5,11 +5,9 @@ import { useDateField } from "@react-aria/datepicker";
|
|
|
5
5
|
import { useLocale } from "@react-aria/i18n";
|
|
6
6
|
import { useDateFieldState } from "@react-stately/datepicker";
|
|
7
7
|
import { cn } from "../../utils/cn.js";
|
|
8
|
-
import {
|
|
8
|
+
import { useTemporalField } from "../TemporalCore/index.js";
|
|
9
9
|
import { DateInputInternal } from "./DateInputInternal.js";
|
|
10
|
-
const DateInput = /*#__PURE__*/ forwardRef(({ icon, value: controlledValue, defaultValue, onChange, error = false, disabled = false, granularity = 'day', placeholder
|
|
11
|
-
granularity
|
|
12
|
-
}), showTimeDropdown, timeStep, hourCycle, size, className, ...props }, forwardedRef)=>{
|
|
10
|
+
const DateInput = /*#__PURE__*/ forwardRef(({ icon, value: controlledValue, defaultValue, onChange, error = false, disabled = false, granularity = 'day', placeholder, showTimeDropdown, timeStep, hourCycle, className, ...props }, forwardedRef)=>{
|
|
13
11
|
const { locale } = useLocale();
|
|
14
12
|
const ref = useRef(null);
|
|
15
13
|
const finalRef = forwardedRef || ref;
|
|
@@ -48,7 +46,6 @@ const DateInput = /*#__PURE__*/ forwardRef(({ icon, value: controlledValue, defa
|
|
|
48
46
|
showTimeDropdown: showTimeDropdown,
|
|
49
47
|
timeStep: timeStep,
|
|
50
48
|
hourCycle: hourCycle,
|
|
51
|
-
size: size,
|
|
52
49
|
className: cn('w-full')
|
|
53
50
|
})
|
|
54
51
|
});
|
|
@@ -4,7 +4,7 @@ import { CalendarDateTime, getLocalTimeZone, now } from "@internationalized/date
|
|
|
4
4
|
import { cn } from "../../utils/cn.js";
|
|
5
5
|
import { InputGroup, InputGroupAddon } from "../InputGroup/index.js";
|
|
6
6
|
import { TemporalClear, TemporalPlaceholder, TemporalSegmentGroup, TimeDropdown, useTimeDropdownKeyCapture } from "../TemporalCore/index.js";
|
|
7
|
-
const DateInputInternal = /*#__PURE__*/ forwardRef(({ state, icon: IconComponent, error, disabled, placeholder, showTimeDropdown, timeStep = 30, hourCycle,
|
|
7
|
+
const DateInputInternal = /*#__PURE__*/ forwardRef(({ state, icon: IconComponent, error, disabled, placeholder, showTimeDropdown, timeStep = 30, hourCycle, ...props }, ref)=>{
|
|
8
8
|
const dropdownRef = useRef(null);
|
|
9
9
|
const [isFocused, setIsFocused] = useState(false);
|
|
10
10
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
@@ -53,24 +53,22 @@ const DateInputInternal = /*#__PURE__*/ forwardRef(({ state, icon: IconComponent
|
|
|
53
53
|
});
|
|
54
54
|
const currentTimeValue = state.value && hasTimeSegments ? state.value : null;
|
|
55
55
|
return /*#__PURE__*/ jsxs(InputGroup, {
|
|
56
|
-
size: size,
|
|
57
56
|
children: [
|
|
58
57
|
IconComponent && /*#__PURE__*/ jsx(InputGroupAddon, {
|
|
59
58
|
children: /*#__PURE__*/ jsx(IconComponent, {})
|
|
60
59
|
}),
|
|
61
60
|
/*#__PURE__*/ jsxs("div", {
|
|
62
|
-
className: cn('relative flex-1
|
|
61
|
+
className: cn('relative flex-1', !IconComponent && 'pl-12'),
|
|
63
62
|
onKeyDownCapture: handleKeyDownCapture,
|
|
64
63
|
children: [
|
|
65
64
|
showPlaceholder && /*#__PURE__*/ jsx(TemporalPlaceholder, {
|
|
66
|
-
text: placeholder
|
|
67
|
-
className: cn(!IconComponent && 'pl-12')
|
|
65
|
+
text: placeholder
|
|
68
66
|
}),
|
|
69
67
|
/*#__PURE__*/ jsx(TemporalSegmentGroup, {
|
|
70
68
|
...props,
|
|
71
69
|
ref: ref,
|
|
72
70
|
"data-slot": "input",
|
|
73
|
-
className: cn('h-
|
|
71
|
+
className: cn('h-36', showPlaceholder && 'opacity-0'),
|
|
74
72
|
"aria-invalid": error || void 0,
|
|
75
73
|
"aria-disabled": disabled || void 0,
|
|
76
74
|
state: state,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { FC } from 'react';
|
|
2
2
|
import type { SvgIconProps } from '../../icons';
|
|
3
|
-
import type { InputGroupSize } from '../InputGroup';
|
|
4
3
|
export interface DateInputBaseProps {
|
|
5
4
|
/** Optional icon component to display at the start of the input */
|
|
6
5
|
icon?: FC<SvgIconProps>;
|
|
@@ -16,8 +15,6 @@ export interface DateInputBaseProps {
|
|
|
16
15
|
timeStep?: number;
|
|
17
16
|
/** Hour cycle for time display: 12-hour (AM/PM) or 24-hour format */
|
|
18
17
|
hourCycle?: 12 | 24;
|
|
19
|
-
/** Visual size of the input. Default: 'default' (36px) */
|
|
20
|
-
size?: InputGroupSize;
|
|
21
18
|
/**
|
|
22
19
|
* className prop
|
|
23
20
|
*/
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, useRef } from "react";
|
|
2
|
+
import { forwardRef, useCallback, useRef } from "react";
|
|
3
|
+
import { CalendarDate } from "@internationalized/date";
|
|
3
4
|
import { useDateRangePicker } from "@react-aria/datepicker";
|
|
4
5
|
import { useDateRangePickerState } from "@react-stately/datepicker";
|
|
5
|
-
import {
|
|
6
|
+
import { useTemporalField } from "../../TemporalCore/index.js";
|
|
6
7
|
import { DateRangeContext } from "./context.js";
|
|
7
|
-
const DateRangeProvider = /*#__PURE__*/ forwardRef(({ children, value: controlledValue, defaultValue, onChange, error = false, disabled = false, readOnly = false, granularity = 'day', hourCycle, placeholder
|
|
8
|
-
granularity,
|
|
9
|
-
isRange: true
|
|
10
|
-
}), showTimeDropdown, timeStep, icon, size }, forwardedRef)=>{
|
|
8
|
+
const DateRangeProvider = /*#__PURE__*/ forwardRef(({ children, value: controlledValue, defaultValue, onChange, error = false, disabled = false, readOnly = false, granularity = 'day', hourCycle, placeholder, showTimeDropdown, timeStep, icon }, forwardedRef)=>{
|
|
11
9
|
const ref = useRef(null);
|
|
12
10
|
const finalRef = forwardedRef || ref;
|
|
13
11
|
const startRef = useRef(null);
|
|
@@ -17,9 +15,20 @@ const DateRangeProvider = /*#__PURE__*/ forwardRef(({ children, value: controlle
|
|
|
17
15
|
defaultValue,
|
|
18
16
|
onChange
|
|
19
17
|
});
|
|
18
|
+
const handleChangeWithValidation = useCallback((newValue)=>{
|
|
19
|
+
if (void 0 === newValue) return void handleChange(null);
|
|
20
|
+
if (newValue?.start && newValue?.end) {
|
|
21
|
+
const startDate = new CalendarDate(newValue.start.year, newValue.start.month, newValue.start.day);
|
|
22
|
+
const endDate = new CalendarDate(newValue.end.year, newValue.end.month, newValue.end.day);
|
|
23
|
+
if (endDate.compare(startDate) < 0) return;
|
|
24
|
+
}
|
|
25
|
+
handleChange(newValue);
|
|
26
|
+
}, [
|
|
27
|
+
handleChange
|
|
28
|
+
]);
|
|
20
29
|
const state = useDateRangePickerState({
|
|
21
30
|
value,
|
|
22
|
-
onChange:
|
|
31
|
+
onChange: handleChangeWithValidation,
|
|
23
32
|
isDisabled: disabled,
|
|
24
33
|
isReadOnly: readOnly,
|
|
25
34
|
granularity,
|
|
@@ -51,8 +60,7 @@ const DateRangeProvider = /*#__PURE__*/ forwardRef(({ children, value: controlle
|
|
|
51
60
|
showTimeDropdown,
|
|
52
61
|
timeStep,
|
|
53
62
|
hourCycle,
|
|
54
|
-
icon
|
|
55
|
-
size
|
|
63
|
+
icon
|
|
56
64
|
},
|
|
57
65
|
children: children
|
|
58
66
|
});
|
|
@@ -4,7 +4,6 @@ import type { DateRangePickerState } from '@react-stately/datepicker';
|
|
|
4
4
|
import type { AriaDatePickerProps } from '@react-types/datepicker';
|
|
5
5
|
import type { GroupDOMAttributes } from '@react-types/shared';
|
|
6
6
|
import type { SvgIconProps } from '../../../icons';
|
|
7
|
-
import type { InputGroupSize } from '../../InputGroup';
|
|
8
7
|
export interface DateRangeContextValue {
|
|
9
8
|
groupProps: GroupDOMAttributes;
|
|
10
9
|
startFieldProps: AriaDatePickerProps<DateValue>;
|
|
@@ -22,5 +21,4 @@ export interface DateRangeContextValue {
|
|
|
22
21
|
timeStep?: number;
|
|
23
22
|
hourCycle?: 12 | 24;
|
|
24
23
|
icon?: FC<SvgIconProps>;
|
|
25
|
-
size?: InputGroupSize;
|
|
26
24
|
}
|
|
@@ -2,7 +2,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { cva } from "class-variance-authority";
|
|
3
3
|
import { cn } from "../../utils/cn.js";
|
|
4
4
|
import { useDateRangeContext } from "./DateRangeContext/index.js";
|
|
5
|
-
const dateRangeGroupVariants = cva(cn('
|
|
5
|
+
const dateRangeGroupVariants = cva(cn('group/temporal flex-1 h-full flex items-center gap-4', 'focus-within:outline-none', 'data-disabled:opacity-50 data-disabled:cursor-not-allowed'));
|
|
6
6
|
const DateRangeGroup = ({ children })=>{
|
|
7
7
|
const context = useDateRangeContext();
|
|
8
8
|
const { groupProps = {}, finalRef, disabled, error } = context ?? {};
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useCallback, useState } from "react";
|
|
3
3
|
import { cn } from "../../utils/cn.js";
|
|
4
4
|
import { InputGroup, InputGroupAddon } from "../InputGroup/index.js";
|
|
5
|
-
import { TemporalClear
|
|
5
|
+
import { TemporalClear } from "../TemporalCore/index.js";
|
|
6
6
|
import { useDateRangeContext } from "./DateRangeContext/index.js";
|
|
7
7
|
import { DateRangeGroup } from "./DateRangeGroup.js";
|
|
8
8
|
import { DateRangeSegmentGroup } from "./DateRangeSegmentGroup.js";
|
|
@@ -11,7 +11,6 @@ const DateRangeInputInternal = ({ icon: IconComponent })=>{
|
|
|
11
11
|
const context = useDateRangeContext();
|
|
12
12
|
const [startHasValue, setStartHasValue] = useState(false);
|
|
13
13
|
const [endHasValue, setEndHasValue] = useState(false);
|
|
14
|
-
const [isFocused, setIsFocused] = useState(false);
|
|
15
14
|
const [clearKey, setClearKey] = useState(0);
|
|
16
15
|
const hasAnyValue = startHasValue || endHasValue;
|
|
17
16
|
const handleClear = useCallback(()=>{
|
|
@@ -21,47 +20,30 @@ const DateRangeInputInternal = ({ icon: IconComponent })=>{
|
|
|
21
20
|
}, [
|
|
22
21
|
context
|
|
23
22
|
]);
|
|
24
|
-
const handleFocusCapture = ()=>setIsFocused(true);
|
|
25
|
-
const handleBlurCapture = (event)=>{
|
|
26
|
-
if (!event.currentTarget.contains(event.relatedTarget)) setIsFocused(false);
|
|
27
|
-
};
|
|
28
23
|
if (!context) return null;
|
|
29
|
-
const { startFieldProps, startRef, endFieldProps, endRef, disabled
|
|
30
|
-
const showPlaceholder = Boolean(placeholder && !hasAnyValue && !isFocused);
|
|
24
|
+
const { startFieldProps, startRef, endFieldProps, endRef, disabled } = context;
|
|
31
25
|
return /*#__PURE__*/ jsx("div", {
|
|
32
26
|
className: cn('**:data-[slot=input]:first:pr-0 **:data-[slot=input]:last:pl-0 min-w-284'),
|
|
33
|
-
onFocusCapture: handleFocusCapture,
|
|
34
|
-
onBlurCapture: handleBlurCapture,
|
|
35
27
|
children: /*#__PURE__*/ jsxs(InputGroup, {
|
|
36
|
-
size: size,
|
|
37
28
|
children: [
|
|
38
29
|
IconComponent && /*#__PURE__*/ jsx(InputGroupAddon, {
|
|
39
30
|
children: /*#__PURE__*/ jsx(IconComponent, {})
|
|
40
31
|
}),
|
|
41
32
|
/*#__PURE__*/ jsxs(DateRangeGroup, {
|
|
42
33
|
children: [
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
/*#__PURE__*/ jsx(DateRangeSeparator, {}),
|
|
57
|
-
/*#__PURE__*/ jsx(DateRangeSegmentGroup, {
|
|
58
|
-
...endFieldProps,
|
|
59
|
-
ref: endRef,
|
|
60
|
-
type: "end",
|
|
61
|
-
onHasPartialValueChange: setEndHasValue
|
|
62
|
-
}, `end-${clearKey}`)
|
|
63
|
-
]
|
|
64
|
-
})
|
|
34
|
+
/*#__PURE__*/ jsx(DateRangeSegmentGroup, {
|
|
35
|
+
...startFieldProps,
|
|
36
|
+
ref: startRef,
|
|
37
|
+
type: "start",
|
|
38
|
+
onHasPartialValueChange: setStartHasValue
|
|
39
|
+
}, `start-${clearKey}`),
|
|
40
|
+
/*#__PURE__*/ jsx(DateRangeSeparator, {}),
|
|
41
|
+
/*#__PURE__*/ jsx(DateRangeSegmentGroup, {
|
|
42
|
+
...endFieldProps,
|
|
43
|
+
ref: endRef,
|
|
44
|
+
type: "end",
|
|
45
|
+
onHasPartialValueChange: setEndHasValue
|
|
46
|
+
}, `end-${clearKey}`)
|
|
65
47
|
]
|
|
66
48
|
}),
|
|
67
49
|
/*#__PURE__*/ jsx(InputGroupAddon, {
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { InputGroup, InputGroupAddon } from "../InputGroup/index.js";
|
|
3
|
-
|
|
4
|
-
const DateRangeSegment = ({ children, icon: IconComponent })=>{
|
|
5
|
-
const context = useDateRangeContext();
|
|
6
|
-
return /*#__PURE__*/ jsxs(InputGroup, {
|
|
7
|
-
size: context?.size,
|
|
3
|
+
const DateRangeSegment = ({ children, icon: IconComponent })=>/*#__PURE__*/ jsxs(InputGroup, {
|
|
8
4
|
children: [
|
|
9
5
|
IconComponent && /*#__PURE__*/ jsx(InputGroupAddon, {
|
|
10
6
|
children: /*#__PURE__*/ jsx(IconComponent, {})
|
|
@@ -12,5 +8,4 @@ const DateRangeSegment = ({ children, icon: IconComponent })=>{
|
|
|
12
8
|
children
|
|
13
9
|
]
|
|
14
10
|
});
|
|
15
|
-
};
|
|
16
11
|
export { DateRangeSegment };
|
|
@@ -5,13 +5,14 @@ import { useDateField } from "@react-aria/datepicker";
|
|
|
5
5
|
import { useLocale } from "@react-aria/i18n";
|
|
6
6
|
import { useDateFieldState } from "@react-stately/datepicker";
|
|
7
7
|
import { cn } from "../../utils/cn.js";
|
|
8
|
-
import { TemporalSegmentGroup, TimeDropdown, useTimeDropdownKeyCapture } from "../TemporalCore/index.js";
|
|
8
|
+
import { TemporalPlaceholder, TemporalSegmentGroup, TimeDropdown, useTimeDropdownKeyCapture } from "../TemporalCore/index.js";
|
|
9
9
|
import { useDateRangeContext } from "./DateRangeContext/index.js";
|
|
10
10
|
const DateRangeSegmentGroup = /*#__PURE__*/ forwardRef(({ type, onHasPartialValueChange, ...props }, ref)=>{
|
|
11
11
|
const context = useDateRangeContext();
|
|
12
|
-
const { disabled = false, error = false, readOnly = false, showTimeDropdown, timeStep = 30, hourCycle, icon } = context ?? {};
|
|
12
|
+
const { disabled = false, error = false, readOnly = false, placeholder, showTimeDropdown, timeStep = 30, hourCycle, icon } = context ?? {};
|
|
13
13
|
const { locale } = useLocale();
|
|
14
14
|
const dropdownRef = useRef(null);
|
|
15
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
15
16
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
16
17
|
const blurTimeoutRef = useRef(null);
|
|
17
18
|
const fieldState = useDateFieldState({
|
|
@@ -23,6 +24,7 @@ const DateRangeSegmentGroup = /*#__PURE__*/ forwardRef(({ type, onHasPartialValu
|
|
|
23
24
|
});
|
|
24
25
|
const { fieldProps } = useDateField(props, fieldState, ref);
|
|
25
26
|
const hasPartialValue = fieldState.segments.some((seg)=>seg.isEditable && !seg.isPlaceholder);
|
|
27
|
+
const showPlaceholder = placeholder && !hasPartialValue && !isFocused;
|
|
26
28
|
useEffect(()=>{
|
|
27
29
|
onHasPartialValueChange?.(hasPartialValue);
|
|
28
30
|
}, [
|
|
@@ -32,6 +34,7 @@ const DateRangeSegmentGroup = /*#__PURE__*/ forwardRef(({ type, onHasPartialValu
|
|
|
32
34
|
const hasTimeSegments = fieldState.segments.some((seg)=>'hour' === seg.type || 'minute' === seg.type);
|
|
33
35
|
const hasDateSegments = fieldState.segments.some((seg)=>'year' === seg.type || 'month' === seg.type || 'day' === seg.type);
|
|
34
36
|
const handleFocus = ()=>{
|
|
37
|
+
setIsFocused(true);
|
|
35
38
|
if (blurTimeoutRef.current) {
|
|
36
39
|
clearTimeout(blurTimeoutRef.current);
|
|
37
40
|
blurTimeoutRef.current = null;
|
|
@@ -41,6 +44,7 @@ const DateRangeSegmentGroup = /*#__PURE__*/ forwardRef(({ type, onHasPartialValu
|
|
|
41
44
|
if (showTimeDropdown && hasTimeSegments && !isDropdownOpen) setIsDropdownOpen(true);
|
|
42
45
|
};
|
|
43
46
|
const handleBlur = ()=>{
|
|
47
|
+
setIsFocused(false);
|
|
44
48
|
blurTimeoutRef.current = window.setTimeout(()=>{
|
|
45
49
|
setIsDropdownOpen(false);
|
|
46
50
|
}, 200);
|
|
@@ -80,15 +84,19 @@ const DateRangeSegmentGroup = /*#__PURE__*/ forwardRef(({ type, onHasPartialValu
|
|
|
80
84
|
const currentTimeValue = fieldState.value && hasTimeSegments ? fieldState.value : null;
|
|
81
85
|
const hasIcon = Boolean(icon);
|
|
82
86
|
return /*#__PURE__*/ jsxs("div", {
|
|
83
|
-
className: cn('relative
|
|
87
|
+
className: cn('relative flex-1', !hasIcon && 'pl-12'),
|
|
84
88
|
onKeyDownCapture: handleKeyDownCapture,
|
|
85
89
|
onClick: handleClick,
|
|
86
90
|
children: [
|
|
91
|
+
showPlaceholder && /*#__PURE__*/ jsx(TemporalPlaceholder, {
|
|
92
|
+
text: placeholder,
|
|
93
|
+
className: "overflow-hidden text-ellipsis"
|
|
94
|
+
}),
|
|
87
95
|
/*#__PURE__*/ jsx(TemporalSegmentGroup, {
|
|
88
96
|
...fieldProps,
|
|
89
97
|
ref: ref,
|
|
90
98
|
"data-slot": "input",
|
|
91
|
-
className: cn('h-
|
|
99
|
+
className: cn('h-36', showPlaceholder && 'opacity-0'),
|
|
92
100
|
"aria-disabled": disabled || void 0,
|
|
93
101
|
"aria-invalid": error || void 0,
|
|
94
102
|
"data-field-type": type,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { FC } from 'react';
|
|
2
2
|
/**
|
|
3
|
-
* Visual separator between start and end date fields in a date range input.
|
|
4
|
-
* Renders a Unicode right arrow as plain text.
|
|
3
|
+
* Visual separator (arrow icon) between start and end date fields in a date range input.
|
|
5
4
|
* Used within DateRangeProvider for custom compositions.
|
|
6
5
|
*
|
|
7
6
|
* @example
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ArrowRight } from "../../icons/index.js";
|
|
2
3
|
import { cn } from "../../utils/cn.js";
|
|
3
4
|
const DateRangeSeparator = ()=>/*#__PURE__*/ jsx("span", {
|
|
4
|
-
className: cn('text-
|
|
5
|
+
className: cn('text-icon-secondary select-none'),
|
|
5
6
|
"aria-hidden": "true",
|
|
6
|
-
children:
|
|
7
|
+
children: /*#__PURE__*/ jsx(ArrowRight, {
|
|
8
|
+
size: "md"
|
|
9
|
+
})
|
|
7
10
|
});
|
|
8
11
|
DateRangeSeparator.displayName = 'DateRangeSeparator';
|
|
9
12
|
export { DateRangeSeparator };
|
|
@@ -2,7 +2,6 @@ import type { FC } from 'react';
|
|
|
2
2
|
import type { DateValue } from '@react-aria/datepicker';
|
|
3
3
|
import type { RangeValue } from '@react-types/shared';
|
|
4
4
|
import type { SvgIconProps } from '../../icons';
|
|
5
|
-
import type { InputGroupSize } from '../InputGroup';
|
|
6
5
|
export interface DateRangeBaseProps {
|
|
7
6
|
/** Optional icon component to display at the start of the input */
|
|
8
7
|
icon?: FC<SvgIconProps>;
|
|
@@ -18,8 +17,6 @@ export interface DateRangeBaseProps {
|
|
|
18
17
|
showTimeDropdown?: boolean;
|
|
19
18
|
/** Time interval in minutes for dropdown options. Default: 30 */
|
|
20
19
|
timeStep?: number;
|
|
21
|
-
/** Visual size of the input. Default: 'default' (36px) */
|
|
22
|
-
size?: InputGroupSize;
|
|
23
20
|
}
|
|
24
21
|
export interface DateRangeInputProps extends DateRangeBaseProps {
|
|
25
22
|
/** Controlled value - range with start and end dates */
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import type { FC, HTMLAttributes } from 'react';
|
|
2
2
|
import type { ExprNode, FieldMetadata } from './types';
|
|
3
3
|
export interface FilterInputProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onChange'> {
|
|
4
|
+
/**
|
|
5
|
+
* Filter-field configurations driving the autocomplete. Most fields are
|
|
6
|
+
* passed through as-is, but a few names are **reserved** and auto-wired
|
|
7
|
+
* with design-system helpers (`acceptChar` / `normalize` / `getSuggestions`
|
|
8
|
+
* / `validate`). Current reserved names:
|
|
9
|
+
*
|
|
10
|
+
* - `status_code` — HTTP status code field (mask suggestions, format
|
|
11
|
+
* validation, digit-or-X input filter, partial-input normalization).
|
|
12
|
+
*
|
|
13
|
+
* Consumer-supplied callbacks always override the auto-wiring, so you can
|
|
14
|
+
* opt out per-field. For the same helpers on a field with a different
|
|
15
|
+
* `name`, import the factories (`createStatusCodeSuggestions`, …) and
|
|
16
|
+
* attach them manually.
|
|
17
|
+
*/
|
|
4
18
|
fields?: FieldMetadata[];
|
|
5
19
|
value?: ExprNode | null;
|
|
6
20
|
onChange?: (expression: ExprNode | null) => void;
|
|
@@ -6,7 +6,8 @@ import { FilterInputErrors, parseFilterInputErrors } from "./FilterInputErrors/i
|
|
|
6
6
|
import { FilterInputField } from "./FilterInputField/index.js";
|
|
7
7
|
import { FilterInputMenu } from "./FilterInputMenu/FilterInputMenu.js";
|
|
8
8
|
import { useFilterInputAutocomplete, useFilterInputExpression, useFilterInputSelection } from "./hooks/index.js";
|
|
9
|
-
|
|
9
|
+
import { applyKnownFieldHelpers } from "./lib/applyKnownFieldHelpers.js";
|
|
10
|
+
const FilterInput = ({ fields: rawFields = [], value, onChange, placeholder = 'Type to filter...', error = false, showKeyboardHint = false, className, ...props })=>{
|
|
10
11
|
const inputRef = useRef(null);
|
|
11
12
|
const containerRef = useRef(null);
|
|
12
13
|
const buildingChipRef = useRef(null);
|
|
@@ -15,6 +16,9 @@ const FilterInput = ({ fields = [], value, onChange, placeholder = 'Type to filt
|
|
|
15
16
|
if (el) chipRegistryRef.current.set(id, el);
|
|
16
17
|
else chipRegistryRef.current.delete(id);
|
|
17
18
|
}, []);
|
|
19
|
+
const fields = useMemo(()=>applyKnownFieldHelpers(rawFields), [
|
|
20
|
+
rawFields
|
|
21
|
+
]);
|
|
18
22
|
const { conditions, connectors, chips, upsertCondition, removeCondition, removeConditionAtIndex, clearAll, setConnectorValue } = useFilterInputExpression({
|
|
19
23
|
fields,
|
|
20
24
|
value,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { FilterInput, type FilterInputProps } from './FilterInput';
|
|
2
2
|
export { FilterInputChip, type FilterInputChipProps } from './FilterInputField';
|
|
3
3
|
export { FilterInputFieldMenu, type FilterInputFieldMenuProps, FilterInputOperatorMenu, type FilterInputOperatorMenuProps, FilterInputValueMenu, type FilterInputValueMenuProps, type ValueOption, } from './FilterInputMenu';
|
|
4
|
-
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator, type FilterParseError, isFilterParseError, parseExpression,
|
|
4
|
+
export { applyFieldValueTransforms, createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator, type FilterParseError, isFilterParseError, parseExpression, serializeExpression, } from './lib';
|
|
5
5
|
export type { Condition, ExprNode, FieldMetadata, FieldType, FieldValueOption, FilterInputChipData, FilterInputChipVariant, FilterOperator, Group, } from './types';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FilterInput } from "./FilterInput.js";
|
|
2
2
|
import { FilterInputChip } from "./FilterInputField/index.js";
|
|
3
3
|
import { FilterInputFieldMenu, FilterInputOperatorMenu, FilterInputValueMenu } from "./FilterInputMenu/index.js";
|
|
4
|
-
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator, isFilterParseError, parseExpression, serializeExpression } from "./lib/index.js";
|
|
5
|
-
export { FilterInput, FilterInputChip, FilterInputFieldMenu, FilterInputOperatorMenu, FilterInputValueMenu, createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator, isFilterParseError, parseExpression, serializeExpression };
|
|
4
|
+
import { applyFieldValueTransforms, createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator, isFilterParseError, parseExpression, serializeExpression } from "./lib/index.js";
|
|
5
|
+
export { FilterInput, FilterInputChip, FilterInputFieldMenu, FilterInputOperatorMenu, FilterInputValueMenu, applyFieldValueTransforms, createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator, isFilterParseError, parseExpression, serializeExpression };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ExprNode, FieldMetadata } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Walk an expression tree and apply each field's `serializeValue` hook to the
|
|
4
|
+
* matching condition's value. Typical use: consumer has the UI-facing
|
|
5
|
+
* `ExprNode` (e.g. status code chip with `"2XX"`) and wants the backend
|
|
6
|
+
* payload to carry the transformed form (`"2"`).
|
|
7
|
+
*
|
|
8
|
+
* Returns the original node (by reference) when nothing changed, so
|
|
9
|
+
* downstream memoization stays stable.
|
|
10
|
+
*/
|
|
11
|
+
export declare const applyFieldValueTransforms: (expr: ExprNode | null, fields: FieldMetadata[]) => ExprNode | null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const transformConditionValue = (condition, fieldsByName)=>{
|
|
2
|
+
const field = fieldsByName.get(condition.field);
|
|
3
|
+
const transform = field?.serializeValue;
|
|
4
|
+
if (!transform) return condition;
|
|
5
|
+
const { value } = condition;
|
|
6
|
+
if (null == value) return condition;
|
|
7
|
+
if (Array.isArray(value)) {
|
|
8
|
+
const next = value.map((v)=>transform(v));
|
|
9
|
+
if (next.every((v, i)=>v === value[i])) return condition;
|
|
10
|
+
return {
|
|
11
|
+
...condition,
|
|
12
|
+
value: next
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const next = transform(value);
|
|
16
|
+
if (next === value) return condition;
|
|
17
|
+
return {
|
|
18
|
+
...condition,
|
|
19
|
+
value: next
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
const transformGroup = (group, fieldsByName)=>{
|
|
23
|
+
const children = group.children.map((child)=>transformNode(child, fieldsByName));
|
|
24
|
+
if (children.every((c, i)=>c === group.children[i])) return group;
|
|
25
|
+
return {
|
|
26
|
+
...group,
|
|
27
|
+
children
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const transformNode = (node, fieldsByName)=>{
|
|
31
|
+
if ('condition' === node.type) return transformConditionValue(node, fieldsByName);
|
|
32
|
+
return transformGroup(node, fieldsByName);
|
|
33
|
+
};
|
|
34
|
+
const applyFieldValueTransforms = (expr, fields)=>{
|
|
35
|
+
if (!expr) return expr;
|
|
36
|
+
if (!fields.some((f)=>f.serializeValue)) return expr;
|
|
37
|
+
const fieldsByName = new Map(fields.map((f)=>[
|
|
38
|
+
f.name,
|
|
39
|
+
f
|
|
40
|
+
]));
|
|
41
|
+
return transformNode(expr, fieldsByName);
|
|
42
|
+
};
|
|
43
|
+
export { applyFieldValueTransforms };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FieldMetadata } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Decorate `fields` in place with design-system helpers for known field names.
|
|
4
|
+
* `FilterInput` calls this on the `fields` prop before rendering.
|
|
5
|
+
*
|
|
6
|
+
* Reserved names and what they auto-attach (unless the consumer already
|
|
7
|
+
* provided a value for that slot):
|
|
8
|
+
*
|
|
9
|
+
* | `name` | Attaches |
|
|
10
|
+
* | ------------- | ------------------------------------------------------------------------------------------ |
|
|
11
|
+
* | `status_code` | HTTP status code: `acceptChar`, `normalize`, `getSuggestions`, `validate`, `serializeValue` |
|
|
12
|
+
*
|
|
13
|
+
* Consumer-supplied callbacks always win over the auto-wired ones. If the
|
|
14
|
+
* backend uses a different name (e.g. `http_status_code`), the helpers are
|
|
15
|
+
* NOT applied — the consumer must either rename the field to match or wire
|
|
16
|
+
* the factories (`createStatusCode*`) manually.
|
|
17
|
+
*
|
|
18
|
+
* The returned array has **reference-stable identity** when no field matches,
|
|
19
|
+
* so downstream `useMemo` that depends on it does not invalidate unnecessarily.
|
|
20
|
+
*/
|
|
21
|
+
export declare const applyKnownFieldHelpers: (fields: FieldMetadata[]) => FieldMetadata[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator } from "./statusCode/index.js";
|
|
2
|
+
const KNOWN_FIELD_HELPERS = {
|
|
3
|
+
status_code: ()=>({
|
|
4
|
+
acceptChar: createStatusCodeInputFilter(),
|
|
5
|
+
normalize: createStatusCodeNormalizer(),
|
|
6
|
+
getSuggestions: createStatusCodeSuggestions(),
|
|
7
|
+
validate: createStatusCodeValidator(),
|
|
8
|
+
serializeValue: createStatusCodeSerializer()
|
|
9
|
+
})
|
|
10
|
+
};
|
|
11
|
+
const applyKnownFieldHelpers = (fields)=>{
|
|
12
|
+
let changed = false;
|
|
13
|
+
const out = fields.map((field)=>{
|
|
14
|
+
const factory = KNOWN_FIELD_HELPERS[field.name];
|
|
15
|
+
if (!factory) return field;
|
|
16
|
+
const helpers = factory();
|
|
17
|
+
changed = true;
|
|
18
|
+
return {
|
|
19
|
+
...field,
|
|
20
|
+
acceptChar: field.acceptChar ?? helpers.acceptChar,
|
|
21
|
+
normalize: field.normalize ?? helpers.normalize,
|
|
22
|
+
getSuggestions: field.getSuggestions ?? helpers.getSuggestions,
|
|
23
|
+
validate: field.validate ?? helpers.validate,
|
|
24
|
+
serializeValue: field.serializeValue ?? helpers.serializeValue
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
return changed ? out : fields;
|
|
28
|
+
};
|
|
29
|
+
export { applyKnownFieldHelpers };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export type { DatePreset } from '../FilterInputMenu/FilterInputDateValueMenu/constants';
|
|
2
2
|
export { DATE_PRESETS, formatDateForChip, getDateDisplayLabel, isDatePreset, } from '../FilterInputMenu/FilterInputDateValueMenu/constants';
|
|
3
3
|
export { applyAcceptChar } from './applyAcceptChar';
|
|
4
|
+
export { applyFieldValueTransforms } from './applyFieldValueTransforms';
|
|
5
|
+
export { applyKnownFieldHelpers } from './applyKnownFieldHelpers';
|
|
4
6
|
export { chipIdToConditionIndex, findChipSplitIndex } from './conditions';
|
|
5
7
|
export { CONNECTOR_ID_PATTERN, NO_VALUE_OPERATORS, OPERATOR_LABELS, OPERATOR_LABELS_BY_TYPE, OPERATOR_SYMBOLS, OPERATORS_BY_TYPE, QUERY_BAR_SELECTOR, VARIANT_LABELS, } from './constants';
|
|
6
8
|
export { buildContainerAnchoredRect, isMenuRelated } from './dom';
|
|
@@ -10,4 +12,4 @@ export { getCurrentValueTokenText, getValueFilterText } from './menuFilterText';
|
|
|
10
12
|
export { getOperatorFromLabel, getOperatorLabel, isBetweenOperator, isMultiSelectOperator, isNoValueOperator, } from './operators';
|
|
11
13
|
export { type FilterParseError, isFilterParseError, parseExpression } from './parseExpression';
|
|
12
14
|
export { serializeExpression } from './serializeExpression';
|
|
13
|
-
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator,
|
|
15
|
+
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator, } from './statusCode';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DATE_PRESETS, formatDateForChip, getDateDisplayLabel, isDatePreset } from "../FilterInputMenu/FilterInputDateValueMenu/constants.js";
|
|
2
2
|
import { applyAcceptChar } from "./applyAcceptChar.js";
|
|
3
|
+
import { applyFieldValueTransforms } from "./applyFieldValueTransforms.js";
|
|
4
|
+
import { applyKnownFieldHelpers } from "./applyKnownFieldHelpers.js";
|
|
3
5
|
import { chipIdToConditionIndex, findChipSplitIndex } from "./conditions.js";
|
|
4
6
|
import { CONNECTOR_ID_PATTERN, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, OPERATOR_LABELS, OPERATOR_LABELS_BY_TYPE, OPERATOR_SYMBOLS, QUERY_BAR_SELECTOR, VARIANT_LABELS } from "./constants.js";
|
|
5
7
|
import { buildContainerAnchoredRect, isMenuRelated } from "./dom.js";
|
|
@@ -9,5 +11,5 @@ import { getCurrentValueTokenText, getValueFilterText } from "./menuFilterText.j
|
|
|
9
11
|
import { getOperatorFromLabel, getOperatorLabel, isBetweenOperator, isMultiSelectOperator, isNoValueOperator } from "./operators.js";
|
|
10
12
|
import { isFilterParseError, parseExpression } from "./parseExpression/index.js";
|
|
11
13
|
import { serializeExpression } from "./serializeExpression.js";
|
|
12
|
-
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator } from "./statusCode/index.js";
|
|
13
|
-
export { CONNECTOR_ID_PATTERN, DATE_PRESETS, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, OPERATOR_LABELS, OPERATOR_LABELS_BY_TYPE, OPERATOR_SYMBOLS, QUERY_BAR_SELECTOR, VARIANT_LABELS, applyAcceptChar, buildContainerAnchoredRect, chipIdToConditionIndex, createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator, filterAndSort, findChipSplitIndex, formatDateForChip, getCurrentValueTokenText, getDateDisplayLabel, getFieldValues, getOperatorFromLabel, getOperatorLabel, getValueFilterText, hasFieldValues, hasStaticAllowlist, isBetweenOperator, isDatePreset, isFilterParseError, isMenuRelated, isMultiSelectOperator, isNoValueOperator, parseExpression, serializeExpression };
|
|
14
|
+
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator } from "./statusCode/index.js";
|
|
15
|
+
export { CONNECTOR_ID_PATTERN, DATE_PRESETS, NO_VALUE_OPERATORS, OPERATORS_BY_TYPE, OPERATOR_LABELS, OPERATOR_LABELS_BY_TYPE, OPERATOR_SYMBOLS, QUERY_BAR_SELECTOR, VARIANT_LABELS, applyAcceptChar, applyFieldValueTransforms, applyKnownFieldHelpers, buildContainerAnchoredRect, chipIdToConditionIndex, createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator, filterAndSort, findChipSplitIndex, formatDateForChip, getCurrentValueTokenText, getDateDisplayLabel, getFieldValues, getOperatorFromLabel, getOperatorLabel, getValueFilterText, hasFieldValues, hasStaticAllowlist, isBetweenOperator, isDatePreset, isFilterParseError, isMenuRelated, isMultiSelectOperator, isNoValueOperator, parseExpression, serializeExpression };
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import type { ExprNode } from '../types';
|
|
1
|
+
import type { ExprNode, FieldMetadata } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* Serialize an expression tree to a canonical text string.
|
|
4
4
|
* Top-level conditions are sorted alphabetically by field name.
|
|
5
|
+
*
|
|
6
|
+
* **Pass `fields` when the output targets the backend.** Per-field
|
|
7
|
+
* `serializeValue` hooks run first, so values like the status-code mask
|
|
8
|
+
* `"2XX"` become `"2"` in the emitted string. Omitting `fields` keeps the
|
|
9
|
+
* UI-facing values verbatim — useful for clipboard round-trip, debug
|
|
10
|
+
* display, or any case where the output feeds `parseExpression` back. If
|
|
11
|
+
* you forget `fields` on the path to the backend, the placeholder `X`s
|
|
12
|
+
* ride through silently — name the backend call-site helper explicitly
|
|
13
|
+
* (e.g. `const query = serializeExpression(expr, fields)`) to make the
|
|
14
|
+
* intent obvious at callsite.
|
|
5
15
|
*/
|
|
6
|
-
export declare const serializeExpression: (expr: ExprNode | null) => string;
|
|
16
|
+
export declare const serializeExpression: (expr: ExprNode | null, fields?: FieldMetadata[]) => string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { applyFieldValueTransforms } from "./applyFieldValueTransforms.js";
|
|
1
2
|
const quoteValue = (v)=>`"${v}"`;
|
|
2
3
|
const serializeValue = (condition)=>{
|
|
3
4
|
if ('is_null' === condition.operator || 'is_not_null' === condition.operator) return '';
|
|
@@ -27,8 +28,10 @@ const serializeNode = (node, isTopLevel)=>{
|
|
|
27
28
|
if ('condition' === node.type) return serializeCondition(node);
|
|
28
29
|
return serializeGroup(node, isTopLevel);
|
|
29
30
|
};
|
|
30
|
-
const serializeExpression = (expr)=>{
|
|
31
|
+
const serializeExpression = (expr, fields)=>{
|
|
31
32
|
if (!expr) return '';
|
|
32
|
-
|
|
33
|
+
const normalized = fields ? applyFieldValueTransforms(expr, fields) : expr;
|
|
34
|
+
if (!normalized) return '';
|
|
35
|
+
return serializeNode(normalized, true);
|
|
33
36
|
};
|
|
34
37
|
export { serializeExpression };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the `serializeValue` callback for the HTTP status code field. Strips
|
|
3
|
+
* trailing mask placeholders (`X` / `x`) from the UI value so the backend
|
|
4
|
+
* receives the shorter class form:
|
|
5
|
+
*
|
|
6
|
+
* "2XX" → "2"
|
|
7
|
+
* "22X" → "22"
|
|
8
|
+
* "222" → "222"
|
|
9
|
+
* "4XX" → "4"
|
|
10
|
+
* "40X" → "40"
|
|
11
|
+
*
|
|
12
|
+
* Anything that isn't a status-code-shaped string (e.g. a number, boolean,
|
|
13
|
+
* or freeform text) is returned unchanged so invalid committed values still
|
|
14
|
+
* surface in the backend payload for the parser to reject.
|
|
15
|
+
*/
|
|
16
|
+
export declare const createStatusCodeSerializer: () => ((value: string | number | boolean) => string | number | boolean);
|