Project-specific UI hints (meta)
Attach your own typed metadata to filters and options without changing the core.
Your UI often needs extra per-filter information that the library has no opinion
about — a layout variant, a group, an icon, a step size. Attach it via meta. The
core never reads meta; it only carries it through to filters / filterMap for
your UI to branch on. Because the shapes are yours, they're fully typed — you
declare them once by augmenting the library's interfaces:
// e.g. src/types/filters.d.ts
declare module '@mbsatimov/use-filters' {
interface FilterMeta {
variant?: 'inline' | 'stacked'; // available on EVERY filter kind
}
interface SelectFilterMeta {
group?: 'primary' | 'advanced'; // only on select filters
}
interface NumberFilterMeta {
unit?: string; // only on number filters, e.g. '$'
}
interface FilterOptionMeta {
icon?: React.ComponentType; // on every option
}
interface FiltersMeta {
layout?: 'toolbar' | 'sidebar'; // the whole set
}
}Now pass meta where it's relevant, checked against the shape you declared:
status: f.select({
label: 'Status',
valueType: 'string',
options: [{ label: 'Open', value: 'open', meta: { icon: OpenIcon } }],
meta: { group: 'primary' }
});
min_price: f.number({ label: 'Min price', meta: { unit: '$' } });
useFilters(configs, { meta: { layout: 'sidebar' } });And read it back when rendering:
filters.map((filter) =>
filter.meta.group === 'advanced' ? <AdvancedSlot filter={filter} /> : <Control filter={filter} />
);There's a per-kind interface (SelectFilterMeta, NumberFilterMeta, …) so a hint
can be specific to one kind, a shared FilterMeta for hints that apply to all, a
FilterOptionMeta for options, and a FiltersMeta for the whole set.
The old FilterOption.icon / leftSlot / rightSlot, the per-filter className, and f.number
/ f.numberRange's unit were removed in 1.0 — rendering concerns don't belong on a headless
core. Declare what you need on FilterOptionMeta / FilterMeta / NumberFilterMeta and pass it
via meta instead (same data, typed by you).