@synerise/ds-filter 1.2.59 → 1.2.60
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/CHANGELOG.md +4 -0
- package/CLAUDE.md +126 -0
- package/package.json +8 -7
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.2.60](https://github.com/Synerise/synerise-design/compare/@synerise/ds-filter@1.2.59...@synerise/ds-filter@1.2.60) (2026-07-23)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @synerise/ds-filter
|
|
9
|
+
|
|
6
10
|
## [1.2.59](https://github.com/Synerise/synerise-design/compare/@synerise/ds-filter@1.2.58...@synerise/ds-filter@1.2.59) (2026-07-16)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @synerise/ds-filter
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Filter (`@synerise/ds-filter`)
|
|
2
|
+
|
|
3
|
+
> A container component that renders and manages a list of filter expressions (step cards with optional logic operators between them), supporting drag-and-drop reordering, per-step actions, a conditions limit, and a fully render-prop-based content API.
|
|
4
|
+
|
|
5
|
+
## Package structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
src/
|
|
9
|
+
Filter.tsx — main component
|
|
10
|
+
Filter.types.ts — FilterProps and all data-model types
|
|
11
|
+
Filter.styles.ts — styled-components
|
|
12
|
+
index.ts — public exports
|
|
13
|
+
utils.ts — isStepType() type guard
|
|
14
|
+
components/
|
|
15
|
+
ExpressionItem/
|
|
16
|
+
index.ts — re-exports ExpressionItem, DraggableExpressionItem, ExpressionItemProps
|
|
17
|
+
ExpressionItem.tsx — renders a single StepCard + optional Logic between items
|
|
18
|
+
ExpressionItem.types.ts — ExpressionItemProps, SortableItemProps
|
|
19
|
+
DraggableExpressionItem.tsx — wraps ExpressionItem with useDndMonitor for drag support
|
|
20
|
+
__specs__/
|
|
21
|
+
Filter.spec.tsx — Vitest tests
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Public exports
|
|
25
|
+
|
|
26
|
+
### `Filter` (default export)
|
|
27
|
+
|
|
28
|
+
| Prop | Type | Default | Description |
|
|
29
|
+
|------|------|---------|-------------|
|
|
30
|
+
| `expressions` | `Expression[]` | — | **Required.** The ordered list of STEP and LOGIC expressions to render |
|
|
31
|
+
| `matching` | `MatchingProps` | — | Top-level matching toggle props (from `@synerise/ds-logic`) |
|
|
32
|
+
| `onChangeOrder` | `(newOrder: Expression[]) => void` | — | Order-change callback; also activates drag mode when `expressions.length > 1` |
|
|
33
|
+
| `onChangeLogic` | `(id: string, logic: LogicOperatorValue) => void` | — | Called when the Logic operator between steps changes |
|
|
34
|
+
| `onChangeStepMatching` | `(id: string, matching: boolean) => void` | — | Called when a step's matching toggle changes |
|
|
35
|
+
| `onChangeStepName` | `(id: string, name: string) => void` | — | Called when a step's name input changes |
|
|
36
|
+
| `onDeleteStep` | `(id: string) => void` | — | Called when a step's delete button is clicked |
|
|
37
|
+
| `onDuplicateStep` | `(id: string) => void` | — | Called on duplicate; silently disabled (button hidden) if `maxConditionsLimit` is exceeded |
|
|
38
|
+
| `renderStepFooter` | `(expression: Expression) => ReactNode` | — | Render prop for the footer slot of each StepCard |
|
|
39
|
+
| `renderStepContent` | `(expression: Expression, hoverDisabled?: boolean) => ReactNode` | — | Render prop for the body of each StepCard; `hoverDisabled` is `true` when another step is active |
|
|
40
|
+
| `renderStepHeaderRightSide` | `(expression: Expression, index: number, options?: { placeholder?: boolean }) => ReactNode` | — | Render prop for the right side of each StepCard header |
|
|
41
|
+
| `renderHeaderRightSide` | `(expressions: Expression[]) => ReactNode` | — | Render prop for the right side of the Filter header bar |
|
|
42
|
+
| `addFilterComponent` | `ReactNode \| ((arg: { isLimitExceeded: boolean }) => ReactNode)` | — | "Add filter" button area; hidden in `readOnly` mode; function form receives limit state |
|
|
43
|
+
| `logicOptions` | `LogicOperator[]` | — | Available logic operator choices for Logic components |
|
|
44
|
+
| `maxConditionsLimit` | `number` | — | When set, shows `count/limit` in header and disables duplicate once reached |
|
|
45
|
+
| `readOnly` | `boolean` | `false` | Disables all editing interactions |
|
|
46
|
+
| `singleStepCondition` | `boolean` | `false` | Passed through to StepCard to render single-condition UI variant |
|
|
47
|
+
| `visibilityConfig` | `{ isStepCardHeaderVisible?: boolean }` | `{ isStepCardHeaderVisible: true }` | Controls StepCard header visibility |
|
|
48
|
+
| `getMoveByLabel` | `(moveByOffset: number) => string` | — | Produces accessible aria label for keyboard-move buttons |
|
|
49
|
+
| `texts` | `DeepPartial<FilterTexts>` | — | Overrides any subset of i18n strings (merged with react-intl defaults) |
|
|
50
|
+
|
|
51
|
+
No `forwardRef`.
|
|
52
|
+
|
|
53
|
+
### `Expression`
|
|
54
|
+
|
|
55
|
+
Union type: `StepType | LogicType`
|
|
56
|
+
|
|
57
|
+
### `StepType`
|
|
58
|
+
|
|
59
|
+
| Field | Type | Description |
|
|
60
|
+
|-------|------|-------------|
|
|
61
|
+
| `type` | `'STEP'` | Discriminant |
|
|
62
|
+
| `id` | `string` | Unique identifier |
|
|
63
|
+
| `data` | `Partial<StepCardProps>` | Props passed to the StepCard |
|
|
64
|
+
| `logic` | `LogicType` (optional) | Logic operator displayed before this step |
|
|
65
|
+
| `expressionType` | `'attribute' \| 'event'` (optional) | Controls matching text variants shown in the step header |
|
|
66
|
+
|
|
67
|
+
### `LogicType`
|
|
68
|
+
|
|
69
|
+
| Field | Type | Description |
|
|
70
|
+
|-------|------|-------------|
|
|
71
|
+
| `type` | `'LOGIC'` | Discriminant |
|
|
72
|
+
| `id` | `string` | Unique identifier |
|
|
73
|
+
| `data` | `Partial<LogicProps>` | Props passed to the Logic component |
|
|
74
|
+
|
|
75
|
+
### `FilterProps`
|
|
76
|
+
|
|
77
|
+
TypeScript type re-exported for consumers.
|
|
78
|
+
|
|
79
|
+
## Usage patterns
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import Filter from '@synerise/ds-filter';
|
|
83
|
+
import type { Expression } from '@synerise/ds-filter';
|
|
84
|
+
|
|
85
|
+
const [expressions, setExpressions] = useState<Expression[]>([]);
|
|
86
|
+
|
|
87
|
+
<Filter
|
|
88
|
+
expressions={expressions}
|
|
89
|
+
matching={{ matching: true, onChange: (v) => setMatching(v) }}
|
|
90
|
+
onChangeOrder={setExpressions}
|
|
91
|
+
onDeleteStep={(id) => setExpressions(prev => prev.filter(e => e.id !== id))}
|
|
92
|
+
onDuplicateStep={(id) => { /* clone and append */ }}
|
|
93
|
+
onChangeStepName={(id, name) => { /* update */ }}
|
|
94
|
+
onChangeLogic={(id, logic) => { /* update */ }}
|
|
95
|
+
maxConditionsLimit={5}
|
|
96
|
+
addFilterComponent={({ isLimitExceeded }) => (
|
|
97
|
+
<Button disabled={isLimitExceeded} onClick={handleAdd}>Add filter</Button>
|
|
98
|
+
)}
|
|
99
|
+
renderStepContent={(expression) => <MyConditionEditor expression={expression} />}
|
|
100
|
+
renderStepFooter={(expression) => <MyFooter expression={expression} />}
|
|
101
|
+
/>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Styling
|
|
105
|
+
|
|
106
|
+
Styles in `Filter.styles.ts` use `@synerise/ds-core` theme palette tokens. `placeholderCss` is passed to `@synerise/ds-sortable` to style the drag-and-drop placeholder. No hardcoded values.
|
|
107
|
+
|
|
108
|
+
## Key dependencies
|
|
109
|
+
|
|
110
|
+
- `@synerise/ds-logic` — `Matching`, `Placeholder`, `Logic` components and related types
|
|
111
|
+
- `@synerise/ds-step-card` — `StepCard` rendered for each STEP expression
|
|
112
|
+
- `@synerise/ds-sortable` — drag-and-drop container used when `isDraggable` is true
|
|
113
|
+
- `@synerise/ds-utils` — `usePrevious`, `NOOP`, `DeepPartial`
|
|
114
|
+
- `react-intl` — i18n for all default text strings
|
|
115
|
+
|
|
116
|
+
## Implementation notes
|
|
117
|
+
|
|
118
|
+
- **Drag mode is automatic**: `isDraggable = Boolean(onChangeOrder && expressions.length > 1)`. With only 1 expression, static rendering is used. Drag wraps expressions in `Sortable`; without it, `ExpressionItem` is rendered directly.
|
|
119
|
+
- **CSS reorder animation**: On order change, the component calculates translateY offsets via DOM `getBoundingClientRect`, sets them synchronously, then clears them in a `requestAnimationFrame` to trigger CSS transitions. `z-index` is cleaned up on `transitionend`.
|
|
120
|
+
- **Active expression tracking**: The last-added expression becomes active (highlighted); clicking any expression activates it. Active state passes `hoverDisabled=true` to other steps' `renderStepContent`.
|
|
121
|
+
- **`addFilterComponent` function form**: Pass a function `(arg) => ReactNode` to receive `{ isLimitExceeded }` — useful for disabling the add button when the limit is hit. The `readOnly` prop hides the add area entirely.
|
|
122
|
+
- **`texts.overwritten.filterTitle`**: When set, replaces the entire matching + conditions-limit header row with a plain text title.
|
|
123
|
+
- **`logic` is on StepType, not separate**: The LOGIC operator before a step is embedded as `step.logic` — it is not a standalone sibling item in the `expressions` array. The `ExpressionItem` renders it conditionally (not shown for the last item or during drag).
|
|
124
|
+
- **`// @ts-expect-error` in ExpressionItem.tsx**: Type mismatches between `StepCardProps` and `LogicProps` are suppressed — this is a known issue.
|
|
125
|
+
- **Uses Vitest**: `jest.config.js` present — not yet migrated.
|
|
126
|
+
- **`react-intl` is a peer dependency** — component throws at runtime without an `IntlProvider` ancestor.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synerise/ds-filter",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.60",
|
|
4
4
|
"description": "Filter UI Component for the Synerise Design System",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": "Synerise/synerise-design",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"/dist",
|
|
19
19
|
"CHANGELOG.md",
|
|
20
|
+
"CLAUDE.md",
|
|
20
21
|
"README.md",
|
|
21
22
|
"package.json",
|
|
22
23
|
"LICENSE.md"
|
|
@@ -41,11 +42,11 @@
|
|
|
41
42
|
],
|
|
42
43
|
"types": "dist/index.d.ts",
|
|
43
44
|
"dependencies": {
|
|
44
|
-
"@synerise/ds-button": "^1.5.
|
|
45
|
-
"@synerise/ds-logic": "^1.1.
|
|
46
|
-
"@synerise/ds-sortable": "^1.3.
|
|
47
|
-
"@synerise/ds-step-card": "^1.2.
|
|
48
|
-
"@synerise/ds-utils": "^1.10.
|
|
45
|
+
"@synerise/ds-button": "^1.5.35",
|
|
46
|
+
"@synerise/ds-logic": "^1.1.46",
|
|
47
|
+
"@synerise/ds-sortable": "^1.3.21",
|
|
48
|
+
"@synerise/ds-step-card": "^1.2.57",
|
|
49
|
+
"@synerise/ds-utils": "^1.10.2"
|
|
49
50
|
},
|
|
50
51
|
"peerDependencies": {
|
|
51
52
|
"@synerise/ds-core": "*",
|
|
@@ -54,5 +55,5 @@
|
|
|
54
55
|
"styled-components": "^5.3.3",
|
|
55
56
|
"vitest": "4"
|
|
56
57
|
},
|
|
57
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "d0a43cc43d8528a36f105aceea52ab470edb71d9"
|
|
58
59
|
}
|