@xh/hoist 80.0.0-SNAPSHOT.1768931272469 → 80.0.0-SNAPSHOT.1769011463076
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.
- package/CHANGELOG.md +8 -0
- package/build/types/cmp/grid/GridModel.d.ts +1 -1
- package/build/types/cmp/grid/Types.d.ts +7 -3
- package/build/types/cmp/store/StoreFilterField.d.ts +3 -3
- package/build/types/cmp/store/impl/StoreFilterFieldImplModel.d.ts +9 -7
- package/build/types/data/filter/Types.d.ts +7 -0
- package/build/types/desktop/cmp/grid/find/GridFindField.d.ts +3 -2
- package/build/types/desktop/cmp/grid/find/impl/GridFindFieldImplModel.d.ts +5 -3
- package/build/types/desktop/cmp/grid/impl/colchooser/ColChooserModel.d.ts +6 -11
- package/build/types/desktop/cmp/leftrightchooser/LeftRightChooserFilter.d.ts +3 -2
- package/cmp/grid/GridModel.ts +1 -1
- package/cmp/grid/Types.ts +15 -4
- package/cmp/store/StoreFilterField.ts +3 -3
- package/cmp/store/impl/StoreFilterFieldImplModel.ts +32 -26
- package/data/Store.ts +4 -2
- package/data/filter/Types.ts +8 -0
- package/desktop/cmp/grid/find/GridFindField.ts +3 -2
- package/desktop/cmp/grid/find/impl/GridFindFieldImplModel.ts +41 -37
- package/desktop/cmp/grid/impl/colchooser/ColChooser.ts +2 -2
- package/desktop/cmp/grid/impl/colchooser/ColChooserModel.ts +9 -5
- package/desktop/cmp/leftrightchooser/LeftRightChooserFilter.ts +26 -11
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
* `Store.isStore`
|
|
20
20
|
* `View.isView`
|
|
21
21
|
* `Filter.isFilter`
|
|
22
|
+
* Replaced `LeftRightChooserFilter.anyMatch` with `matchMode`. Changes are not expected to be
|
|
23
|
+
required as apps typically do not create this component directly.
|
|
24
|
+
|
|
25
|
+
### 🐞 Bug Fixes
|
|
26
|
+
|
|
27
|
+
* Fixed error encountered when attempting to `store.revert()` on a store with summary records.
|
|
22
28
|
|
|
23
29
|
### 🎁 New Features
|
|
24
30
|
|
|
@@ -28,6 +34,8 @@
|
|
|
28
34
|
hamburger menu. Set to `true` to render the current user's initials instead or provide a function
|
|
29
35
|
to render a custom element for the user.
|
|
30
36
|
* Added `AggregationContext` as an additional argument to `CubeField.canAggregateFn`.
|
|
37
|
+
* Added `filterMatchMode` option to `ColChooserModel`, allowing customizing match to `start`,
|
|
38
|
+
`startWord`, or `any`.
|
|
31
39
|
|
|
32
40
|
### ⚙️ Typescript API Adjustments
|
|
33
41
|
|
|
@@ -29,7 +29,7 @@ export interface GridConfig {
|
|
|
29
29
|
/** Config with which to create a GridFilterModel, or `true` to enable default. Desktop only.*/
|
|
30
30
|
filterModel?: GridFilterModelConfig | boolean;
|
|
31
31
|
/** Config with which to create a ColChooserModel, or boolean `true` to enable default.*/
|
|
32
|
-
colChooserModel?: ColChooserConfig | boolean;
|
|
32
|
+
colChooserModel?: Omit<ColChooserConfig, 'gridModel'> | boolean;
|
|
33
33
|
/**
|
|
34
34
|
* Function to be called when the user triggers GridModel.restoreDefaultsAsync(). This
|
|
35
35
|
* function will be called after the built-in defaults have been restored, and can be
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { FilterBindTarget, FilterValueSource, Store, StoreRecord } from '@xh/hoist/data';
|
|
1
|
+
import type { HSide, PersistOptions, Some } from '@xh/hoist/core';
|
|
2
|
+
import type { FilterBindTarget, FilterMatchMode, FilterValueSource, Store, StoreRecord } from '@xh/hoist/data';
|
|
4
3
|
import type { CellClassParams, CustomCellEditorProps, HeaderClassParams, HeaderValueGetterParams, ICellRendererParams, IRowNode, ITooltipParams, RowClassParams, ValueSetterParams } from '@xh/hoist/kit/ag-grid';
|
|
5
4
|
import type { ReactElement, ReactNode } from 'react';
|
|
6
5
|
import type { Column, ColumnSpec } from './columns/Column';
|
|
7
6
|
import type { ColumnGroup, ColumnGroupSpec } from './columns/ColumnGroup';
|
|
7
|
+
import type { GridFilterFieldSpecConfig } from './filter/GridFilterFieldSpec';
|
|
8
8
|
import type { GridModel } from './GridModel';
|
|
9
9
|
export interface ColumnState {
|
|
10
10
|
colId: string;
|
|
@@ -89,6 +89,8 @@ export interface GridFilterBindTarget extends FilterBindTarget, FilterValueSourc
|
|
|
89
89
|
*/
|
|
90
90
|
export type GroupRowRenderer = (context: ICellRendererParams) => ReactNode;
|
|
91
91
|
export interface ColChooserConfig {
|
|
92
|
+
/** GridModel to bind to. Not required if creating via `GridModel.colChooserModel` */
|
|
93
|
+
gridModel?: GridModel;
|
|
92
94
|
/**
|
|
93
95
|
* Immediately render changed columns on grid (default true).
|
|
94
96
|
* Set to false to enable Save button for committing changes on save. Desktop only.
|
|
@@ -108,6 +110,8 @@ export interface ColChooserConfig {
|
|
|
108
110
|
width?: string | number;
|
|
109
111
|
/** Chooser height for popover and dialog. Desktop only. */
|
|
110
112
|
height?: string | number;
|
|
113
|
+
/** Mode to use when filtering (default 'startWord'). Desktop only. */
|
|
114
|
+
filterMatchMode?: FilterMatchMode;
|
|
111
115
|
}
|
|
112
116
|
export type ColumnOrGroup = Column | ColumnGroup;
|
|
113
117
|
export type ColumnOrGroupSpec = ColumnSpec | ColumnGroupSpec;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { GridModel } from '@xh/hoist/cmp/grid';
|
|
1
|
+
import type { GridModel } from '@xh/hoist/cmp/grid';
|
|
2
2
|
import { DefaultHoistProps, HoistModel } from '@xh/hoist/core';
|
|
3
|
-
import { FilterTestFn, Store } from '@xh/hoist/data';
|
|
3
|
+
import type { FilterMatchMode, FilterTestFn, Store } from '@xh/hoist/data';
|
|
4
4
|
export interface StoreFilterFieldProps extends DefaultHoistProps {
|
|
5
5
|
/**
|
|
6
6
|
* Automatically apply the filter to bound store (default true). Applications that need to
|
|
@@ -37,7 +37,7 @@ export interface StoreFilterFieldProps extends DefaultHoistProps {
|
|
|
37
37
|
*/
|
|
38
38
|
includeFields?: string[];
|
|
39
39
|
/** Mode to use when filtering (default 'startWord'). */
|
|
40
|
-
matchMode?:
|
|
40
|
+
matchMode?: FilterMatchMode;
|
|
41
41
|
/** Optional model for raw value binding - see comments on the `bind` prop for details. */
|
|
42
42
|
model?: HoistModel;
|
|
43
43
|
/**
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { HoistModel } from '@xh/hoist/core';
|
|
2
1
|
import { GridModel } from '@xh/hoist/cmp/grid';
|
|
2
|
+
import { HoistModel } from '@xh/hoist/core';
|
|
3
|
+
import type { FilterMatchMode, StoreRecord } from '@xh/hoist/data';
|
|
3
4
|
import { Store } from '@xh/hoist/data';
|
|
4
5
|
/**
|
|
5
6
|
* @internal
|
|
@@ -9,15 +10,16 @@ export declare class StoreFilterFieldImplModel extends HoistModel {
|
|
|
9
10
|
model: any;
|
|
10
11
|
gridModel: GridModel;
|
|
11
12
|
store: Store;
|
|
12
|
-
filter
|
|
13
|
-
bufferedApplyFilter
|
|
13
|
+
private filter;
|
|
14
|
+
private bufferedApplyFilter;
|
|
15
|
+
get matchMode(): FilterMatchMode;
|
|
14
16
|
constructor();
|
|
15
17
|
onLinked(): void;
|
|
16
|
-
get filterText():
|
|
17
|
-
setFilterText(v:
|
|
18
|
+
get filterText(): string;
|
|
19
|
+
setFilterText(v: string): void;
|
|
18
20
|
applyFilter(): void;
|
|
19
21
|
regenerateFilter(): void;
|
|
20
|
-
getRegex(searchTerm:
|
|
22
|
+
getRegex(searchTerm: string): RegExp;
|
|
21
23
|
getActiveFields(): string[];
|
|
22
|
-
getValGetters(fieldName:
|
|
24
|
+
getValGetters(fieldName: string): ((record: StoreRecord) => any)[] | ((rec: StoreRecord) => any);
|
|
23
25
|
}
|
|
@@ -58,3 +58,10 @@ export interface FilterValueSource {
|
|
|
58
58
|
isFilterValueSource: true;
|
|
59
59
|
}
|
|
60
60
|
export declare function isFilterValueSource(v: unknown): v is FilterValueSource;
|
|
61
|
+
/**
|
|
62
|
+
* Option to customize matching behavior for {@link StoreFilterField} and related components.
|
|
63
|
+
* - `start`: match beginning of candidate strings only.
|
|
64
|
+
* - `startWord`: match beginning of words within candidate strings.
|
|
65
|
+
* - `any`: match anywhere within candidate strings.
|
|
66
|
+
*/
|
|
67
|
+
export type FilterMatchMode = 'start' | 'startWord' | 'any';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { GridModel } from '@xh/hoist/cmp/grid';
|
|
1
|
+
import type { GridModel } from '@xh/hoist/cmp/grid';
|
|
2
2
|
import { LayoutProps } from '@xh/hoist/core';
|
|
3
|
+
import type { FilterMatchMode } from '@xh/hoist/data';
|
|
3
4
|
import { TextInputProps } from '@xh/hoist/desktop/cmp/input';
|
|
4
5
|
import '@xh/hoist/desktop/register';
|
|
5
6
|
import './GridFindField.scss';
|
|
@@ -10,7 +11,7 @@ export interface GridFindFieldProps extends TextInputProps, LayoutProps {
|
|
|
10
11
|
*/
|
|
11
12
|
gridModel?: GridModel;
|
|
12
13
|
/** Mode to use when searching (default 'startWord'). */
|
|
13
|
-
matchMode?:
|
|
14
|
+
matchMode?: FilterMatchMode;
|
|
14
15
|
/**
|
|
15
16
|
* Delay (in ms) to buffer searching the grid after the value changes from user input.
|
|
16
17
|
* Default 200ms. Set to 0 to filter immediately on each keystroke.
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { GridModel } from '@xh/hoist/cmp/grid';
|
|
1
2
|
import { HoistModel } from '@xh/hoist/core';
|
|
3
|
+
import type { FilterMatchMode, StoreRecord } from '@xh/hoist/data';
|
|
2
4
|
import { TextInputModel } from '@xh/hoist/desktop/cmp/input';
|
|
3
5
|
/**
|
|
4
6
|
* @internal
|
|
@@ -6,20 +8,20 @@ import { TextInputModel } from '@xh/hoist/desktop/cmp/input';
|
|
|
6
8
|
export declare class GridFindFieldImplModel extends HoistModel {
|
|
7
9
|
xhImpl: boolean;
|
|
8
10
|
query: string;
|
|
9
|
-
get matchMode():
|
|
11
|
+
get matchMode(): FilterMatchMode;
|
|
10
12
|
get queryBuffer(): number;
|
|
11
13
|
get includeFields(): string[];
|
|
12
14
|
get excludeFields(): string[];
|
|
13
15
|
results: any;
|
|
14
16
|
inputRef: import("react").RefObject<TextInputModel> & import("react").RefCallback<TextInputModel>;
|
|
15
|
-
_records:
|
|
17
|
+
_records: StoreRecord[];
|
|
16
18
|
get count(): number;
|
|
17
19
|
get selectedIdx(): number;
|
|
18
20
|
get countLabel(): string;
|
|
19
21
|
get hasFocus(): boolean;
|
|
20
22
|
get hasQuery(): boolean;
|
|
21
23
|
get hasResults(): boolean;
|
|
22
|
-
get gridModel():
|
|
24
|
+
get gridModel(): GridModel;
|
|
23
25
|
constructor();
|
|
24
26
|
onLinked(): void;
|
|
25
27
|
selectPrev(): void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { GridModel } from '@xh/hoist/cmp/grid';
|
|
1
|
+
import { ColChooserConfig, GridModel } from '@xh/hoist/cmp/grid';
|
|
2
2
|
import { HoistModel } from '@xh/hoist/core';
|
|
3
|
+
import type { FilterMatchMode } from '@xh/hoist/data';
|
|
3
4
|
import { LeftRightChooserModel } from '@xh/hoist/desktop/cmp/leftrightchooser';
|
|
4
5
|
/**
|
|
5
6
|
* State management for the ColChooser component.
|
|
@@ -14,16 +15,10 @@ export declare class ColChooserModel extends HoistModel {
|
|
|
14
15
|
commitOnChange: boolean;
|
|
15
16
|
showRestoreDefaults: boolean;
|
|
16
17
|
autosizeOnCommit: boolean;
|
|
17
|
-
width: number;
|
|
18
|
-
height: number;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
commitOnChange?: boolean;
|
|
22
|
-
showRestoreDefaults?: boolean;
|
|
23
|
-
autosizeOnCommit?: boolean;
|
|
24
|
-
width?: number;
|
|
25
|
-
height?: number;
|
|
26
|
-
});
|
|
18
|
+
width: string | number;
|
|
19
|
+
height: string | number;
|
|
20
|
+
filterMatchMode: FilterMatchMode;
|
|
21
|
+
constructor({ gridModel, commitOnChange, showRestoreDefaults, autosizeOnCommit, width, height, filterMatchMode }: ColChooserConfig);
|
|
27
22
|
open(): void;
|
|
28
23
|
openPopover(): void;
|
|
29
24
|
close(): void;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { HoistProps } from '@xh/hoist/core';
|
|
2
|
+
import type { FilterMatchMode } from '@xh/hoist/data';
|
|
2
3
|
import '@xh/hoist/desktop/register';
|
|
3
4
|
import { LeftRightChooserModel } from './LeftRightChooserModel';
|
|
4
5
|
export interface LeftRightChooserFilterProps extends HoistProps<LeftRightChooserModel> {
|
|
5
6
|
/** Names of fields in chooser on which to filter. Defaults to ['text', 'group'] */
|
|
6
7
|
fields?: string[];
|
|
7
|
-
/**
|
|
8
|
-
|
|
8
|
+
/** Mode to use when filtering (default 'startWord'). */
|
|
9
|
+
matchMode?: FilterMatchMode;
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* A Component that can bind to a LeftRightChooser and filter both lists
|
package/cmp/grid/GridModel.ts
CHANGED
|
@@ -146,7 +146,7 @@ export interface GridConfig {
|
|
|
146
146
|
filterModel?: GridFilterModelConfig | boolean;
|
|
147
147
|
|
|
148
148
|
/** Config with which to create a ColChooserModel, or boolean `true` to enable default.*/
|
|
149
|
-
colChooserModel?: ColChooserConfig | boolean;
|
|
149
|
+
colChooserModel?: Omit<ColChooserConfig, 'gridModel'> | boolean;
|
|
150
150
|
|
|
151
151
|
/**
|
|
152
152
|
* Function to be called when the user triggers GridModel.restoreDefaultsAsync(). This
|
package/cmp/grid/Types.ts
CHANGED
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
* Copyright © 2026 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
import type {HSide, PersistOptions, Some} from '@xh/hoist/core';
|
|
9
|
+
import type {
|
|
10
|
+
FilterBindTarget,
|
|
11
|
+
FilterMatchMode,
|
|
12
|
+
FilterValueSource,
|
|
13
|
+
Store,
|
|
14
|
+
StoreRecord
|
|
15
|
+
} from '@xh/hoist/data';
|
|
12
16
|
import type {
|
|
13
17
|
CellClassParams,
|
|
14
18
|
CustomCellEditorProps,
|
|
@@ -23,6 +27,7 @@ import type {
|
|
|
23
27
|
import type {ReactElement, ReactNode} from 'react';
|
|
24
28
|
import type {Column, ColumnSpec} from './columns/Column';
|
|
25
29
|
import type {ColumnGroup, ColumnGroupSpec} from './columns/ColumnGroup';
|
|
30
|
+
import type {GridFilterFieldSpecConfig} from './filter/GridFilterFieldSpec';
|
|
26
31
|
import type {GridModel} from './GridModel';
|
|
27
32
|
|
|
28
33
|
export interface ColumnState {
|
|
@@ -124,6 +129,9 @@ export interface GridFilterBindTarget extends FilterBindTarget, FilterValueSourc
|
|
|
124
129
|
export type GroupRowRenderer = (context: ICellRendererParams) => ReactNode;
|
|
125
130
|
|
|
126
131
|
export interface ColChooserConfig {
|
|
132
|
+
/** GridModel to bind to. Not required if creating via `GridModel.colChooserModel` */
|
|
133
|
+
gridModel?: GridModel;
|
|
134
|
+
|
|
127
135
|
/**
|
|
128
136
|
* Immediately render changed columns on grid (default true).
|
|
129
137
|
* Set to false to enable Save button for committing changes on save. Desktop only.
|
|
@@ -147,6 +155,9 @@ export interface ColChooserConfig {
|
|
|
147
155
|
|
|
148
156
|
/** Chooser height for popover and dialog. Desktop only. */
|
|
149
157
|
height?: string | number;
|
|
158
|
+
|
|
159
|
+
/** Mode to use when filtering (default 'startWord'). Desktop only. */
|
|
160
|
+
filterMatchMode?: FilterMatchMode;
|
|
150
161
|
}
|
|
151
162
|
|
|
152
163
|
export type ColumnOrGroup = Column | ColumnGroup;
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2026 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
-
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
7
|
+
import type {GridModel} from '@xh/hoist/cmp/grid';
|
|
8
8
|
import {DefaultHoistProps, hoistCmp, HoistModel, useLocalModel, XH} from '@xh/hoist/core';
|
|
9
|
-
import {FilterTestFn, Store} from '@xh/hoist/data';
|
|
9
|
+
import type {FilterMatchMode, FilterTestFn, Store} from '@xh/hoist/data';
|
|
10
10
|
import {storeFilterFieldImpl as desktopStoreFilterFieldImpl} from '@xh/hoist/dynamics/desktop';
|
|
11
11
|
import {storeFilterFieldImpl as mobileStoreFilterFieldImpl} from '@xh/hoist/dynamics/mobile';
|
|
12
12
|
import {StoreFilterFieldImplModel} from './impl/StoreFilterFieldImplModel';
|
|
@@ -53,7 +53,7 @@ export interface StoreFilterFieldProps extends DefaultHoistProps {
|
|
|
53
53
|
includeFields?: string[];
|
|
54
54
|
|
|
55
55
|
/** Mode to use when filtering (default 'startWord'). */
|
|
56
|
-
matchMode?:
|
|
56
|
+
matchMode?: FilterMatchMode;
|
|
57
57
|
|
|
58
58
|
/** Optional model for raw value binding - see comments on the `bind` prop for details. */
|
|
59
59
|
model?: HoistModel;
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2026 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
-
import {HoistModel, XH, lookup} from '@xh/hoist/core';
|
|
8
7
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
8
|
+
import {HoistModel, lookup, XH} from '@xh/hoist/core';
|
|
9
|
+
import type {FilterMatchMode, StoreRecord} from '@xh/hoist/data';
|
|
9
10
|
import {CompoundFilter, FilterLike, Store, withFilterByKey} from '@xh/hoist/data';
|
|
10
|
-
import {action,
|
|
11
|
+
import {action, comparer, makeObservable} from '@xh/hoist/mobx';
|
|
11
12
|
import {stripTags, throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
|
|
12
13
|
import {
|
|
13
14
|
debounce,
|
|
@@ -33,8 +34,12 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
33
34
|
gridModel: GridModel;
|
|
34
35
|
store: Store;
|
|
35
36
|
|
|
36
|
-
filter;
|
|
37
|
-
bufferedApplyFilter;
|
|
37
|
+
private filter: (rec: StoreRecord) => boolean;
|
|
38
|
+
private bufferedApplyFilter;
|
|
39
|
+
|
|
40
|
+
get matchMode(): FilterMatchMode {
|
|
41
|
+
return this.componentProps.matchMode ?? 'startWord';
|
|
42
|
+
}
|
|
38
43
|
|
|
39
44
|
constructor() {
|
|
40
45
|
super();
|
|
@@ -59,29 +64,30 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
59
64
|
|
|
60
65
|
this.bufferedApplyFilter = debounce(() => this.applyFilter(), filterBuffer);
|
|
61
66
|
|
|
62
|
-
this.addReaction(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
this.addReaction(
|
|
68
|
+
{
|
|
69
|
+
track: () => [this.filterText, gridModel?.columns, gridModel?.groupBy],
|
|
70
|
+
run: () => this.regenerateFilter(),
|
|
71
|
+
fireImmediately: true
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
track: () => [this.componentProps.includeFields, this.componentProps.excludeFields],
|
|
75
|
+
run: () => this.regenerateFilter(),
|
|
76
|
+
equals: comparer.structural
|
|
77
|
+
}
|
|
78
|
+
);
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
//------------------------------------------------------------------
|
|
76
82
|
// Trampoline value to bindable -- from bound model, or store
|
|
77
83
|
//------------------------------------------------------------------
|
|
78
|
-
get filterText() {
|
|
84
|
+
get filterText(): string {
|
|
79
85
|
const {bind, model} = this.componentProps;
|
|
80
86
|
return bind ? model[bind] : this.store.xhFilterText;
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
@action
|
|
84
|
-
setFilterText(v) {
|
|
90
|
+
setFilterText(v: string) {
|
|
85
91
|
const {bind, model} = this.componentProps;
|
|
86
92
|
if (bind) {
|
|
87
93
|
model.setBindable(bind, v);
|
|
@@ -122,7 +128,7 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
122
128
|
if (filterText && !isEmpty(activeFields)) {
|
|
123
129
|
const regex = this.getRegex(filterText),
|
|
124
130
|
valGetters = flatMap(activeFields, fieldPath => this.getValGetters(fieldPath));
|
|
125
|
-
newFilter = rec => valGetters.some(fn => regex.test(fn(rec)));
|
|
131
|
+
newFilter = (rec: StoreRecord) => valGetters.some(fn => regex.test(fn(rec)));
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
if (filter === newFilter) return;
|
|
@@ -140,9 +146,9 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
140
146
|
}
|
|
141
147
|
}
|
|
142
148
|
|
|
143
|
-
getRegex(searchTerm) {
|
|
149
|
+
getRegex(searchTerm: string): RegExp {
|
|
144
150
|
searchTerm = escapeRegExp(searchTerm);
|
|
145
|
-
switch (this.
|
|
151
|
+
switch (this.matchMode) {
|
|
146
152
|
case 'any':
|
|
147
153
|
return new RegExp(searchTerm, 'i');
|
|
148
154
|
case 'start':
|
|
@@ -153,11 +159,11 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
153
159
|
throw XH.exception('Unknown matchMode in StoreFilterField');
|
|
154
160
|
}
|
|
155
161
|
|
|
156
|
-
getActiveFields() {
|
|
162
|
+
getActiveFields(): string[] {
|
|
157
163
|
const {gridModel, store, componentProps} = this,
|
|
158
164
|
{includeFields, excludeFields} = componentProps;
|
|
159
165
|
|
|
160
|
-
let ret = store ? ['id', ...store.
|
|
166
|
+
let ret = store ? ['id', ...store.fieldNames] : [];
|
|
161
167
|
if (includeFields) ret = store ? intersection(ret, includeFields) : includeFields;
|
|
162
168
|
if (excludeFields) ret = without(ret, ...excludeFields);
|
|
163
169
|
|
|
@@ -196,7 +202,7 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
196
202
|
return ret;
|
|
197
203
|
}
|
|
198
204
|
|
|
199
|
-
getValGetters(fieldName) {
|
|
205
|
+
getValGetters(fieldName: string) {
|
|
200
206
|
const {gridModel} = this;
|
|
201
207
|
|
|
202
208
|
// If a GridModel has been configured, the user is looking at rendered values in a grid and
|
|
@@ -219,7 +225,7 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
219
225
|
|
|
220
226
|
return cols.map(column => {
|
|
221
227
|
const {renderer, getValueFn} = column;
|
|
222
|
-
return record => {
|
|
228
|
+
return (record: StoreRecord) => {
|
|
223
229
|
const ctx = {
|
|
224
230
|
record,
|
|
225
231
|
field: field.name,
|
|
@@ -239,7 +245,7 @@ export class StoreFilterFieldImplModel extends HoistModel {
|
|
|
239
245
|
// Otherwise just match raw.
|
|
240
246
|
// Use expensive get() only when needed to support dot-separated paths.
|
|
241
247
|
return fieldName.includes('.')
|
|
242
|
-
? rec => get(rec.data, fieldName)
|
|
243
|
-
: rec => rec.data[fieldName];
|
|
248
|
+
? (rec: StoreRecord) => get(rec.data, fieldName)
|
|
249
|
+
: (rec: StoreRecord) => rec.data[fieldName];
|
|
244
250
|
}
|
|
245
251
|
}
|
package/data/Store.ts
CHANGED
|
@@ -1221,12 +1221,14 @@ export class Store
|
|
|
1221
1221
|
const recToRevert = records.find(it => it.id === summaryRec.id);
|
|
1222
1222
|
if (!recToRevert) return summaryRec;
|
|
1223
1223
|
|
|
1224
|
+
// StoreRecordConfig requires data to be a "new object dedicated to this StoreRecord".
|
|
1225
|
+
const data = {...recToRevert.committedData};
|
|
1224
1226
|
const ret = new StoreRecord({
|
|
1225
1227
|
id: recToRevert.id,
|
|
1226
1228
|
store: this,
|
|
1227
1229
|
raw: recToRevert.raw,
|
|
1228
|
-
data
|
|
1229
|
-
committedData:
|
|
1230
|
+
data,
|
|
1231
|
+
committedData: data,
|
|
1230
1232
|
parent: null,
|
|
1231
1233
|
isSummary: true
|
|
1232
1234
|
});
|
package/data/filter/Types.ts
CHANGED
|
@@ -97,3 +97,11 @@ export interface FilterValueSource {
|
|
|
97
97
|
export function isFilterValueSource(v: unknown): v is FilterValueSource {
|
|
98
98
|
return (v as any)?.isFilterValueSource === true;
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Option to customize matching behavior for {@link StoreFilterField} and related components.
|
|
103
|
+
* - `start`: match beginning of candidate strings only.
|
|
104
|
+
* - `startWord`: match beginning of words within candidate strings.
|
|
105
|
+
* - `any`: match anywhere within candidate strings.
|
|
106
|
+
*/
|
|
107
|
+
export type FilterMatchMode = 'start' | 'startWord' | 'any';
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
* Copyright © 2026 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import composeRefs from '@seznam/compose-react-refs/composeRefs';
|
|
8
|
-
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
8
|
+
import type {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
9
|
import {hbox, span, vbox} from '@xh/hoist/cmp/layout';
|
|
10
10
|
import {hoistCmp, LayoutProps, useLocalModel} from '@xh/hoist/core';
|
|
11
|
+
import type {FilterMatchMode} from '@xh/hoist/data';
|
|
11
12
|
import {button} from '@xh/hoist/desktop/cmp/button';
|
|
12
13
|
import {textInput, TextInputProps} from '@xh/hoist/desktop/cmp/input';
|
|
13
14
|
import '@xh/hoist/desktop/register';
|
|
@@ -25,7 +26,7 @@ export interface GridFindFieldProps extends TextInputProps, LayoutProps {
|
|
|
25
26
|
gridModel?: GridModel;
|
|
26
27
|
|
|
27
28
|
/** Mode to use when searching (default 'startWord'). */
|
|
28
|
-
matchMode?:
|
|
29
|
+
matchMode?: FilterMatchMode;
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Delay (in ms) to buffer searching the grid after the value changes from user input.
|