@xh/hoist 86.1.0 → 86.3.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.
Files changed (104) hide show
  1. package/.gitattributes +4 -0
  2. package/CHANGELOG.md +104 -0
  3. package/admin/AdminJsonDisplay.ts +31 -0
  4. package/admin/App.scss +3 -11
  5. package/admin/AppModel.ts +3 -4
  6. package/admin/jsonsearch/impl/JsonSearchImplModel.ts +4 -4
  7. package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +56 -6
  8. package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +9 -26
  9. package/admin/tabs/clients/ClientsModel.ts +4 -1
  10. package/admin/tabs/clients/activity/ClientDetailModel.ts +5 -1
  11. package/admin/tabs/cluster/instances/connpool/ConnPoolMonitorPanel.ts +3 -11
  12. package/admin/tabs/cluster/instances/services/DetailsPanel.ts +2 -13
  13. package/admin/tabs/cluster/objects/DetailPanel.ts +3 -12
  14. package/admin/tabs/userData/roles/RolePanel.ts +2 -2
  15. package/appcontainer/RouterModel.ts +6 -6
  16. package/build/types/admin/AdminJsonDisplay.d.ts +7 -0
  17. package/build/types/admin/AppModel.d.ts +3 -4
  18. package/build/types/admin/jsonsearch/impl/JsonSearchImplModel.d.ts +2 -2
  19. package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +14 -3
  20. package/build/types/admin/tabs/clients/ClientsModel.d.ts +3 -0
  21. package/build/types/appcontainer/RouterModel.d.ts +5 -5
  22. package/build/types/cmp/grid/Grid.d.ts +8 -4
  23. package/build/types/cmp/grid/GridModel.d.ts +13 -2
  24. package/build/types/cmp/grid/Types.d.ts +8 -1
  25. package/build/types/cmp/grid/filter/GridFilterFieldSpec.d.ts +24 -6
  26. package/build/types/cmp/input/SegmentedControlOption.d.ts +12 -0
  27. package/build/types/core/HoistAppModel.d.ts +2 -3
  28. package/build/types/core/types/Types.d.ts +12 -0
  29. package/build/types/desktop/cmp/button/grid/ExpandToLevelButton.d.ts +2 -1
  30. package/build/types/desktop/cmp/filter/FilterChooser.d.ts +5 -0
  31. package/build/types/desktop/cmp/filter/PopoverFilterChooser.d.ts +3 -1
  32. package/build/types/desktop/cmp/grid/impl/colchooser/ColChooserModel.d.ts +2 -2
  33. package/build/types/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomRowModel.d.ts +9 -1
  34. package/build/types/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTabModel.d.ts +8 -2
  35. package/build/types/desktop/cmp/input/CodeInput.d.ts +7 -0
  36. package/build/types/desktop/cmp/input/NumberInput.d.ts +1 -1
  37. package/build/types/desktop/cmp/input/Select.d.ts +8 -0
  38. package/build/types/desktop/cmp/input/impl/CalcWindowedMenuWidth.d.ts +20 -0
  39. package/build/types/desktop/cmp/rest/impl/RestFormModel.d.ts +1 -1
  40. package/build/types/format/FormatNumber.d.ts +11 -3
  41. package/build/types/icon/Icon.d.ts +4 -3
  42. package/build/types/kit/react-dropzone/index.d.ts +1 -0
  43. package/build/types/kit/swiper/index.d.ts +4 -3
  44. package/build/types/mobile/cmp/button/grid/ExpandToLevelButton.d.ts +2 -1
  45. package/build/types/mobile/cmp/grid/impl/ColChooserModel.d.ts +2 -2
  46. package/build/types/mobile/cmp/input/NumberInput.d.ts +1 -1
  47. package/build/types/mobile/cmp/input/Select.d.ts +8 -0
  48. package/cmp/grid/Grid.ts +27 -2
  49. package/cmp/grid/GridModel.ts +21 -8
  50. package/cmp/grid/Types.ts +9 -1
  51. package/cmp/grid/filter/GridFilterFieldSpec.ts +28 -5
  52. package/cmp/grid/impl/MenuSupport.ts +3 -5
  53. package/cmp/input/SegmentedControlOption.ts +14 -0
  54. package/cmp/store/impl/StoreFilterFieldImplModel.ts +5 -6
  55. package/core/HoistAppModel.ts +2 -3
  56. package/core/types/Types.ts +14 -5
  57. package/desktop/cmp/button/grid/ExpandToLevelButton.ts +4 -5
  58. package/desktop/cmp/filechooser/FileChooser.ts +6 -3
  59. package/desktop/cmp/filechooser/FileChooserModel.ts +12 -5
  60. package/desktop/cmp/filter/FilterChooser.scss +41 -0
  61. package/desktop/cmp/filter/FilterChooser.ts +147 -7
  62. package/desktop/cmp/filter/PopoverFilterChooser.ts +7 -84
  63. package/desktop/cmp/grid/editors/NumberEditor.ts +16 -17
  64. package/desktop/cmp/grid/editors/SelectEditor.ts +15 -10
  65. package/desktop/cmp/grid/editors/impl/InlineEditorModel.ts +6 -1
  66. package/desktop/cmp/grid/find/impl/GridFindFieldImplModel.ts +3 -5
  67. package/desktop/cmp/grid/impl/colchooser/ColChooserModel.ts +2 -2
  68. package/desktop/cmp/grid/impl/filter/GridFilterDialog.ts +2 -2
  69. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomRow.ts +12 -12
  70. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomRowModel.ts +18 -0
  71. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTab.scss +5 -0
  72. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTab.ts +13 -2
  73. package/desktop/cmp/grid/impl/filter/headerfilter/custom/CustomTabModel.ts +97 -14
  74. package/desktop/cmp/grid/impl/filter/headerfilter/values/ValuesTabModel.ts +46 -7
  75. package/desktop/cmp/input/CheckboxButton.ts +21 -1
  76. package/desktop/cmp/input/CodeInput.ts +20 -3
  77. package/desktop/cmp/input/NumberInput.ts +1 -1
  78. package/desktop/cmp/input/SegmentedControl.ts +7 -3
  79. package/desktop/cmp/input/Select.ts +37 -18
  80. package/desktop/cmp/input/impl/CalcWindowedMenuWidth.ts +106 -0
  81. package/desktop/cmp/rest/impl/RestFormField.ts +1 -1
  82. package/desktop/cmp/tab/Tabs.scss +72 -25
  83. package/docs/routing.md +4 -2
  84. package/docs/upgrade-notes/v86-upgrade-notes.md +73 -8
  85. package/format/FormatNumber.ts +69 -32
  86. package/icon/Icon.scss +13 -0
  87. package/icon/Icon.ts +4 -3
  88. package/icon/impl/IconHtml.ts +1 -1
  89. package/kit/react-dropzone/index.ts +1 -0
  90. package/mcp/README.md +12 -0
  91. package/mcp/data/ts-registry.spec.ts +156 -0
  92. package/mcp/data/ts-registry.ts +14 -7
  93. package/mcp/formatters/typescript.ts +7 -3
  94. package/mcp/util/paths.ts +21 -0
  95. package/mobile/cmp/button/grid/ExpandToLevelButton.ts +4 -5
  96. package/mobile/cmp/grid/impl/ColChooserModel.ts +2 -2
  97. package/mobile/cmp/input/CheckboxButton.ts +18 -1
  98. package/mobile/cmp/input/NumberInput.ts +1 -1
  99. package/mobile/cmp/input/SegmentedControl.ts +7 -3
  100. package/mobile/cmp/input/Select.ts +21 -15
  101. package/mobx/README.md +2 -1
  102. package/package.json +10 -10
  103. package/styles/vars.scss +15 -0
  104. package/desktop/cmp/filter/PopoverFilterChooser.scss +0 -42
@@ -1,5 +1,5 @@
1
1
  import { GridConfig, GridModel } from '@xh/hoist/cmp/grid';
2
- import { HoistModel, TaskObserver } from '@xh/hoist/core';
2
+ import { HoistModel, PlainObject, TaskObserver } from '@xh/hoist/core';
3
3
  /**
4
4
  * @internal
5
5
  */
@@ -16,7 +16,7 @@ export declare class JsonSearchImplModel extends HoistModel {
16
16
  path: string;
17
17
  readerContentType: 'document' | 'matches';
18
18
  pathFormat: 'XPath' | 'JSONPath';
19
- readerContent: string;
19
+ readerContent: string | PlainObject[];
20
20
  matchingNodeCount: number;
21
21
  get subjectName(): string;
22
22
  get docSearchUrl(): string;
@@ -3,10 +3,20 @@ import { FilterChooserModel } from '@xh/hoist/cmp/filter';
3
3
  import { FormModel } from '@xh/hoist/cmp/form';
4
4
  import { ColumnSpec, GridModel } from '@xh/hoist/cmp/grid';
5
5
  import { GroupingChooserModel } from '@xh/hoist/cmp/grouping';
6
- import { HoistModel, LoadSpec, PlainObject } from '@xh/hoist/core';
6
+ import { HoistModel, LoadSpec, LocalDateUnit, PlainObject } from '@xh/hoist/core';
7
7
  import { Cube } from '@xh/hoist/data';
8
8
  import { LocalDate } from '@xh/hoist/utils/datetime';
9
9
  import { ActivityDetailProvider } from './detail/ActivityDetailModel';
10
+ /**
11
+ * A relative time interval (e.g. 7 days) ending on the current app day. Drives the quick-select
12
+ * buttons and the persisted time period, which rolls forward to end on today on restore.
13
+ */
14
+ export interface ActivityInterval {
15
+ value: number;
16
+ unit: LocalDateUnit;
17
+ }
18
+ /** Quick-select intervals offered in the toolbar - labels are derived as `${value}${unit[0]}`. */
19
+ export declare const INTERVALS: ActivityInterval[];
10
20
  export declare class ActivityTrackingModel extends HoistModel implements ActivityDetailProvider {
11
21
  telemetryPrefix: string;
12
22
  /** FormModel for server-side querying controls. */
@@ -45,10 +55,11 @@ export declare class ActivityTrackingModel extends HoistModel implements Activit
45
55
  setDataFields(dataFields: ActivityTrackingDataFieldSpec[]): void;
46
56
  toggleFilterChooser(): void;
47
57
  adjustDates(dir: 'add' | 'subtract'): void;
48
- adjustStartDate(value: any, unit: any): void;
49
- isInterval(value: any, unit: any): boolean;
58
+ adjustStartDate(interval: ActivityInterval): void;
59
+ isInterval(interval: ActivityInterval): boolean;
50
60
  getDisplayName(fieldName: string): string;
51
61
  private createQueryFormModel;
62
+ private setupPeriodPersistence;
52
63
  private loadGridAsync;
53
64
  private cubeLabelComparator;
54
65
  private getComparableValForDim;
@@ -4,6 +4,9 @@ import { RecordActionSpec, StoreRecord } from '@xh/hoist/data';
4
4
  import { BaseAdminTabModel } from '@xh/hoist/admin/tabs/BaseAdminTabModel';
5
5
  export declare class ClientsModel extends BaseAdminTabModel {
6
6
  telemetryPrefix: string;
7
+ persistWith: {
8
+ localStorageKey: string;
9
+ };
7
10
  lastRefresh: number;
8
11
  gridModel: GridModel;
9
12
  groupBy: 'user' | 'instance';
@@ -1,4 +1,4 @@
1
- import { HoistModel } from '../core';
1
+ import { HoistModel, HoistRoute } from '../core';
2
2
  import { Router, State } from 'router5';
3
3
  import 'router5-plugin-browser';
4
4
  /**
@@ -19,11 +19,11 @@ export declare class RouterModel extends HoistModel {
19
19
  /**
20
20
  * Add routes to the router.
21
21
  *
22
- * @param routes - collection of router5 route spec.
23
- * This method supports an additional keyword 'omit' on each spec, in order to allow declarative
24
- * exclusion. Otherwise these are Router5 configs to be passed directly to the Router5 API.
22
+ * @param routes - collection of {@link HoistRoute} specs. In addition to the standard Router5
23
+ * route config, each spec supports an `omit` keyword to allow declarative exclusion.
24
+ * Otherwise these are Router5 configs to be passed directly to the Router5 API.
25
25
  */
26
- addRoutes(routes: object[]): void;
26
+ addRoutes(routes: HoistRoute[]): void;
27
27
  /**
28
28
  * Add a routeName to the current route, preserving params
29
29
  * @param routeName - the routeName to append
@@ -3,6 +3,8 @@ import { ColumnState } from '@xh/hoist/cmp/grid';
3
3
  import { HoistModel, HoistProps, LayoutProps, PlainObject, ReactionSpec, TestSupportProps } from '@xh/hoist/core';
4
4
  import { RecordSet } from '@xh/hoist/data/impl/RecordSet';
5
5
  import type { ColDef, ColGroupDef, GetContextMenuItemsParams, GridOptions, GridReadyEvent, ProcessCellForExportParams } from '@xh/hoist/kit/ag-grid';
6
+ import { type MouseEvent } from 'react';
7
+ import { PartialDeep } from 'type-fest';
6
8
  import './Grid.scss';
7
9
  import { GridModel } from './GridModel';
8
10
  export interface GridProps<M extends GridModel = GridModel> extends HoistProps<M>, LayoutProps, TestSupportProps {
@@ -15,7 +17,7 @@ export interface GridProps<M extends GridModel = GridModel> extends HoistProps<M
15
17
  *
16
18
  * Note that changes to these options after the component's initial render will be ignored.
17
19
  */
18
- agOptions?: GridOptions;
20
+ agOptions?: PartialDeep<GridOptions>;
19
21
  /**
20
22
  * Callback when the grid has initialized. The component will call this with the ag-Grid
21
23
  * event after running its internal handler to associate the ag-Grid APIs with its model.
@@ -41,6 +43,7 @@ export interface GridProps<M extends GridModel = GridModel> extends HoistProps<M
41
43
  export declare const Grid: import("react").FC<GridProps<GridModel>>, grid: import("@xh/hoist/core").ElementFactory<GridProps<GridModel>>;
42
44
  export declare class GridLocalModel extends HoistModel {
43
45
  xhImpl: boolean;
46
+ private static EMPTY_SPACE_SELECTOR;
44
47
  private model;
45
48
  agOptions: GridOptions;
46
49
  viewRef: import("react").RefObject<HTMLElement> & import("react").RefCallback<HTMLElement>;
@@ -55,7 +58,7 @@ export declare class GridLocalModel extends HoistModel {
55
58
  getColumnDefs(): Array<ColDef | ColGroupDef>;
56
59
  getContextMenuItems: (params: GetContextMenuItemsParams) => (string | import("ag-grid-community").MenuItemDef<any, any>)[];
57
60
  dataReaction(): {
58
- track: () => (boolean | import("../../data").StoreRecord[] | RecordSet | import("@xh/hoist/core").VSide)[];
61
+ track: () => (boolean | import("@xh/hoist/core").VSide | import("../../data").StoreRecord[] | RecordSet)[];
59
62
  run: () => void;
60
63
  };
61
64
  selectionReaction(): {
@@ -63,7 +66,7 @@ export declare class GridLocalModel extends HoistModel {
63
66
  run: () => void;
64
67
  };
65
68
  sortReaction(): {
66
- track: () => (import("@xh/hoist/cmp/grid").GridSorter[] | GridApi<any>)[];
69
+ track: () => (GridApi<any> | import("@xh/hoist/cmp/grid").GridSorter[])[];
67
70
  run: ([agApi, sortBy]: [any, any]) => void;
68
71
  };
69
72
  groupReaction(): {
@@ -83,7 +86,7 @@ export declare class GridLocalModel extends HoistModel {
83
86
  get useScrollOptimization(): boolean;
84
87
  applyScrollOptimization(): void;
85
88
  columnsReaction(): {
86
- track: () => (import("@xh/hoist/cmp/grid").ColumnOrGroup[] | GridApi<any>)[];
89
+ track: () => (GridApi<any> | import("@xh/hoist/cmp/grid").ColumnOrGroup[])[];
87
90
  run: ([api]: [any]) => void;
88
91
  };
89
92
  columnStateReaction(): ReactionSpec<[GridApi, ColumnState[]]>;
@@ -129,6 +132,7 @@ export declare class GridLocalModel extends HoistModel {
129
132
  writeFilterState(filterState: any): void;
130
133
  processCellForClipboard: ({ value, node, column }: ProcessCellForExportParams) => any;
131
134
  navigateToNextCell: (agParams: any) => import("ag-grid-community").CellPosition;
135
+ onViewMouseDown: (evt: MouseEvent) => void;
132
136
  onCellMouseDown: (evt: any) => void;
133
137
  onKeyDown: (evt: any) => void;
134
138
  onRowClicked: (evt: any) => void;
@@ -1,5 +1,5 @@
1
1
  import { AgGridModel } from '@xh/hoist/cmp/ag-grid';
2
- import { Column, ColumnGroup, ColumnOrGroup, ColumnOrGroupSpec, ColumnSpec, GridAutosizeMode, GridFilterModelConfig, GridGroupSortFn, TreeStyle } from '@xh/hoist/cmp/grid';
2
+ import { Column, ColumnGroup, ColumnOrGroup, ColumnOrGroupSpec, ColumnSpec, GridAutosizeMode, GridFilterModelConfig, GridGroupSortFn, IColChooserModel, TreeStyle } from '@xh/hoist/cmp/grid';
3
3
  import { GridFilterModel } from '@xh/hoist/cmp/grid/filter/GridFilterModel';
4
4
  import { Awaitable, HoistModel, HSide, LoadSpec, PlainObject, SizingMode, Some, TaskObserver, Thunkable, VSide } from '@xh/hoist/core';
5
5
  import { Store, StoreConfig, StoreRecord, StoreRecordId, StoreRecordOrId, StoreSelectionConfig, StoreSelectionModel, StoreTransaction } from '@xh/hoist/data';
@@ -155,6 +155,10 @@ export interface GridConfig {
155
155
  * expand/collapse options in the default context menu will be enhanced to allow users to
156
156
  * expand/collapse to a specific level. See {@link GroupingChooserModel.valueDisplayNames}
157
157
  * for a convenient getter that will satisfy this API when a GroupingChooser is in play.
158
+ *
159
+ * Labels are matched to levels top-down and need not cover the full depth of the grid - provide
160
+ * a partial array to label only the top levels (e.g. when deeper levels should not be
161
+ * expand-to targets). Deeper, unlabelled levels are omitted from the menu.
158
162
  */
159
163
  levelLabels?: Thunkable<string[]>;
160
164
  /**
@@ -281,7 +285,7 @@ export declare class GridModel extends HoistModel {
281
285
  store: Store;
282
286
  selModel: StoreSelectionModel;
283
287
  treeMode: boolean;
284
- colChooserModel: HoistModel;
288
+ colChooserModel: IColChooserModel;
285
289
  rowClassFn: RowClassFn;
286
290
  rowClassRules: Record<string, RowClassRuleFn>;
287
291
  contextMenu: GridContextMenuSpec;
@@ -501,8 +505,15 @@ export declare class GridModel extends HoistModel {
501
505
  expandToLevel(level: number): void;
502
506
  /**
503
507
  * Get the resolved level labels for the current state of the grid.
508
+ * An over-long array is truncated to the current `maxDepth`.
504
509
  */
505
510
  get resolvedLevelLabels(): string[];
511
+ /**
512
+ * True if the given `resolvedLevelLabels` index is the grid's current expand level - used to
513
+ * mark the active item in the "Expand to..." menu. The deepest labelled level counts as current
514
+ * whenever the grid is expanded to or beyond it.
515
+ */
516
+ isCurrentExpandLevel(idx: number): boolean;
506
517
  /**
507
518
  * Sort this grid.
508
519
  * This method is a no-op if provided any sorters without a corresponding column.
@@ -1,4 +1,4 @@
1
- import type { HSide, PersistOptions, Some } from '@xh/hoist/core';
1
+ import type { HoistModel, HSide, PersistOptions, Some } from '@xh/hoist/core';
2
2
  import type { FilterBindTarget, FilterMatchMode, FilterValueSource, Store, StoreRecord } from '@xh/hoist/data';
3
3
  import type { CellClassParams, CustomCellEditorProps, HeaderClassParams, HeaderValueGetterParams, ICellRendererParams, IRowNode, ITooltipParams, RowClassParams, ValueSetterParams } from '@xh/hoist/kit/ag-grid';
4
4
  import type { ReactElement, ReactNode } from 'react';
@@ -101,6 +101,13 @@ export interface GridFilterBindTarget extends FilterBindTarget, FilterValueSourc
101
101
  * @returns the formatted value for display.
102
102
  */
103
103
  export type GroupRowRenderer = (context: ICellRendererParams) => ReactNode;
104
+ /** Cross-platform interface for desktop and mobile ColChooserModels. */
105
+ export interface IColChooserModel extends HoistModel {
106
+ readonly gridModel: GridModel;
107
+ readonly isOpen: boolean;
108
+ open(): void;
109
+ close(): void;
110
+ }
104
111
  /**
105
112
  * Configuration for a {@link ColChooserModel} - the model backing the grid column chooser UI.
106
113
  * Passed via the `colChooserModel` config on {@link GridConfig}, or set app-wide via
@@ -1,17 +1,34 @@
1
- import { ColumnRenderer } from '@xh/hoist/cmp/grid';
2
1
  import { HoistInputProps } from '@xh/hoist/cmp/input';
3
2
  import { PlainObject } from '@xh/hoist/core';
4
3
  import { FieldFilterOperator } from '@xh/hoist/data';
5
4
  import { BaseFilterFieldSpec, BaseFilterFieldSpecConfig } from '@xh/hoist/data/filter/BaseFilterFieldSpec';
5
+ import { ReactNode } from 'react';
6
6
  import { GridFilterModel } from './GridFilterModel';
7
+ /**
8
+ * Produces the display content for an entry in the Values tab of a column filter. Must be a pure
9
+ * transform of the value - the values list carries no source record, and there is no column or
10
+ * grid context to reach for (unlike a Column's `renderer`, which runs against the source grid).
11
+ */
12
+ export type GridFilterRenderer = (value: any) => ReactNode;
13
+ /**
14
+ * Produces the value to sort by for an entry in the Values tab of a column filter. Must be a pure
15
+ * transform of the value - the values list carries no source record, and there is no column or
16
+ * grid context to reach for (unlike a Column's `sortValue`, which runs against the source grid).
17
+ */
18
+ export type GridFilterSortValueFn = (value: any) => any;
7
19
  export interface GridFilterFieldSpecConfig extends BaseFilterFieldSpecConfig {
8
20
  /** GridFilterModel instance owning this fieldSpec. */
9
21
  filterModel?: GridFilterModel;
10
22
  /**
11
- * Function returning a formatted string for each value in this values filter display.
12
- * If not provided, the Column's renderer will be used.
23
+ * Pure function producing the display content for each entry in the values filter display. If
24
+ * not provided, the Column's renderer is used where it can be applied to a bare value.
25
+ */
26
+ renderer?: GridFilterRenderer;
27
+ /**
28
+ * Pure function producing the value to sort each entry of the values filter display by. If not
29
+ * provided, the Column's sortValue is used where it can be applied to a bare value.
13
30
  */
14
- renderer?: ColumnRenderer;
31
+ sortValue?: GridFilterSortValueFn;
15
32
  /**
16
33
  * Props to pass through to the HoistInput components used on the custom filter tab.
17
34
  * Note that the HoistInput component used is decided by fieldType.
@@ -26,12 +43,13 @@ export interface GridFilterFieldSpecConfig extends BaseFilterFieldSpecConfig {
26
43
  */
27
44
  export declare class GridFilterFieldSpec extends BaseFilterFieldSpec {
28
45
  filterModel: GridFilterModel;
29
- renderer: ColumnRenderer;
46
+ renderer: GridFilterRenderer;
47
+ sortValue: GridFilterSortValueFn;
30
48
  inputProps: PlainObject;
31
49
  defaultOp: FieldFilterOperator;
32
50
  /** Total number of unique values for this field in the source, regardless of other filters. */
33
51
  allValuesCount: number;
34
- constructor({ filterModel, renderer, inputProps, defaultOp, ...rest }: GridFilterFieldSpecConfig);
52
+ constructor({ filterModel, renderer, sortValue, inputProps, defaultOp, ...rest }: GridFilterFieldSpecConfig);
35
53
  getUniqueValue(value: unknown): unknown;
36
54
  loadValuesFromSource(): void;
37
55
  private cleanFilter;
@@ -21,6 +21,12 @@ export interface SegmentedControlOption {
21
21
  * `intent` default. Defaults to the control's `intent`.
22
22
  */
23
23
  intent?: Intent;
24
+ /**
25
+ * Optional stable identifier emitted on this option's rendered button as `data-testid`, for
26
+ * use by E2E tests. If omitted and the control itself has a `testId`, one is auto-derived as
27
+ * `${controlTestId}-${value}`. If neither is set, no attribute is emitted.
28
+ */
29
+ testId?: string;
24
30
  }
25
31
  /**
26
32
  * Variant of SegmentedControlOption for representing a null/"no value" selection.
@@ -41,4 +47,10 @@ export interface SegmentedControlNullOption {
41
47
  * `intent` default. Defaults to the control's `intent`.
42
48
  */
43
49
  intent?: Intent;
50
+ /**
51
+ * Optional stable identifier emitted on this option's rendered button as `data-testid`, for
52
+ * use by E2E tests. If omitted and the control itself has a `testId`, one is auto-derived as
53
+ * `${controlTestId}-null`. If neither is set, no attribute is emitted.
54
+ */
55
+ testId?: string;
44
56
  }
@@ -1,5 +1,4 @@
1
- import { AppOptionSpec, HoistModel, InitContext, Thunkable } from './';
2
- import { Route } from 'router5';
1
+ import { AppOptionSpec, HoistModel, HoistRoute, InitContext, Thunkable } from './';
3
2
  import { ReactNode } from 'react';
4
3
  /**
5
4
  * Specialized base class for defining the central model for a Hoist app as specified by its
@@ -40,7 +39,7 @@ export declare class HoistAppModel extends HoistModel {
40
39
  /**
41
40
  * Provide the initial set of Router5 Routes to be used by this application.
42
41
  */
43
- getRoutes(): Route[];
42
+ getRoutes(): HoistRoute[];
44
43
  /**
45
44
  * Provide a list of app-wide options to be displayed in the App's built-in Options
46
45
  * dialog, accessible from the default AppBar menu when this method returns non-empty.
@@ -3,6 +3,7 @@ import { LocalDate } from '@xh/hoist/utils/datetime';
3
3
  import { MomentInput } from 'moment';
4
4
  import { Component, FunctionComponent, ReactElement } from 'react';
5
5
  import { DebounceSettings } from 'lodash';
6
+ import { Route } from 'router5';
6
7
  /** Values available for intents. */
7
8
  export type Intent = 'primary' | 'success' | 'warning' | 'danger';
8
9
  /** Values available for App Theme. */
@@ -42,6 +43,17 @@ export type DebounceSpec = number | (DebounceSettings & {
42
43
  */
43
44
  export type Content = ReactElement | FunctionComponent | Component | ElementFactory | (() => ReactElement);
44
45
  export type DateLike = Date | LocalDate | MomentInput;
46
+ /**
47
+ * A Router5 {@link Route} spec, extended with Hoist's `omit` support for declarative exclusion of
48
+ * routes at registration time (e.g. role-gated sections). Note `omit` is evaluated once when routes
49
+ * are added to the router during app startup - it is not reactive.
50
+ *
51
+ * @see HoistAppModel.getRoutes
52
+ */
53
+ export interface HoistRoute extends Omit<Route, 'children'> {
54
+ omit?: Thunkable<boolean>;
55
+ children?: HoistRoute[];
56
+ }
45
57
  /** Valid units for the {@link LocalDate} adjustment methods. */
46
58
  export type LocalDateUnit = 'year' | 'years' | 'quarter' | 'quarters' | 'month' | 'months' | 'week' | 'weeks' | 'day' | 'days';
47
59
  export type PageState =
@@ -13,6 +13,7 @@ export interface ExpandToLevelButtonProps extends Omit<ButtonProps, 'title'> {
13
13
  }
14
14
  /**
15
15
  * A menu button to expand a multi-level grouped or tree grid out to a desired level.
16
- * Requires {@link GridConfig.levelLabels} to be configured on the bound GridModel.
16
+ * Requires {@link GridConfig.levelLabels} to be configured on the bound GridModel - the menu offers
17
+ * one entry per labelled level, so a partial array will limit the available expand-to targets.
17
18
  */
18
19
  export declare const ExpandToLevelButton: import("react").FC<ExpandToLevelButtonProps>, expandToLevelButton: import("@xh/hoist/core").ElementFactory<ExpandToLevelButtonProps>;
@@ -24,6 +24,11 @@ export interface FilterChooserProps extends HoistProps<FilterChooserModel>, Layo
24
24
  placeholder?: string;
25
25
  /** Icon clicked to launch favorites menu. (Defaults to Icon.favorite()) */
26
26
  favoritesIcon?: ReactElement;
27
+ /**
28
+ * True to render collapsed in-place, expanding into a popover when opened - useful in toolbars
29
+ * and other height-constrained containers. Opens in the direction set by `menuPlacement`.
30
+ */
31
+ popover?: boolean;
27
32
  }
28
33
  /**
29
34
  * A Select based control for searching and choosing filters.
@@ -1,9 +1,11 @@
1
1
  import '@xh/hoist/desktop/register';
2
- import './PopoverFilterChooser.scss';
3
2
  import { FilterChooserProps } from './FilterChooser';
4
3
  /**
5
4
  * A wrapper around a FilterChooser that renders in a popover when opened, allowing it to expand
6
5
  * vertically beyond the height of a toolbar.
6
+ *
7
+ * @deprecated Use `filterChooser({popover: true})` instead - the popover behavior is now a built-in
8
+ * mode of `FilterChooser`. This alias will be removed in a future major release.
7
9
  * @see FilterChooser
8
10
  */
9
11
  export declare const PopoverFilterChooser: import("react").FC<FilterChooserProps>, popoverFilterChooser: import("@xh/hoist/core").ElementFactory<FilterChooserProps>;
@@ -1,4 +1,4 @@
1
- import { ColChooserConfig, GridModel } from '@xh/hoist/cmp/grid';
1
+ import { ColChooserConfig, GridModel, IColChooserModel } from '@xh/hoist/cmp/grid';
2
2
  import { HoistModel } from '@xh/hoist/core';
3
3
  import type { FilterMatchMode } from '@xh/hoist/data';
4
4
  import { LeftRightChooserModel } from '@xh/hoist/desktop/cmp/leftrightchooser';
@@ -6,7 +6,7 @@ import { LeftRightChooserModel } from '@xh/hoist/desktop/cmp/leftrightchooser';
6
6
  * State management for the ColChooser component.
7
7
  * @internal
8
8
  */
9
- export declare class ColChooserModel extends HoistModel {
9
+ export declare class ColChooserModel extends HoistModel implements IColChooserModel {
10
10
  xhImpl: boolean;
11
11
  gridModel: GridModel;
12
12
  lrModel: LeftRightChooserModel;
@@ -1,8 +1,16 @@
1
+ import type { GridFilterFieldSpec } from '@xh/hoist/cmp/grid';
1
2
  import { HoistModel } from '@xh/hoist/core';
2
3
  import { FieldFilterOperator, FieldFilterSpec } from '@xh/hoist/data';
3
4
  import { HeaderFilterModel } from '../HeaderFilterModel';
4
5
  import { CustomTabModel } from './CustomTabModel';
5
6
  type OperatorOptionValue = 'blank' | 'not blank' | FieldFilterOperator;
7
+ /**
8
+ * Whether a row for the given op renders the multi-value `select` input - the only custom-tab input
9
+ * that holds an array of values directly. The single-value inputs (number, date, text) are used
10
+ * otherwise, so array filter values bound for them must be expanded into one row each (see
11
+ * `CustomTabModel.doSyncWithFilter`). Mirrors the input choice made in `CustomRow`.
12
+ */
13
+ export declare function usesMultiValueInput(fieldSpec: GridFilterFieldSpec, op: FieldFilterOperator): boolean;
6
14
  /**
7
15
  * @internal
8
16
  */
@@ -14,7 +22,7 @@ export declare class CustomRowModel extends HoistModel {
14
22
  inputVal: any;
15
23
  /** FieldFilter config output of this row. */
16
24
  get value(): FieldFilterSpec;
17
- get fieldSpec(): import("../../../../../../../cmp/grid").GridFilterFieldSpec;
25
+ get fieldSpec(): GridFilterFieldSpec;
18
26
  get options(): {
19
27
  label: string;
20
28
  value: OperatorOptionValue;
@@ -1,5 +1,5 @@
1
1
  import { HoistModel } from '@xh/hoist/core';
2
- import { CompoundFilterOperator, FilterLike } from '@xh/hoist/data';
2
+ import { CompoundFilterOperator, FieldFilter, FilterLike } from '@xh/hoist/data';
3
3
  import { HeaderFilterModel } from '../HeaderFilterModel';
4
4
  import { CustomRowModel } from './CustomRowModel';
5
5
  export declare class CustomTabModel extends HoistModel {
@@ -11,11 +11,17 @@ export declare class CustomTabModel extends HoistModel {
11
11
  get filter(): FilterLike;
12
12
  get fieldSpec(): import("../../../../../../../cmp/grid").GridFilterFieldSpec;
13
13
  get currentGridFilter(): import("@xh/hoist/data").Filter;
14
- get columnFilters(): import("@xh/hoist/data").FieldFilter[];
14
+ get columnFilters(): FieldFilter[];
15
+ get columnCompoundFilter(): import("@xh/hoist/data").CompoundFilter;
15
16
  constructor(headerFilterModel: HeaderFilterModel);
16
17
  syncWithFilter(): void;
17
18
  reset(): void;
18
19
  addEmptyRow(): void;
19
20
  removeRow(model: any): void;
20
21
  private doSyncWithFilter;
22
+ private needsExpansion;
23
+ private mergeOpFor;
24
+ private deriveOp;
25
+ private get isRepresentable();
26
+ private collapseToArrayFilters;
21
27
  }
@@ -4,6 +4,13 @@ import './CodeInput.scss';
4
4
  export interface CodeInputProps extends HoistProps, HoistInputProps, LayoutProps {
5
5
  /** True to focus the control on render. */
6
6
  autoFocus?: boolean;
7
+ /**
8
+ * True to automatically format content for display using the configured `formatter`.
9
+ * Defaults to true for `readonly` inputs - set false to opt out. May also be enabled on
10
+ * editable inputs, in which case content is formatted on blur (never mid-edit, so user
11
+ * edits and cursor position are preserved while typing).
12
+ */
13
+ autoFormat?: boolean;
7
14
  /** False to not commit on every change/keystroke, default true. */
8
15
  commitOnChange?: boolean;
9
16
  /**
@@ -36,7 +36,7 @@ export interface NumberInputProps extends HoistProps, LayoutProps, StyleProps, H
36
36
  onKeyDown?: KeyboardEventHandler<HTMLInputElement>;
37
37
  /** Text to display when control is empty. */
38
38
  placeholder?: string;
39
- /** Max decimal precision of the value, defaults to 4. */
39
+ /** Max decimal precision of the value, defaults to 4. Set to null for full, unrestricted precision. */
40
40
  precision?: NumericPrecision;
41
41
  /** Element to display inline on the right side of the input. */
42
42
  rightElement?: ReactNode;
@@ -127,6 +127,14 @@ export interface SelectProps extends HoistProps, HoistInputProps, LayoutProps {
127
127
  selectOnFocus?: boolean;
128
128
  /** Field on provided options for sourcing each option's value (default `value`). */
129
129
  valueField?: string;
130
+ /**
131
+ * Function to generate a `SelectOption` for a (non-null) selected value not present in the
132
+ * current options list. Return null to fall back to the default value-as-label behavior.
133
+ *
134
+ * Useful with queryFn-based selects, readonly forms, or any case where options may not be
135
+ * loaded when a value is set, ensuring the value renders with its proper label.
136
+ */
137
+ generateOptionFn?: (value: any) => SelectOption;
130
138
  }
131
139
  /**
132
140
  * A managed wrapper around the React-Select combobox/dropdown component.
@@ -0,0 +1,20 @@
1
+ import { ReactNode } from 'react';
2
+ /**
3
+ * Compute an explicit pixel width for a windowed (virtualized) `Select` menu.
4
+ *
5
+ * Windowed menus can't auto-size via CSS - react-window absolutely-positions rows at width:100%,
6
+ * so option content never widens the menu and it collapses to the control width. This restores
7
+ * content-based sizing using Canvas + off-screen DOM, the same render-and-measure approach as the
8
+ * grid's `ColumnWidthCalculator`: render each option's actual menu markup (via the configured
9
+ * `optionRenderer`, if any), canvas-estimate its width to pick the widest candidates, then measure
10
+ * only those candidates' displayed width in a hidden probe - so custom `optionRenderer`s (icons,
11
+ * multi-element content, etc.) size correctly. Unlike the grid (which may autosize many columns
12
+ * over thousands of records), this renders one menu's options once per options change.
13
+ *
14
+ * @param options - normalized (possibly grouped) Select options.
15
+ * @param renderOption - renders an option to its menu `ReactNode` (e.g. model.formatOptionLabel).
16
+ * @param portal - shared menu portal div, used to host probes so menu CSS (font, padding) applies.
17
+ * @returns explicit menu width in px, or null to fall back to the control width.
18
+ * @internal
19
+ */
20
+ export declare function calcWindowedMenuWidth(options: any[], renderOption: (opt: any) => ReactNode, portal: HTMLElement): number;
@@ -20,7 +20,7 @@ export declare class RestFormModel extends HoistModel {
20
20
  del?: import("react").ReactNode | ((recs: import("@xh/hoist/data").StoreRecord[]) => import("react").ReactNode);
21
21
  edit?: import("react").ReactNode | ((recs: import("@xh/hoist/data").StoreRecord[]) => import("react").ReactNode);
22
22
  };
23
- get actions(): (import("@xh/hoist/data").RecordActionSpec | import("@xh/hoist/data").RecordAction)[];
23
+ get actions(): (import("@xh/hoist/data").RecordAction | import("@xh/hoist/data").RecordActionSpec)[];
24
24
  get editors(): RestGridEditor[];
25
25
  get gridModel(): import("../../../../cmp/grid").GridModel;
26
26
  get store(): import("@xh/hoist/desktop/cmp/rest").RestStore;
@@ -33,8 +33,9 @@ export interface NumberFormatOptions extends Omit<FormatOptions<number>, 'toolti
33
33
  */
34
34
  omitFourDigitComma?: boolean;
35
35
  /**
36
- * Desired number of decimal places, or 'auto' (default) to adjust the displayed precision
37
- * automatically based on the scale of the value.
36
+ * Desired number of decimal places, 'auto' (default) to adjust the displayed precision
37
+ * automatically based on the scale of the value, or null for full, unrestricted precision
38
+ * (capped at the max supported precision, with trailing zeros trimmed).
38
39
  */
39
40
  precision?: Precision;
40
41
  /** Prefix to prepend to value (between the number and its sign). */
@@ -65,13 +66,20 @@ export interface NumberFormatOptions extends Omit<FormatOptions<number>, 'toolti
65
66
  *
66
67
  * e.g. `{precision:4, zeroPad:2}` will format `1.2` → "1.20" and `1.234` → "1.234"
67
68
  *
68
- * Default is true if a fixed precision is set, false if precision is 'auto'.
69
+ * Default is true if a fixed precision is set, false if precision is 'auto' or null (full).
69
70
  */
70
71
  zeroPad?: ZeroPad;
71
72
  }
72
73
  export interface QuantityFormatOptions extends NumberFormatOptions {
74
+ /** True to compact values \>= 1 million into units of millions (m). Default true. */
73
75
  useMillions?: boolean;
76
+ /** True to compact values \>= 1 billion into units of billions (b). Default true. */
74
77
  useBillions?: boolean;
78
+ /**
79
+ * True to compact to m/b units only when no precision is lost, else render the full value.
80
+ * Default false.
81
+ */
82
+ lossless?: boolean;
75
83
  }
76
84
  /** Config for pos/neg/neutral color classes. */
77
85
  export interface ColorSpec {
@@ -3,6 +3,7 @@ import { FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
3
3
  import { HoistProps, Intent, Thunkable } from '@xh/hoist/core';
4
4
  import { ReactElement } from 'react';
5
5
  import { SetRequired } from 'type-fest';
6
+ import './Icon.scss';
6
7
  export interface IconProps extends HoistProps, Partial<Omit<FontAwesomeIconProps, 'ref'>> {
7
8
  /** Name of the icon in FontAwesome. */
8
9
  iconName?: IconName;
@@ -333,9 +334,9 @@ export declare const Icon: {
333
334
  filename: string;
334
335
  }): any;
335
336
  /**
336
- * Returns an empty div with FA sizing classes applied. Can be used to take up room in a layout
337
- * where an icon might otherwise go - e.g. to align a series of menu items, where some items do
338
- * not have an icon but others do.
337
+ * Returns an empty div sized to occupy the width of a standard icon. Can be used to take up
338
+ * room in a layout where an icon might otherwise go - e.g. to align a series of menu items,
339
+ * where some items do not have an icon but others do.
339
340
  */
340
341
  placeholder(opts?: IconProps): any;
341
342
  };
@@ -1,4 +1,5 @@
1
1
  import Dropzone from 'react-dropzone';
2
2
  export { Dropzone };
3
+ export { ErrorCode } from 'react-dropzone';
3
4
  export type { Accept, FileRejection, FileWithPath } from 'react-dropzone';
4
5
  export declare const dropzone: import("@xh/hoist/core").ElementFactory<import("react-dropzone").DropzoneProps & import("react").RefAttributes<import("react-dropzone").DropzoneRef>>;
@@ -27,6 +27,7 @@ export declare const swiper: import("@xh/hoist/core").ElementFactory<import("rea
27
27
  onScrollbarDragStart?: (swiper: import("swiper/types").Swiper, event: MouseEvent | TouchEvent | PointerEvent) => void;
28
28
  onScrollbarDragMove?: (swiper: import("swiper/types").Swiper, event: MouseEvent | TouchEvent | PointerEvent) => void;
29
29
  onScrollbarDragEnd?: (swiper: import("swiper/types").Swiper, event: MouseEvent | TouchEvent | PointerEvent) => void;
30
+ onVirtualUpdate?: (swiper: import("swiper/types").Swiper) => void;
30
31
  onZoomChange?: (swiper: import("swiper/types").Swiper, scale: number, imageEl: HTMLElement, slideEl: HTMLElement) => void;
31
32
  onInit?: (swiper: import("swiper/types").Swiper) => any;
32
33
  onBeforeDestroy?: (swiper: import("swiper/types").Swiper) => void;
@@ -53,8 +54,8 @@ export declare const swiper: import("@xh/hoist/core").ElementFactory<import("rea
53
54
  onReachEnd?: (swiper: import("swiper/types").Swiper) => void;
54
55
  onToEdge?: (swiper: import("swiper/types").Swiper) => void;
55
56
  onFromEdge?: (swiper: import("swiper/types").Swiper) => void;
56
- onSetTranslate?: (swiper: import("swiper/types").Swiper, translate: number) => void;
57
- onSetTransition?: (swiper: import("swiper/types").Swiper, transition: number) => void;
57
+ onSetTranslate?: (swiper: import("swiper/types").Swiper, translate: number, byController?: boolean | Swiper) => void;
58
+ onSetTransition?: (swiper: import("swiper/types").Swiper, transition: number, byController?: boolean | Swiper) => void;
58
59
  onResize?: (swiper: import("swiper/types").Swiper) => void;
59
60
  onObserverUpdate?: (swiper: import("swiper/types").Swiper) => void;
60
61
  onBeforeLoopFix?: (swiper: import("swiper/types").Swiper) => void;
@@ -77,7 +78,7 @@ export declare const swiper: import("@xh/hoist/core").ElementFactory<import("rea
77
78
  onBeforeInit?: (swiper: import("swiper/types").Swiper) => void;
78
79
  onBeforeResize?: (swiper: import("swiper/types").Swiper) => void;
79
80
  onBeforeSlideChangeStart?: (swiper: import("swiper/types").Swiper) => void;
80
- onBeforeTransitionStart?: (swiper: import("swiper/types").Swiper, speed: number, internal: any) => void;
81
+ onBeforeTransitionStart?: (swiper: import("swiper/types").Swiper, speed: number, internal: unknown) => void;
81
82
  onChangeDirection?: (swiper: import("swiper/types").Swiper) => void;
82
83
  onDoubleClick?: (swiper: import("swiper/types").Swiper, event: MouseEvent | TouchEvent | PointerEvent) => void;
83
84
  onDestroy?: (swiper: import("swiper/types").Swiper) => void;
@@ -10,6 +10,7 @@ export interface ExpandToLevelButtonProps extends MenuButtonProps {
10
10
  }
11
11
  /**
12
12
  * A menu button to expand a multi-level grouped or tree grid out to a desired level.
13
- * Requires {@link GridConfig.levelLabels} to be configured on the bound GridModel.
13
+ * Requires {@link GridConfig.levelLabels} to be configured on the bound GridModel - the menu offers
14
+ * one entry per labelled level, so a partial array will limit the available expand-to targets.
14
15
  */
15
16
  export declare const ExpandToLevelButton: import("react").FC<ExpandToLevelButtonProps>, expandToLevelButton: import("@xh/hoist/core").ElementFactory<ExpandToLevelButtonProps>;
@@ -1,4 +1,4 @@
1
- import { GridModel } from '@xh/hoist/cmp/grid';
1
+ import { GridModel, IColChooserModel } from '@xh/hoist/cmp/grid';
2
2
  import { HoistModel, HSide } from '@xh/hoist/core';
3
3
  import '@xh/hoist/mobile/register';
4
4
  /**
@@ -7,7 +7,7 @@ import '@xh/hoist/mobile/register';
7
7
  * It is not necessary to manually create instances of this class within an application.
8
8
  * @internal
9
9
  */
10
- export declare class ColChooserModel extends HoistModel {
10
+ export declare class ColChooserModel extends HoistModel implements IColChooserModel {
11
11
  xhImpl: boolean;
12
12
  gridModel: GridModel;
13
13
  showRestoreDefaults: boolean;