@wallarm-org/design-system 1.0.0-rc-feature-AS-877-fix-filter-code.3 → 1.0.0-rc-feature-AS-877-fix-filter-code.4
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/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 +3 -3
- package/dist/components/FilterInput/lib/applyKnownFieldHelpers.js +5 -3
- package/dist/components/FilterInput/lib/index.d.ts +2 -1
- package/dist/components/FilterInput/lib/index.js +3 -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/index.d.ts +1 -0
- package/dist/components/FilterInput/lib/statusCode/index.js +2 -1
- package/dist/components/FilterInput/types.d.ts +9 -0
- package/dist/metadata/components.json +1 -1
- package/package.json +1 -1
|
@@ -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, serializeExpression, } from './lib';
|
|
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 };
|
|
@@ -6,9 +6,9 @@ import type { FieldMetadata } from '../types';
|
|
|
6
6
|
* Reserved names and what they auto-attach (unless the consumer already
|
|
7
7
|
* provided a value for that slot):
|
|
8
8
|
*
|
|
9
|
-
* | `name` | Attaches
|
|
10
|
-
* | ------------- |
|
|
11
|
-
* | `status_code` | HTTP status code: `acceptChar`, `normalize`, `getSuggestions`, `validate` |
|
|
9
|
+
* | `name` | Attaches |
|
|
10
|
+
* | ------------- | ------------------------------------------------------------------------------------------ |
|
|
11
|
+
* | `status_code` | HTTP status code: `acceptChar`, `normalize`, `getSuggestions`, `validate`, `serializeValue` |
|
|
12
12
|
*
|
|
13
13
|
* Consumer-supplied callbacks always win over the auto-wired ones. If the
|
|
14
14
|
* backend uses a different name (e.g. `http_status_code`), the helpers are
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator } from "./statusCode/index.js";
|
|
1
|
+
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator } from "./statusCode/index.js";
|
|
2
2
|
const KNOWN_FIELD_HELPERS = {
|
|
3
3
|
status_code: ()=>({
|
|
4
4
|
acceptChar: createStatusCodeInputFilter(),
|
|
5
5
|
normalize: createStatusCodeNormalizer(),
|
|
6
6
|
getSuggestions: createStatusCodeSuggestions(),
|
|
7
|
-
validate: createStatusCodeValidator()
|
|
7
|
+
validate: createStatusCodeValidator(),
|
|
8
|
+
serializeValue: createStatusCodeSerializer()
|
|
8
9
|
})
|
|
9
10
|
};
|
|
10
11
|
const applyKnownFieldHelpers = (fields)=>{
|
|
@@ -19,7 +20,8 @@ const applyKnownFieldHelpers = (fields)=>{
|
|
|
19
20
|
acceptChar: field.acceptChar ?? helpers.acceptChar,
|
|
20
21
|
normalize: field.normalize ?? helpers.normalize,
|
|
21
22
|
getSuggestions: field.getSuggestions ?? helpers.getSuggestions,
|
|
22
|
-
validate: field.validate ?? helpers.validate
|
|
23
|
+
validate: field.validate ?? helpers.validate,
|
|
24
|
+
serializeValue: field.serializeValue ?? helpers.serializeValue
|
|
23
25
|
};
|
|
24
26
|
});
|
|
25
27
|
return changed ? out : fields;
|
|
@@ -1,6 +1,7 @@
|
|
|
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';
|
|
4
5
|
export { applyKnownFieldHelpers } from './applyKnownFieldHelpers';
|
|
5
6
|
export { chipIdToConditionIndex, findChipSplitIndex } from './conditions';
|
|
6
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';
|
|
@@ -11,4 +12,4 @@ export { getCurrentValueTokenText, getValueFilterText } from './menuFilterText';
|
|
|
11
12
|
export { getOperatorFromLabel, getOperatorLabel, isBetweenOperator, isMultiSelectOperator, isNoValueOperator, } from './operators';
|
|
12
13
|
export { type FilterParseError, isFilterParseError, parseExpression } from './parseExpression';
|
|
13
14
|
export { serializeExpression } from './serializeExpression';
|
|
14
|
-
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator, } from './statusCode';
|
|
15
|
+
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator, } from './statusCode';
|
|
@@ -1,5 +1,6 @@
|
|
|
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";
|
|
3
4
|
import { applyKnownFieldHelpers } from "./applyKnownFieldHelpers.js";
|
|
4
5
|
import { chipIdToConditionIndex, findChipSplitIndex } from "./conditions.js";
|
|
5
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";
|
|
@@ -10,5 +11,5 @@ import { getCurrentValueTokenText, getValueFilterText } from "./menuFilterText.j
|
|
|
10
11
|
import { getOperatorFromLabel, getOperatorLabel, isBetweenOperator, isMultiSelectOperator, isNoValueOperator } from "./operators.js";
|
|
11
12
|
import { isFilterParseError, parseExpression } from "./parseExpression/index.js";
|
|
12
13
|
import { serializeExpression } from "./serializeExpression.js";
|
|
13
|
-
import { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator } from "./statusCode/index.js";
|
|
14
|
-
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, applyKnownFieldHelpers, 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);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createStatusCodeInputFilter } from './createStatusCodeInputFilter';
|
|
2
2
|
export { createStatusCodeNormalizer } from './createStatusCodeNormalizer';
|
|
3
|
+
export { createStatusCodeSerializer } from './createStatusCodeSerializer';
|
|
3
4
|
export { createStatusCodeSuggestions } from './createStatusCodeSuggestions';
|
|
4
5
|
export { createStatusCodeValidator } from './createStatusCodeValidator';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createStatusCodeInputFilter } from "./createStatusCodeInputFilter.js";
|
|
2
2
|
import { createStatusCodeNormalizer } from "./createStatusCodeNormalizer.js";
|
|
3
|
+
import { createStatusCodeSerializer } from "./createStatusCodeSerializer.js";
|
|
3
4
|
import { createStatusCodeSuggestions } from "./createStatusCodeSuggestions.js";
|
|
4
5
|
import { createStatusCodeValidator } from "./createStatusCodeValidator.js";
|
|
5
|
-
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSuggestions, createStatusCodeValidator };
|
|
6
|
+
export { createStatusCodeInputFilter, createStatusCodeNormalizer, createStatusCodeSerializer, createStatusCodeSuggestions, createStatusCodeValidator };
|
|
@@ -98,6 +98,15 @@ export interface FieldMetadata {
|
|
|
98
98
|
* commits apply this per token.
|
|
99
99
|
*/
|
|
100
100
|
normalize?: (value: string | number | boolean) => string | number | boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Optional backend-value transformer. The UI stores whatever
|
|
103
|
+
* `normalize` produced (e.g. `"2XX"`), but some backends want a
|
|
104
|
+
* stripped form (e.g. `"2"`). Pass the expression tree through
|
|
105
|
+
* `applyFieldValueTransforms(expr, fields)` — or a string through
|
|
106
|
+
* `serializeExpression(expr, fields)` — to apply this hook when
|
|
107
|
+
* emitting the query. Display in the chip is unaffected.
|
|
108
|
+
*/
|
|
109
|
+
serializeValue?: (value: string | number | boolean) => string | number | boolean;
|
|
101
110
|
}
|
|
102
111
|
/**
|
|
103
112
|
* Expression Tree Types
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wallarm-org/design-system",
|
|
3
|
-
"version": "1.0.0-rc-feature-AS-877-fix-filter-code.
|
|
3
|
+
"version": "1.0.0-rc-feature-AS-877-fix-filter-code.4",
|
|
4
4
|
"description": "Core design system library with React components and Storybook documentation",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|