@illinois-grad/grad-vue 6.0.15 → 7.1.0

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.
@@ -2172,10 +2172,10 @@
2172
2172
  "kind": "field",
2173
2173
  "name": "filtering",
2174
2174
  "type": {
2175
- "text": "UseFilteringReturn<any>"
2175
+ "text": "UseFilteringReturn<any, AnyFilterRecord>"
2176
2176
  },
2177
2177
  "optional": true,
2178
- "description": "Filtering object created with useFiltering()"
2178
+ "description": "Filtering object created with useFiltering() Filter state is keyed by each column's filter key (`filter.key ?? key`)."
2179
2179
  },
2180
2180
  {
2181
2181
  "kind": "field",
@@ -2284,7 +2284,7 @@
2284
2284
  "kind": "field",
2285
2285
  "name": "filter",
2286
2286
  "type": {
2287
- "text": "Partial<Record<keyof TableRow, any>>"
2287
+ "text": "FilterState<AnyFilterRecord>"
2288
2288
  },
2289
2289
  "optional": true
2290
2290
  },
@@ -147,8 +147,8 @@ declare const __VLS_export: import("vue").DefineComponent<{
147
147
  onChange?: ((value: (string | number)[]) => any) | undefined;
148
148
  }>, {
149
149
  required: boolean;
150
+ searchDescription: boolean;
150
151
  disabled: boolean;
151
152
  errors: string[];
152
153
  hiddenLabel: boolean;
153
- searchDescription: boolean;
154
154
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -161,10 +161,10 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
161
161
  "onUpdate:modelValue"?: ((value: string | number | null | undefined) => any) | undefined;
162
162
  }>, {
163
163
  required: boolean;
164
- disabled: boolean;
165
- errors: string[];
166
164
  searchDescription: boolean;
167
165
  searchable: boolean;
166
+ disabled: boolean;
167
+ errors: string[];
168
168
  compact: boolean;
169
169
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
170
170
  option?: (props: {
@@ -1,6 +1,6 @@
1
- import type { TableColumn, TableColumnState, TableRow, TableSort } from "./table/TableColumn.ts";
1
+ import type { AnyFilterRecord, TableColumn, TableColumnState, TableRow, TableSort } from "./table/TableColumn.ts";
2
2
  import type { VNode } from "vue";
3
- import type { UseFilteringReturn } from "../compose/useFiltering.ts";
3
+ import type { FilterState, UseFilteringReturn } from "../compose/useFiltering.ts";
4
4
  import type { CellChangePayload, UseTableChangesReturn } from "../compose/useTableChanges.ts";
5
5
  export interface BulkAction {
6
6
  /**
@@ -34,6 +34,12 @@ export interface BulkAction {
34
34
  * objects to use, and `label` for the column header.
35
35
  * - `sortable: true` makes the column sortable.
36
36
  * - `filter` can be used to provide a `TableColumnFilter` configuration.
37
+ * Filter state is keyed by `filter.key`, or by the column `key` when
38
+ * `filter.key` is omitted. Pass a filter/request type as the third
39
+ * `TableColumn` type argument to type-check `filter.key` and values, and
40
+ * use `buildFilterRequest()` to convert filter state into request values
41
+ * (for example `match: "contains"` produces `%text%`). `filterDefaults()`
42
+ * builds the initial filter state from the same columns.
37
43
  * - `display` accepts a custom render function for the column data.
38
44
  * - `trClass` and `tdClass` can be used to provide custom classes for table rows and cells.
39
45
  * - `data` array with objects containing fields for the columns.
@@ -48,7 +54,7 @@ export interface BulkAction {
48
54
  */
49
55
  declare const _default: typeof __VLS_export;
50
56
  export default _default;
51
- declare const __VLS_export: <T extends TableRow, C extends TableColumn<T>>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
57
+ declare const __VLS_export: <T extends TableRow, C extends TableColumn<T> = TableColumn<T>, F = AnyFilterRecord>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
52
58
  props: import("vue").PublicProps & __VLS_PrettifyLocal<({
53
59
  /**
54
60
  * Accessible label
@@ -91,8 +97,11 @@ declare const __VLS_export: <T extends TableRow, C extends TableColumn<T>>(__VLS
91
97
  groupRender?: (groupValue: any, row: T) => VNode;
92
98
  /**
93
99
  * Filtering object created with useFiltering()
100
+ *
101
+ * Filter state is keyed by each column's filter key
102
+ * (`filter.key ?? key`).
94
103
  */
95
- filtering?: UseFilteringReturn<any>;
104
+ filtering?: UseFilteringReturn<any, F>;
96
105
  /**
97
106
  * Make the table rows clickable
98
107
  */
@@ -142,7 +151,7 @@ declare const __VLS_export: <T extends TableRow, C extends TableColumn<T>>(__VLS
142
151
  resizableColumns?: boolean;
143
152
  } & {
144
153
  sort?: TableSort<T>[];
145
- filter?: Partial<Record<keyof T, any>>;
154
+ filter?: FilterState<F>;
146
155
  columnState?: TableColumnState<T>;
147
156
  selectedRows?: string[];
148
157
  }) & {
@@ -150,7 +159,7 @@ declare const __VLS_export: <T extends TableRow, C extends TableColumn<T>>(__VLS
150
159
  "onCell-change"?: ((payload: CellChangePayload<T, Extract<keyof T, string>>) => any) | undefined;
151
160
  "onUpdate:pageSize"?: ((value: number) => any) | undefined;
152
161
  "onUpdate:sort"?: ((value: TableSort<T, Extract<keyof T, string>>[]) => any) | undefined;
153
- "onUpdate:filter"?: ((value: Partial<Record<keyof T, any>>) => any) | undefined;
162
+ "onUpdate:filter"?: ((value: FilterState<F>) => any) | undefined;
154
163
  "onUpdate:columnState"?: ((value: Partial<Record<Extract<keyof T, string>, import("./table/TableColumn.ts").TableColumnStateValue>>) => any) | undefined;
155
164
  "onUpdate:selectedRows"?: ((value: string[]) => any) | undefined;
156
165
  "onUpdate:startIndex"?: ((value: number) => any) | undefined;
@@ -171,7 +180,7 @@ declare const __VLS_export: <T extends TableRow, C extends TableColumn<T>>(__VLS
171
180
  (e: "cell-change", payload: CellChangePayload<T>): void;
172
181
  (e: "update:startIndex", value: number): void;
173
182
  (e: "update:pageSize", value: number): void;
174
- } & (((event: "update:sort", value: TableSort<T, Extract<keyof T, string>>[]) => void) & ((event: "update:filter", value: Partial<Record<keyof T, any>>) => void) & ((event: "update:columnState", value: Partial<Record<Extract<keyof T, string>, import("./table/TableColumn.ts").TableColumnStateValue>>) => void) & ((event: "update:selectedRows", value: string[]) => void));
183
+ } & (((event: "update:sort", value: TableSort<T, Extract<keyof T, string>>[]) => void) & ((event: "update:filter", value: FilterState<F>) => void) & ((event: "update:columnState", value: Partial<Record<Extract<keyof T, string>, import("./table/TableColumn.ts").TableColumnStateValue>>) => void) & ((event: "update:selectedRows", value: string[]) => void));
175
184
  }>) => import("vue").VNode & {
176
185
  __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
177
186
  };
@@ -1,12 +1,53 @@
1
1
  import { VNode } from "vue";
2
- export type TableColumnFilter = SelectColumnFilter | MultiSelectColumnFilter | ToggleColumnFilter | SearchColumnFilter;
3
- export interface SelectColumnFilter {
4
- type: 'select';
5
- options: Array<{
6
- label: string;
7
- value: any;
8
- description?: string;
9
- }>;
2
+ /**
3
+ * Default filter/request type used when a column does not declare one.
4
+ */
5
+ export type AnyFilterRecord = Record<string, any>;
6
+ /**
7
+ * String keys of a filter/request type.
8
+ */
9
+ export type FilterKey<F> = Extract<keyof F, string>;
10
+ /**
11
+ * The non-null value type accepted by the request field `K` of `F`.
12
+ */
13
+ export type FilterApiValue<F, K extends keyof F> = Exclude<F[K], null | undefined>;
14
+ export type FilterPrimitive = string | number | boolean;
15
+ /**
16
+ * How a search filter's text is converted for the request.
17
+ *
18
+ * - `exact` (default): the trimmed text is sent unchanged.
19
+ * - `contains`: `%text%`
20
+ * - `startsWith`: `text%`
21
+ * - `endsWith`: `%text`
22
+ */
23
+ export type SearchFilterMatch = "exact" | "contains" | "startsWith" | "endsWith";
24
+ export interface FilterOption<V = any> {
25
+ label: string;
26
+ value: V;
27
+ description?: string;
28
+ }
29
+ /**
30
+ * Converts a normalized UI value into the request value for `F[K]`.
31
+ * Returning `undefined` omits the field from the request.
32
+ */
33
+ export type FilterTransform<In, F, K extends keyof F> = (value: In) => FilterApiValue<F, K> | undefined;
34
+ type ArrayElement<V> = V extends readonly (infer E)[] ? E : never;
35
+ interface SearchFilterBase {
36
+ type: "search";
37
+ /**
38
+ * Placeholder text shown in the search input.
39
+ */
40
+ placeholder?: string;
41
+ }
42
+ type SearchFilterMapping<F, K extends keyof F> = (string extends FilterApiValue<F, K> ? {
43
+ match?: SearchFilterMatch;
44
+ transform?: undefined;
45
+ } : never) | {
46
+ match?: undefined;
47
+ transform: FilterTransform<string, F, K>;
48
+ };
49
+ interface SelectFilterBase {
50
+ type: "select";
10
51
  placeholder?: string;
11
52
  /**
12
53
  * Include the option `description` in the searchable text match.
@@ -14,20 +55,15 @@ export interface SelectColumnFilter {
14
55
  */
15
56
  searchDescription?: boolean;
16
57
  }
17
- export interface SearchColumnFilter {
18
- type: 'search';
19
- /**
20
- * Placeholder text shown in the search input.
21
- */
22
- placeholder?: string;
23
- }
24
- export interface MultiSelectColumnFilter {
25
- type: 'multi-select';
26
- options: Array<{
27
- label: string;
28
- value: any;
29
- description?: string;
30
- }>;
58
+ type SelectFilterMapping<F, K extends keyof F> = {
59
+ options: Array<FilterOption<FilterApiValue<F, K>>>;
60
+ transform?: undefined;
61
+ } | {
62
+ options: Array<FilterOption<FilterPrimitive>>;
63
+ transform: FilterTransform<FilterPrimitive, F, K>;
64
+ };
65
+ interface MultiSelectFilterBase {
66
+ type: "multi-select";
31
67
  placeholder?: string;
32
68
  /**
33
69
  * When true, renders a searchable GMultiSelect combobox instead of a
@@ -41,11 +77,87 @@ export interface MultiSelectColumnFilter {
41
77
  */
42
78
  searchDescription?: boolean;
43
79
  }
44
- export interface ToggleColumnFilter {
45
- type: 'toggle';
80
+ type MultiSelectFilterMapping<F, K extends keyof F> = ([FilterApiValue<F, K>] extends [readonly unknown[]] ? {
81
+ options: Array<FilterOption<ArrayElement<FilterApiValue<F, K>>>>;
82
+ transform?: undefined;
83
+ } : never) | {
84
+ options: Array<FilterOption<FilterPrimitive>>;
85
+ transform: FilterTransform<FilterPrimitive[], F, K>;
86
+ };
87
+ interface ToggleFilterBase {
88
+ type: "toggle";
46
89
  label: string;
47
90
  description?: string;
48
91
  }
92
+ type ToggleFilterMapping<F, K extends keyof F> = (true extends FilterApiValue<F, K> ? {
93
+ transform?: undefined;
94
+ } : never) | {
95
+ transform: FilterTransform<true, F, K>;
96
+ };
97
+ /**
98
+ * A search input filter.
99
+ *
100
+ * The UI value is the entered text. Without `transform`, the request field
101
+ * must accept a string; `match` controls wildcard wrapping. With
102
+ * `transform`, the trimmed text is converted to the request field's type.
103
+ */
104
+ export type SearchColumnFilter<F = AnyFilterRecord, K extends FilterKey<F> = FilterKey<F>> = SearchFilterBase & {
105
+ key?: K;
106
+ } & SearchFilterMapping<F, K>;
107
+ /**
108
+ * A single-select filter. Without `transform`, option values must match the
109
+ * request field's type. `0` and `false` are valid option values.
110
+ *
111
+ * For a "has value / has no value" filter on a nullable field, use boolean
112
+ * options with a boolean request key; clearing the select removes the filter:
113
+ *
114
+ * ```ts
115
+ * filter: {
116
+ * type: "select",
117
+ * key: "deposit_date__notnull",
118
+ * options: [
119
+ * { label: "Has Deposit Date", value: true },
120
+ * { label: "No Deposit Date", value: false },
121
+ * ],
122
+ * }
123
+ * ```
124
+ */
125
+ export type SelectColumnFilter<F = AnyFilterRecord, K extends FilterKey<F> = FilterKey<F>> = SelectFilterBase & {
126
+ key?: K;
127
+ } & SelectFilterMapping<F, K>;
128
+ /**
129
+ * A multi-select filter. Without `transform`, the request field must be an
130
+ * array and option values must match its element type.
131
+ */
132
+ export type MultiSelectColumnFilter<F = AnyFilterRecord, K extends FilterKey<F> = FilterKey<F>> = MultiSelectFilterBase & {
133
+ key?: K;
134
+ } & MultiSelectFilterMapping<F, K>;
135
+ /**
136
+ * A toggle filter. It is active only when on. Without `transform`, the
137
+ * request field must accept `true`.
138
+ */
139
+ export type ToggleColumnFilter<F = AnyFilterRecord, K extends FilterKey<F> = FilterKey<F>> = ToggleFilterBase & {
140
+ key?: K;
141
+ } & ToggleFilterMapping<F, K>;
142
+ type ColumnFilterFor<F, K extends FilterKey<F>> = (SearchFilterBase & SearchFilterMapping<F, K>) | (SelectFilterBase & SelectFilterMapping<F, K>) | (MultiSelectFilterBase & MultiSelectFilterMapping<F, K>) | (ToggleFilterBase & ToggleFilterMapping<F, K>);
143
+ type KeyedColumnFilter<F, K extends FilterKey<F>> = K extends unknown ? ColumnFilterFor<F, K> & {
144
+ /**
145
+ * The filter/request field this filter reads and writes. Defaults to
146
+ * the column key, which must then be a key of the filter type.
147
+ */
148
+ key: K;
149
+ } : never;
150
+ type DefaultKeyColumnFilter<F, K> = K extends FilterKey<F> ? ColumnFilterFor<F, K> & {
151
+ key?: undefined;
152
+ } : never;
153
+ /**
154
+ * Filter configuration for a column.
155
+ *
156
+ * `F` is the filter/request type (for example a generated API query type).
157
+ * `filter.key` must be a key of `F`. When `key` is omitted, the column key
158
+ * (`DefaultKey`) is used and must itself be a key of `F`.
159
+ */
160
+ export type TableColumnFilter<F = AnyFilterRecord, DefaultKey extends string = FilterKey<F>> = KeyedColumnFilter<F, FilterKey<F>> | DefaultKeyColumnFilter<F, DefaultKey>;
49
161
  export interface EditableColumnConfig {
50
162
  /**
51
163
  * Type of editable control. Defaults to "input".
@@ -77,7 +189,7 @@ export interface EditableColumnConfig {
77
189
  */
78
190
  labelKey?: string;
79
191
  }
80
- type ColumnKey<T> = Extract<keyof T, string>;
192
+ export type ColumnKey<T> = Extract<keyof T, string>;
81
193
  export interface TableColumnStateValue {
82
194
  visible?: boolean;
83
195
  width?: number;
@@ -87,11 +199,18 @@ export interface TableSort<T extends TableRow, K extends ColumnKey<T> = ColumnKe
87
199
  key: K;
88
200
  order: 1 | -1;
89
201
  }
90
- export interface TableColumn<T extends TableRow, K extends ColumnKey<T> = ColumnKey<T>> {
202
+ export interface TableColumnConfig<T extends TableRow, K extends ColumnKey<T> = ColumnKey<T>, F = AnyFilterRecord> {
203
+ /**
204
+ * Row field used for display and sorting.
205
+ */
91
206
  key: K;
92
207
  label: string;
93
208
  sortable?: boolean;
94
- filter?: TableColumnFilter;
209
+ /**
210
+ * Filter configuration. Use `filter.key` when the filter/request field
211
+ * differs from the column key.
212
+ */
213
+ filter?: TableColumnFilter<F, K>;
95
214
  /**
96
215
  * Custom render function for the column data.
97
216
  * Cannot be used with `editable`.
@@ -106,6 +225,14 @@ export interface TableColumn<T extends TableRow, K extends ColumnKey<T> = Column
106
225
  */
107
226
  editable?: EditableColumnConfig;
108
227
  }
228
+ /**
229
+ * A table column for rows of type `T`.
230
+ *
231
+ * `F` is an independent filter/request type that column filters map to.
232
+ * This distributes over `K` so each column's default filter key is checked
233
+ * against its own row key.
234
+ */
235
+ export type TableColumn<T extends TableRow, K extends ColumnKey<T> = ColumnKey<T>, F = AnyFilterRecord> = K extends ColumnKey<T> ? TableColumnConfig<T, K, F> : never;
109
236
  export interface TableRow extends Record<string, any> {
110
237
  key: string;
111
238
  }
@@ -0,0 +1,58 @@
1
+ import type { FilterOption, FilterPrimitive, SearchFilterMatch } from "./TableColumn.ts";
2
+ /**
3
+ * A raw filter value as stored in filter state and route queries.
4
+ *
5
+ * Values read back from a URL are strings, so column-aware helpers normalize
6
+ * them against the column filter configuration before use.
7
+ */
8
+ export type FilterInputValue = FilterPrimitive | FilterPrimitive[] | null | undefined;
9
+ /**
10
+ * Structural view of any `TableColumnFilter`, independent of its filter type.
11
+ */
12
+ type AnyColumnFilter = {
13
+ type: "search";
14
+ match?: SearchFilterMatch;
15
+ transform?: (value: string) => unknown;
16
+ } | {
17
+ type: "select";
18
+ options: readonly FilterOption<unknown>[];
19
+ transform?: (value: FilterPrimitive) => unknown;
20
+ } | {
21
+ type: "multi-select";
22
+ options: readonly FilterOption<unknown>[];
23
+ transform?: (value: FilterPrimitive[]) => unknown;
24
+ } | {
25
+ type: "toggle";
26
+ transform?: (value: true) => unknown;
27
+ };
28
+ interface FilterableColumn {
29
+ key: string;
30
+ filter?: {
31
+ key?: string;
32
+ };
33
+ }
34
+ /**
35
+ * The filter/request key a column filter reads and writes.
36
+ */
37
+ export declare function columnFilterKey(column: FilterableColumn): string;
38
+ /**
39
+ * Normalizes a raw state value into the value expected by the filter control.
40
+ */
41
+ export declare function filterInputValue(filter: AnyColumnFilter, raw: FilterInputValue): FilterPrimitive | FilterPrimitive[] | undefined;
42
+ /**
43
+ * Converts a value emitted by a filter control into a raw state value.
44
+ * Empty values (including an unchecked toggle) become `undefined`, except
45
+ * multi-select values, which stay arrays.
46
+ */
47
+ export declare function filterStateValue(filter: AnyColumnFilter, input: unknown): FilterInputValue;
48
+ /**
49
+ * Whether a raw state value represents an active filter for the column.
50
+ * `0` and `false` are meaningful select values; toggles are active only when on.
51
+ */
52
+ export declare function isColumnFilterActive(filter: AnyColumnFilter, raw: FilterInputValue): boolean;
53
+ /**
54
+ * Converts a raw state value into the request value for the column filter.
55
+ * Returns `undefined` when the filter is inactive.
56
+ */
57
+ export declare function filterRequestValue(filter: AnyColumnFilter, raw: FilterInputValue): unknown;
58
+ export {};
@@ -1,4 +1,23 @@
1
1
  import { Reactive, type Ref } from "vue";
2
+ import type { AnyFilterRecord, ColumnKey, FilterApiValue, FilterKey, TableColumn, TableRow } from "../components/table/TableColumn.ts";
3
+ import { type FilterInputValue } from "../components/table/columnFilters.ts";
4
+ export type { FilterInputValue } from "../components/table/columnFilters.ts";
5
+ /**
6
+ * Raw UI filter state keyed by filter/request keys of `F`.
7
+ *
8
+ * Values are kept as entered (or as read from the URL) and are only
9
+ * converted to request values by `buildFilterRequest()`.
10
+ */
11
+ export type FilterState<F> = {
12
+ [K in keyof F]?: FilterInputValue;
13
+ };
14
+ /**
15
+ * A request object built from filter state. Each value has the type of the
16
+ * corresponding field in `F`.
17
+ */
18
+ export type FilterRequest<F> = {
19
+ [K in keyof F]?: FilterApiValue<F, K>;
20
+ };
2
21
  export type FilterLocationQueryValueRaw = string | number;
3
22
  export type FilterRouteQueryValue = string | null;
4
23
  export type FilterRouteQuery = {
@@ -13,7 +32,15 @@ export type FilterLocationQuery = {
13
32
  export interface FilteringOptions {
14
33
  syncWith?: Ref<FilterRouteQuery>;
15
34
  }
16
- export interface QueryFilteringOptions<F extends Record<string, any> = Record<string, any>> {
35
+ export interface FilterStateFromQueryOptions<F = AnyFilterRecord> {
36
+ /**
37
+ * Array filters whose `"true"`/`"false"` query values should be
38
+ * converted to booleans. Not needed for column filters with boolean
39
+ * option values, since `buildFilterRequest()` matches those itself.
40
+ */
41
+ booleanArrayKeys?: readonly FilterKey<F>[];
42
+ }
43
+ export interface QueryFilteringOptions<F = AnyFilterRecord> extends FilterStateFromQueryOptions<F> {
17
44
  route: {
18
45
  query: FilterRouteQuery;
19
46
  };
@@ -22,7 +49,6 @@ export interface QueryFilteringOptions<F extends Record<string, any> = Record<st
22
49
  query: FilterLocationQuery;
23
50
  }) => unknown;
24
51
  };
25
- booleanArrayKeys?: readonly Extract<keyof F, string>[];
26
52
  }
27
53
  /**
28
54
  * Represents a type that defines a set of filters for a given record type.
@@ -37,14 +63,15 @@ export type FiltersForRecord<T extends object, F extends {
37
63
  /**
38
64
  * Represents the return type of a composition function used for handling
39
65
  * filtering logic in a data structure.
66
+ *
67
+ * `T` is the row type and `F` is the independent filter/request type. Filter
68
+ * state and `filteredColumns` are keyed by filter keys of `F`.
40
69
  */
41
- export interface UseFilteringReturn<T extends Record<string, any> = Record<string, any>, F extends {
42
- [K in keyof T]?: any;
43
- } = Record<keyof T, any>> {
44
- filters: Reactive<F>;
70
+ export interface UseFilteringReturn<T extends object = AnyFilterRecord, F = Partial<Record<keyof T, any>>> {
71
+ filters: Reactive<FilterState<F>>;
45
72
  isFiltered: Ref<boolean>;
46
73
  clearFilters: () => void;
47
- filteredColumns: Ref<Partial<Record<keyof T, boolean>>>;
74
+ filteredColumns: Ref<Partial<Record<FilterKey<F>, boolean>>>;
48
75
  }
49
76
  /**
50
77
  * Returns the value if it's not empty, or undefined if it's empty.
@@ -63,6 +90,55 @@ export declare function asArray<T>(value: T | T[]): NonNullable<T>[] | undefined
63
90
  * values (`?tag=a,b`) and removes null entries from array values.
64
91
  */
65
92
  export declare function parseQueryArrayValue(value: FilterRouteQueryValue | FilterRouteQueryValue[] | readonly FilterRouteQueryValue[] | undefined): string[] | undefined;
93
+ /**
94
+ * Builds a typed request object from column filter configuration and raw
95
+ * filter state.
96
+ *
97
+ * Each filtered column reads `filters[filter.key ?? column.key]` and applies
98
+ * its explicit transformation (`match` for search filters, or `transform`).
99
+ * Only keys produced by column filters are included.
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * type Query = NonNullable<GetStudentsData["query"]>;
104
+ * const columns: TableColumn<StudentRow, ColumnKey<StudentRow>, Query>[] = [
105
+ * { key: "major", label: "Major", filter: { type: "search", key: "major__like", match: "contains" } },
106
+ * ];
107
+ * const query: FilterRequest<Query> = buildFilterRequest(columns, filters);
108
+ * ```
109
+ */
110
+ export declare function buildFilterRequest<T extends TableRow, F>(columns: readonly TableColumn<T, ColumnKey<T>, F>[], filters: FilterState<F>): FilterRequest<F>;
111
+ /**
112
+ * Builds the default filter state for `useFiltering()` / `useQueryFiltering()`
113
+ * from column filter configuration, so filters don't have to be listed twice.
114
+ *
115
+ * Each filtered column adds its filter key (`filter.key ?? column.key`).
116
+ * Multi-select filters default to `[]`, so their query params are always read
117
+ * as arrays; all other filters default to `undefined`.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * const filtering = useQueryFiltering<StudentRow, Query>(filterDefaults(columns), { route, router });
122
+ * ```
123
+ */
124
+ export declare function filterDefaults<T extends TableRow, F>(columns: readonly TableColumn<T, ColumnKey<T>, F>[]): FilterState<F>;
125
+ /**
126
+ * Reads filter state from route query params, the same way
127
+ * `useQueryFiltering()` does, without creating reactive state or writing to
128
+ * the URL.
129
+ *
130
+ * Use this when another view needs the filters of a query-synced table, for
131
+ * example a detail page that loads the same list. Keys come from `defaults`;
132
+ * filters with array defaults are always read as arrays.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * const request = computed(() =>
137
+ * buildFilterRequest(columns, filterStateFromQuery(filterDefaults(columns), route.query)),
138
+ * );
139
+ * ```
140
+ */
141
+ export declare function filterStateFromQuery<F>(defaults: FilterState<F>, query: FilterRouteQuery, options?: FilterStateFromQueryOptions<F>): FilterState<F>;
66
142
  /**
67
143
  * Converts filter criteria into a format suitable for use as a query object
68
144
  * in vue-router.
@@ -85,17 +161,20 @@ export declare function filtersToQueryParams<T extends Record<string, any>>(filt
85
161
  * read from and written to query params as arrays, and `booleanArrayKeys` can
86
162
  * be used for multi-value filters that should be converted to boolean values
87
163
  * inside the filter state.
164
+ *
165
+ * Use `filterDefaults(columns)` to build `filters` from column configuration,
166
+ * and `filterStateFromQuery()` to read the same state elsewhere without syncing.
88
167
  */
89
- export declare function useQueryFiltering<T extends Record<string, any>, F extends {
90
- [K in keyof T]?: any;
91
- } = Record<keyof T, any>>(filters: F, options: QueryFilteringOptions<F>): UseFilteringReturn<T, F>;
168
+ export declare function useQueryFiltering<T extends object = AnyFilterRecord, F = Partial<Record<keyof T, any>>>(filters: FilterState<F>, options: QueryFilteringOptions<F>): UseFilteringReturn<T, F>;
92
169
  /**
93
170
  * Provides a mechanism to manage and synchronize filterable data with given filters and options.
94
171
  *
172
+ * Filter state is keyed by filter/request keys (`filter.key ?? column.key`)
173
+ * and holds raw UI values. Use `buildFilterRequest()` to convert it into
174
+ * typed request values.
175
+ *
95
176
  * @param filters An object that defines the filters applicable to the data record.
96
177
  * @param options Configuration options for filtering, such as synchronization.
97
178
  * @return Returns an object that can be used with GTable.
98
179
  */
99
- export declare function useFiltering<T extends Record<string, any> = Record<string, any>, F extends {
100
- [K in keyof T]?: any;
101
- } = Record<keyof T, any>>(filters: F, options?: FilteringOptions): UseFilteringReturn<T, F>;
180
+ export declare function useFiltering<T extends object = AnyFilterRecord, F = Partial<Record<keyof T, any>>>(filters: FilterState<F>, options?: FilteringOptions): UseFilteringReturn<T, F>;
@@ -1,5 +1,5 @@
1
1
  import { ComputedRef } from "vue";
2
- import { TableColumn, TableRow } from "../components/table/TableColumn.ts";
2
+ import { TableColumnConfig, TableRow } from "../components/table/TableColumn.ts";
3
3
  import { EventHookOn } from "@vueuse/core";
4
4
  export type ColumnKey<R extends TableRow> = Extract<keyof R, string>;
5
5
  /**
@@ -33,7 +33,7 @@ export interface CellChangeEvent<R extends TableRow = TableRow, K extends Column
33
33
  */
34
34
  export interface CellChangePayload<T extends TableRow = TableRow, K extends ColumnKey<T> = ColumnKey<T>> {
35
35
  row: T;
36
- column: TableColumn<T, K>;
36
+ column: TableColumnConfig<T, K>;
37
37
  value: T[K];
38
38
  previousValue: T[K];
39
39
  }