Skip to content

Commit be56582

Browse files
authored
Merge pull request #1 from armand1m/feat/filter-state-enhancements
feat: smaller build, unit tests, more confidence in the library
2 parents 2693275 + 851e0cd commit be56582

22 files changed

+1110
-347
lines changed

.eslintrc.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = {
2+
"extends": [
3+
"react-app",
4+
"prettier/@typescript-eslint",
5+
"plugin:prettier/recommended"
6+
],
7+
"settings": {
8+
"react": {
9+
"version": "detect"
10+
}
11+
},
12+
"rules": {
13+
"no-redeclare": "off",
14+
}
15+
}

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
runs-on: ${{ matrix.os }}
88
strategy:
99
matrix:
10-
node: ['10.x', '12.x', '14.x']
10+
node: ['12.x', '14.x']
1111
os: [ubuntu-latest, macOS-latest]
1212

1313
steps:

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
node_modules
44
.cache
55
dist
6-
*.tgz
6+
coverage
7+
*.tgz

.prettierrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"jsxBracketSameLine": true,
3+
"printWidth": 70,
4+
"singleQuote": true,
5+
"trailingComma": "es5"
6+
}

README.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
# react-query-filters
1+
# react-query-filter
2+
3+
<div style="max-width: 700px">
4+
<img src="./.github/chakra-ui-demo.gif?raw=true">
5+
</div>
26

37
> **Heads up:** This is still a work in progress. A lot of breaking change might happen and a lot of features are still missing. PR's are very welcome but please open an issue first describing what you think could be better.
48
59
Set of utilities to implement a Query Builder for filters.
610

711
This library ships a `useQueryFilters` hook that you can use to implement an UI on top of it.
812

9-
The `useQueryFilters` will track state changes and enable you do build your query filter builder using the styles you want.
13+
The `useQueryFilters` will track state changes and enable you to build your own UI implementation on top of it.
1014

1115
- [Features](#features)
1216
- [Signature](#signature)
@@ -24,8 +28,9 @@ The `useQueryFilters` will track state changes and enable you do build your quer
2428
- [ ] Single Select
2529
- [ ] Multiple Select
2630
- [x] Conditional value based on operation type
27-
- Condition value is always `undefined` if operation type is `is-empty` or `is-not-empty`
31+
- Condition value is always `undefined` if operation type is `IS_EMPTY` or `IS_NOT_EMPTY`
2832
- [x] `AND` & `OR` logic gates supported, implemented as the `Binding` enum
33+
- [x] Custom Operation Labels enabled
2934
- [ ] Support for controlled state
3035
- [ ] Support for nested conditions
3136

@@ -143,7 +148,7 @@ import {
143148
SlideFade,
144149
Code,
145150
} from '@chakra-ui/react';
146-
import { useQueryFilters, Filter, PropertyDescription } from 'react-query-filters';
151+
import { useQueryFilters, Filter, PropertyDescription } from 'react-query-filter';
147152
import { FilterRow } from './FilterRow';
148153

149154
interface Props {
@@ -192,7 +197,7 @@ import {
192197
Select,
193198
Tooltip,
194199
} from '@chakra-ui/react';
195-
import { FilterRowProps } from 'react-query-filters';
200+
import { FilterRowProps } from 'react-query-filter';
196201

197202
export const FilterRow: React.FC<FilterRowProps> = ({
198203
filter,
@@ -305,10 +310,6 @@ const properties: PropertyDescription[] = [
305310
<FilterSelection properties={properties} />
306311
```
307312

308-
<div style="max-width: 700px">
309-
<img src="./.github/chakra-ui-demo.gif?raw=true">
310-
</div>
311-
312313
## License
313314

314-
MIT © [Armando Magalhaes](https://github.com/armand1m)
315+
MIT © [Armando Magalhaes](https://github.com/armand1m)

package.json

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
},
3232
"husky": {
3333
"hooks": {
34-
"pre-commit": "tsdx lint"
34+
"pre-commit": "tsdx test"
3535
}
3636
},
3737
"prettier": {
@@ -40,6 +40,10 @@
4040
"singleQuote": true,
4141
"trailingComma": "es5"
4242
},
43+
"resolutions": {
44+
"**/@typescript-eslint/eslint-plugin": "^4.1.1",
45+
"**/@typescript-eslint/parser": "^4.1.1"
46+
},
4347
"name": "react-query-filter",
4448
"author": "Armando Magalhães",
4549
"module": "dist/react-query-filter.esm.js",
@@ -65,10 +69,11 @@
6569
"@storybook/addon-links": "^6.1.11",
6670
"@storybook/addons": "^6.1.11",
6771
"@storybook/react": "^6.1.11",
68-
"@testing-library/react-hooks": "^3.7.0",
72+
"@testing-library/react-hooks": "^7.0.0",
6973
"@types/react": "^17.0.0",
7074
"@types/react-dom": "^17.0.0",
7175
"@types/react-select": "^3.0.28",
76+
"@types/uuid": "^8.3.0",
7277
"babel-loader": "^8.2.2",
7378
"framer-motion": "^3.1.1",
7479
"husky": "^4.3.6",
@@ -80,16 +85,18 @@
8085
"size-limit": "^4.9.1",
8186
"tsdx": "^0.14.1",
8287
"tslib": "^2.0.3",
83-
"typescript": "^4.1.3"
88+
"typescript": "^4.3.2"
8489
},
8590
"dependencies": {
86-
"react-use": "^15.3.4"
91+
"uuid": "^8.3.2"
8792
},
8893
"repository": {
8994
"type": "git",
9095
"url": "https://github.com/armand1m/react-query-filter.git"
9196
},
9297
"release": {
93-
"branches": ["main"]
98+
"branches": [
99+
"main"
100+
]
94101
}
95102
}

src/bindings.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ export enum Binding {
55
OR = 'OR',
66
}
77

8+
export const AndOption: SelectOption<Binding> = {
9+
value: Binding.AND,
10+
label: 'And',
11+
};
12+
13+
export const OrOption: SelectOption<Binding> = {
14+
value: Binding.OR,
15+
label: 'Or',
16+
};
17+
818
export const defaultBindingOptions: SelectOption<Binding>[] = [
9-
{
10-
value: Binding.AND,
11-
label: 'And',
12-
},
13-
{
14-
value: Binding.OR,
15-
label: 'Or',
16-
},
19+
AndOption,
20+
OrOption,
1721
];

src/components/chakra-ui/FilterRow.stories.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@ const meta: Meta<FilterRowProps> = {
1010
controls: { expanded: true },
1111
},
1212
args: {
13-
filter: {},
13+
filter: {
14+
id: 'test-id',
15+
},
1416
fields: [],
1517
operations: [],
1618
bindings: [],
19+
selectStates: {
20+
onChangeBinding: () => {},
21+
onChangeField: () => {},
22+
onChangeOperation: () => {},
23+
},
1724
shouldRenderBindingSelect: false,
1825
shouldRenderValueInput: true,
1926
},

src/components/chakra-ui/FilterRow.tsx

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
import React, { FC } from 'react';
2-
import {
3-
CloseButton,
4-
Text,
5-
HStack,
6-
Input,
7-
Select,
8-
Tooltip,
9-
} from '@chakra-ui/react';
2+
import { CloseButton, Text, HStack, Select, Tooltip } from '@chakra-ui/react';
103
import { FilterRowProps } from '../../';
4+
import { ValueInput } from '../shared/ValueInput';
115

126
export const FilterRow: FC<FilterRowProps> = ({
137
filter,
148
fields,
159
bindings,
1610
operations,
11+
suggestions,
1712
shouldRenderBindingSelect,
1813
shouldRenderValueInput,
1914
onRemove,
20-
onChangeBinding,
21-
onChangeField,
22-
onChangeOperation,
2315
onChangeValue,
16+
selectStates: {
17+
bindingIndex,
18+
fieldIndex,
19+
operationIndex,
20+
onChangeBinding,
21+
onChangeField,
22+
onChangeOperation,
23+
},
2424
}) => {
2525
return (
2626
<HStack>
@@ -32,12 +32,15 @@ export const FilterRow: FC<FilterRowProps> = ({
3232
<Select
3333
size="sm"
3434
maxWidth="6rem"
35-
value={filter.binding}
36-
onChange={onChangeBinding}
35+
value={bindingIndex}
36+
onChange={event => {
37+
const index = Number(event.target.value);
38+
onChangeBinding(bindings[index]);
39+
}}
3740
>
38-
{bindings.map(binding => (
41+
{bindings.map((binding, index) => (
3942
<option
40-
value={binding.value}
43+
value={index}
4144
key={binding.value}
4245
selected={filter.binding === binding.value}
4346
>
@@ -51,13 +54,16 @@ export const FilterRow: FC<FilterRowProps> = ({
5154

5255
<Select
5356
size="sm"
54-
value={filter.field}
55-
onChange={onChangeField}
57+
value={fieldIndex}
58+
onChange={event => {
59+
const index = Number(event.target.value);
60+
onChangeField(fields[index]);
61+
}}
5662
placeholder="Field"
5763
>
58-
{fields.map(field => (
64+
{fields.map((field, index) => (
5965
<option
60-
value={field.value}
66+
value={index}
6167
key={field.value}
6268
selected={filter.field === field.value}
6369
>
@@ -68,13 +74,16 @@ export const FilterRow: FC<FilterRowProps> = ({
6874

6975
<Select
7076
size="sm"
71-
value={filter.operation}
72-
onChange={onChangeOperation}
77+
value={operationIndex}
78+
onChange={event => {
79+
const index = Number(event.target.value);
80+
onChangeOperation(operations[index]);
81+
}}
7382
placeholder="Operation"
7483
>
75-
{operations.map(operation => (
84+
{operations.map((operation, index) => (
7685
<option
77-
value={operation.value}
86+
value={index}
7887
key={operation.value}
7988
selected={filter.operation === operation.value}
8089
>
@@ -84,11 +93,13 @@ export const FilterRow: FC<FilterRowProps> = ({
8493
</Select>
8594

8695
{shouldRenderValueInput && (
87-
<Input
96+
<ValueInput
8897
size="sm"
89-
placeholder="Value"
90-
value={filter.value ?? ''}
98+
name={filter.id}
99+
type={filter.type}
100+
value={filter.value}
91101
onChange={onChangeValue}
102+
suggestions={suggestions}
92103
/>
93104
)}
94105
</HStack>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
import { Meta, Story } from '@storybook/react';
3+
import { FilterRowProps } from '../../';
4+
import { FilterRow } from './FilterRow';
5+
6+
const meta: Meta<FilterRowProps> = {
7+
title: 'React Select/Filter Row',
8+
component: FilterRow,
9+
parameters: {
10+
controls: { expanded: true },
11+
},
12+
args: {
13+
filter: {
14+
id: 'test-id',
15+
},
16+
fields: [],
17+
operations: [],
18+
bindings: [],
19+
selectStates: {
20+
onChangeBinding: () => {},
21+
onChangeField: () => {},
22+
onChangeOperation: () => {},
23+
},
24+
shouldRenderBindingSelect: false,
25+
shouldRenderValueInput: true,
26+
},
27+
};
28+
29+
export default meta;
30+
31+
const Template: Story<FilterRowProps> = args => {
32+
return <FilterRow {...args} />;
33+
};
34+
35+
// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
36+
// https://storybook.js.org/docs/react/workflows/unit-testing
37+
export const Default = Template.bind({});
38+
39+
Default.args = {};

0 commit comments

Comments
 (0)