@xh/hoist 75.0.0-SNAPSHOT.1753198948130 → 75.0.0-SNAPSHOT.1753280710081

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 (36) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/build/types/cmp/grid/GridModel.d.ts +2 -1
  3. package/build/types/cmp/layout/Tags.d.ts +2 -0
  4. package/build/types/desktop/cmp/button/{ColAutosizeButton.d.ts → grid/ColAutosizeButton.d.ts} +3 -3
  5. package/build/types/desktop/cmp/button/{ColChooserButton.d.ts → grid/ColChooserButton.d.ts} +3 -3
  6. package/build/types/desktop/cmp/button/grid/ExpandToLevelButton.d.ts +18 -0
  7. package/build/types/desktop/cmp/button/{ExportButton.d.ts → grid/ExportButton.d.ts} +7 -7
  8. package/build/types/desktop/cmp/button/index.d.ts +7 -6
  9. package/build/types/desktop/cmp/button/{ZoneMapperButton.d.ts → zoneGrid/ZoneMapperButton.d.ts} +3 -4
  10. package/build/types/mobile/cmp/button/{ColAutosizeButton.d.ts → grid/ColAutosizeButton.d.ts} +2 -2
  11. package/build/types/mobile/cmp/button/{ColChooserButton.d.ts → grid/ColChooserButton.d.ts} +4 -4
  12. package/build/types/mobile/cmp/button/{ExpandCollapseButton.d.ts → grid/ExpandCollapseButton.d.ts} +5 -2
  13. package/build/types/mobile/cmp/button/grid/ExpandToLevelButton.d.ts +15 -0
  14. package/build/types/mobile/cmp/button/index.d.ts +5 -4
  15. package/build/types/mobile/cmp/button/{ZoneMapperButton.d.ts → zoneGrid/ZoneMapperButton.d.ts} +2 -3
  16. package/cmp/grid/GridModel.ts +2 -1
  17. package/cmp/layout/Tags.ts +2 -0
  18. package/desktop/cmp/button/{ColAutosizeButton.ts → grid/ColAutosizeButton.ts} +25 -15
  19. package/desktop/cmp/button/{ColChooserButton.ts → grid/ColChooserButton.ts} +10 -10
  20. package/desktop/cmp/button/grid/ExpandToLevelButton.ts +96 -0
  21. package/desktop/cmp/button/grid/ExportButton.ts +75 -0
  22. package/desktop/cmp/button/index.ts +7 -6
  23. package/desktop/cmp/button/{ModalToggleButton.ts → panel/ModalToggleButton.ts} +12 -6
  24. package/desktop/cmp/button/{ZoneMapperButton.ts → zoneGrid/ZoneMapperButton.ts} +11 -11
  25. package/mobile/cmp/button/{ColAutosizeButton.ts → grid/ColAutosizeButton.ts} +26 -10
  26. package/mobile/cmp/button/grid/ColChooserButton.ts +58 -0
  27. package/mobile/cmp/button/{ExpandCollapseButton.ts → grid/ExpandCollapseButton.ts} +12 -6
  28. package/mobile/cmp/button/grid/ExpandToLevelButton.ts +91 -0
  29. package/mobile/cmp/button/index.ts +5 -4
  30. package/mobile/cmp/button/zoneGrid/ZoneMapperButton.ts +58 -0
  31. package/package.json +1 -1
  32. package/tsconfig.tsbuildinfo +1 -1
  33. package/desktop/cmp/button/ExportButton.ts +0 -65
  34. package/mobile/cmp/button/ColChooserButton.ts +0 -44
  35. package/mobile/cmp/button/ZoneMapperButton.ts +0 -42
  36. /package/build/types/desktop/cmp/button/{ModalToggleButton.d.ts → panel/ModalToggleButton.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -9,6 +9,9 @@
9
9
  * The most recently expanded level is persistable with other grid state.
10
10
  * The default grid context menu now supports a new item to allow users to expand/collapse out to
11
11
  a specific level/depth. Set `GridModel.levelLabels` to activate this feature.
12
+ * A new `ExpandToLevelButton` menu component is also available for both desktop and mobile.
13
+ Provides easier discoverability on desktop and supports this feature on mobile, where we
14
+ don't have context menus.
12
15
  * Added new `GroupingChooserModel.sortDimensions` config. Set to `false` to respect the order in
13
16
  which `dimensions` are provided to the model.
14
17
  * The usage of the `RelativeTimestamp` component has been streamlined by deprecating the `options`
@@ -143,7 +143,8 @@ export interface GridConfig {
143
143
  * Array of strings (or a function returning one) providing user-facing labels for each depth
144
144
  * level in a tree or grouped grid - e.g. `['Country', 'State', 'City']`. If set, the
145
145
  * expand/collapse options in the default context menu will be enhanced to allow users to
146
- * expand/collapse to a specific level.
146
+ * expand/collapse to a specific level. See {@link GroupingChooserModel.valueDisplayNames}
147
+ * for a convenient getter that will satisfy this API when a GroupingChooser is in play.
147
148
  */
148
149
  levelLabels?: Thunkable<string[]>;
149
150
  /**
@@ -32,3 +32,5 @@ export declare const th: import("@xh/hoist/core").ElementFactory<import("react")
32
32
  export declare const thead: import("@xh/hoist/core").ElementFactory<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableSectionElement>, HTMLTableSectionElement>>;
33
33
  export declare const tr: import("@xh/hoist/core").ElementFactory<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLTableRowElement>, HTMLTableRowElement>>;
34
34
  export declare const ul: import("@xh/hoist/core").ElementFactory<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>>;
35
+ export declare const details: import("@xh/hoist/core").ElementFactory<import("react").DetailedHTMLProps<import("react").DetailsHTMLAttributes<HTMLDetailsElement>, HTMLDetailsElement>>;
36
+ export declare const summary: import("@xh/hoist/core").ElementFactory<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLElement>, HTMLElement>>;
@@ -1,8 +1,8 @@
1
- import { GridModel, GridAutosizeOptions } from '@xh/hoist/cmp/grid';
1
+ import { GridAutosizeOptions, GridModel } from '@xh/hoist/cmp/grid';
2
2
  import '@xh/hoist/desktop/register';
3
- import { ButtonProps } from './Button';
3
+ import { ButtonProps } from '../Button';
4
4
  export interface ColAutosizeButtonProps extends ButtonProps {
5
- /** GridModel of the grid for which this button should autosize columns. */
5
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
6
6
  gridModel?: GridModel;
7
7
  /** Options for the grid autosize. */
8
8
  autosizeOptions?: Omit<GridAutosizeOptions, 'mode'>;
@@ -1,9 +1,9 @@
1
1
  import { GridModel } from '@xh/hoist/cmp/grid';
2
2
  import '@xh/hoist/desktop/register';
3
3
  import { Position } from '@xh/hoist/kit/blueprint';
4
- import { ButtonProps } from './Button';
4
+ import { ButtonProps } from '../Button';
5
5
  export interface ColChooserButtonProps extends ButtonProps {
6
- /** GridModel of the grid for which this button should show a chooser. */
6
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
7
7
  gridModel?: GridModel;
8
8
  /** Position for chooser popover, as per Blueprint docs. */
9
9
  popoverPosition?: Position;
@@ -13,6 +13,6 @@ export interface ColChooserButtonProps extends ButtonProps {
13
13
  * available Grid columns. For use by applications when a button is desired in addition to the
14
14
  * context menu item built into the Grid component directly.
15
15
  *
16
- * Requires the `GridModel.colChooserModel` config option. Set to true for default implementation.
16
+ * Requires {@link GridConfig.colChooserModel} to be configured on the bound GridModel.
17
17
  */
18
18
  export declare const ColChooserButton: import("react").FC<ColChooserButtonProps>, colChooserButton: import("@xh/hoist/core").ElementFactory<ColChooserButtonProps>;
@@ -0,0 +1,18 @@
1
+ import { GridModel } from '@xh/hoist/cmp/grid';
2
+ import '@xh/hoist/desktop/register';
3
+ import { Position } from '@xh/hoist/kit/blueprint';
4
+ import { ReactNode } from 'react';
5
+ import { ButtonProps } from '../Button';
6
+ export interface ExpandToLevelButtonProps extends Omit<ButtonProps, 'title'> {
7
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
8
+ gridModel?: GridModel;
9
+ /** Position for menu, as per Blueprint docs. */
10
+ popoverPosition?: Position;
11
+ /** Title for the menu popover - defaults to "Expand To Level". */
12
+ title: ReactNode;
13
+ }
14
+ /**
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.
17
+ */
18
+ export declare const ExpandToLevelButton: import("react").FC<ExpandToLevelButtonProps>, expandToLevelButton: import("@xh/hoist/core").ElementFactory<ExpandToLevelButtonProps>;
@@ -1,21 +1,21 @@
1
1
  import { GridModel } from '@xh/hoist/cmp/grid';
2
2
  import '@xh/hoist/desktop/register';
3
3
  import { ExportOptions } from '@xh/hoist/svc';
4
- import { ButtonProps } from './Button';
4
+ import { ButtonProps } from '../Button';
5
5
  export interface ExportButtonProps extends ButtonProps {
6
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
6
7
  gridModel?: GridModel;
7
8
  exportOptions?: ExportOptions;
8
9
  }
9
10
  /**
10
11
  * Convenience Button preconfigured for use as a trigger for an export/download of data.
11
12
  *
12
- * Must be provided either an onClick handler *or* a gridModel. GridModel may be provided
13
- * in props, or otherwise will be looked up by this model from context.
13
+ * Must be provided either an onClick handler *or* a gridModel. GridModel may be provided via props,
14
+ * otherwise will be looked up by this model from context.
14
15
  *
15
- * If a gridModel is provided, this button will call exportAsync() on the model class.
16
- * Options supported by GridExportService.exportAsync() can be set via the exportOptions
17
- * props.
16
+ * If a GridModel is provided, this button will call {@link GridModel.exportAsync}. The grid's
17
+ * {@link ExportOptions} will be used unless overridden via this component's `exportOptions` prop.
18
18
  *
19
- * Requires the `GridModel.enableExport` config option to be true.
19
+ * Requires {@link GridConfig.enableExport} option to be true on the bound GridModel.
20
20
  */
21
21
  export declare const ExportButton: import("react").FC<ExportButtonProps>, exportButton: import("@xh/hoist/core").ElementFactory<ExportButtonProps>;
@@ -1,16 +1,17 @@
1
- export * from './Button';
2
1
  export * from './AppMenuButton';
2
+ export * from './Button';
3
3
  export * from './ButtonGroup';
4
- export * from './ColAutosizeButton';
5
- export * from './ColChooserButton';
6
4
  export * from './DashCanvasAddViewButton';
7
- export * from './ExportButton';
8
5
  export * from './FeedbackButton';
9
6
  export * from './LaunchAdminButton';
10
7
  export * from './LogoutButton';
11
- export * from './ModalToggleButton';
8
+ export * from './panel/ModalToggleButton';
12
9
  export * from './OptionsButton';
13
10
  export * from './RefreshButton';
14
11
  export * from './RestoreDefaultsButton';
15
12
  export * from './ThemeToggleButton';
16
- export * from './ZoneMapperButton';
13
+ export * from './grid/ColAutosizeButton';
14
+ export * from './grid/ColChooserButton';
15
+ export * from './grid/ExpandToLevelButton';
16
+ export * from './grid/ExportButton';
17
+ export * from './zoneGrid/ZoneMapperButton';
@@ -1,16 +1,15 @@
1
1
  import '@xh/hoist/desktop/register';
2
2
  import { ZoneGridModel } from '@xh/hoist/cmp/zoneGrid';
3
3
  import { Position } from '@xh/hoist/kit/blueprint';
4
- import { ButtonProps } from './Button';
4
+ import { ButtonProps } from '../Button';
5
5
  export interface ZoneMapperButtonProps extends ButtonProps {
6
- /** ZoneGridModel of the grid for which this button should show a chooser. */
6
+ /** ZoneGridModel to which this button should bind. Will find nearest in context if not provided. */
7
7
  zoneGridModel?: ZoneGridModel;
8
8
  /** Position for chooser popover, as per Blueprint docs. */
9
9
  popoverPosition?: Position;
10
10
  }
11
11
  /**
12
12
  * A convenience button to trigger the display of a ZoneMapper UI for ZoneGrid configuration.
13
- *
14
- * Requires a `ZoneGridModel.zoneMapperModel` config option, set to true for default implementation.
13
+ * Requires {@link ZoneGridConfig.zoneMapperModel} to be configured on the bound ZoneGridModel.
15
14
  */
16
15
  export declare const ZoneMapperButton: import("react").FC<ZoneMapperButtonProps>, zoneMapperButton: import("@xh/hoist/core").ElementFactory<ZoneMapperButtonProps>;
@@ -2,9 +2,9 @@ import { GridModel, GridAutosizeOptions } from '@xh/hoist/cmp/grid';
2
2
  import { ButtonProps } from '@xh/hoist/mobile/cmp/button';
3
3
  import '@xh/hoist/mobile/register';
4
4
  export interface ColAutosizeButtonProps extends ButtonProps {
5
- /** GridModel of the grid for which this button should autosize columns. */
5
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
6
6
  gridModel?: GridModel;
7
- /** Options for the grid autosize. */
7
+ /** Options to override grid's default or configured autosize settings. */
8
8
  autosizeOptions?: Omit<GridAutosizeOptions, 'mode'>;
9
9
  }
10
10
  /**
@@ -2,13 +2,13 @@ import { GridModel } from '@xh/hoist/cmp/grid';
2
2
  import { ButtonProps } from '@xh/hoist/mobile/cmp/button';
3
3
  import '@xh/hoist/mobile/register';
4
4
  export interface ColChooserButtonProps extends ButtonProps {
5
- /** GridModel of the grid for which this button should show a chooser. */
5
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
6
6
  gridModel?: GridModel;
7
7
  }
8
8
  /**
9
- * A convenience button to trigger the display of a ColChooser for user selection,
10
- * discovery and reordering of available Grid columns.
9
+ * A convenience button to trigger the display of a ColChooser for user selection, discovery and
10
+ * reordering of available Grid columns.
11
11
  *
12
- * Requires a `GridModel.colChooserModel` config option, set to true for default implementation.
12
+ * Requires {@link GridConfig.colChooserModel} to be configured on the bound GridModel.
13
13
  */
14
14
  export declare const ColChooserButton: import("react").FC<ColChooserButtonProps>, colChooserButton: import("@xh/hoist/core").ElementFactory<ColChooserButtonProps>;
@@ -2,10 +2,13 @@ import { GridModel } from '@xh/hoist/cmp/grid';
2
2
  import { ButtonProps } from '@xh/hoist/mobile/cmp/button';
3
3
  import '@xh/hoist/mobile/register';
4
4
  export interface ExpandCollapseButtonProps extends ButtonProps {
5
- /** GridModel of the grid for which this button should show a chooser. */
5
+ /**
6
+ * `GridModel` to which this button should bind.
7
+ * Optional, will find nearest GridModel in context if not provided.
8
+ */
6
9
  gridModel?: GridModel;
7
10
  }
8
11
  /**
9
- * A convenience button to expand / collapse all rows in grouped or tree grid.
12
+ * A convenience button to expand / collapse all rows in a grouped or tree Grid.
10
13
  */
11
14
  export declare const ExpandCollapseButton: import("react").FC<ExpandCollapseButtonProps>, expandCollapseButton: import("@xh/hoist/core").ElementFactory<ExpandCollapseButtonProps>;
@@ -0,0 +1,15 @@
1
+ import { GridModel } from '@xh/hoist/cmp/grid';
2
+ import '@xh/hoist/mobile/register';
3
+ import { MenuButtonProps } from '../../menu';
4
+ export interface ExpandToLevelButtonProps extends MenuButtonProps {
5
+ /**
6
+ * `GridModel` to which this button should bind.
7
+ * Optional, will find nearest GridModel in context if not provided.
8
+ */
9
+ gridModel?: GridModel;
10
+ }
11
+ /**
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.
14
+ */
15
+ export declare const ExpandToLevelButton: import("react").FC<ExpandToLevelButtonProps>, expandToLevelButton: import("@xh/hoist/core").ElementFactory<ExpandToLevelButtonProps>;
@@ -1,12 +1,13 @@
1
1
  export * from './Button';
2
2
  export * from './ButtonGroup';
3
- export * from './ColAutosizeButton';
4
- export * from './ColChooserButton';
5
- export * from './ExpandCollapseButton';
3
+ export * from './grid/ColAutosizeButton';
4
+ export * from './grid/ColChooserButton';
5
+ export * from './grid/ExpandCollapseButton';
6
+ export * from './grid/ExpandToLevelButton';
6
7
  export * from './FeedbackButton';
7
8
  export * from './ThemeToggleButton';
8
9
  export * from './LogoutButton';
9
10
  export * from './RefreshButton';
10
11
  export * from './RestoreDefaultsButton';
11
12
  export * from './NavigatorBackButton';
12
- export * from './ZoneMapperButton';
13
+ export * from './zoneGrid/ZoneMapperButton';
@@ -1,5 +1,5 @@
1
- import { ZoneGridModel } from '../../../cmp/zoneGrid';
2
1
  import { ButtonProps } from '@xh/hoist/mobile/cmp/button';
2
+ import { ZoneGridModel } from '@xh/hoist/cmp/zoneGrid';
3
3
  import '@xh/hoist/mobile/register';
4
4
  export interface ZoneMapperButtonProps extends ButtonProps {
5
5
  /** ZoneGridModel of the grid for which this button should show a chooser. */
@@ -7,7 +7,6 @@ export interface ZoneMapperButtonProps extends ButtonProps {
7
7
  }
8
8
  /**
9
9
  * A convenience button to trigger the display of a ZoneMapper UI for ZoneGrid configuration.
10
- *
11
- * Requires a `ZoneGridModel.zoneMapperModel` config option, set to true for default implementation.
10
+ * Requires {@link ZoneGridConfig.zoneMapperModel} to be configured on the bound ZoneGridModel.
12
11
  */
13
12
  export declare const ZoneMapperButton: import("react").FC<ZoneMapperButtonProps>, zoneMapperButton: import("@xh/hoist/core").ElementFactory<ZoneMapperButtonProps>;
@@ -283,7 +283,8 @@ export interface GridConfig {
283
283
  * Array of strings (or a function returning one) providing user-facing labels for each depth
284
284
  * level in a tree or grouped grid - e.g. `['Country', 'State', 'City']`. If set, the
285
285
  * expand/collapse options in the default context menu will be enhanced to allow users to
286
- * expand/collapse to a specific level.
286
+ * expand/collapse to a specific level. See {@link GroupingChooserModel.valueDisplayNames}
287
+ * for a convenient getter that will satisfy this API when a GroupingChooser is in play.
287
288
  */
288
289
  levelLabels?: Thunkable<string[]>;
289
290
 
@@ -51,3 +51,5 @@ export const th = elementFactory('th');
51
51
  export const thead = elementFactory('thead');
52
52
  export const tr = elementFactory('tr');
53
53
  export const ul = elementFactory('ul');
54
+ export const details = elementFactory('details');
55
+ export const summary = elementFactory('summary');
@@ -4,15 +4,15 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {GridModel, GridAutosizeOptions} from '@xh/hoist/cmp/grid';
7
+ import {GridAutosizeOptions, GridModel} from '@xh/hoist/cmp/grid';
8
8
  import {hoistCmp, useContextModel} from '@xh/hoist/core';
9
9
  import '@xh/hoist/desktop/register';
10
10
  import {Icon} from '@xh/hoist/icon';
11
- import {errorIf, withDefault} from '@xh/hoist/utils/js';
12
- import {button, ButtonProps} from './Button';
11
+ import {logError, withDefault} from '@xh/hoist/utils/js';
12
+ import {button, ButtonProps} from '../Button';
13
13
 
14
14
  export interface ColAutosizeButtonProps extends ButtonProps {
15
- /** GridModel of the grid for which this button should autosize columns. */
15
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
16
16
  gridModel?: GridModel;
17
17
 
18
18
  /** Options for the grid autosize. */
@@ -24,15 +24,29 @@ export interface ColAutosizeButtonProps extends ButtonProps {
24
24
  */
25
25
  export const [ColAutosizeButton, colAutosizeButton] = hoistCmp.withFactory<ColAutosizeButtonProps>({
26
26
  displayName: 'ColAutosizeButton',
27
+ className: 'xh-col-autosize-button',
27
28
  model: false,
28
29
 
29
- render({icon, title, onClick, gridModel, disabled, autosizeOptions = {}, ...rest}, ref) {
30
+ render(
31
+ {className, icon, title, onClick, gridModel, disabled, autosizeOptions = {}, ...rest},
32
+ ref
33
+ ) {
30
34
  gridModel = withDefault(gridModel, useContextModel(GridModel));
31
35
 
32
- errorIf(
33
- !gridModel,
34
- "No GridModel available to ColAutosizeButton. Provide via a 'gridModel' prop, or context."
35
- );
36
+ // Validate bound model available and suitable for use.
37
+ if (!gridModel) {
38
+ logError(
39
+ 'No GridModel available - provide via a `gridModel` prop or context - button will be disabled.',
40
+ ColAutosizeButton
41
+ );
42
+ disabled = true;
43
+ } else if (!gridModel.autosizeEnabled) {
44
+ logError(
45
+ 'Autosize not enabled on bound GridModel - button will be disabled.',
46
+ ColAutosizeButton
47
+ );
48
+ disabled = true;
49
+ }
36
50
 
37
51
  onClick =
38
52
  onClick ??
@@ -42,17 +56,13 @@ export const [ColAutosizeButton, colAutosizeButton] = hoistCmp.withFactory<ColAu
42
56
  ...autosizeOptions
43
57
  }));
44
58
 
45
- errorIf(
46
- !gridModel?.autosizeEnabled,
47
- 'AutosizeButton must be bound to GridModel with autosize enabled. See autosizeOptions.mode'
48
- );
49
-
50
59
  return button({
51
60
  ref,
52
61
  icon: withDefault(icon, Icon.arrowsLeftRight()),
53
62
  title: withDefault(title, 'Autosize Columns'),
63
+ disabled: withDefault(disabled, gridModel?.empty),
64
+ className,
54
65
  onClick,
55
- disabled: withDefault(disabled, gridModel && gridModel.empty),
56
66
  ...rest
57
67
  });
58
68
  }
@@ -13,10 +13,10 @@ import '@xh/hoist/desktop/register';
13
13
  import {Icon} from '@xh/hoist/icon';
14
14
  import {popover, Position} from '@xh/hoist/kit/blueprint';
15
15
  import {logError, stopPropagation, withDefault} from '@xh/hoist/utils/js';
16
- import {button, ButtonProps} from './Button';
16
+ import {button, ButtonProps} from '../Button';
17
17
 
18
18
  export interface ColChooserButtonProps extends ButtonProps {
19
- /** GridModel of the grid for which this button should show a chooser. */
19
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
20
20
  gridModel?: GridModel;
21
21
 
22
22
  /** Position for chooser popover, as per Blueprint docs. */
@@ -28,28 +28,27 @@ export interface ColChooserButtonProps extends ButtonProps {
28
28
  * available Grid columns. For use by applications when a button is desired in addition to the
29
29
  * context menu item built into the Grid component directly.
30
30
  *
31
- * Requires the `GridModel.colChooserModel` config option. Set to true for default implementation.
31
+ * Requires {@link GridConfig.colChooserModel} to be configured on the bound GridModel.
32
32
  */
33
33
  export const [ColChooserButton, colChooserButton] = hoistCmp.withFactory<ColChooserButtonProps>({
34
34
  displayName: 'ColChooserButton',
35
+ className: 'xh-col-chooser-button',
35
36
  model: false,
36
37
 
37
- render({icon, title, gridModel, popoverPosition, disabled, ...rest}, ref) {
38
+ render({className, icon, title, gridModel, popoverPosition, disabled, ...rest}, ref) {
38
39
  gridModel = withDefault(gridModel, useContextModel(GridModel));
39
-
40
40
  const colChooserModel = gridModel?.colChooserModel as ColChooserModel;
41
41
 
42
+ // Validate bound model available and suitable for use.
42
43
  if (!gridModel) {
43
44
  logError(
44
- "No GridModel available. Provide via a 'gridModel' prop, or context.",
45
+ 'No GridModel available - provide via a `gridModel` prop or context - button will be disabled.',
45
46
  ColChooserButton
46
47
  );
47
48
  disabled = true;
48
- }
49
-
50
- if (!colChooserModel) {
49
+ } else if (!colChooserModel) {
51
50
  logError(
52
- 'No ColChooserModel available on bound GridModel - enable via GridModel.colChooserModel config.',
51
+ 'ColChooser not enabled on bound GridModel - button will be disabled.',
53
52
  ColChooserButton
54
53
  );
55
54
  disabled = true;
@@ -62,6 +61,7 @@ export const [ColChooserButton, colChooserButton] = hoistCmp.withFactory<ColChoo
62
61
  item: button({
63
62
  icon: withDefault(icon, Icon.gridPanel()),
64
63
  title: withDefault(title, 'Choose grid columns...'),
64
+ className,
65
65
  disabled,
66
66
  ...rest
67
67
  }),
@@ -0,0 +1,96 @@
1
+ /*
2
+ * This file belongs to Hoist, an application development toolkit
3
+ * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
+ *
5
+ * Copyright © 2025 Extremely Heavy Industries Inc.
6
+ */
7
+ import {GridModel} from '@xh/hoist/cmp/grid';
8
+ import {div, vbox} from '@xh/hoist/cmp/layout';
9
+ import {hoistCmp, MenuItemLike, useContextModel} from '@xh/hoist/core';
10
+ import '@xh/hoist/desktop/register';
11
+ import {Icon} from '@xh/hoist/icon';
12
+ import {menu, popover, Position} from '@xh/hoist/kit/blueprint';
13
+ import {parseMenuItems} from '@xh/hoist/utils/impl';
14
+ import {executeIfFunction, logDebug, logError, withDefault} from '@xh/hoist/utils/js';
15
+ import {ReactNode} from 'react';
16
+ import {button, ButtonProps} from '../Button';
17
+
18
+ export interface ExpandToLevelButtonProps extends Omit<ButtonProps, 'title'> {
19
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
20
+ gridModel?: GridModel;
21
+
22
+ /** Position for menu, as per Blueprint docs. */
23
+ popoverPosition?: Position;
24
+
25
+ /** Title for the menu popover - defaults to "Expand To Level". */
26
+ title: ReactNode;
27
+ }
28
+
29
+ /**
30
+ * A menu button to expand a multi-level grouped or tree grid out to a desired level.
31
+ * Requires {@link GridConfig.levelLabels} to be configured on the bound GridModel.
32
+ */
33
+ export const [ExpandToLevelButton, expandToLevelButton] =
34
+ hoistCmp.withFactory<ExpandToLevelButtonProps>({
35
+ displayName: 'ExpandToLevelButton',
36
+ className: 'xh-expand-to-level-button',
37
+ model: false,
38
+
39
+ render({gridModel, className, icon, title, popoverPosition, disabled, ...rest}) {
40
+ gridModel = withDefault(gridModel, useContextModel(GridModel));
41
+ icon = withDefault(icon, Icon.treeList());
42
+ title = withDefault(title, 'Expand To Level');
43
+
44
+ const disabledButton = () => button({icon, className, ...rest, disabled: true});
45
+
46
+ // Validate bound model available and suitable for use.
47
+ if (!gridModel) {
48
+ logError(
49
+ 'No GridModel available - provide via `gridModel` prop or context - button will be disabled.',
50
+ ExpandToLevelButton
51
+ );
52
+ return disabledButton();
53
+ }
54
+
55
+ // Render a disabled button if requested or if we have a flat grid.
56
+ const {maxDepth, expandLevel} = gridModel;
57
+ if (disabled || !maxDepth) return disabledButton();
58
+
59
+ // Validate level labels - disable quietly if unspecified or w/log if mismatched to grid depth.
60
+ const levelLabels = executeIfFunction(gridModel.levelLabels);
61
+ if (!levelLabels) return disabledButton();
62
+ if (levelLabels.length < maxDepth + 1) {
63
+ logDebug(
64
+ 'Value produced by `GridModel.levelLabels` has insufficient length - button will be disabled.',
65
+ ExpandToLevelButton
66
+ );
67
+ return disabledButton();
68
+ }
69
+
70
+ const menuItems: MenuItemLike[] = levelLabels.map((label, idx) => {
71
+ const isCurrLevel =
72
+ expandLevel === idx ||
73
+ (expandLevel > maxDepth && idx === levelLabels.length - 1);
74
+
75
+ return {
76
+ icon: isCurrLevel ? Icon.check() : Icon.placeholder(),
77
+ text: label,
78
+ actionFn: () => gridModel.expandToLevel(idx)
79
+ };
80
+ });
81
+
82
+ return popover({
83
+ popoverClassName: 'xh-expand-to-level-button__popover xh-popup--framed',
84
+ position: withDefault(popoverPosition, 'auto'),
85
+ item: button({
86
+ icon,
87
+ className,
88
+ ...rest
89
+ }),
90
+ content: vbox(
91
+ div({className: 'xh-popup__title', item: title, omit: !title}),
92
+ menu(parseMenuItems(menuItems))
93
+ )
94
+ });
95
+ }
96
+ });
@@ -0,0 +1,75 @@
1
+ /*
2
+ * This file belongs to Hoist, an application development toolkit
3
+ * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
+ *
5
+ * Copyright © 2025 Extremely Heavy Industries Inc.
6
+ */
7
+ import {GridModel} from '@xh/hoist/cmp/grid';
8
+ import {hoistCmp, useContextModel} from '@xh/hoist/core';
9
+ import '@xh/hoist/desktop/register';
10
+ import {Icon} from '@xh/hoist/icon';
11
+ import {ExportOptions} from '@xh/hoist/svc';
12
+ import {logError, withDefault} from '@xh/hoist/utils/js';
13
+ import {button, ButtonProps} from '../Button';
14
+
15
+ export interface ExportButtonProps extends ButtonProps {
16
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
17
+ gridModel?: GridModel;
18
+
19
+ exportOptions?: ExportOptions;
20
+ }
21
+
22
+ /**
23
+ * Convenience Button preconfigured for use as a trigger for an export/download of data.
24
+ *
25
+ * Must be provided either an onClick handler *or* a gridModel. GridModel may be provided via props,
26
+ * otherwise will be looked up by this model from context.
27
+ *
28
+ * If a GridModel is provided, this button will call {@link GridModel.exportAsync}. The grid's
29
+ * {@link ExportOptions} will be used unless overridden via this component's `exportOptions` prop.
30
+ *
31
+ * Requires {@link GridConfig.enableExport} option to be true on the bound GridModel.
32
+ */
33
+ export const [ExportButton, exportButton] = hoistCmp.withFactory<ExportButtonProps>({
34
+ displayName: 'ExportButton',
35
+ className: 'xh-export-button',
36
+ model: false,
37
+
38
+ render(
39
+ {className, icon, title, onClick, gridModel, exportOptions = {}, disabled, ...rest},
40
+ ref
41
+ ) {
42
+ const contextGridModel = useContextModel(GridModel);
43
+
44
+ if (!onClick) {
45
+ gridModel = withDefault(gridModel, contextGridModel);
46
+
47
+ // Validate bound model available and suitable for use.
48
+ if (!gridModel) {
49
+ logError(
50
+ 'No GridModel available - provide via a `gridModel` prop or context - button will be disabled.',
51
+ ExportButton
52
+ );
53
+ disabled = true;
54
+ } else if (!gridModel.enableExport) {
55
+ logError(
56
+ 'Export not enabled on bound GridModel - button will be disabled',
57
+ ExportButton
58
+ );
59
+ disabled = true;
60
+ } else {
61
+ onClick = () => gridModel.exportAsync(exportOptions).catchDefault();
62
+ }
63
+ }
64
+
65
+ return button({
66
+ ref,
67
+ icon: withDefault(icon, Icon.download()),
68
+ title: withDefault(title, 'Export'),
69
+ disabled: withDefault(disabled, gridModel && gridModel.empty),
70
+ className,
71
+ onClick,
72
+ ...rest
73
+ });
74
+ }
75
+ });
@@ -1,17 +1,18 @@
1
1
  // Export button first as others (e.g. AppMenuButton) depend on its static propTypes.
2
- export * from './Button';
3
2
  export * from './AppMenuButton';
3
+ export * from './Button';
4
4
  export * from './ButtonGroup';
5
- export * from './ColAutosizeButton';
6
- export * from './ColChooserButton';
7
5
  export * from './DashCanvasAddViewButton';
8
- export * from './ExportButton';
9
6
  export * from './FeedbackButton';
10
7
  export * from './LaunchAdminButton';
11
8
  export * from './LogoutButton';
12
- export * from './ModalToggleButton';
9
+ export * from './panel/ModalToggleButton';
13
10
  export * from './OptionsButton';
14
11
  export * from './RefreshButton';
15
12
  export * from './RestoreDefaultsButton';
16
13
  export * from './ThemeToggleButton';
17
- export * from './ZoneMapperButton';
14
+ export * from './grid/ColAutosizeButton';
15
+ export * from './grid/ColChooserButton';
16
+ export * from './grid/ExpandToLevelButton';
17
+ export * from './grid/ExportButton';
18
+ export * from './zoneGrid/ZoneMapperButton';