@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
@@ -9,7 +9,7 @@ import {button, ButtonProps} from '@xh/hoist/desktop/cmp/button/Button';
9
9
  import {PanelModel} from '@xh/hoist/desktop/cmp/panel';
10
10
  import '@xh/hoist/desktop/register';
11
11
  import {Icon} from '@xh/hoist/icon';
12
- import {errorIf, withDefault} from '@xh/hoist/utils/js';
12
+ import {logError, withDefault} from '@xh/hoist/utils/js';
13
13
 
14
14
  export interface ModalToggleButtonProps extends ButtonProps {
15
15
  panelModel?: PanelModel;
@@ -20,21 +20,27 @@ export interface ModalToggleButtonProps extends ButtonProps {
20
20
  */
21
21
  export const [ModalToggleButton, modalToggleButton] = hoistCmp.withFactory<ModalToggleButtonProps>({
22
22
  displayName: 'ModalToggleButton',
23
+ className: 'xh-modal-toggle-button',
23
24
  model: false,
24
25
 
25
- render({panelModel, ...rest}, ref) {
26
+ render({className, panelModel, disabled, ...rest}, ref) {
26
27
  panelModel = withDefault(panelModel, useContextModel(PanelModel));
27
28
 
28
- errorIf(
29
- !panelModel,
30
- "No PanelModel available to ModalToggleButton. Provide via 'panelModel' prop, or context."
31
- );
29
+ if (!panelModel) {
30
+ logError(
31
+ 'No PanelModel available - provide via `panelModel` prop or context - button will be disabled.',
32
+ ModalToggleButton
33
+ );
34
+ disabled = true;
35
+ }
32
36
 
33
37
  return button({
34
38
  ref,
35
39
  icon: panelModel.isModal ? Icon.close() : Icon.openExternal(),
36
40
  onClick: () => panelModel.toggleIsModal(),
37
41
  minimal: true,
42
+ className,
43
+ disabled,
38
44
  ...rest
39
45
  });
40
46
  }
@@ -13,10 +13,10 @@ import {zoneMapper} from '@xh/hoist/desktop/cmp/zoneGrid/impl/ZoneMapper';
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 ZoneMapperButtonProps extends ButtonProps {
19
- /** ZoneGridModel of the grid for which this button should show a chooser. */
19
+ /** ZoneGridModel to which this button should bind. Will find nearest in context if not provided. */
20
20
  zoneGridModel?: ZoneGridModel;
21
21
 
22
22
  /** Position for chooser popover, as per Blueprint docs. */
@@ -25,28 +25,27 @@ export interface ZoneMapperButtonProps extends ButtonProps {
25
25
 
26
26
  /**
27
27
  * A convenience button to trigger the display of a ZoneMapper UI for ZoneGrid configuration.
28
- *
29
- * Requires a `ZoneGridModel.zoneMapperModel` config option, set to true for default implementation.
28
+ * Requires {@link ZoneGridConfig.zoneMapperModel} to be configured on the bound ZoneGridModel.
30
29
  */
31
30
  export const [ZoneMapperButton, zoneMapperButton] = hoistCmp.withFactory<ZoneMapperButtonProps>({
32
31
  displayName: 'ZoneMapperButton',
32
+ className: 'xh-zone-mapper-button',
33
33
  model: false,
34
- render({icon, title, zoneGridModel, popoverPosition, disabled, ...rest}, ref) {
35
- zoneGridModel = withDefault(zoneGridModel, useContextModel(ZoneGridModel));
36
34
 
35
+ render({className, icon, title, zoneGridModel, popoverPosition, disabled, ...rest}, ref) {
36
+ zoneGridModel = withDefault(zoneGridModel, useContextModel(ZoneGridModel));
37
37
  const mapperModel = zoneGridModel?.mapperModel as ZoneMapperModel;
38
38
 
39
+ // Validate bound model available and suitable for use.
39
40
  if (!zoneGridModel) {
40
41
  logError(
41
- "No ZoneGridModel available. Provide via a 'zoneGridModel' prop, or context.",
42
+ 'No ZoneGridModel available - provide via `zoneGridModel` prop or context - button will be disabled',
42
43
  ZoneMapperButton
43
44
  );
44
45
  disabled = true;
45
- }
46
-
47
- if (!mapperModel) {
46
+ } else if (!mapperModel) {
48
47
  logError(
49
- 'No ZoneMapperModel available on bound ZoneGridModel - enable via ZoneGridModel.zoneMapperModel config.',
48
+ 'ZoneMapper not enabled on bound ZoneGridModel - button will be disabled.',
50
49
  ZoneMapperButton
51
50
  );
52
51
  disabled = true;
@@ -60,6 +59,7 @@ export const [ZoneMapperButton, zoneMapperButton] = hoistCmp.withFactory<ZoneMap
60
59
  item: button({
61
60
  icon: withDefault(icon, Icon.gridLarge()),
62
61
  title: withDefault(title, 'Customize fields...'),
62
+ className,
63
63
  disabled,
64
64
  ...rest
65
65
  }),
@@ -13,10 +13,10 @@ import '@xh/hoist/mobile/register';
13
13
  import {logError, withDefault} from '@xh/hoist/utils/js';
14
14
 
15
15
  export interface ColAutosizeButtonProps extends ButtonProps {
16
- /** GridModel of the grid for which this button should autosize columns. */
16
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
17
17
  gridModel?: GridModel;
18
18
 
19
- /** Options for the grid autosize. */
19
+ /** Options to override grid's default or configured autosize settings. */
20
20
  autosizeOptions?: Omit<GridAutosizeOptions, 'mode'>;
21
21
  }
22
22
 
@@ -25,17 +25,27 @@ export interface ColAutosizeButtonProps extends ButtonProps {
25
25
  */
26
26
  export const [ColAutosizeButton, colAutosizeButton] = hoistCmp.withFactory<ColAutosizeButtonProps>({
27
27
  displayName: 'ColAutosizeButton',
28
+ className: 'xh-col-autosize-button',
28
29
  model: false,
29
30
 
30
- render({gridModel, icon = Icon.arrowsLeftRight(), onClick, autosizeOptions = {}, ...props}) {
31
+ render({className, gridModel, icon, onClick, disabled, autosizeOptions = {}, ...props}) {
31
32
  gridModel = withDefault(gridModel, useContextModel(GridModel));
32
33
 
33
- if (!gridModel?.autosizeEnabled) {
34
- logError(
35
- "No GridModel available with autosize enabled. Provide via a 'gridModel' prop, or context.",
36
- ColAutosizeButton
37
- );
38
- return button({icon, disabled: true, ...props});
34
+ // Validate bound model available and suitable for use.
35
+ if (!onClick) {
36
+ if (!gridModel) {
37
+ logError(
38
+ 'No GridModel available - provide via a `gridModel` prop or context - button will be disabled.',
39
+ ColAutosizeButton
40
+ );
41
+ disabled = true;
42
+ } else if (!gridModel.autosizeEnabled) {
43
+ logError(
44
+ 'Autosize not enabled on bound GridModel - button will be disabled.',
45
+ ColAutosizeButton
46
+ );
47
+ disabled = true;
48
+ }
39
49
  }
40
50
 
41
51
  onClick =
@@ -46,6 +56,12 @@ export const [ColAutosizeButton, colAutosizeButton] = hoistCmp.withFactory<ColAu
46
56
  ...autosizeOptions
47
57
  }));
48
58
 
49
- return button({icon, onClick, ...props});
59
+ return button({
60
+ icon: withDefault(icon, Icon.arrowsLeftRight()),
61
+ disabled: withDefault(disabled, gridModel?.empty),
62
+ className,
63
+ onClick,
64
+ ...props
65
+ });
50
66
  }
51
67
  });
@@ -0,0 +1,58 @@
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 {Icon} from '@xh/hoist/icon';
10
+ import {button, ButtonProps} from '@xh/hoist/mobile/cmp/button';
11
+ import '@xh/hoist/mobile/register';
12
+ import {logError, withDefault} from '@xh/hoist/utils/js';
13
+
14
+ export interface ColChooserButtonProps extends ButtonProps {
15
+ /** GridModel to which this button should bind. Will find nearest in context if not provided. */
16
+ gridModel?: GridModel;
17
+ }
18
+
19
+ /**
20
+ * A convenience button to trigger the display of a ColChooser for user selection, discovery and
21
+ * reordering of available Grid columns.
22
+ *
23
+ * Requires {@link GridConfig.colChooserModel} to be configured on the bound GridModel.
24
+ */
25
+ export const [ColChooserButton, colChooserButton] = hoistCmp.withFactory<ColChooserButtonProps>({
26
+ displayName: 'ColChooserButton',
27
+ className: 'xh-col-chooser-button',
28
+ model: false,
29
+
30
+ render({className, gridModel, icon, onClick, disabled, ...props}) {
31
+ gridModel = withDefault(gridModel, useContextModel(GridModel));
32
+
33
+ if (!onClick) {
34
+ // Validate bound model available and suitable for use.
35
+ if (!gridModel) {
36
+ logError(
37
+ 'No GridModel available - provide via a `gridModel` prop or context - button will be disabled.',
38
+ ColChooserButton
39
+ );
40
+ disabled = true;
41
+ } else if (!gridModel.colChooserModel) {
42
+ logError(
43
+ 'ColChooser not enabled on bound GridModel - button will be disabled.',
44
+ ColChooserButton
45
+ );
46
+ disabled = true;
47
+ }
48
+ }
49
+
50
+ onClick = onClick ?? (() => gridModel.showColChooser());
51
+ return button({
52
+ icon: withDefault(icon, Icon.gridPanel()),
53
+ disabled,
54
+ onClick,
55
+ ...props
56
+ });
57
+ }
58
+ });
@@ -13,23 +13,29 @@ import {logError, withDefault} from '@xh/hoist/utils/js';
13
13
  import {isEmpty} from 'lodash';
14
14
 
15
15
  export interface ExpandCollapseButtonProps extends ButtonProps {
16
- /** GridModel of the grid for which this button should show a chooser. */
16
+ /**
17
+ * `GridModel` to which this button should bind.
18
+ * Optional, will find nearest GridModel in context if not provided.
19
+ */
17
20
  gridModel?: GridModel;
18
21
  }
19
22
 
20
23
  /**
21
- * A convenience button to expand / collapse all rows in grouped or tree grid.
24
+ * A convenience button to expand / collapse all rows in a grouped or tree Grid.
22
25
  */
23
26
  export const [ExpandCollapseButton, expandCollapseButton] =
24
27
  hoistCmp.withFactory<ExpandCollapseButtonProps>({
25
28
  displayName: 'ExpandCollapseButton',
29
+ className: 'xh-expand-collapse-button',
26
30
  model: false,
27
- render({gridModel, onClick, ...props}) {
31
+
32
+ render({className, gridModel, onClick, ...props}) {
28
33
  gridModel = withDefault(gridModel, useContextModel(GridModel));
29
34
 
30
- if (!gridModel) {
35
+ // Validate bound model available and suitable for use.
36
+ if (!onClick && !gridModel) {
31
37
  logError(
32
- "No GridModel available. Provide via a 'gridModel' prop, or context.",
38
+ 'No GridModel available - provide via `gridModel` prop or context - button will be disabled.',
33
39
  ExpandCollapseButton
34
40
  );
35
41
  return button({icon: Icon.expand(), disabled: true, ...props});
@@ -45,6 +51,6 @@ export const [ExpandCollapseButton, expandCollapseButton] =
45
51
  onClick ??
46
52
  (() => (shouldCollapse ? gridModel.collapseAll() : gridModel.expandAll()));
47
53
 
48
- return button({disabled, icon, onClick, ...props});
54
+ return button({className, disabled, icon, onClick, ...props});
49
55
  }
50
56
  });
@@ -0,0 +1,91 @@
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, MenuItemLike, useContextModel} from '@xh/hoist/core';
9
+ import {Icon} from '@xh/hoist/icon';
10
+ import '@xh/hoist/mobile/register';
11
+ import {executeIfFunction, logDebug, logError, withDefault} from '@xh/hoist/utils/js';
12
+ import {menuButton, MenuButtonProps} from '../../menu';
13
+
14
+ export interface ExpandToLevelButtonProps extends MenuButtonProps {
15
+ /**
16
+ * `GridModel` to which this button should bind.
17
+ * Optional, will find nearest GridModel in context if not provided.
18
+ */
19
+ gridModel?: GridModel;
20
+ }
21
+
22
+ /**
23
+ * A menu button to expand a multi-level grouped or tree grid out to a desired level.
24
+ * Requires {@link GridConfig.levelLabels} to be configured on the bound GridModel.
25
+ */
26
+ export const [ExpandToLevelButton, expandToLevelButton] =
27
+ hoistCmp.withFactory<ExpandToLevelButtonProps>({
28
+ displayName: 'ExpandToLevelButton',
29
+ className: 'xh-expand-to-level-button',
30
+ model: false,
31
+
32
+ render({gridModel, className, icon, ...rest}) {
33
+ gridModel = withDefault(gridModel, useContextModel(GridModel));
34
+ icon = withDefault(icon, Icon.treeList());
35
+
36
+ const disabledButton = () =>
37
+ menuButton({
38
+ icon,
39
+ className,
40
+ ...rest,
41
+ disabled: true,
42
+ menuItems: []
43
+ });
44
+
45
+ if (!gridModel) {
46
+ logError(
47
+ "No GridModel available. Provide via a 'gridModel' prop, or context.",
48
+ ExpandToLevelButton
49
+ );
50
+ return disabledButton();
51
+ }
52
+
53
+ // Disable for flat grids. Still show for grids with a single grouping level, although
54
+ // in this case we're effectively a less efficient way to expand/collapse all.
55
+ const {maxDepth, expandLevel} = gridModel;
56
+ if (!maxDepth) return disabledButton();
57
+
58
+ // Validate level labels - disable if unspecified or mismatched to grid depth.
59
+ const levelLabels = executeIfFunction(gridModel.levelLabels);
60
+ if (!levelLabels) {
61
+ return disabledButton();
62
+ }
63
+ if (levelLabels.length < maxDepth + 1) {
64
+ logDebug(
65
+ 'Value produced by `GridModel.levelLabels` has insufficient length. No menu items shown.',
66
+ ExpandToLevelButton
67
+ );
68
+ return disabledButton();
69
+ }
70
+
71
+ const menuItems: MenuItemLike[] = levelLabels.map((label, idx) => {
72
+ const isCurrLevel =
73
+ expandLevel === idx ||
74
+ (expandLevel > maxDepth && idx === levelLabels.length - 1);
75
+
76
+ return {
77
+ icon: isCurrLevel ? Icon.check() : Icon.placeholder(),
78
+ text: label,
79
+ actionFn: () => gridModel.expandToLevel(idx)
80
+ };
81
+ });
82
+
83
+ return menuButton({
84
+ title: 'Expand To',
85
+ icon,
86
+ className,
87
+ menuItems,
88
+ ...rest
89
+ });
90
+ }
91
+ });
@@ -6,13 +6,14 @@
6
6
  */
7
7
  export * from './Button';
8
8
  export * from './ButtonGroup';
9
- export * from './ColAutosizeButton';
10
- export * from './ColChooserButton';
11
- export * from './ExpandCollapseButton';
9
+ export * from './grid/ColAutosizeButton';
10
+ export * from './grid/ColChooserButton';
11
+ export * from './grid/ExpandCollapseButton';
12
+ export * from './grid/ExpandToLevelButton';
12
13
  export * from './FeedbackButton';
13
14
  export * from './ThemeToggleButton';
14
15
  export * from './LogoutButton';
15
16
  export * from './RefreshButton';
16
17
  export * from './RestoreDefaultsButton';
17
18
  export * from './NavigatorBackButton';
18
- export * from './ZoneMapperButton';
19
+ export * from './zoneGrid/ZoneMapperButton';
@@ -0,0 +1,58 @@
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 {hoistCmp, useContextModel} from '@xh/hoist/core';
8
+ import {Icon} from '@xh/hoist/icon';
9
+ import {button, ButtonProps} from '@xh/hoist/mobile/cmp/button';
10
+ import {logError, withDefault} from '@xh/hoist/utils/js';
11
+ import {ZoneGridModel} from '@xh/hoist/cmp/zoneGrid';
12
+ import '@xh/hoist/mobile/register';
13
+
14
+ export interface ZoneMapperButtonProps extends ButtonProps {
15
+ /** ZoneGridModel of the grid for which this button should show a chooser. */
16
+ zoneGridModel?: ZoneGridModel;
17
+ }
18
+
19
+ /**
20
+ * A convenience button to trigger the display of a ZoneMapper UI for ZoneGrid configuration.
21
+ * Requires {@link ZoneGridConfig.zoneMapperModel} to be configured on the bound ZoneGridModel.
22
+ */
23
+ export const [ZoneMapperButton, zoneMapperButton] = hoistCmp.withFactory<ZoneMapperButtonProps>({
24
+ displayName: 'ZoneMapperButton',
25
+ className: 'xh-zone-mapper-button',
26
+ model: false,
27
+
28
+ render({className, icon, zoneGridModel, onClick, disabled, ...rest}) {
29
+ zoneGridModel = withDefault(zoneGridModel, useContextModel(ZoneGridModel));
30
+
31
+ // Validate bound model available and suitable for use.
32
+ if (!onClick) {
33
+ if (!zoneGridModel) {
34
+ logError(
35
+ 'No ZoneGridModel available - provide via `zoneGridModel` prop or context - button will be disabled',
36
+ ZoneMapperButton
37
+ );
38
+ disabled = true;
39
+ } else if (!zoneGridModel.mapperModel) {
40
+ logError(
41
+ 'ZoneMapper not enabled on bound ZoneGridModel - button will be disabled.',
42
+ ZoneMapperButton
43
+ );
44
+ disabled = true;
45
+ }
46
+ }
47
+
48
+ onClick = onClick ?? (() => zoneGridModel.showMapper());
49
+
50
+ return button({
51
+ icon: withDefault(icon, Icon.gridLarge()),
52
+ className,
53
+ disabled,
54
+ onClick,
55
+ ...rest
56
+ });
57
+ }
58
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "75.0.0-SNAPSHOT.1753198948130",
3
+ "version": "75.0.0-SNAPSHOT.1753280710081",
4
4
  "description": "Hoist add-on for building and deploying React Applications.",
5
5
  "repository": "github:xh/hoist-react",
6
6
  "homepage": "https://xh.io",