@xh/hoist 71.0.0-SNAPSHOT.1735061018823 → 71.0.0-SNAPSHOT.1735061320692
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 +12 -0
- package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +1 -1
- package/admin/tabs/cluster/ClusterTab.ts +1 -1
- package/admin/tabs/cluster/connpool/ConnPoolMonitorPanel.ts +1 -1
- package/admin/tabs/cluster/environment/ServerEnvPanel.ts +1 -1
- package/admin/tabs/cluster/logs/LogDisplay.ts +1 -1
- package/admin/tabs/cluster/logs/LogViewer.ts +1 -1
- package/admin/tabs/cluster/memory/MemoryMonitorPanel.ts +1 -1
- package/admin/tabs/cluster/services/DetailsPanel.ts +1 -1
- package/admin/tabs/cluster/websocket/WebSocketPanel.ts +1 -1
- package/admin/tabs/monitor/MonitorTab.ts +1 -1
- package/admin/tabs/userData/roles/RolePanel.ts +1 -1
- package/build/types/{desktop/cmp → cmp}/error/ErrorMessage.d.ts +4 -4
- package/build/types/cmp/error/index.d.ts +1 -0
- package/build/types/{desktop/cmp → cmp}/loadingindicator/LoadingIndicator.d.ts +0 -1
- package/build/types/{desktop/cmp → cmp}/mask/Mask.d.ts +1 -3
- package/build/types/{desktop/cmp → cmp}/treemap/SplitTreeMap.d.ts +0 -1
- package/build/types/{desktop/cmp → cmp}/treemap/SplitTreeMapModel.d.ts +0 -1
- package/build/types/{desktop/cmp → cmp}/treemap/TreeMap.d.ts +0 -1
- package/build/types/{desktop/cmp → cmp}/treemap/TreeMapModel.d.ts +0 -1
- package/build/types/desktop/cmp/error/impl/ErrorMessage.d.ts +7 -0
- package/build/types/desktop/cmp/mask/impl/Mask.d.ts +8 -0
- package/build/types/dynamics/desktop.d.ts +2 -1
- package/build/types/dynamics/mobile.d.ts +2 -1
- package/build/types/mobile/cmp/error/impl/ErrorMessage.d.ts +7 -0
- package/build/types/mobile/cmp/mask/impl/Mask.d.ts +8 -0
- package/cmp/error/ErrorBoundary.ts +2 -4
- package/{desktop/cmp → cmp}/error/ErrorMessage.scss +8 -1
- package/{desktop/cmp → cmp}/error/ErrorMessage.ts +24 -50
- package/cmp/error/index.ts +1 -0
- package/{desktop/cmp → cmp}/loadingindicator/LoadingIndicator.scss +4 -1
- package/{desktop/cmp → cmp}/loadingindicator/LoadingIndicator.ts +5 -9
- package/{desktop/cmp → cmp}/mask/Mask.ts +16 -25
- package/{desktop/cmp → cmp}/treemap/SplitTreeMap.scss +16 -0
- package/{desktop/cmp → cmp}/treemap/SplitTreeMap.ts +14 -6
- package/{desktop/cmp → cmp}/treemap/SplitTreeMapModel.ts +0 -1
- package/{desktop/cmp → cmp}/treemap/TreeMap.ts +2 -3
- package/{desktop/cmp → cmp}/treemap/TreeMapModel.ts +0 -1
- package/desktop/appcontainer/AppContainer.ts +5 -3
- package/desktop/cmp/dash/container/DashContainer.ts +1 -1
- package/desktop/cmp/error/impl/ErrorMessage.ts +65 -0
- package/desktop/cmp/mask/impl/Mask.ts +40 -0
- package/desktop/cmp/panel/Panel.ts +2 -2
- package/desktop/cmp/rest/RestGrid.ts +1 -1
- package/dynamics/desktop.ts +4 -2
- package/dynamics/mobile.ts +4 -2
- package/mobile/appcontainer/AppContainer.ts +5 -3
- package/mobile/appcontainer/OptionsDialog.ts +1 -1
- package/mobile/cmp/error/impl/ErrorMessage.ts +65 -0
- package/mobile/cmp/mask/impl/Mask.ts +34 -0
- package/mobile/cmp/panel/Panel.ts +2 -2
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/build/types/desktop/cmp/error/index.d.ts +0 -1
- package/build/types/desktop/cmp/treemap/impl/Splitter.d.ts +0 -6
- package/build/types/mobile/cmp/error/ErrorMessage.d.ts +0 -42
- package/build/types/mobile/cmp/error/index.d.ts +0 -1
- package/build/types/mobile/cmp/loadingindicator/LoadingIndicator.d.ts +0 -27
- package/build/types/mobile/cmp/loadingindicator/index.d.ts +0 -1
- package/build/types/mobile/cmp/mask/Mask.d.ts +0 -25
- package/build/types/mobile/cmp/mask/index.d.ts +0 -1
- package/desktop/cmp/error/index.ts +0 -1
- package/desktop/cmp/treemap/impl/Splitter.scss +0 -15
- package/desktop/cmp/treemap/impl/Splitter.ts +0 -28
- package/mobile/cmp/error/ErrorMessage.scss +0 -25
- package/mobile/cmp/error/ErrorMessage.ts +0 -140
- package/mobile/cmp/error/index.ts +0 -8
- package/mobile/cmp/loadingindicator/LoadingIndicator.scss +0 -81
- package/mobile/cmp/loadingindicator/LoadingIndicator.ts +0 -90
- package/mobile/cmp/loadingindicator/index.ts +0 -7
- package/mobile/cmp/mask/Mask.ts +0 -75
- package/mobile/cmp/mask/index.ts +0 -7
- /package/build/types/{desktop/cmp → cmp}/loadingindicator/index.d.ts +0 -0
- /package/build/types/{desktop/cmp → cmp}/mask/index.d.ts +0 -0
- /package/build/types/{desktop/cmp → cmp}/treemap/index.d.ts +0 -0
- /package/{desktop/cmp → cmp}/loadingindicator/index.ts +0 -0
- /package/{desktop/cmp → cmp}/mask/index.ts +0 -0
- /package/{desktop/cmp → cmp}/treemap/TreeMap.scss +0 -0
- /package/{desktop/cmp → cmp}/treemap/index.ts +0 -0
- /package/desktop/cmp/mask/{Mask.scss → impl/Mask.scss} +0 -0
- /package/mobile/cmp/mask/{Mask.scss → impl/Mask.scss} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ErrorMessage';
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { HoistProps } from '@xh/hoist/core';
|
|
2
|
-
import { ButtonProps } from '@xh/hoist/mobile/cmp/button';
|
|
3
|
-
import '@xh/hoist/mobile/register';
|
|
4
|
-
import { ReactNode, MouseEvent } from 'react';
|
|
5
|
-
import './ErrorMessage.scss';
|
|
6
|
-
export interface ErrorMessageProps extends HoistProps {
|
|
7
|
-
/**
|
|
8
|
-
* If provided, will render a "Retry" button that calls this function.
|
|
9
|
-
* Use `actionButtonProps` for further control over this button.
|
|
10
|
-
*/
|
|
11
|
-
actionFn?: (e: MouseEvent) => void;
|
|
12
|
-
/**
|
|
13
|
-
* If provided, component will render an inline action button - prompting to user to take some
|
|
14
|
-
* action that might resolve the error, such as retrying a failed data load.
|
|
15
|
-
*/
|
|
16
|
-
actionButtonProps?: ButtonProps;
|
|
17
|
-
/**
|
|
18
|
-
* If provided, will render a "Details" button that calls this function.
|
|
19
|
-
* Use `detailsButtonProps` for further control over this button. Default false.
|
|
20
|
-
*/
|
|
21
|
-
detailsFn?: (error: unknown) => void;
|
|
22
|
-
/**
|
|
23
|
-
* If provided, component will render an inline details button.
|
|
24
|
-
*/
|
|
25
|
-
detailsButtonProps?: ButtonProps;
|
|
26
|
-
/**
|
|
27
|
-
* Error to display. If undefined, this component will look for an error property on its model.
|
|
28
|
-
* If no error is found, this component will not be displayed.
|
|
29
|
-
*/
|
|
30
|
-
error?: unknown;
|
|
31
|
-
/**
|
|
32
|
-
* Message to display for the error.
|
|
33
|
-
* Defaults to the error, or any 'message' property contained within it.
|
|
34
|
-
*/
|
|
35
|
-
message?: ReactNode;
|
|
36
|
-
/** Optional title to display above the message. */
|
|
37
|
-
title?: ReactNode;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Component for displaying an error with standardized styling.
|
|
41
|
-
*/
|
|
42
|
-
export declare const ErrorMessage: import("react").FC<ErrorMessageProps>, errorMessage: import("@xh/hoist/core").ElementFactory<ErrorMessageProps>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ErrorMessage';
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
import { HoistProps, Some, TaskObserver } from '@xh/hoist/core';
|
|
3
|
-
import '@xh/hoist/mobile/register';
|
|
4
|
-
import './LoadingIndicator.scss';
|
|
5
|
-
export interface LoadingIndicatorProps extends HoistProps {
|
|
6
|
-
/** TaskObserver(s) that should be monitored to determine if the Indicator should be displayed. */
|
|
7
|
-
bind?: Some<TaskObserver>;
|
|
8
|
-
/** Position of the indicator relative to its containing component. */
|
|
9
|
-
corner?: 'tl' | 'tr' | 'bl' | 'br';
|
|
10
|
-
/** True to display the indicator. */
|
|
11
|
-
isDisplayed?: boolean;
|
|
12
|
-
/** Max characters allowed in message, after which it will be elided. Default 30. */
|
|
13
|
-
maxMessageLength?: number;
|
|
14
|
-
/** Optional text to be displayed - can also be sourced from bound TaskObserver. */
|
|
15
|
-
message?: string;
|
|
16
|
-
/** True (default) to display with an animated spinner. */
|
|
17
|
-
spinner?: boolean;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* A minimal / unobtrusive LoadingIndicator displaying an optional spinner and/or message to signal
|
|
21
|
-
* that a longer-running operation is in progress, without using a modal Mask. Can be explicitly
|
|
22
|
-
* shown or bound to one or more tasks.
|
|
23
|
-
*
|
|
24
|
-
* Note that the Panel component's `loadingIndicator` prop provides a common and convenient way to
|
|
25
|
-
* add an indicator to a Panel without needing to manually create or manage this component.
|
|
26
|
-
*/
|
|
27
|
-
export declare const LoadingIndicator: import("react").FC<LoadingIndicatorProps>, loadingIndicator: import("@xh/hoist/core").ElementFactory<LoadingIndicatorProps>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './LoadingIndicator';
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { HoistProps, Some, TaskObserver } from '@xh/hoist/core';
|
|
2
|
-
import '@xh/hoist/mobile/register';
|
|
3
|
-
import { ReactNode, MouseEvent } from 'react';
|
|
4
|
-
import './Mask.scss';
|
|
5
|
-
export interface MaskProps extends HoistProps {
|
|
6
|
-
/** Task(s) that should be monitored to determine if the mask should be displayed. */
|
|
7
|
-
bind?: Some<TaskObserver>;
|
|
8
|
-
/** True to display the mask. */
|
|
9
|
-
isDisplayed?: boolean;
|
|
10
|
-
/** Text to be displayed under the loading spinner image */
|
|
11
|
-
message?: ReactNode;
|
|
12
|
-
/** Callback when mask is tapped, relayed to underlying div element. */
|
|
13
|
-
onClick?: (e: MouseEvent) => void;
|
|
14
|
-
/** True (default) to display a spinning image. */
|
|
15
|
-
spinner?: boolean;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Mask with optional spinner and text.
|
|
19
|
-
*
|
|
20
|
-
* The mask can be explicitly controlled via props or bound to a TaskObserver.
|
|
21
|
-
*
|
|
22
|
-
* Note that the Panel component's `mask` prop provides a common and convenient method for masking
|
|
23
|
-
* sections of the UI without needing to manually create or manage this component.
|
|
24
|
-
*/
|
|
25
|
-
export declare const Mask: import("react").FC<MaskProps>, mask: import("@xh/hoist/core").ElementFactory<MaskProps>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './Mask';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './ErrorMessage';
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
.xh-treemap-splitter {
|
|
2
|
-
background-color: var(--xh-resizable-bg);
|
|
3
|
-
|
|
4
|
-
&.vertical {
|
|
5
|
-
height: 4px;
|
|
6
|
-
border-top: var(--xh-resizable-border-width-px) solid var(--xh-resizable-border-color);
|
|
7
|
-
border-bottom: var(--xh-resizable-border-width-px) solid var(--xh-resizable-border-color);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
&.horizontal {
|
|
11
|
-
width: 4px;
|
|
12
|
-
border-left: var(--xh-resizable-border-width-px) solid var(--xh-resizable-border-color);
|
|
13
|
-
border-right: var(--xh-resizable-border-width-px) solid var(--xh-resizable-border-color);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
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 © 2024 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
import {hbox, vbox} from '@xh/hoist/cmp/layout';
|
|
8
|
-
import {hoistCmp, uses} from '@xh/hoist/core';
|
|
9
|
-
|
|
10
|
-
import {SplitTreeMapModel} from '../SplitTreeMapModel';
|
|
11
|
-
import './Splitter.scss';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
16
|
-
export const splitter = hoistCmp.factory({
|
|
17
|
-
displayName: 'TreeMap Splitter',
|
|
18
|
-
model: uses(SplitTreeMapModel),
|
|
19
|
-
|
|
20
|
-
render({model}) {
|
|
21
|
-
const {orientation} = model,
|
|
22
|
-
vertical = orientation === 'vertical',
|
|
23
|
-
cmp = vertical ? hbox : vbox,
|
|
24
|
-
cfg = {className: `xh-treemap-splitter ${vertical ? 'vertical' : 'horizontal'}`};
|
|
25
|
-
|
|
26
|
-
return cmp(cfg);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
.xh-error-message {
|
|
2
|
-
align-items: center;
|
|
3
|
-
justify-content: center;
|
|
4
|
-
|
|
5
|
-
&__inner {
|
|
6
|
-
margin: 0 var(--xh-pad-px);
|
|
7
|
-
padding: var(--xh-pad-px);
|
|
8
|
-
background: var(--xh-intent-danger-trans1);
|
|
9
|
-
border: 1px solid var(--xh-intent-danger);
|
|
10
|
-
text-align: center;
|
|
11
|
-
word-break: break-word;
|
|
12
|
-
|
|
13
|
-
& > * {
|
|
14
|
-
margin: 0 0 var(--xh-pad-px);
|
|
15
|
-
|
|
16
|
-
&:last-child {
|
|
17
|
-
margin-bottom: 0;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
&__title {
|
|
23
|
-
font-weight: bold;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
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 © 2024 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
import {div, filler, frame, hbox, p} from '@xh/hoist/cmp/layout';
|
|
8
|
-
import {hoistCmp, HoistProps} from '@xh/hoist/core';
|
|
9
|
-
import {button, ButtonProps} from '@xh/hoist/mobile/cmp/button';
|
|
10
|
-
import '@xh/hoist/mobile/register';
|
|
11
|
-
import {isNil, isString} from 'lodash';
|
|
12
|
-
import {isValidElement, ReactNode, MouseEvent} from 'react';
|
|
13
|
-
|
|
14
|
-
import './ErrorMessage.scss';
|
|
15
|
-
import {Icon} from '@xh/hoist/icon';
|
|
16
|
-
|
|
17
|
-
export interface ErrorMessageProps extends HoistProps {
|
|
18
|
-
/**
|
|
19
|
-
* If provided, will render a "Retry" button that calls this function.
|
|
20
|
-
* Use `actionButtonProps` for further control over this button.
|
|
21
|
-
*/
|
|
22
|
-
actionFn?: (e: MouseEvent) => void;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* If provided, component will render an inline action button - prompting to user to take some
|
|
26
|
-
* action that might resolve the error, such as retrying a failed data load.
|
|
27
|
-
*/
|
|
28
|
-
actionButtonProps?: ButtonProps;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* If provided, will render a "Details" button that calls this function.
|
|
32
|
-
* Use `detailsButtonProps` for further control over this button. Default false.
|
|
33
|
-
*/
|
|
34
|
-
detailsFn?: (error: unknown) => void;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* If provided, component will render an inline details button.
|
|
38
|
-
*/
|
|
39
|
-
detailsButtonProps?: ButtonProps;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Error to display. If undefined, this component will look for an error property on its model.
|
|
43
|
-
* If no error is found, this component will not be displayed.
|
|
44
|
-
*/
|
|
45
|
-
error?: unknown;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Message to display for the error.
|
|
49
|
-
* Defaults to the error, or any 'message' property contained within it.
|
|
50
|
-
*/
|
|
51
|
-
message?: ReactNode;
|
|
52
|
-
|
|
53
|
-
/** Optional title to display above the message. */
|
|
54
|
-
title?: ReactNode;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Component for displaying an error with standardized styling.
|
|
59
|
-
*/
|
|
60
|
-
export const [ErrorMessage, errorMessage] = hoistCmp.withFactory<ErrorMessageProps>({
|
|
61
|
-
className: 'xh-error-message',
|
|
62
|
-
render(props, ref) {
|
|
63
|
-
let {
|
|
64
|
-
className,
|
|
65
|
-
model,
|
|
66
|
-
error = model?.['error'],
|
|
67
|
-
message,
|
|
68
|
-
title,
|
|
69
|
-
actionFn,
|
|
70
|
-
actionButtonProps,
|
|
71
|
-
detailsFn,
|
|
72
|
-
detailsButtonProps
|
|
73
|
-
} = props;
|
|
74
|
-
|
|
75
|
-
if (isNil(error)) return null;
|
|
76
|
-
|
|
77
|
-
if (!message) {
|
|
78
|
-
if (isString(error)) {
|
|
79
|
-
message = error;
|
|
80
|
-
} else {
|
|
81
|
-
message = error.message || error.name || 'Unknown Error';
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (actionFn) {
|
|
86
|
-
actionButtonProps = {...actionButtonProps, onClick: () => actionFn(error)};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (detailsFn) {
|
|
90
|
-
detailsButtonProps = {...detailsButtonProps, onClick: () => detailsFn(error)};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let buttons = [],
|
|
94
|
-
buttonBar = null;
|
|
95
|
-
if (detailsButtonProps) buttons.push(detailsButton(detailsButtonProps));
|
|
96
|
-
if (actionButtonProps) buttons.push(actionButton(actionButtonProps));
|
|
97
|
-
if (buttons.length == 1) {
|
|
98
|
-
buttonBar = buttons[0];
|
|
99
|
-
} else if (buttons.length == 2) {
|
|
100
|
-
buttonBar = hbox(buttons[0], filler(), buttons[1]);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return frame({
|
|
104
|
-
ref,
|
|
105
|
-
className,
|
|
106
|
-
item: div({
|
|
107
|
-
className: 'xh-error-message__inner',
|
|
108
|
-
items: [titleCmp({title}), messageCmp({message, error}), buttonBar]
|
|
109
|
-
})
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const titleCmp = hoistCmp.factory(({title}) => {
|
|
115
|
-
if (isValidElement(title)) return title;
|
|
116
|
-
if (isString(title)) return div({className: 'xh-error-message__title', item: title});
|
|
117
|
-
return null;
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const messageCmp = hoistCmp.factory(({message}) => {
|
|
121
|
-
if (isValidElement(message)) return message;
|
|
122
|
-
if (isString(message)) return p(message);
|
|
123
|
-
return null;
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const actionButton = hoistCmp.factory<ButtonProps>(props => {
|
|
127
|
-
return button({
|
|
128
|
-
text: 'Retry',
|
|
129
|
-
icon: Icon.refresh(),
|
|
130
|
-
...props
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const detailsButton = hoistCmp.factory<ButtonProps>(props => {
|
|
135
|
-
return button({
|
|
136
|
-
text: 'Show Details',
|
|
137
|
-
icon: Icon.detail(),
|
|
138
|
-
...props
|
|
139
|
-
});
|
|
140
|
-
});
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
.xh-loading-indicator {
|
|
2
|
-
--border-width: 1px;
|
|
3
|
-
--height: 20px; // should match spinner height
|
|
4
|
-
|
|
5
|
-
position: absolute;
|
|
6
|
-
padding: var(--xh-pad-half-px);
|
|
7
|
-
background-color: var(--xh-loading-indicator-bg);
|
|
8
|
-
color: var(--xh-loading-indicator-color);
|
|
9
|
-
border-color: var(--xh-loading-indicator-border-color);
|
|
10
|
-
border-style: solid;
|
|
11
|
-
border-width: 0;
|
|
12
|
-
|
|
13
|
-
&--tl {
|
|
14
|
-
top: 0;
|
|
15
|
-
left: 0;
|
|
16
|
-
border-bottom-width: var(--border-width);
|
|
17
|
-
border-right-width: var(--border-width);
|
|
18
|
-
border-radius: 0 0 4px 0;
|
|
19
|
-
|
|
20
|
-
&.xh-loading-indicator--has-spinner {
|
|
21
|
-
.xh-loading-indicator__message {
|
|
22
|
-
margin-left: var(--xh-pad-px);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
&--tr {
|
|
28
|
-
top: 0;
|
|
29
|
-
right: 0;
|
|
30
|
-
border-bottom-width: var(--border-width);
|
|
31
|
-
border-left-width: var(--border-width);
|
|
32
|
-
border-radius: 0 0 0 4px;
|
|
33
|
-
|
|
34
|
-
&.xh-loading-indicator--has-spinner {
|
|
35
|
-
.xh-loading-indicator__message {
|
|
36
|
-
margin-right: var(--xh-pad-px);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
&--bl {
|
|
42
|
-
bottom: 0;
|
|
43
|
-
left: 0;
|
|
44
|
-
border-top-width: var(--border-width);
|
|
45
|
-
border-right-width: var(--border-width);
|
|
46
|
-
border-radius: 0 4px 0 0;
|
|
47
|
-
|
|
48
|
-
&.xh-loading-indicator--has-spinner {
|
|
49
|
-
.xh-loading-indicator__message {
|
|
50
|
-
margin-left: var(--xh-pad-px);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
&--br {
|
|
56
|
-
bottom: 0;
|
|
57
|
-
right: 0;
|
|
58
|
-
border-top-width: var(--border-width);
|
|
59
|
-
border-left-width: var(--border-width);
|
|
60
|
-
border-radius: 4px 0 0 0;
|
|
61
|
-
|
|
62
|
-
&.xh-loading-indicator--has-spinner {
|
|
63
|
-
.xh-loading-indicator__message {
|
|
64
|
-
margin-right: var(--xh-pad-px);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.xh-hbox {
|
|
70
|
-
flex: none;
|
|
71
|
-
align-items: start;
|
|
72
|
-
flex-wrap: nowrap;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
&__message {
|
|
76
|
-
height: var(--height);
|
|
77
|
-
line-height: var(--height);
|
|
78
|
-
align-items: center;
|
|
79
|
-
white-space: nowrap;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
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 © 2024 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
import {hbox} from '@xh/hoist/cmp/layout';
|
|
8
|
-
import {div} from '@xh/hoist/cmp/layout/Tags';
|
|
9
|
-
import {spinner as spinnerCmp} from '@xh/hoist/cmp/spinner';
|
|
10
|
-
import {hoistCmp, HoistModel, HoistProps, Some, TaskObserver, useLocalModel} from '@xh/hoist/core';
|
|
11
|
-
import '@xh/hoist/mobile/register';
|
|
12
|
-
import {withDefault} from '@xh/hoist/utils/js';
|
|
13
|
-
import classNames from 'classnames';
|
|
14
|
-
import {truncate} from 'lodash';
|
|
15
|
-
import './LoadingIndicator.scss';
|
|
16
|
-
|
|
17
|
-
export interface LoadingIndicatorProps extends HoistProps {
|
|
18
|
-
/** TaskObserver(s) that should be monitored to determine if the Indicator should be displayed. */
|
|
19
|
-
bind?: Some<TaskObserver>;
|
|
20
|
-
/** Position of the indicator relative to its containing component. */
|
|
21
|
-
corner?: 'tl' | 'tr' | 'bl' | 'br';
|
|
22
|
-
/** True to display the indicator. */
|
|
23
|
-
isDisplayed?: boolean;
|
|
24
|
-
/** Max characters allowed in message, after which it will be elided. Default 30. */
|
|
25
|
-
maxMessageLength?: number;
|
|
26
|
-
/** Optional text to be displayed - can also be sourced from bound TaskObserver. */
|
|
27
|
-
message?: string;
|
|
28
|
-
/** True (default) to display with an animated spinner. */
|
|
29
|
-
spinner?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* A minimal / unobtrusive LoadingIndicator displaying an optional spinner and/or message to signal
|
|
34
|
-
* that a longer-running operation is in progress, without using a modal Mask. Can be explicitly
|
|
35
|
-
* shown or bound to one or more tasks.
|
|
36
|
-
*
|
|
37
|
-
* Note that the Panel component's `loadingIndicator` prop provides a common and convenient way to
|
|
38
|
-
* add an indicator to a Panel without needing to manually create or manage this component.
|
|
39
|
-
*/
|
|
40
|
-
export const [LoadingIndicator, loadingIndicator] = hoistCmp.withFactory<LoadingIndicatorProps>({
|
|
41
|
-
displayName: 'LoadingIndicator',
|
|
42
|
-
className: 'xh-loading-indicator',
|
|
43
|
-
|
|
44
|
-
render(
|
|
45
|
-
{isDisplayed, message, spinner = true, corner = 'br', maxMessageLength = 30, className},
|
|
46
|
-
ref
|
|
47
|
-
) {
|
|
48
|
-
const impl = useLocalModel(LocalMaskModel);
|
|
49
|
-
|
|
50
|
-
isDisplayed = withDefault(isDisplayed, impl.task?.isPending);
|
|
51
|
-
message = withDefault(message, impl.task?.message);
|
|
52
|
-
message = truncate(message, {length: maxMessageLength});
|
|
53
|
-
|
|
54
|
-
if (!isDisplayed || (!spinner && !message)) return null;
|
|
55
|
-
|
|
56
|
-
const innerItems = () => {
|
|
57
|
-
const spinnerEl = spinnerCmp({compact: true});
|
|
58
|
-
if (!message) return [spinnerEl];
|
|
59
|
-
const msgBox = div({className: `xh-loading-indicator__message`, item: message});
|
|
60
|
-
|
|
61
|
-
return corner === 'tl' || corner === 'bl'
|
|
62
|
-
? [spinner ? spinnerEl : null, msgBox]
|
|
63
|
-
: [msgBox, spinner ? spinnerEl : null];
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const hasMessageCls = message ? 'xh-loading-indicator--has-message' : null,
|
|
67
|
-
hasSpinnerCls = spinner ? 'xh-loading-indicator--has-spinner' : null,
|
|
68
|
-
cornerCls = `xh-loading-indicator--${corner}`;
|
|
69
|
-
|
|
70
|
-
return div({
|
|
71
|
-
ref,
|
|
72
|
-
className: classNames(className, hasMessageCls, hasSpinnerCls, cornerCls),
|
|
73
|
-
item: hbox(innerItems())
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
class LocalMaskModel extends HoistModel {
|
|
79
|
-
task;
|
|
80
|
-
|
|
81
|
-
override onLinked() {
|
|
82
|
-
const {bind} = this.componentProps;
|
|
83
|
-
if (bind) {
|
|
84
|
-
this.task =
|
|
85
|
-
bind instanceof TaskObserver
|
|
86
|
-
? bind
|
|
87
|
-
: this.markManaged(TaskObserver.trackAll({tasks: bind}));
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
package/mobile/cmp/mask/Mask.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
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 © 2024 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
import {box, div, vbox, vspacer} from '@xh/hoist/cmp/layout';
|
|
8
|
-
import {spinner as spinnerCmp} from '@xh/hoist/cmp/spinner';
|
|
9
|
-
import {hoistCmp, HoistModel, HoistProps, Some, TaskObserver, useLocalModel} from '@xh/hoist/core';
|
|
10
|
-
import '@xh/hoist/mobile/register';
|
|
11
|
-
import {withDefault} from '@xh/hoist/utils/js';
|
|
12
|
-
import {ReactNode, MouseEvent} from 'react';
|
|
13
|
-
import './Mask.scss';
|
|
14
|
-
|
|
15
|
-
export interface MaskProps extends HoistProps {
|
|
16
|
-
/** Task(s) that should be monitored to determine if the mask should be displayed. */
|
|
17
|
-
bind?: Some<TaskObserver>;
|
|
18
|
-
/** True to display the mask. */
|
|
19
|
-
isDisplayed?: boolean;
|
|
20
|
-
/** Text to be displayed under the loading spinner image */
|
|
21
|
-
message?: ReactNode;
|
|
22
|
-
/** Callback when mask is tapped, relayed to underlying div element. */
|
|
23
|
-
onClick?: (e: MouseEvent) => void;
|
|
24
|
-
/** True (default) to display a spinning image. */
|
|
25
|
-
spinner?: boolean;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Mask with optional spinner and text.
|
|
30
|
-
*
|
|
31
|
-
* The mask can be explicitly controlled via props or bound to a TaskObserver.
|
|
32
|
-
*
|
|
33
|
-
* Note that the Panel component's `mask` prop provides a common and convenient method for masking
|
|
34
|
-
* sections of the UI without needing to manually create or manage this component.
|
|
35
|
-
*/
|
|
36
|
-
export const [Mask, mask] = hoistCmp.withFactory<MaskProps>({
|
|
37
|
-
displayName: 'Mask',
|
|
38
|
-
className: 'xh-mask',
|
|
39
|
-
|
|
40
|
-
render({isDisplayed, message, spinner = false, onClick, className}, ref) {
|
|
41
|
-
const impl = useLocalModel(LocalMaskModel);
|
|
42
|
-
|
|
43
|
-
isDisplayed = isDisplayed ?? impl.task?.isPending;
|
|
44
|
-
message = withDefault(message, impl.task?.message);
|
|
45
|
-
|
|
46
|
-
if (!isDisplayed) return null;
|
|
47
|
-
return div({
|
|
48
|
-
ref,
|
|
49
|
-
onClick,
|
|
50
|
-
className,
|
|
51
|
-
item: vbox({
|
|
52
|
-
className: 'xh-mask-body',
|
|
53
|
-
items: [
|
|
54
|
-
spinner ? spinnerCmp() : null,
|
|
55
|
-
spinner ? vspacer(10) : null,
|
|
56
|
-
message ? box({className: 'xh-mask-text', item: message}) : null
|
|
57
|
-
]
|
|
58
|
-
})
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
class LocalMaskModel extends HoistModel {
|
|
64
|
-
task;
|
|
65
|
-
|
|
66
|
-
override onLinked() {
|
|
67
|
-
const {bind} = this.componentProps;
|
|
68
|
-
if (bind) {
|
|
69
|
-
this.task =
|
|
70
|
-
bind instanceof TaskObserver
|
|
71
|
-
? bind
|
|
72
|
-
: this.markManaged(TaskObserver.trackAll({tasks: bind}));
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
package/mobile/cmp/mask/index.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|