@xh/hoist 75.0.0-SNAPSHOT.1753116344421 → 75.0.0-SNAPSHOT.1753279912670
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/admin/tabs/clients/activity/ClientDetailPanel.ts +3 -2
- package/admin/tabs/general/alertBanner/AlertBannerPanel.ts +2 -5
- package/build/types/cmp/grid/GridModel.d.ts +2 -1
- package/build/types/cmp/relativetimestamp/RelativeTimestamp.d.ts +6 -2
- package/build/types/desktop/cmp/button/{ColAutosizeButton.d.ts → grid/ColAutosizeButton.d.ts} +3 -3
- package/build/types/desktop/cmp/button/{ColChooserButton.d.ts → grid/ColChooserButton.d.ts} +3 -3
- package/build/types/desktop/cmp/button/grid/ExpandToLevelButton.d.ts +18 -0
- package/build/types/desktop/cmp/button/{ExportButton.d.ts → grid/ExportButton.d.ts} +7 -7
- package/build/types/desktop/cmp/button/index.d.ts +7 -6
- package/build/types/desktop/cmp/button/{ZoneMapperButton.d.ts → zoneGrid/ZoneMapperButton.d.ts} +3 -4
- package/build/types/mobile/cmp/button/{ColAutosizeButton.d.ts → grid/ColAutosizeButton.d.ts} +2 -2
- package/build/types/mobile/cmp/button/{ColChooserButton.d.ts → grid/ColChooserButton.d.ts} +4 -4
- package/build/types/mobile/cmp/button/{ExpandCollapseButton.d.ts → grid/ExpandCollapseButton.d.ts} +5 -2
- package/build/types/mobile/cmp/button/grid/ExpandToLevelButton.d.ts +15 -0
- package/build/types/mobile/cmp/button/index.d.ts +5 -4
- package/build/types/mobile/cmp/button/{ZoneMapperButton.d.ts → zoneGrid/ZoneMapperButton.d.ts} +2 -3
- package/cmp/grid/GridModel.ts +2 -1
- package/cmp/relativetimestamp/RelativeTimestamp.ts +21 -8
- package/desktop/cmp/button/{ColAutosizeButton.ts → grid/ColAutosizeButton.ts} +25 -15
- package/desktop/cmp/button/{ColChooserButton.ts → grid/ColChooserButton.ts} +10 -10
- package/desktop/cmp/button/grid/ExpandToLevelButton.ts +96 -0
- package/desktop/cmp/button/grid/ExportButton.ts +75 -0
- package/desktop/cmp/button/index.ts +7 -6
- package/desktop/cmp/button/{ModalToggleButton.ts → panel/ModalToggleButton.ts} +12 -6
- package/desktop/cmp/button/{ZoneMapperButton.ts → zoneGrid/ZoneMapperButton.ts} +11 -11
- package/mobile/cmp/button/{ColAutosizeButton.ts → grid/ColAutosizeButton.ts} +26 -10
- package/mobile/cmp/button/grid/ColChooserButton.ts +58 -0
- package/mobile/cmp/button/{ExpandCollapseButton.ts → grid/ExpandCollapseButton.ts} +12 -6
- package/mobile/cmp/button/grid/ExpandToLevelButton.ts +91 -0
- package/mobile/cmp/button/index.ts +5 -4
- package/mobile/cmp/button/zoneGrid/ZoneMapperButton.ts +58 -0
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/desktop/cmp/button/ExportButton.ts +0 -65
- package/mobile/cmp/button/ColChooserButton.ts +0 -44
- package/mobile/cmp/button/ZoneMapperButton.ts +0 -42
- /package/build/types/desktop/cmp/button/{ModalToggleButton.d.ts → panel/ModalToggleButton.d.ts} +0 -0
|
@@ -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 './
|
|
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';
|
|
@@ -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 {
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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 '
|
|
16
|
+
import {button, ButtonProps} from '../Button';
|
|
17
17
|
|
|
18
18
|
export interface ZoneMapperButtonProps extends ButtonProps {
|
|
19
|
-
/** ZoneGridModel
|
|
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
|
-
|
|
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
|
-
'
|
|
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
|
|
16
|
+
/** GridModel to which this button should bind. Will find nearest in context if not provided. */
|
|
17
17
|
gridModel?: GridModel;
|
|
18
18
|
|
|
19
|
-
/** Options
|
|
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
|
|
31
|
+
render({className, gridModel, icon, onClick, disabled, autosizeOptions = {}, ...props}) {
|
|
31
32
|
gridModel = withDefault(gridModel, useContextModel(GridModel));
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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({
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
31
|
+
|
|
32
|
+
render({className, gridModel, onClick, ...props}) {
|
|
28
33
|
gridModel = withDefault(gridModel, useContextModel(GridModel));
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
// Validate bound model available and suitable for use.
|
|
36
|
+
if (!onClick && !gridModel) {
|
|
31
37
|
logError(
|
|
32
|
-
|
|
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.
|
|
3
|
+
"version": "75.0.0-SNAPSHOT.1753279912670",
|
|
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",
|