jlnstack

Built-in Filters

Ready-to-use filter types for common data types

Built-in Filters

The package includes built-in filter definitions for common data types. Each filter comes with sensible defaults and configurable options.

String Filter

Filter text values with various operators.

import { stringFilter } from "@jlnstack/filter"

const filters = defineFilters({
  name: stringFilter({
    label: "Name",
    placeholder: "Enter name...",
    operators: ["eq", "contains", "startsWith", "endsWith"],
  }),
})

Options

OptionTypeDefaultDescription
labelstringDisplay label for the filter
placeholderstringInput placeholder text
operatorsStringOperators[]AllAllowed operators

Operators

OperatorDescription
eqEquals
neqNot equals
containsContains substring
startsWithStarts with
endsWithEnds with

Value Type

type StringValue = {
  operator: "eq" | "neq" | "contains" | "startsWith" | "endsWith"
  value: string
}

Usage

// condition is a Condition<Schema> for the \"name\" field
<filter.Filter
  condition={condition}
  render={({ value, onValueChange }) => (
    <input
      value={value?.value ?? ""}
      onChange={(e) =>
        onValueChange({ operator: "contains", value: e.target.value })
      }
    />
  )}
/>

Number Filter

Filter numeric values with comparison operators.

import { numberFilter } from "@jlnstack/filter"

const filters = defineFilters({
  age: numberFilter({
    label: "Age",
    min: 0,
    max: 120,
    operators: ["eq", "gt", "lt"],
  }),
})

Options

OptionTypeDefaultDescription
labelstringDisplay label for the filter
minnumberMinimum allowed value
maxnumberMaximum allowed value
operatorsNumberOperators[]AllAllowed operators

Operators

OperatorDescription
eqEquals
neqNot equals
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal

Value Type

type NumberValue = {
  operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte"
  value: number
}

Usage

// condition is a Condition<Schema> for the \"age\" field
<filter.Filter
  condition={condition}
  render={({ value, onValueChange, definition }) => (
    <div>
      <select
        value={value?.operator ?? "eq"}
        onChange={(e) =>
          onValueChange({ ...value, operator: e.target.value })
        }
      >
        <option value="eq">Equals</option>
        <option value="gt">Greater than</option>
        <option value="lt">Less than</option>
      </select>
      <input
        type="number"
        min={definition.min}
        max={definition.max}
        value={value?.value ?? ""}
        onChange={(e) =>
          onValueChange({ 
            operator: value?.operator ?? "eq", 
            value: Number(e.target.value) 
          })
        }
      />
    </div>
  )}
/>

Date Filter

Filter date values with comparison operators.

import { dateFilter } from "@jlnstack/filter"

const filters = defineFilters({
  createdAt: dateFilter({
    label: "Created At",
    operators: ["gte", "lte"],
  }),
})

Options

OptionTypeDefaultDescription
labelstringDisplay label for the filter
operatorsDateOperators[]AllAllowed operators

Operators

OperatorDescription
eqEquals
neqNot equals
gtAfter
gteOn or after
ltBefore
lteOn or before

Value Type

type DateValue = {
  operator: "eq" | "neq" | "gt" | "gte" | "lt" | "lte"
  value: Date | string
}

Usage

// condition is a Condition<Schema> for the \"createdAt\" field
<filter.Filter
  condition={condition}
  render={({ value, onValueChange }) => (
    <input
      type="date"
      value={value?.value instanceof Date 
        ? value.value.toISOString().split("T")[0] 
        : value?.value ?? ""
      }
      onChange={(e) =>
        onValueChange({ operator: "gte", value: e.target.value })
      }
    />
  )}
/>

Boolean Filter

Filter boolean values.

import { booleanFilter } from "@jlnstack/filter"

const filters = defineFilters({
  verified: booleanFilter({
    label: "Verified",
    trueLabel: "Verified only",
    falseLabel: "Unverified only",
  }),
})

Options

OptionTypeDefaultDescription
labelstringDisplay label for the filter
trueLabelstringLabel for true option
falseLabelstringLabel for false option

Value Type

type BooleanValue = boolean

Usage

// condition is a Condition<Schema> for the \"verified\" field
<filter.Filter
  condition={condition}
  render={({ value, onValueChange, onRemove, definition }) => (
    <select
      value={value ? "true" : "false"}
      onChange={(e) =>
        e.target.value === "" ? onRemove() : onValueChange(e.target.value === "true")
      }
    >
      <option value="">All</option>
      <option value="true">{definition.trueLabel ?? "Yes"}</option>
      <option value="false">{definition.falseLabel ?? "No"}</option>
    </select>
  )}
/>

Restricting Operators

You can restrict which operators are available for a filter:

const filters = defineFilters({
  // Only allow exact match
  status: stringFilter({ 
    label: "Status", 
    operators: ["eq"] 
  }),
  
  // Only allow range comparisons
  price: numberFilter({ 
    label: "Price", 
    operators: ["gte", "lte"] 
  }),
})

On this page