pne-ui 3.0.19 → 3.0.21
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/cjs/component/fab/PneFloatingActionButtons.d.ts +17 -4
- package/cjs/component/fab/PneFloatingActionButtons.js +39 -17
- package/cjs/component/fab/PneFloatingActionButtons.js.map +1 -1
- package/cjs/component/widget-board/PneLayoutsPanel.d.ts +18 -0
- package/cjs/component/widget-board/PneLayoutsPanel.js +86 -0
- package/cjs/component/widget-board/PneLayoutsPanel.js.map +1 -0
- package/cjs/component/widget-board/WidgetBoard.js +173 -43
- package/cjs/component/widget-board/WidgetBoard.js.map +1 -1
- package/cjs/component/widget-board/index.d.ts +1 -0
- package/cjs/component/widget-board/index.js +1 -0
- package/cjs/component/widget-board/index.js.map +1 -1
- package/cjs/component/widget-board/types.d.ts +15 -8
- package/cjs/exports/fab.d.ts +1 -1
- package/cjs/exports/fab.js.map +1 -1
- package/esm/component/fab/PneFloatingActionButtons.d.ts +17 -4
- package/esm/component/fab/PneFloatingActionButtons.js +41 -19
- package/esm/component/fab/PneFloatingActionButtons.js.map +1 -1
- package/esm/component/widget-board/PneLayoutsPanel.d.ts +18 -0
- package/esm/component/widget-board/PneLayoutsPanel.js +81 -0
- package/esm/component/widget-board/PneLayoutsPanel.js.map +1 -0
- package/esm/component/widget-board/WidgetBoard.js +175 -45
- package/esm/component/widget-board/WidgetBoard.js.map +1 -1
- package/esm/component/widget-board/index.d.ts +1 -0
- package/esm/component/widget-board/index.js +1 -0
- package/esm/component/widget-board/index.js.map +1 -1
- package/esm/component/widget-board/types.d.ts +15 -8
- package/esm/exports/fab.d.ts +1 -1
- package/esm/exports/fab.js +1 -1
- package/esm/exports/fab.js.map +1 -1
- package/package.json +2 -2
|
@@ -7,8 +7,18 @@ export type PneFabAction = {
|
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
tooltip?: string;
|
|
9
9
|
};
|
|
10
|
+
export type PneFabContent = {
|
|
11
|
+
id: string;
|
|
12
|
+
kind: 'content';
|
|
13
|
+
node: React.ReactNode;
|
|
14
|
+
};
|
|
15
|
+
export type PneFabDivider = {
|
|
16
|
+
id: string;
|
|
17
|
+
kind: 'divider';
|
|
18
|
+
};
|
|
19
|
+
export type PneFabItem = PneFabAction | PneFabContent | PneFabDivider;
|
|
10
20
|
export type PneFloatingActionButtonsProps = {
|
|
11
|
-
actions:
|
|
21
|
+
actions: PneFabItem[];
|
|
12
22
|
breakpoints?: readonly number[];
|
|
13
23
|
mobileBreakpoint?: number;
|
|
14
24
|
position?: {
|
|
@@ -18,10 +28,13 @@ export type PneFloatingActionButtonsProps = {
|
|
|
18
28
|
fabLabel?: React.ReactNode;
|
|
19
29
|
fabIcon?: React.ReactNode;
|
|
20
30
|
className?: string;
|
|
31
|
+
bannerText?: React.ReactNode;
|
|
21
32
|
};
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
34
|
+
* Floating action menu:
|
|
35
|
+
* - on mobile: actions/content rendered inside a Menu
|
|
36
|
+
* - on desktop: actions rendered as floating Fabs stacked above the trigger; Menu still opens for content/banner
|
|
37
|
+
* Actions array may include content blocks (`{ kind: 'content', node: <...> }`) to embed custom UI.
|
|
25
38
|
*/
|
|
26
|
-
export declare function PneFloatingActionButtons({ actions, breakpoints, mobileBreakpoint, position, fabLabel, fabIcon, className, }: PneFloatingActionButtonsProps): React.JSX.Element;
|
|
39
|
+
export declare function PneFloatingActionButtons({ actions, breakpoints, mobileBreakpoint, position, fabLabel, fabIcon, className, bannerText, }: PneFloatingActionButtonsProps): React.JSX.Element;
|
|
27
40
|
export default PneFloatingActionButtons;
|
|
@@ -3,15 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PneFloatingActionButtons = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importStar(require("react"));
|
|
6
|
-
const
|
|
6
|
+
const Edit_1 = tslib_1.__importDefault(require("@mui/icons-material/Edit"));
|
|
7
7
|
const material_1 = require("@mui/material");
|
|
8
8
|
const breakpoints_1 = require("../../common/responsive/breakpoints");
|
|
9
9
|
const useBreakpoint_1 = require("../responsive/useBreakpoint");
|
|
10
|
+
const isContentItem = (item) => 'kind' in item && item.kind === 'content';
|
|
11
|
+
const isDividerItem = (item) => 'kind' in item && item.kind === 'divider';
|
|
12
|
+
const isActionItem = (item) => !isContentItem(item) && !isDividerItem(item);
|
|
10
13
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
14
|
+
* Floating action menu:
|
|
15
|
+
* - on mobile: actions/content rendered inside a Menu
|
|
16
|
+
* - on desktop: actions rendered as floating Fabs stacked above the trigger; Menu still opens for content/banner
|
|
17
|
+
* Actions array may include content blocks (`{ kind: 'content', node: <...> }`) to embed custom UI.
|
|
13
18
|
*/
|
|
14
|
-
function PneFloatingActionButtons({ actions, breakpoints = breakpoints_1.DEFAULT_BREAKPOINTS, mobileBreakpoint = 800, position = { bottom: 24, right: 24 }, fabLabel = 'Actions', fabIcon = react_1.default.createElement(
|
|
19
|
+
function PneFloatingActionButtons({ actions, breakpoints = breakpoints_1.DEFAULT_BREAKPOINTS, mobileBreakpoint = 800, position = { bottom: 24, right: 24 }, fabLabel = 'Actions', fabIcon = react_1.default.createElement(Edit_1.default, null), className, bannerText, }) {
|
|
15
20
|
const breakpoint = (0, useBreakpoint_1.useBreakpoint)({ breakpoints });
|
|
16
21
|
const isMobile = breakpoint <= mobileBreakpoint;
|
|
17
22
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
|
|
@@ -21,20 +26,37 @@ function PneFloatingActionButtons({ actions, breakpoints = breakpoints_1.DEFAULT
|
|
|
21
26
|
handleClose();
|
|
22
27
|
action.onClick();
|
|
23
28
|
};
|
|
24
|
-
const
|
|
25
|
-
react_1.default.createElement(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
react_1.default.createElement(material_1.Tooltip, { title: fabLabel },
|
|
30
|
-
react_1.default.createElement(material_1.Fab, { color: 'primary', onClick: handleOpen, "aria-label": typeof fabLabel === 'string' ? fabLabel : 'Actions' }, fabIcon)),
|
|
31
|
-
react_1.default.createElement(material_1.Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, anchorOrigin: { vertical: 'top', horizontal: 'left' } }, actions.map(action => (react_1.default.createElement(material_1.MenuItem, { key: action.id, disabled: action.disabled, onClick: () => handleAction(action) },
|
|
32
|
-
action.icon ? react_1.default.createElement(material_1.ListItemIcon, null, action.icon) : null,
|
|
33
|
-
react_1.default.createElement(material_1.ListItemText, null, action.label)))))));
|
|
34
|
-
}
|
|
29
|
+
const renderMenuItems = (items) => items.map(item => isContentItem(item) ? (react_1.default.createElement(material_1.Box, { key: item.id }, item.node)) : isDividerItem(item) ? (react_1.default.createElement(material_1.Divider, { key: item.id, component: 'li', role: 'presentation', sx: { my: 2 } })) : isActionItem(item) ? (react_1.default.createElement(material_1.MenuItem, { key: item.id, disabled: item.disabled, onClick: () => handleAction(item), sx: { fontSize: '0.875rem', display: 'flex', alignItems: 'center', gap: 1 } },
|
|
30
|
+
react_1.default.createElement(material_1.ListItemText, { primaryTypographyProps: { fontSize: '0.875rem' }, sx: { flex: 1 } }, item.label),
|
|
31
|
+
item.icon ? (react_1.default.createElement(material_1.Box, { component: 'span', sx: { display: 'inline-flex', color: 'inherit', lineHeight: 0 } }, item.icon)) : null)) : null);
|
|
32
|
+
const menuItems = isMobile ? actions : actions.filter(item => !isActionItem(item));
|
|
33
|
+
const actionItems = isMobile ? [] : actions.filter(isActionItem);
|
|
35
34
|
return (react_1.default.createElement(material_1.Box, { position: 'fixed', bottom: position.bottom ?? 24, right: position.right ?? 24, zIndex: 1300, className: className },
|
|
36
|
-
react_1.default.createElement(material_1.
|
|
37
|
-
|
|
35
|
+
react_1.default.createElement(material_1.Stack, { spacing: 1, alignItems: 'flex-end' },
|
|
36
|
+
!isMobile
|
|
37
|
+
? actionItems.map(item => {
|
|
38
|
+
const title = item.tooltip ?? (typeof item.label === 'string' ? item.label : typeof fabLabel === 'string' ? fabLabel : 'Action');
|
|
39
|
+
return (react_1.default.createElement(material_1.Tooltip, { key: item.id, title: title, placement: 'left' },
|
|
40
|
+
react_1.default.createElement("span", null,
|
|
41
|
+
react_1.default.createElement(material_1.Fab, { color: 'primary', onClick: () => handleAction(item), "aria-label": typeof title === 'string' ? title : 'Action' }, item.icon ?? (typeof item.label === 'string' ? item.label.charAt(0) : fabIcon)))));
|
|
42
|
+
})
|
|
43
|
+
: null,
|
|
44
|
+
react_1.default.createElement(material_1.Tooltip, { title: fabLabel },
|
|
45
|
+
react_1.default.createElement(material_1.Fab, { color: 'primary', onClick: handleOpen, "aria-label": typeof fabLabel === 'string' ? fabLabel : 'Actions' }, fabIcon))),
|
|
46
|
+
react_1.default.createElement(material_1.Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, anchorOrigin: { vertical: 'top', horizontal: 'left' }, MenuListProps: { sx: { py: 0 } } },
|
|
47
|
+
renderMenuItems(menuItems),
|
|
48
|
+
bannerText ? (react_1.default.createElement(material_1.MenuItem, { disabled: true, sx: {
|
|
49
|
+
pointerEvents: 'none',
|
|
50
|
+
bgcolor: theme => theme.palette.primary.main,
|
|
51
|
+
color: theme => theme.palette.primary.contrastText,
|
|
52
|
+
'&.Mui-disabled': { opacity: 1 },
|
|
53
|
+
minHeight: 60,
|
|
54
|
+
} },
|
|
55
|
+
react_1.default.createElement(material_1.ListItemIcon, { sx: { minWidth: 36, color: 'inherit' } }, fabIcon),
|
|
56
|
+
react_1.default.createElement(material_1.ListItemText, { primaryTypographyProps: {
|
|
57
|
+
fontWeight: 600,
|
|
58
|
+
fontSize: '20px',
|
|
59
|
+
} }, bannerText))) : null)));
|
|
38
60
|
}
|
|
39
61
|
exports.PneFloatingActionButtons = PneFloatingActionButtons;
|
|
40
62
|
exports.default = PneFloatingActionButtons;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PneFloatingActionButtons.js","sourceRoot":"","sources":["../../../src/component/fab/PneFloatingActionButtons.tsx"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"PneFloatingActionButtons.js","sourceRoot":"","sources":["../../../src/component/fab/PneFloatingActionButtons.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type PneLayoutOption = {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
export type PneLayoutsPanelProps = {
|
|
7
|
+
items: PneLayoutOption[];
|
|
8
|
+
selectedId?: string;
|
|
9
|
+
onSelect?: (id: string) => void;
|
|
10
|
+
onDelete?: (id: string) => void;
|
|
11
|
+
onUpdate?: (id: string) => void;
|
|
12
|
+
onAdd?: (name: string) => void;
|
|
13
|
+
title?: React.ReactNode;
|
|
14
|
+
addLabel?: React.ReactNode;
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare const PneLayoutsPanel: React.FC<PneLayoutsPanelProps>;
|
|
18
|
+
export default PneLayoutsPanel;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PneLayoutsPanel = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const react_1 = tslib_1.__importStar(require("react"));
|
|
6
|
+
const Delete_1 = tslib_1.__importDefault(require("@mui/icons-material/Delete"));
|
|
7
|
+
const Refresh_1 = tslib_1.__importDefault(require("@mui/icons-material/Refresh"));
|
|
8
|
+
const material_1 = require("@mui/material");
|
|
9
|
+
const PneModal_1 = tslib_1.__importDefault(require("../PneModal"));
|
|
10
|
+
const PneTextField_1 = tslib_1.__importDefault(require("../PneTextField"));
|
|
11
|
+
const PneButton_1 = tslib_1.__importDefault(require("../PneButton"));
|
|
12
|
+
const defaultTitle = 'Layouts';
|
|
13
|
+
const defaultAddLabel = 'Add new layout';
|
|
14
|
+
const PneLayoutsPanel = ({ items, selectedId, onSelect, onDelete, onUpdate, onAdd, title = defaultTitle, addLabel = defaultAddLabel, className, }) => {
|
|
15
|
+
const [modalOpen, setModalOpen] = (0, react_1.useState)(false);
|
|
16
|
+
const [name, setName] = (0, react_1.useState)('');
|
|
17
|
+
const handleSave = () => {
|
|
18
|
+
const trimmed = name.trim();
|
|
19
|
+
if (!trimmed || !onAdd)
|
|
20
|
+
return;
|
|
21
|
+
onAdd(trimmed);
|
|
22
|
+
setName('');
|
|
23
|
+
setModalOpen(false);
|
|
24
|
+
};
|
|
25
|
+
const hasAdd = Boolean(onAdd);
|
|
26
|
+
return (react_1.default.createElement(material_1.Box, { sx: { width: 320, maxWidth: '100%', bgcolor: '#fff', fontSize: '14px', lineHeight: '20px' }, className: className },
|
|
27
|
+
react_1.default.createElement(material_1.Box, { sx: {
|
|
28
|
+
bgcolor: '#fff',
|
|
29
|
+
color: '#8A94A6',
|
|
30
|
+
px: 2,
|
|
31
|
+
minHeight: 32,
|
|
32
|
+
display: 'flex',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
borderBottom: '1px solid #0000001F',
|
|
35
|
+
} },
|
|
36
|
+
react_1.default.createElement(material_1.Typography, { variant: 'subtitle2', sx: { lineHeight: '20px', fontWeight: 400, fontSize: '14px' } }, title)),
|
|
37
|
+
react_1.default.createElement(material_1.Stack, null, items.length === 0 ? (react_1.default.createElement(material_1.Box, { sx: { px: 2, minHeight: 32, display: 'flex', alignItems: 'center', color: 'text.secondary' } }, "No layouts yet")) : (items.map(item => {
|
|
38
|
+
const selected = item.id === selectedId;
|
|
39
|
+
return (react_1.default.createElement(material_1.Box, { key: item.id, onClick: () => onSelect?.(item.id), sx: {
|
|
40
|
+
display: 'flex',
|
|
41
|
+
alignItems: 'center',
|
|
42
|
+
gap: 0.5,
|
|
43
|
+
px: 2,
|
|
44
|
+
minHeight: 32,
|
|
45
|
+
cursor: onSelect ? 'pointer' : 'default',
|
|
46
|
+
bgcolor: selected ? '#EFF2F5' : '#fff',
|
|
47
|
+
color: selected ? 'primary.main' : 'text.primary',
|
|
48
|
+
transition: 'background-color 0.2s ease, color 0.2s ease',
|
|
49
|
+
} },
|
|
50
|
+
react_1.default.createElement(material_1.Box, { sx: { flex: 1, fontWeight: 400, fontSize: '14px', lineHeight: '20px' } }, item.name),
|
|
51
|
+
onUpdate && selected ? (react_1.default.createElement(material_1.IconButton, { size: 'small', color: 'inherit', onClick: event => {
|
|
52
|
+
event.stopPropagation();
|
|
53
|
+
onUpdate(item.id);
|
|
54
|
+
} },
|
|
55
|
+
react_1.default.createElement(Refresh_1.default, { fontSize: 'small' }))) : null,
|
|
56
|
+
onDelete ? (react_1.default.createElement(material_1.IconButton, { size: 'small', color: 'inherit', onClick: event => {
|
|
57
|
+
event.stopPropagation();
|
|
58
|
+
onDelete(item.id);
|
|
59
|
+
} },
|
|
60
|
+
react_1.default.createElement(Delete_1.default, { fontSize: 'small' }))) : null));
|
|
61
|
+
}))),
|
|
62
|
+
hasAdd ? (react_1.default.createElement(material_1.Box, null,
|
|
63
|
+
react_1.default.createElement(PneButton_1.default, { fullWidth: true, pneStyle: 'text', size: 'small', onClick: () => setModalOpen(true), sx: {
|
|
64
|
+
height: 32,
|
|
65
|
+
justifyContent: 'flex-start',
|
|
66
|
+
px: 2,
|
|
67
|
+
fontSize: '14px',
|
|
68
|
+
lineHeight: '20px',
|
|
69
|
+
color: 'primary.main',
|
|
70
|
+
textDecoration: 'none',
|
|
71
|
+
minWidth: 0,
|
|
72
|
+
'&:hover': {
|
|
73
|
+
backgroundColor: 'transparent',
|
|
74
|
+
textDecoration: 'none',
|
|
75
|
+
},
|
|
76
|
+
} }, addLabel))) : null,
|
|
77
|
+
hasAdd ? (react_1.default.createElement(PneModal_1.default, { open: modalOpen, onClose: () => setModalOpen(false), title: 'New layout' },
|
|
78
|
+
react_1.default.createElement(material_1.Stack, { spacing: 2 },
|
|
79
|
+
react_1.default.createElement(PneTextField_1.default, { label: 'Template name', fullWidth: true, value: name, onChange: event => setName(event.target.value), autoFocus: true }),
|
|
80
|
+
react_1.default.createElement(material_1.Box, { sx: { display: 'flex', gap: 1, justifyContent: 'flex-end' } },
|
|
81
|
+
react_1.default.createElement(PneButton_1.default, { pneStyle: 'text', size: 'small', onClick: () => setModalOpen(false), sx: { height: 32, fontSize: '14px', lineHeight: '20px' } }, "Cancel"),
|
|
82
|
+
react_1.default.createElement(PneButton_1.default, { pneStyle: 'contained', size: 'small', onClick: handleSave, disabled: !name.trim(), sx: { height: 32, fontSize: '14px', lineHeight: '20px' } }, "Save"))))) : null));
|
|
83
|
+
};
|
|
84
|
+
exports.PneLayoutsPanel = PneLayoutsPanel;
|
|
85
|
+
exports.default = exports.PneLayoutsPanel;
|
|
86
|
+
//# sourceMappingURL=PneLayoutsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PneLayoutsPanel.js","sourceRoot":"","sources":["../../../src/component/widget-board/PneLayoutsPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -8,9 +8,7 @@ const board_item_1 = tslib_1.__importDefault(require("@cloudscape-design/board-c
|
|
|
8
8
|
const Close_1 = tslib_1.__importDefault(require("@mui/icons-material/Close"));
|
|
9
9
|
const ExpandLess_1 = tslib_1.__importDefault(require("@mui/icons-material/ExpandLess"));
|
|
10
10
|
const ExpandMore_1 = tslib_1.__importDefault(require("@mui/icons-material/ExpandMore"));
|
|
11
|
-
const RestartAlt_1 = tslib_1.__importDefault(require("@mui/icons-material/RestartAlt"));
|
|
12
11
|
const material_1 = require("@mui/material");
|
|
13
|
-
const PneButton_1 = tslib_1.__importDefault(require("../PneButton"));
|
|
14
12
|
const CloudscapeBoardStyles_1 = require("../cloudscape/CloudscapeBoardStyles");
|
|
15
13
|
const CloudscapeThemeProvider_1 = require("../cloudscape/CloudscapeThemeProvider");
|
|
16
14
|
const boardI18n_1 = require("../cloudscape/boardI18n");
|
|
@@ -87,20 +85,168 @@ const getLayoutConfigForWidth = (width, layoutMap, breakpoints) => {
|
|
|
87
85
|
const breakpoint = resolveBreakpoint(width, breakpoints);
|
|
88
86
|
return { breakpoint, layout: layoutMap[breakpoint] };
|
|
89
87
|
};
|
|
90
|
-
const buildStoragePayload = (state) =>
|
|
88
|
+
const buildStoragePayload = (state) => ({
|
|
91
89
|
items: state.items.map(({ id, columnSpan, columnOffset, rowSpan }) => ({ id, columnSpan, columnOffset, rowSpan })),
|
|
92
90
|
hidden: state.hidden,
|
|
93
91
|
collapsed: state.collapsed,
|
|
94
92
|
sizeMemory: state.sizeMemory,
|
|
95
93
|
});
|
|
96
|
-
const hydrateStoragePayload = (raw) => JSON.parse(raw);
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
const hydrateStoragePayload = (raw) => (typeof raw === 'string' ? JSON.parse(raw) : raw);
|
|
95
|
+
const readPersistedLayouts = (storageKey) => {
|
|
96
|
+
if (typeof window === 'undefined')
|
|
97
|
+
return null;
|
|
98
|
+
const raw = window.localStorage.getItem(storageKey);
|
|
99
|
+
if (!raw)
|
|
100
|
+
return null;
|
|
101
|
+
try {
|
|
102
|
+
const parsed = JSON.parse(raw);
|
|
103
|
+
if (parsed && typeof parsed === 'object' && 'layouts' in parsed) {
|
|
104
|
+
const layouts = parsed.layouts ?? {};
|
|
105
|
+
const selectedLayoutId = parsed.selectedLayoutId;
|
|
106
|
+
return { layouts, selectedLayoutId };
|
|
107
|
+
}
|
|
108
|
+
if (parsed && typeof parsed === 'object' && 'items' in parsed) {
|
|
109
|
+
return {
|
|
110
|
+
layouts: { __legacy: parsed },
|
|
111
|
+
selectedLayoutId: '__legacy',
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// ignore corrupt storage payloads
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
};
|
|
120
|
+
const buildLayoutOptions = (options, layoutByBreakpoint) => {
|
|
121
|
+
if (options?.length) {
|
|
122
|
+
return options.map(option => ({
|
|
123
|
+
...option,
|
|
124
|
+
preset: option.preset ?? {
|
|
125
|
+
layoutByBreakpoint,
|
|
126
|
+
source: 'static',
|
|
127
|
+
},
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
id: 'default',
|
|
133
|
+
name: 'Default layout',
|
|
134
|
+
preset: {
|
|
135
|
+
layoutByBreakpoint,
|
|
136
|
+
source: 'static',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
];
|
|
140
|
+
};
|
|
141
|
+
const layoutOptionsEqual = (a, b) => a.length === b.length && a.every((option, index) => option.id === b[index]?.id && option.name === b[index]?.name && option.preset === b[index]?.preset);
|
|
142
|
+
exports.WidgetBoard = (0, react_1.forwardRef)(function WidgetBoard({ widgets, layoutByBreakpoint, breakpoints: customBreakpoints, storageKey = 'pne-widget-board-layout', loadLayouts, layouts, empty, hideNavigationArrows = true, onLayoutPersist, isWidgetEnabled, className, }, ref) {
|
|
143
|
+
const initialPersistedLayouts = typeof window !== 'undefined' ? readPersistedLayouts(storageKey) : null;
|
|
144
|
+
const persistedLayoutsRef = (0, react_1.useRef)(initialPersistedLayouts ?? { layouts: {} });
|
|
145
|
+
const [layoutOptions, setLayoutOptions] = (0, react_1.useState)(() => buildLayoutOptions(layouts?.options, layoutByBreakpoint));
|
|
146
|
+
(0, react_1.useEffect)(() => {
|
|
147
|
+
if (loadLayouts)
|
|
148
|
+
return;
|
|
149
|
+
const nextOptions = buildLayoutOptions(layouts?.options, layoutByBreakpoint);
|
|
150
|
+
setLayoutOptions(prev => (layoutOptionsEqual(prev, nextOptions) ? prev : nextOptions));
|
|
151
|
+
}, [layoutByBreakpoint, layouts?.options, loadLayouts]);
|
|
152
|
+
const layoutOptionsMap = (0, react_1.useMemo)(() => new Map(layoutOptions.map(option => [option.id, option])), [layoutOptions]);
|
|
153
|
+
const initialLayoutId = (0, react_1.useMemo)(() => {
|
|
154
|
+
const fromLayouts = layouts?.selectedId;
|
|
155
|
+
if (fromLayouts && layoutOptionsMap.has(fromLayouts))
|
|
156
|
+
return fromLayouts;
|
|
157
|
+
const persistedId = persistedLayoutsRef.current.selectedLayoutId;
|
|
158
|
+
if (persistedId && layoutOptionsMap.has(persistedId))
|
|
159
|
+
return persistedId;
|
|
160
|
+
if (layouts?.initialSelectedId && layoutOptionsMap.has(layouts.initialSelectedId))
|
|
161
|
+
return layouts.initialSelectedId;
|
|
162
|
+
return layoutOptions[0]?.id;
|
|
163
|
+
}, [layoutOptions, layoutOptionsMap, layouts?.initialSelectedId, layouts?.selectedId]);
|
|
99
164
|
const [layoutSource, setLayoutSource] = (0, react_1.useState)(() => ({
|
|
100
|
-
layoutByBreakpoint,
|
|
101
|
-
source: 'static',
|
|
165
|
+
...(layoutOptionsMap.get(initialLayoutId ?? '')?.preset ?? { layoutByBreakpoint, source: 'static' }),
|
|
102
166
|
}));
|
|
167
|
+
const breakpoints = (0, react_1.useMemo)(() => customBreakpoints ?? Object.keys(layoutSource.layoutByBreakpoint).map(Number).sort((a, b) => a - b), [customBreakpoints, layoutSource.layoutByBreakpoint]);
|
|
103
168
|
const [layoutPreset, setLayoutPreset] = (0, react_1.useState)(() => getLayoutConfigForWidth(typeof window !== 'undefined' ? window.innerWidth : undefined, layoutSource.layoutByBreakpoint, breakpoints));
|
|
169
|
+
(0, react_1.useEffect)(() => {
|
|
170
|
+
setLayoutPreset(getLayoutConfigForWidth(typeof window !== 'undefined' ? window.innerWidth : undefined, layoutSource.layoutByBreakpoint, breakpoints));
|
|
171
|
+
}, [breakpoints, layoutSource.layoutByBreakpoint]);
|
|
172
|
+
const [selectedLayoutId, setSelectedLayoutId] = (0, react_1.useState)(initialLayoutId);
|
|
173
|
+
const selectedLayoutRef = (0, react_1.useRef)(initialLayoutId);
|
|
174
|
+
(0, react_1.useEffect)(() => {
|
|
175
|
+
selectedLayoutRef.current = selectedLayoutId;
|
|
176
|
+
}, [selectedLayoutId]);
|
|
177
|
+
(0, react_1.useEffect)(() => {
|
|
178
|
+
if (!selectedLayoutId || layoutOptionsMap.has(selectedLayoutId))
|
|
179
|
+
return;
|
|
180
|
+
const fallbackId = layoutOptions[0]?.id;
|
|
181
|
+
if (fallbackId && fallbackId !== selectedLayoutId) {
|
|
182
|
+
setSelectedLayoutId(fallbackId);
|
|
183
|
+
layouts?.onSelect?.(fallbackId);
|
|
184
|
+
}
|
|
185
|
+
}, [layoutOptions, layoutOptionsMap, layouts?.onSelect, selectedLayoutId]);
|
|
186
|
+
(0, react_1.useEffect)(() => {
|
|
187
|
+
const externalSelected = layouts?.selectedId;
|
|
188
|
+
if (!externalSelected)
|
|
189
|
+
return;
|
|
190
|
+
if (!layoutOptionsMap.has(externalSelected))
|
|
191
|
+
return;
|
|
192
|
+
if (externalSelected !== selectedLayoutId) {
|
|
193
|
+
setSelectedLayoutId(externalSelected);
|
|
194
|
+
}
|
|
195
|
+
}, [layoutOptionsMap, layouts?.selectedId, selectedLayoutId]);
|
|
196
|
+
(0, react_1.useEffect)(() => {
|
|
197
|
+
if (!selectedLayoutId || !layouts?.onSelect)
|
|
198
|
+
return;
|
|
199
|
+
if (layouts.selectedId === selectedLayoutId)
|
|
200
|
+
return;
|
|
201
|
+
layouts.onSelect(selectedLayoutId);
|
|
202
|
+
}, [layouts?.onSelect, layouts?.selectedId, selectedLayoutId]);
|
|
203
|
+
(0, react_1.useEffect)(() => {
|
|
204
|
+
const nextSource = layoutOptionsMap.get(selectedLayoutId ?? '')?.preset ?? {
|
|
205
|
+
layoutByBreakpoint,
|
|
206
|
+
source: 'static',
|
|
207
|
+
};
|
|
208
|
+
setLayoutSource(prev => (prev === nextSource ? prev : nextSource));
|
|
209
|
+
}, [layoutByBreakpoint, layoutOptionsMap, selectedLayoutId]);
|
|
210
|
+
(0, react_1.useEffect)(() => {
|
|
211
|
+
if (typeof window === 'undefined')
|
|
212
|
+
return;
|
|
213
|
+
const nextPersisted = readPersistedLayouts(storageKey) ?? { layouts: {} };
|
|
214
|
+
persistedLayoutsRef.current = nextPersisted;
|
|
215
|
+
if (nextPersisted.selectedLayoutId &&
|
|
216
|
+
layoutOptionsMap.has(nextPersisted.selectedLayoutId) &&
|
|
217
|
+
nextPersisted.selectedLayoutId !== selectedLayoutId) {
|
|
218
|
+
setSelectedLayoutId(nextPersisted.selectedLayoutId);
|
|
219
|
+
}
|
|
220
|
+
}, [layoutOptionsMap, selectedLayoutId, storageKey]);
|
|
221
|
+
(0, react_1.useEffect)(() => {
|
|
222
|
+
let cancelled = false;
|
|
223
|
+
if (!loadLayouts)
|
|
224
|
+
return undefined;
|
|
225
|
+
loadLayouts().then(result => {
|
|
226
|
+
if (cancelled || !result?.options)
|
|
227
|
+
return;
|
|
228
|
+
const nextOptions = buildLayoutOptions(result.options, layoutByBreakpoint);
|
|
229
|
+
setLayoutOptions(prev => (layoutOptionsEqual(prev, nextOptions) ? prev : nextOptions));
|
|
230
|
+
const currentSelected = selectedLayoutRef.current;
|
|
231
|
+
let nextSelected = currentSelected && nextOptions.some(option => option.id === currentSelected) ? currentSelected : undefined;
|
|
232
|
+
if (result.selectedId && nextOptions.some(option => option.id === result.selectedId)) {
|
|
233
|
+
nextSelected = result.selectedId;
|
|
234
|
+
}
|
|
235
|
+
else if (!nextSelected) {
|
|
236
|
+
nextSelected = nextOptions[0]?.id;
|
|
237
|
+
}
|
|
238
|
+
if (nextSelected && nextSelected !== currentSelected) {
|
|
239
|
+
setSelectedLayoutId(nextSelected);
|
|
240
|
+
layouts?.onSelect?.(nextSelected);
|
|
241
|
+
}
|
|
242
|
+
else if (!currentSelected && nextSelected) {
|
|
243
|
+
setSelectedLayoutId(nextSelected);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
return () => {
|
|
247
|
+
cancelled = true;
|
|
248
|
+
};
|
|
249
|
+
}, [layoutByBreakpoint, loadLayouts, layouts?.onSelect]);
|
|
104
250
|
const fallbackLayoutConfig = (0, react_1.useMemo)(() => {
|
|
105
251
|
const firstKey = breakpoints[0];
|
|
106
252
|
return layoutSource.layoutByBreakpoint[firstKey] ?? Object.values(layoutSource.layoutByBreakpoint)[0];
|
|
@@ -110,10 +256,11 @@ exports.WidgetBoard = (0, react_1.forwardRef)(function WidgetBoard({ widgets, la
|
|
|
110
256
|
const definitionsMap = (0, react_1.useMemo)(() => new Map(activeDefinitions.map(def => [def.id, def])), [activeDefinitions]);
|
|
111
257
|
const [layoutState, setLayoutState] = (0, react_1.useState)(() => buildDefaultState(activeDefinitions));
|
|
112
258
|
(0, react_1.useEffect)(() => {
|
|
113
|
-
const
|
|
114
|
-
|
|
259
|
+
const storagePayload = (selectedLayoutId && persistedLayoutsRef.current.layouts[selectedLayoutId]) ??
|
|
260
|
+
persistedLayoutsRef.current.layouts.__legacy;
|
|
261
|
+
if (storagePayload) {
|
|
115
262
|
try {
|
|
116
|
-
const parsed = hydrateStoragePayload(
|
|
263
|
+
const parsed = hydrateStoragePayload(storagePayload);
|
|
117
264
|
const items = (parsed.items || []).flatMap(item => {
|
|
118
265
|
const definition = definitionsMap.get(item.id);
|
|
119
266
|
if (!definition)
|
|
@@ -142,7 +289,7 @@ exports.WidgetBoard = (0, react_1.forwardRef)(function WidgetBoard({ widgets, la
|
|
|
142
289
|
}
|
|
143
290
|
}
|
|
144
291
|
setLayoutState(buildDefaultState(activeDefinitions));
|
|
145
|
-
}, [activeDefinitions, definitionsMap,
|
|
292
|
+
}, [activeDefinitions, definitionsMap, selectedLayoutId]);
|
|
146
293
|
(0, react_1.useEffect)(() => {
|
|
147
294
|
if (typeof window === 'undefined')
|
|
148
295
|
return;
|
|
@@ -151,35 +298,26 @@ exports.WidgetBoard = (0, react_1.forwardRef)(function WidgetBoard({ widgets, la
|
|
|
151
298
|
return () => window.removeEventListener('resize', handleResize);
|
|
152
299
|
}, [breakpoints, layoutSource.layoutByBreakpoint]);
|
|
153
300
|
(0, react_1.useEffect)(() => {
|
|
154
|
-
|
|
155
|
-
if (!loadRemoteLayout)
|
|
156
|
-
return undefined;
|
|
157
|
-
loadRemoteLayout().then(preset => {
|
|
158
|
-
if (!mounted || !preset?.layoutByBreakpoint)
|
|
159
|
-
return;
|
|
160
|
-
setLayoutSource(preset);
|
|
161
|
-
const nextPreset = getLayoutConfigForWidth(typeof window !== 'undefined' ? window.innerWidth : undefined, preset.layoutByBreakpoint, breakpoints);
|
|
162
|
-
const nextLayout = nextPreset.layout ?? Object.values(preset.layoutByBreakpoint)[0] ?? fallbackLayoutConfig;
|
|
163
|
-
setLayoutPreset(nextPreset);
|
|
164
|
-
const nextDefinitions = withLayout(widgets, nextLayout);
|
|
165
|
-
const nextActiveDefinitions = nextDefinitions.filter(def => (isWidgetEnabled ? isWidgetEnabled(def) : true));
|
|
166
|
-
setLayoutState(buildDefaultState(nextActiveDefinitions));
|
|
167
|
-
});
|
|
168
|
-
return () => {
|
|
169
|
-
mounted = false;
|
|
170
|
-
};
|
|
171
|
-
}, [breakpoints, fallbackLayoutConfig, isWidgetEnabled, loadRemoteLayout, widgets]);
|
|
172
|
-
(0, react_1.useEffect)(() => {
|
|
173
|
-
if (typeof window === 'undefined')
|
|
301
|
+
if (typeof window === 'undefined' || !selectedLayoutId)
|
|
174
302
|
return;
|
|
175
303
|
try {
|
|
176
|
-
|
|
304
|
+
const payload = buildStoragePayload(layoutState);
|
|
305
|
+
const nextPersisted = {
|
|
306
|
+
...persistedLayoutsRef.current,
|
|
307
|
+
selectedLayoutId,
|
|
308
|
+
layouts: {
|
|
309
|
+
...persistedLayoutsRef.current.layouts,
|
|
310
|
+
[selectedLayoutId]: payload,
|
|
311
|
+
},
|
|
312
|
+
};
|
|
313
|
+
persistedLayoutsRef.current = nextPersisted;
|
|
314
|
+
window.localStorage.setItem(storageKey, JSON.stringify(nextPersisted));
|
|
177
315
|
onLayoutPersist?.(layoutState);
|
|
178
316
|
}
|
|
179
317
|
catch {
|
|
180
318
|
// ignore storage failures
|
|
181
319
|
}
|
|
182
|
-
}, [layoutState, onLayoutPersist, storageKey]);
|
|
320
|
+
}, [layoutState, onLayoutPersist, selectedLayoutId, storageKey]);
|
|
183
321
|
const hideItem = (0, react_1.useCallback)((id) => {
|
|
184
322
|
setLayoutState(prev => ({
|
|
185
323
|
...prev,
|
|
@@ -286,17 +424,9 @@ exports.WidgetBoard = (0, react_1.forwardRef)(function WidgetBoard({ widgets, la
|
|
|
286
424
|
return (react_1.default.createElement(board_item_1.default, { key: item.id, i18nStrings: boardI18n_1.boardItemI18nStrings, header: headerElement, settings: settingsElement, disableContentPaddings: true },
|
|
287
425
|
react_1.default.createElement(material_1.Box, { sx: { p: 2, height: '100%', boxSizing: 'border-box', overflow: 'hidden' } }, isCollapsed ? react_1.default.createElement(material_1.Typography, { sx: { color: 'text.secondary', fontSize: 14 } }, "Collapsed") : definition.render())));
|
|
288
426
|
};
|
|
289
|
-
const controlsConfig = controls ?? {};
|
|
290
|
-
const showControls = controlsConfig.hideReset !== true || (controlsConfig.hideRestore !== true && layoutState.hidden.length > 0);
|
|
291
427
|
return (react_1.default.createElement(CloudscapeThemeProvider_1.CloudscapeThemeProvider, null,
|
|
292
428
|
react_1.default.createElement(CloudscapeBoardStyles_1.CloudscapeBoardStyles, { hideNavigationArrows: hideNavigationArrows }),
|
|
293
|
-
react_1.default.createElement(material_1.
|
|
294
|
-
showControls && (react_1.default.createElement(material_1.Stack, { direction: { xs: 'column', sm: 'row' }, alignItems: { xs: 'flex-start', sm: 'center' }, justifyContent: 'space-between', spacing: 1 },
|
|
295
|
-
react_1.default.createElement(material_1.Typography, { variant: 'h6', fontWeight: 700 }, controlsConfig.title ?? 'Widgets layout'),
|
|
296
|
-
react_1.default.createElement(material_1.Stack, { direction: 'row', spacing: 1 },
|
|
297
|
-
controlsConfig.hideReset !== true && (react_1.default.createElement(PneButton_1.default, { onClick: resetLayout, pneStyle: 'outlined', startIcon: react_1.default.createElement(RestartAlt_1.default, null) }, controlsConfig.resetLabel ?? 'Reset to default')),
|
|
298
|
-
layoutState.hidden.length > 0 && controlsConfig.hideRestore !== true && (react_1.default.createElement(PneButton_1.default, { pneStyle: 'text', onClick: () => layoutState.hidden.forEach(restoreItem) }, controlsConfig.restoreLabel ?? 'Restore hidden'))))),
|
|
299
|
-
layoutState.hidden.length > 0 && (react_1.default.createElement(material_1.Stack, { direction: 'row', spacing: 1, flexWrap: 'wrap' }, layoutState.hidden.map(id => (react_1.default.createElement(material_1.Chip, { key: id, variant: 'outlined', label: `Show ${definitionsMap.get(id)?.title ?? id}`, onClick: () => restoreItem(id), size: 'small' }))))),
|
|
429
|
+
react_1.default.createElement(material_1.Box, { className: className },
|
|
300
430
|
react_1.default.createElement(board_1.default, { items: visibleItems, renderItem: renderItem, i18nStrings: boardI18nStrings, onItemsChange: handleItemsChange, empty: empty ?? react_1.default.createElement(material_1.Box, { sx: { p: 2, color: 'text.secondary' } }, "No widgets available") }))));
|
|
301
431
|
});
|
|
302
432
|
//# sourceMappingURL=WidgetBoard.js.map
|