@xh/hoist 80.0.0-SNAPSHOT.1768251400948 → 80.0.0-SNAPSHOT.1768264663674
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 +9 -14
- package/build/types/cmp/grid/GridModel.d.ts +2 -2
- package/build/types/cmp/layout/Tags.d.ts +0 -2
- package/build/types/cmp/tab/TabContainerModel.d.ts +1 -1
- package/build/types/cmp/tab/Types.d.ts +2 -2
- package/build/types/core/XH.d.ts +3 -1
- package/build/types/core/enums/RenderMode.d.ts +1 -1
- package/build/types/desktop/cmp/button/AppMenuButton.d.ts +10 -1
- package/build/types/desktop/cmp/dash/canvas/DashCanvasModel.d.ts +6 -46
- package/build/types/dynamics/desktop.d.ts +0 -1
- package/build/types/dynamics/mobile.d.ts +0 -1
- package/build/types/mobile/cmp/header/AppMenuButton.d.ts +10 -1
- package/build/types/svc/IdentityService.d.ts +4 -2
- package/cmp/grid/GridModel.ts +2 -2
- package/cmp/layout/Tags.ts +0 -2
- package/cmp/tab/TabContainerModel.ts +1 -1
- package/cmp/tab/Types.ts +2 -2
- package/core/XH.ts +9 -4
- package/core/enums/RenderMode.ts +1 -1
- package/desktop/appcontainer/AppContainer.ts +0 -2
- package/desktop/cmp/appbar/AppBar.scss +24 -5
- package/desktop/cmp/button/AppMenuButton.ts +30 -2
- package/desktop/cmp/dash/canvas/DashCanvas.ts +4 -21
- package/desktop/cmp/dash/canvas/DashCanvasModel.ts +24 -140
- package/dynamics/desktop.ts +0 -2
- package/dynamics/mobile.ts +0 -2
- package/mobile/appcontainer/AppContainer.ts +0 -2
- package/mobile/cmp/header/AppBar.scss +11 -0
- package/mobile/cmp/header/AppMenuButton.ts +29 -1
- package/package.json +3 -3
- package/styles/vars.scss +2 -1
- package/svc/IdentityService.ts +14 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/build/types/cmp/layout/CollapsibleSet.d.ts +0 -14
- package/build/types/desktop/cmp/button/CollapsibleSetButton.d.ts +0 -12
- package/build/types/desktop/cmp/dash/canvas/widgetwell/DashCanvasWidgetWell.d.ts +0 -19
- package/build/types/desktop/cmp/dash/canvas/widgetwell/DashCanvasWidgetWellModel.d.ts +0 -11
- package/build/types/mobile/cmp/button/CollapsibleSetButton.d.ts +0 -12
- package/cmp/layout/CollapsibleSet.scss +0 -49
- package/cmp/layout/CollapsibleSet.ts +0 -135
- package/desktop/cmp/button/CollapsibleSetButton.ts +0 -57
- package/desktop/cmp/dash/canvas/widgetwell/DashCanvasWidgetWell.scss +0 -34
- package/desktop/cmp/dash/canvas/widgetwell/DashCanvasWidgetWell.ts +0 -135
- package/desktop/cmp/dash/canvas/widgetwell/DashCanvasWidgetWellModel.ts +0 -65
- package/mobile/cmp/button/CollapsibleSetButton.ts +0 -57
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type FieldsetHTMLAttributes, type ReactElement, type ReactNode } from 'react';
|
|
2
|
-
import type { HoistProps, Intent, LayoutProps, RenderMode, TestSupportProps } from '@xh/hoist/core';
|
|
3
|
-
import './CollapsibleSet.scss';
|
|
4
|
-
export interface CollapsibleSetProps extends FieldsetHTMLAttributes<HTMLFieldSetElement>, HoistProps, TestSupportProps, LayoutProps {
|
|
5
|
-
icon?: ReactElement;
|
|
6
|
-
label: ReactNode;
|
|
7
|
-
tooltip?: JSX.Element | string;
|
|
8
|
-
intent?: Intent;
|
|
9
|
-
clickHandler?: () => void;
|
|
10
|
-
collapsed?: boolean;
|
|
11
|
-
hideItemCount?: boolean;
|
|
12
|
-
renderMode?: RenderMode;
|
|
13
|
-
}
|
|
14
|
-
export declare const CollapsibleSet: import("react").FC<CollapsibleSetProps>, collapsibleSet: import("@xh/hoist/core").ElementFactory<CollapsibleSetProps>;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { type ReactElement, type ReactNode, type JSX } from 'react';
|
|
2
|
-
import type { Intent, HoistProps } from '@xh/hoist/core';
|
|
3
|
-
export interface CollapsibleSetButtonProps extends HoistProps {
|
|
4
|
-
icon?: ReactElement;
|
|
5
|
-
text: ReactNode;
|
|
6
|
-
tooltip?: JSX.Element | string;
|
|
7
|
-
clickHandler?: (boolean: any) => void;
|
|
8
|
-
intent?: Intent;
|
|
9
|
-
collapsed?: boolean;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
}
|
|
12
|
-
export declare const CollapsibleSetButton: import("react").FC<CollapsibleSetButtonProps>, collapsibleSetButton: import("@xh/hoist/core").ElementFactory<CollapsibleSetButtonProps>;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { HoistProps, TestSupportProps } from '@xh/hoist/core';
|
|
2
|
-
import { DashCanvasModel } from '@xh/hoist/desktop/cmp/dash';
|
|
3
|
-
import './DashCanvasWidgetWell.scss';
|
|
4
|
-
export interface DashCanvasWidgetWellProps extends HoistProps, TestSupportProps {
|
|
5
|
-
/** DashCanvasModel for which this widget well should allow the user to add views from. */
|
|
6
|
-
dashCanvasModel?: DashCanvasModel;
|
|
7
|
-
/** Defaults to `column` */
|
|
8
|
-
flexDirection?: 'row' | 'column';
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Widget Well from which to add items to a DashCanvas by drag-and-drop.
|
|
12
|
-
*
|
|
13
|
-
* Available view specs are listed in their defined order,
|
|
14
|
-
* grouped by their 'groupName' property if present.
|
|
15
|
-
*
|
|
16
|
-
* Typically, an app developer would place this inside a collapsible panel to the side of
|
|
17
|
-
* a DashCanvas.
|
|
18
|
-
*/
|
|
19
|
-
export declare const DashCanvasWidgetWell: import("react").FC<DashCanvasWidgetWellProps>, dashCanvasWidgetWell: import("@xh/hoist/core").ElementFactory<DashCanvasWidgetWellProps>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { DragEvent } from 'react';
|
|
2
|
-
import { DashCanvasModel } from '@xh/hoist/desktop/cmp/dash';
|
|
3
|
-
import { HoistModel } from '@xh/hoist/core';
|
|
4
|
-
import '@xh/hoist/desktop/register';
|
|
5
|
-
export declare class DashCanvasWidgetWellModel extends HoistModel {
|
|
6
|
-
dashCanvasModel: DashCanvasModel;
|
|
7
|
-
constructor();
|
|
8
|
-
onLinked(): void;
|
|
9
|
-
onDragStart(evt: DragEvent<HTMLDivElement>): void;
|
|
10
|
-
onDragEnd(evt: DragEvent<HTMLDivElement>): void;
|
|
11
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { type ReactElement, type ReactNode, type JSX } from 'react';
|
|
2
|
-
import type { Intent, HoistProps } from '@xh/hoist/core';
|
|
3
|
-
export interface CollapsibleSetButtonProps extends HoistProps {
|
|
4
|
-
icon?: ReactElement;
|
|
5
|
-
text: ReactNode;
|
|
6
|
-
tooltip?: JSX.Element | string;
|
|
7
|
-
clickHandler?: (boolean: any) => void;
|
|
8
|
-
intent?: Intent;
|
|
9
|
-
collapsed?: boolean;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
}
|
|
12
|
-
export declare const CollapsibleSetButton: import("react").FC<CollapsibleSetButtonProps>, collapsibleSetButton: import("@xh/hoist/core").ElementFactory<CollapsibleSetButtonProps>;
|
|
@@ -1,49 +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 © 2026 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
.xh-collapsible-set {
|
|
9
|
-
&--collapsed {
|
|
10
|
-
border-bottom: none;
|
|
11
|
-
border-left: none;
|
|
12
|
-
border-right: none;
|
|
13
|
-
|
|
14
|
-
&--render-mode--always,
|
|
15
|
-
&--render-mode--lazy {
|
|
16
|
-
> *:not(:first-child) {
|
|
17
|
-
display: none;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
&.xh-collapsible-set--intent-primary {
|
|
23
|
-
border-color: var(--xh-intent-primary-trans2);
|
|
24
|
-
&.xh-collapsible-set--enabled {
|
|
25
|
-
border-color: var(--xh-intent-primary);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
&.xh-collapsible-set--intent-success {
|
|
30
|
-
border-color: var(--xh-intent-success-trans2);
|
|
31
|
-
&.xh-collapsible-set--enabled {
|
|
32
|
-
border-color: var(--xh-intent-success);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
&.xh-collapsible-set--intent-warning {
|
|
37
|
-
border-color: var(--xh-intent-warning-trans2);
|
|
38
|
-
&.xh-collapsible-set--enabled {
|
|
39
|
-
border-color: var(--xh-intent-warning);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
&.xh-collapsible-set--intent-danger {
|
|
44
|
-
border-color: var(--xh-intent-danger-trans2);
|
|
45
|
-
&.xh-collapsible-set--enabled {
|
|
46
|
-
border-color: var(--xh-intent-danger);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,135 +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 © 2026 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import classNames from 'classnames';
|
|
9
|
-
import {castArray} from 'lodash';
|
|
10
|
-
import {type FieldsetHTMLAttributes, type ReactElement, type ReactNode, useState} from 'react';
|
|
11
|
-
import {XH, hoistCmp} from '@xh/hoist/core';
|
|
12
|
-
import type {HoistProps, Intent, LayoutProps, RenderMode, TestSupportProps} from '@xh/hoist/core';
|
|
13
|
-
import {fieldset} from '@xh/hoist/cmp/layout';
|
|
14
|
-
import {TEST_ID, mergeDeep} from '@xh/hoist/utils/js';
|
|
15
|
-
import {splitLayoutProps} from '@xh/hoist/utils/react';
|
|
16
|
-
import {collapsibleSetButton as desktopCollapsibleSetButtonImpl} from '@xh/hoist/dynamics/desktop';
|
|
17
|
-
import {collapsibleSetButton as mobileCollapsibleSetButtonImpl} from '@xh/hoist/dynamics/mobile';
|
|
18
|
-
|
|
19
|
-
import './CollapsibleSet.scss';
|
|
20
|
-
|
|
21
|
-
export interface CollapsibleSetProps
|
|
22
|
-
extends FieldsetHTMLAttributes<HTMLFieldSetElement>, HoistProps, TestSupportProps, LayoutProps {
|
|
23
|
-
icon?: ReactElement;
|
|
24
|
-
label: ReactNode;
|
|
25
|
-
tooltip?: JSX.Element | string;
|
|
26
|
-
intent?: Intent;
|
|
27
|
-
clickHandler?: () => void;
|
|
28
|
-
collapsed?: boolean;
|
|
29
|
-
hideItemCount?: boolean;
|
|
30
|
-
renderMode?: RenderMode;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const [CollapsibleSet, collapsibleSet] = hoistCmp.withFactory<CollapsibleSetProps>({
|
|
34
|
-
displayName: 'CollapsibleSet',
|
|
35
|
-
model: false,
|
|
36
|
-
className: 'xh-collapsible-set',
|
|
37
|
-
render({
|
|
38
|
-
icon,
|
|
39
|
-
label,
|
|
40
|
-
tooltip,
|
|
41
|
-
intent,
|
|
42
|
-
collapsed,
|
|
43
|
-
children,
|
|
44
|
-
hideItemCount,
|
|
45
|
-
className,
|
|
46
|
-
disabled,
|
|
47
|
-
display = 'flex',
|
|
48
|
-
flexDirection = 'column',
|
|
49
|
-
flexWrap = 'wrap',
|
|
50
|
-
renderMode = 'unmountOnHide',
|
|
51
|
-
...rest
|
|
52
|
-
}) {
|
|
53
|
-
// Note `model` destructured off of non-layout props to avoid setting
|
|
54
|
-
// model as a bogus DOM attribute. This low-level component may easily be passed one from
|
|
55
|
-
// a parent that has not properly managed its own props.
|
|
56
|
-
let [layoutProps, {model, testId, ...restProps}] = splitLayoutProps(rest);
|
|
57
|
-
|
|
58
|
-
restProps = mergeDeep(
|
|
59
|
-
{style: {display, flexDirection, flexWrap, ...layoutProps}},
|
|
60
|
-
{[TEST_ID]: testId},
|
|
61
|
-
restProps
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const [isCollapsed, setIsCollapsed] = useState<boolean>(collapsed === true),
|
|
65
|
-
[expandCount, setExpandCount] = useState<number>(!collapsed ? 1 : 0),
|
|
66
|
-
items = castArray(children),
|
|
67
|
-
itemCount = hideItemCount === true ? '' : ` (${items.length})`,
|
|
68
|
-
classes = [];
|
|
69
|
-
|
|
70
|
-
if (isCollapsed) {
|
|
71
|
-
classes.push('xh-collapsible-set--collapsed');
|
|
72
|
-
} else {
|
|
73
|
-
classes.push('xh-collapsible-set--expanded');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (disabled) {
|
|
77
|
-
classes.push('xh-collapsible-set--disabled');
|
|
78
|
-
} else {
|
|
79
|
-
classes.push('xh-collapsible-set--enabled');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (intent) {
|
|
83
|
-
classes.push(`xh-collapsible-set--intent-${intent}`);
|
|
84
|
-
} else {
|
|
85
|
-
classes.push(`xh-collapsible-set--intent-none`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const btn = XH.isMobileApp
|
|
89
|
-
? mobileCollapsibleSetButtonImpl
|
|
90
|
-
: desktopCollapsibleSetButtonImpl;
|
|
91
|
-
|
|
92
|
-
let content;
|
|
93
|
-
switch (renderMode) {
|
|
94
|
-
case 'always':
|
|
95
|
-
content = items;
|
|
96
|
-
if (isCollapsed) {
|
|
97
|
-
classes.push('xh-collapsible-set--collapsed--render-mode--always');
|
|
98
|
-
}
|
|
99
|
-
break;
|
|
100
|
-
|
|
101
|
-
case 'lazy':
|
|
102
|
-
content = isCollapsed && !expandCount ? [] : items;
|
|
103
|
-
if (isCollapsed) {
|
|
104
|
-
classes.push('xh-collapsible-set--collapsed--render-mode--lazy');
|
|
105
|
-
}
|
|
106
|
-
break;
|
|
107
|
-
|
|
108
|
-
// unmountOnHide
|
|
109
|
-
default:
|
|
110
|
-
content = isCollapsed ? [] : items;
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return fieldset({
|
|
115
|
-
className: classNames(className, classes),
|
|
116
|
-
items: [
|
|
117
|
-
btn({
|
|
118
|
-
icon,
|
|
119
|
-
text: `${label}${itemCount}`,
|
|
120
|
-
tooltip,
|
|
121
|
-
intent,
|
|
122
|
-
clickHandler: val => {
|
|
123
|
-
setIsCollapsed(val);
|
|
124
|
-
setExpandCount(expandCount + 1);
|
|
125
|
-
},
|
|
126
|
-
collapsed: isCollapsed,
|
|
127
|
-
disabled
|
|
128
|
-
}),
|
|
129
|
-
...content
|
|
130
|
-
],
|
|
131
|
-
disabled,
|
|
132
|
-
...restProps
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
});
|
|
@@ -1,57 +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 © 2026 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {type ReactElement, type ReactNode, type JSX, useState} from 'react';
|
|
9
|
-
import {tooltip as bpTooltip} from '@xh/hoist/kit/blueprint';
|
|
10
|
-
import {hoistCmp} from '@xh/hoist/core';
|
|
11
|
-
import type {Intent, HoistProps} from '@xh/hoist/core';
|
|
12
|
-
import {button} from '@xh/hoist/desktop/cmp/button';
|
|
13
|
-
import {legend} from '@xh/hoist/cmp/layout';
|
|
14
|
-
import {Icon} from '@xh/hoist/icon/Icon';
|
|
15
|
-
|
|
16
|
-
export interface CollapsibleSetButtonProps extends HoistProps {
|
|
17
|
-
icon?: ReactElement;
|
|
18
|
-
text: ReactNode;
|
|
19
|
-
tooltip?: JSX.Element | string;
|
|
20
|
-
clickHandler?: (boolean) => void;
|
|
21
|
-
intent?: Intent;
|
|
22
|
-
collapsed?: boolean;
|
|
23
|
-
disabled?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const [CollapsibleSetButton, collapsibleSetButton] =
|
|
27
|
-
hoistCmp.withFactory<CollapsibleSetButtonProps>({
|
|
28
|
-
displayName: 'CollapsibleSetButton',
|
|
29
|
-
model: false,
|
|
30
|
-
render({icon, text, tooltip, intent, clickHandler, collapsed, disabled}) {
|
|
31
|
-
const [isCollapsed, setIsCollapsed] = useState<boolean>(collapsed === true),
|
|
32
|
-
btn = button({
|
|
33
|
-
text,
|
|
34
|
-
icon,
|
|
35
|
-
rightIcon: isCollapsed ? Icon.angleDown() : Icon.angleUp(),
|
|
36
|
-
outlined: isCollapsed && !intent,
|
|
37
|
-
minimal: !intent || (intent && !isCollapsed),
|
|
38
|
-
intent,
|
|
39
|
-
disabled,
|
|
40
|
-
onClick: () => {
|
|
41
|
-
const val = !isCollapsed;
|
|
42
|
-
setIsCollapsed(val);
|
|
43
|
-
clickHandler?.(val);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return legend(
|
|
48
|
-
tooltip
|
|
49
|
-
? bpTooltip({
|
|
50
|
-
item: btn,
|
|
51
|
-
content: tooltip,
|
|
52
|
-
intent
|
|
53
|
-
})
|
|
54
|
-
: btn
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
.xh-dash-canvas-widget-well {
|
|
2
|
-
padding: 0 var(--xh-pad-half-px);
|
|
3
|
-
|
|
4
|
-
.xh-collapsible-set {
|
|
5
|
-
padding: 0 var(--xh-pad-half-px) var(--xh-pad-half-px) var(--xh-pad-half-px);
|
|
6
|
-
margin: var(--xh-pad-half-px);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.xh-dash-canvas-draggable-widget {
|
|
10
|
-
border: var(--xh-border-dotted);
|
|
11
|
-
background-color: var(--xh-bg-alt);
|
|
12
|
-
padding: var(--xh-pad-half-px);
|
|
13
|
-
margin: var(--xh-pad-half-px);
|
|
14
|
-
text-wrap-mode: nowrap;
|
|
15
|
-
cursor: grab;
|
|
16
|
-
|
|
17
|
-
&.is-dragging {
|
|
18
|
-
cursor: grabbing;
|
|
19
|
-
// lighten background color of left behind placeholder
|
|
20
|
-
// when dragging
|
|
21
|
-
opacity: 0.25;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
&:active {
|
|
25
|
-
cursor: grabbing;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
&--row {
|
|
30
|
-
.xh-dash-canvas-draggable-widget {
|
|
31
|
-
align-self: flex-start;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,135 +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 © 2025 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {uniqBy} from 'lodash';
|
|
9
|
-
import classNames from 'classnames';
|
|
10
|
-
import type {ReactElement} from 'react';
|
|
11
|
-
import {div, frame} from '@xh/hoist/cmp/layout';
|
|
12
|
-
import {creates, hoistCmp, HoistProps, TestSupportProps, uses} from '@xh/hoist/core';
|
|
13
|
-
import {DashCanvasModel, DashCanvasViewSpec} from '@xh/hoist/desktop/cmp/dash';
|
|
14
|
-
import {DashCanvasWidgetWellModel} from '@xh/hoist/desktop/cmp/dash/canvas/widgetwell/DashCanvasWidgetWellModel';
|
|
15
|
-
import {collapsibleSet} from '@xh/hoist/cmp/layout/CollapsibleSet';
|
|
16
|
-
|
|
17
|
-
import './DashCanvasWidgetWell.scss';
|
|
18
|
-
|
|
19
|
-
export interface DashCanvasWidgetWellProps extends HoistProps, TestSupportProps {
|
|
20
|
-
/** DashCanvasModel for which this widget well should allow the user to add views from. */
|
|
21
|
-
dashCanvasModel?: DashCanvasModel;
|
|
22
|
-
/** Defaults to `column` */
|
|
23
|
-
flexDirection?: 'row' | 'column';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Widget Well from which to add items to a DashCanvas by drag-and-drop.
|
|
28
|
-
*
|
|
29
|
-
* Available view specs are listed in their defined order,
|
|
30
|
-
* grouped by their 'groupName' property if present.
|
|
31
|
-
*
|
|
32
|
-
* Typically, an app developer would place this inside a collapsible panel to the side of
|
|
33
|
-
* a DashCanvas.
|
|
34
|
-
*/
|
|
35
|
-
export const [DashCanvasWidgetWell, dashCanvasWidgetWell] =
|
|
36
|
-
hoistCmp.withFactory<DashCanvasWidgetWellProps>({
|
|
37
|
-
displayName: 'DashCanvasWidgetWell',
|
|
38
|
-
model: creates(DashCanvasWidgetWellModel),
|
|
39
|
-
className: 'xh-dash-canvas-widget-well',
|
|
40
|
-
render({dashCanvasModel, flexDirection, className, testId}) {
|
|
41
|
-
if (!dashCanvasModel) return;
|
|
42
|
-
|
|
43
|
-
const classes = [];
|
|
44
|
-
if (flexDirection === 'row') classes.push('xh-dash-canvas-widget-well--row');
|
|
45
|
-
|
|
46
|
-
return frame({
|
|
47
|
-
className: classNames(className, classes),
|
|
48
|
-
overflowY: 'auto',
|
|
49
|
-
flexDirection: flexDirection || 'column',
|
|
50
|
-
flexWrap: flexDirection === 'row' ? 'wrap' : 'nowrap',
|
|
51
|
-
items: createDraggableItems(dashCanvasModel, flexDirection),
|
|
52
|
-
testId
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
//---------------------------
|
|
58
|
-
// Implementation
|
|
59
|
-
//---------------------------
|
|
60
|
-
const draggableWidget = hoistCmp.factory<DashCanvasWidgetWellModel>({
|
|
61
|
-
displayName: 'DraggableWidget',
|
|
62
|
-
model: uses(DashCanvasWidgetWellModel),
|
|
63
|
-
render({model, viewSpec}) {
|
|
64
|
-
const {id, icon, title} = viewSpec as DashCanvasViewSpec;
|
|
65
|
-
return div({
|
|
66
|
-
id: `draggableFor-${id}`,
|
|
67
|
-
className: 'xh-dash-canvas-draggable-widget',
|
|
68
|
-
draggable: true,
|
|
69
|
-
unselectable: 'on',
|
|
70
|
-
onDragStart: e => model.onDragStart(e),
|
|
71
|
-
onDragEnd: e => model.onDragEnd(e),
|
|
72
|
-
items: [icon, ' ', title]
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Used to create draggable items (for adding views)
|
|
79
|
-
* @internal
|
|
80
|
-
*/
|
|
81
|
-
function createDraggableItems(dashCanvasModel: DashCanvasModel, flexDirection): any[] {
|
|
82
|
-
if (!dashCanvasModel.ref.current) return [];
|
|
83
|
-
|
|
84
|
-
const groupedItems = {},
|
|
85
|
-
ungroupedItems = [];
|
|
86
|
-
|
|
87
|
-
const addToGroup = (item, icon, groupName) => {
|
|
88
|
-
const group = groupedItems[groupName];
|
|
89
|
-
if (group) {
|
|
90
|
-
group.push({item, icon});
|
|
91
|
-
} else {
|
|
92
|
-
groupedItems[groupName] = [{item, icon}];
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
dashCanvasModel.viewSpecs
|
|
97
|
-
.filter(viewSpec => {
|
|
98
|
-
return (
|
|
99
|
-
viewSpec.allowAdd &&
|
|
100
|
-
(!viewSpec.unique || !dashCanvasModel.getViewsBySpecId(viewSpec.id).length)
|
|
101
|
-
);
|
|
102
|
-
})
|
|
103
|
-
.forEach(viewSpec => {
|
|
104
|
-
const {groupName} = viewSpec,
|
|
105
|
-
item = draggableWidget({viewSpec});
|
|
106
|
-
|
|
107
|
-
if (groupName) {
|
|
108
|
-
addToGroup(item, viewSpec.icon, groupName);
|
|
109
|
-
} else {
|
|
110
|
-
ungroupedItems.push(item);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
return [
|
|
115
|
-
...Object.keys(groupedItems).map(group => {
|
|
116
|
-
const label = group,
|
|
117
|
-
items = groupedItems[group],
|
|
118
|
-
sameIcons =
|
|
119
|
-
uniqBy<{item: ReactElement; icon: ReactElement}>(
|
|
120
|
-
items,
|
|
121
|
-
it => it.icon.props.iconName
|
|
122
|
-
).length === 1,
|
|
123
|
-
icon = sameIcons ? items[0].icon : null;
|
|
124
|
-
|
|
125
|
-
return collapsibleSet({
|
|
126
|
-
icon,
|
|
127
|
-
collapsed: false,
|
|
128
|
-
label,
|
|
129
|
-
flexDirection,
|
|
130
|
-
items: items.map(it => it.item)
|
|
131
|
-
});
|
|
132
|
-
}),
|
|
133
|
-
...ungroupedItems
|
|
134
|
-
];
|
|
135
|
-
}
|
|
@@ -1,65 +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 © 2025 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
import {DragEvent} from 'react';
|
|
8
|
-
import {DashCanvasModel} from '@xh/hoist/desktop/cmp/dash';
|
|
9
|
-
import {HoistModel, managed} from '@xh/hoist/core';
|
|
10
|
-
import '@xh/hoist/desktop/register';
|
|
11
|
-
import {makeObservable, observable} from '@xh/hoist/mobx';
|
|
12
|
-
import {runInAction} from 'mobx';
|
|
13
|
-
|
|
14
|
-
export class DashCanvasWidgetWellModel extends HoistModel {
|
|
15
|
-
@managed
|
|
16
|
-
@observable.ref
|
|
17
|
-
dashCanvasModel: DashCanvasModel;
|
|
18
|
-
|
|
19
|
-
constructor() {
|
|
20
|
-
super();
|
|
21
|
-
makeObservable(this);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
override onLinked() {
|
|
25
|
-
this.addReaction({
|
|
26
|
-
track: () => this.componentProps,
|
|
27
|
-
run: () =>
|
|
28
|
-
runInAction(() => (this.dashCanvasModel = this.componentProps.dashCanvasModel)),
|
|
29
|
-
fireImmediately: true
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
onDragStart(evt: DragEvent<HTMLDivElement>) {
|
|
34
|
-
const target = evt.target as HTMLElement;
|
|
35
|
-
if (!target) return;
|
|
36
|
-
|
|
37
|
-
this.dashCanvasModel.showAddViewButtonWhenEmpty = false;
|
|
38
|
-
evt.dataTransfer.effectAllowed = 'move';
|
|
39
|
-
target.classList.add('is-dragging');
|
|
40
|
-
|
|
41
|
-
const viewSpecId: string = target.getAttribute('id').split('draggableFor-')[1],
|
|
42
|
-
viewSpec = this.dashCanvasModel.viewSpecs.find(it => it.id === viewSpecId),
|
|
43
|
-
{width, height} = viewSpec,
|
|
44
|
-
widget = {
|
|
45
|
-
viewSpecId,
|
|
46
|
-
layout: {
|
|
47
|
-
x: 0,
|
|
48
|
-
y: 0,
|
|
49
|
-
w: width,
|
|
50
|
-
h: height
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
this.dashCanvasModel.setDraggedInView(widget);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
onDragEnd(evt: DragEvent<HTMLDivElement>) {
|
|
58
|
-
this.dashCanvasModel.showAddViewButtonWhenEmpty = true;
|
|
59
|
-
|
|
60
|
-
const target = evt.target as HTMLElement;
|
|
61
|
-
if (!target) return;
|
|
62
|
-
|
|
63
|
-
target.classList.remove('is-dragging');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,57 +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 © 2026 Extremely Heavy Industries Inc.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {type ReactElement, type ReactNode, type JSX, useState} from 'react';
|
|
9
|
-
import {tooltip as bpTooltip} from '@xh/hoist/kit/blueprint';
|
|
10
|
-
import {fragment} from '@xh/hoist/cmp/layout';
|
|
11
|
-
import {hoistCmp} from '@xh/hoist/core';
|
|
12
|
-
import type {Intent, HoistProps} from '@xh/hoist/core';
|
|
13
|
-
import {button} from '@xh/hoist/mobile/cmp/button';
|
|
14
|
-
import {legend} from '@xh/hoist/cmp/layout';
|
|
15
|
-
import {Icon} from '@xh/hoist/icon/Icon';
|
|
16
|
-
|
|
17
|
-
export interface CollapsibleSetButtonProps extends HoistProps {
|
|
18
|
-
icon?: ReactElement;
|
|
19
|
-
text: ReactNode;
|
|
20
|
-
tooltip?: JSX.Element | string;
|
|
21
|
-
clickHandler?: (boolean) => void;
|
|
22
|
-
intent?: Intent;
|
|
23
|
-
collapsed?: boolean;
|
|
24
|
-
disabled?: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const [CollapsibleSetButton, collapsibleSetButton] =
|
|
28
|
-
hoistCmp.withFactory<CollapsibleSetButtonProps>({
|
|
29
|
-
displayName: 'CollapsibleSetButton',
|
|
30
|
-
model: false,
|
|
31
|
-
render({icon, text, tooltip, intent, clickHandler, collapsed, disabled}) {
|
|
32
|
-
const [isCollapsed, setIsCollapsed] = useState<boolean>(collapsed === true),
|
|
33
|
-
btn = button({
|
|
34
|
-
text: fragment(text, isCollapsed ? Icon.angleDown() : Icon.angleUp()),
|
|
35
|
-
icon,
|
|
36
|
-
outlined: isCollapsed && !intent,
|
|
37
|
-
minimal: !intent || (intent && !isCollapsed),
|
|
38
|
-
intent,
|
|
39
|
-
disabled,
|
|
40
|
-
onClick: () => {
|
|
41
|
-
const val = !isCollapsed;
|
|
42
|
-
setIsCollapsed(val);
|
|
43
|
-
clickHandler?.(val);
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return legend(
|
|
48
|
-
tooltip
|
|
49
|
-
? bpTooltip({
|
|
50
|
-
item: btn,
|
|
51
|
-
content: tooltip,
|
|
52
|
-
intent
|
|
53
|
-
})
|
|
54
|
-
: btn
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
});
|