Skip to content

Commit

Permalink
fix: improve rounding logic for range filters (#348)
Browse files Browse the repository at this point in the history
* fix: improve rounding logic for range filters

* chore: changeset

* docs: update docs for formatter
  • Loading branch information
sampotts authored Jan 13, 2021
1 parent 967777e commit f20fae2
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 15 deletions.
7 changes: 7 additions & 0 deletions .changeset/pink-flies-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'sajari-sdk-docs': patch
'@sajari/react-hooks': patch
'@sajari/react-search-ui': patch
---

Improve rounding logic for range filters
22 changes: 12 additions & 10 deletions docs/pages/classes/rangefilterbuilder.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,17 @@ function Example() {

The constructor accepts a single object with the following properties:

| Name | Type | Default | Description |
| ----------- | ----------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | | The name of the filter. This should be unique. |
| `group` | `string` | | A group name, for grouping multiple filters together using [`ARRAY_MATCH`](https://docs.sajari.com/user-guide/integrating-search/filters/). |
| `field` | `string` | | A field in schema. |
| `initial` | `[number, number]` | `null` | An intially selected range. |
| `min` | `number` | `0` | The min value of the filter. |
| `max` | `number` | `0` | The max value of the filter. |
| `aggregate` | `boolean` | `true` | If true, set value for min and max from the backend response. |
| `formatter` | `(value: [number, number]) => [number, number]` | `(v) => v.map(Math.round)` | The function to format the range. For example, format `[0.1, 5.5]` to `[0, 6]`. |
| Name | Type | Default | Description |
| ----------- | ----------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` | `string` | | The name of the filter. This should be unique. |
| `group` | `string` | | A group name, for grouping multiple filters together using [`ARRAY_MATCH`](https://docs.sajari.com/user-guide/integrating-search/filters/). |
| `field` | `string` | | A field in schema. |
| `initial` | `[number, number]` | `null` | An intially selected range. |
| `min` | `number` | `0` | The min value of the filter. |
| `max` | `number` | `aggregate ? 0 : 100` | The max value of the filter. |
| `step` | `number` | `1` | A number that specifies the granularity that the values must adhere to. |
| `aggregate` | `boolean` | `true` | If true, set value for min and max from the backend response. |
| `formatter` | `(value: [number, number]) => [number, number]` | | The function to format the range. By default, this will round to the nearest step for the value. For example if step is `1`, the formatter will format `[0.1, 5.5]` to `[0, 6]`. |

## Properties

Expand All @@ -72,6 +73,7 @@ For more advanced implementations, you may want to access properties on the `Fil
| `setMin(value: number)` | Set the minimum value. |
| `setMax(value: number)` | Set the maximum value. |
| `getMinMax()` | Returns the current min and max in an array. |
| `getStep()` | Returns the number that specifies the granularity that the values must adhere to. |
| `filter()` | Builds up the filter string from the current filter and it's children. |
| `getName()` | Returns the `name` property of the filter. |
| `getGroup()` | Returns the `group` property of the filter. |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isArray, round } from '@sajari/react-sdk-utils';
import { isArray, round, roundToStep } from '@sajari/react-sdk-utils';

import { EVENT_RANGE_UPDATED } from '../../events';
import { Listener } from '../Listener';
Expand All @@ -21,6 +21,8 @@ export default class RangeFilterBuilder {

private max: number;

private step: number;

private aggregate: boolean;

private listeners: { [k: string]: Listener };
Expand All @@ -35,7 +37,8 @@ export default class RangeFilterBuilder {
initial,
min = 0,
max = aggregate ? 0 : 100,
formatter = (value: Range) => value.map((v) => round(v, 2)) as Range,
step = 1,
formatter = (value: Range) => value.map((v) => roundToStep(v, step)) as Range,
}: RangeFilterOptions) {
if (typeof initial === 'undefined') {
this.initial = aggregate ? null : [min, max];
Expand All @@ -50,6 +53,7 @@ export default class RangeFilterBuilder {
this.formatter = formatter;
this.min = min;
this.max = max;
this.step = step;
this.aggregate = aggregate;
this.listeners = {
[EVENT_RANGE_UPDATED]: new Listener(),
Expand Down Expand Up @@ -103,6 +107,10 @@ export default class RangeFilterBuilder {
return [this.min, this.max];
}

public getStep() {
return this.step;
}

/**
* Builds up the filter string from the current state.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export interface RangeFilterOptions {
min?: number;
/** The max value of the filter */
max?: number;
/** The step to increment values */
step?: number;
/** If true, set value for min and max from the backend response */
aggregate?: boolean;
/** The function to format the range. For example, format [0.1, 5.5] to [0, 6] */
Expand Down
1 change: 1 addition & 0 deletions packages/hooks/src/useRangeFilter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ function useRangeFilter(name: string) {
return {
min,
max,
step: filter.getStep(),
setRange,
range,
reset,
Expand Down
5 changes: 3 additions & 2 deletions packages/search-ui/src/Filter/RangeFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import Box from './Box';
import { RangeFilterProps } from './types';
import { getHeaderId } from './utils';

const RangeFilter = ({ name, title, format, showInputs, step, steps, tick, ticks }: Omit<RangeFilterProps, 'type'>) => {
const { min, max, range, setRange, reset, showReset } = useRangeFilter(name);
const RangeFilter = (props: Omit<RangeFilterProps, 'type' | 'step'>) => {
const { name, title, format, showInputs, steps, tick, ticks } = props;
const { min, max, range, setRange, reset, showReset, step } = useRangeFilter(name);
const { disableDefaultStyles = false, customClassNames, currency, language } = useSearchUIContext();

if (!range || max === 0) {
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function getDecimalPlaces(value: number): number {
}

/**
* Round to the nearest step
* Round to decimal places
* @param input - the number to round
* @param places - how many decimal places to round to
*/
Expand Down

0 comments on commit f20fae2

Please sign in to comment.