@evoke-platform/ui-components 1.6.0-dev.1 → 1.6.0-dev.3
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/dist/published/components/core/index.d.ts +1 -1
- package/dist/published/components/core/index.js +1 -1
- package/dist/published/components/custom/BuilderGrid/BuilderGrid.js +27 -27
- package/dist/published/theme/hooks.d.ts +78 -0
- package/dist/published/theme/hooks.js +65 -0
- package/dist/published/theme/hooks.test.d.ts +1 -0
- package/dist/published/theme/hooks.test.js +187 -0
- package/dist/published/theme/index.d.ts +2 -2
- package/dist/published/theme/index.js +2 -2
- package/package.json +2 -1
@@ -47,7 +47,7 @@ export { Tooltip } from './Tooltip';
|
|
47
47
|
export { Typography } from './Typography';
|
48
48
|
export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
|
49
49
|
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, MenuList, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
|
50
|
-
export { useGridApiRef } from '@mui/x-data-grid';
|
50
|
+
export { GridToolbarContainer, GridToolbarQuickFilter, useGridApiRef } from '@mui/x-data-grid';
|
51
51
|
export { TreeItem as RichTreeItem, RichTreeView, TreeItem2Content, TreeItem2DragAndDropOverlay, TreeItem2GroupTransition, TreeItem2Icon, TreeItem2IconContainer, TreeItem2Label, TreeItem2Provider, TreeItem2Root, useTreeItem2, } from '@mui/x-tree-view';
|
52
52
|
export type { GridSize } from '@mui/material';
|
53
53
|
export type { GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridInitialState, GridRowParams, GridSortModel, GridValueFormatterParams, GridValueGetterParams, } from '@mui/x-data-grid';
|
@@ -48,5 +48,5 @@ export { Typography } from './Typography';
|
|
48
48
|
//TODO: Review following components. They also need theme control:
|
49
49
|
export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
|
50
50
|
export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, MenuList, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
|
51
|
-
export { useGridApiRef } from '@mui/x-data-grid';
|
51
|
+
export { GridToolbarContainer, GridToolbarQuickFilter, useGridApiRef } from '@mui/x-data-grid';
|
52
52
|
export { TreeItem as RichTreeItem, RichTreeView, TreeItem2Content, TreeItem2DragAndDropOverlay, TreeItem2GroupTransition, TreeItem2Icon, TreeItem2IconContainer, TreeItem2Label, TreeItem2Provider, TreeItem2Root, useTreeItem2, } from '@mui/x-tree-view';
|
@@ -17,7 +17,32 @@ const BuilderGrid = (props) => {
|
|
17
17
|
borderBottom: 'none',
|
18
18
|
boxShadow: 'rgba(145, 158, 171, 0.2) 0px 8px 16px',
|
19
19
|
} },
|
20
|
-
React.createElement(MuiDataGrid, { autoPageSize: !disablePagination, hideFooterPagination: disablePagination, hideFooter: disablePagination, onMenuOpen: (env) => setAnchorEl(env.target), loading: loading, rows: rows,
|
20
|
+
React.createElement(MuiDataGrid, { autoPageSize: !disablePagination, hideFooterPagination: disablePagination, hideFooter: disablePagination, onMenuOpen: (env) => setAnchorEl(env.target), loading: loading, rows: rows, getRowId: (row) => row.id, disableColumnMenu: true, initialState: {
|
21
|
+
sorting: {
|
22
|
+
sortModel: initialSort ? [initialSort] : [],
|
23
|
+
},
|
24
|
+
}, componentsProps: {
|
25
|
+
panel: {
|
26
|
+
anchorEl: anchorEl,
|
27
|
+
placement: 'bottom-end',
|
28
|
+
sx: {
|
29
|
+
'& .MuiPaper-root': {
|
30
|
+
borderRadius: '6px',
|
31
|
+
boxShadow: '0px 24px 48px rgba(145, 158, 171, 0.4)',
|
32
|
+
padding: '8px',
|
33
|
+
stop: -120,
|
34
|
+
},
|
35
|
+
},
|
36
|
+
},
|
37
|
+
}, slots: {
|
38
|
+
toolbar: hideToolbar ? null : toolbar,
|
39
|
+
noResultsOverlay: () => {
|
40
|
+
return React.createElement(Box, null);
|
41
|
+
},
|
42
|
+
noRowsOverlay: () => {
|
43
|
+
return noRowsOverlay ? noRowsOverlay : null;
|
44
|
+
},
|
45
|
+
}, rowHeight: 60, columnHeaderHeight: 62, ...rest, sx: {
|
21
46
|
border: 'none',
|
22
47
|
'& .MuiDataGrid-toolbarContainer': {
|
23
48
|
padding: '0',
|
@@ -64,32 +89,7 @@ const BuilderGrid = (props) => {
|
|
64
89
|
},
|
65
90
|
height: disablePagination && !loading ? 'auto' : 'calc(100vh - 240px)',
|
66
91
|
...rest.sx,
|
67
|
-
}
|
68
|
-
sorting: {
|
69
|
-
sortModel: initialSort ? [initialSort] : [],
|
70
|
-
},
|
71
|
-
}, componentsProps: {
|
72
|
-
panel: {
|
73
|
-
anchorEl: anchorEl,
|
74
|
-
placement: 'bottom-end',
|
75
|
-
sx: {
|
76
|
-
'& .MuiPaper-root': {
|
77
|
-
borderRadius: '6px',
|
78
|
-
boxShadow: '0px 24px 48px rgba(145, 158, 171, 0.4)',
|
79
|
-
padding: '8px',
|
80
|
-
stop: -120,
|
81
|
-
},
|
82
|
-
},
|
83
|
-
},
|
84
|
-
}, slots: {
|
85
|
-
toolbar: hideToolbar ? null : toolbar,
|
86
|
-
noResultsOverlay: () => {
|
87
|
-
return React.createElement(Box, null);
|
88
|
-
},
|
89
|
-
noRowsOverlay: () => {
|
90
|
-
return noRowsOverlay ? noRowsOverlay : null;
|
91
|
-
},
|
92
|
-
}, rowHeight: 60, columnHeaderHeight: 62 }))) : (React.createElement(React.Fragment, null, error ? (React.createElement(Box, { sx: {
|
92
|
+
} }))) : (React.createElement(React.Fragment, null, error ? (React.createElement(Box, { sx: {
|
93
93
|
backgroundColor: '#fff',
|
94
94
|
borderRadius: '6px',
|
95
95
|
display: 'flex',
|
@@ -29,3 +29,81 @@ export declare function useResponsive(): {
|
|
29
29
|
/** Returns true if viewport width is between the specified breakpoints */
|
30
30
|
between: (start: Breakpoint, end: Breakpoint) => boolean;
|
31
31
|
};
|
32
|
+
export interface WidgetSizeInfo {
|
33
|
+
/** The ref to attach to the widget container */
|
34
|
+
ref: (element: HTMLElement | SVGElement | null) => void;
|
35
|
+
/** Width in pixels */
|
36
|
+
width: number;
|
37
|
+
/** Height in pixels */
|
38
|
+
height: number;
|
39
|
+
/** Widget size breakpoints */
|
40
|
+
breakpoints: {
|
41
|
+
/** Extra small: width < 800px */
|
42
|
+
isXs: boolean;
|
43
|
+
/** Small: 800px <= width < 1000px */
|
44
|
+
isSm: boolean;
|
45
|
+
/** Medium: 1000px <= width < 1200px */
|
46
|
+
isMd: boolean;
|
47
|
+
/** Large: 1200px <= width < 1400px */
|
48
|
+
isLg: boolean;
|
49
|
+
/** Extra large: width >= 1400px */
|
50
|
+
isXl: boolean;
|
51
|
+
/** Compact height: height < 300px */
|
52
|
+
isCompact: boolean;
|
53
|
+
/** Tall height: height >= 600px */
|
54
|
+
isTall: boolean;
|
55
|
+
};
|
56
|
+
/** Bounds information from react-use-measure */
|
57
|
+
bounds: {
|
58
|
+
/**
|
59
|
+
* left is usually the same as x, but can differ if width is negative.
|
60
|
+
* See: https://developer.mozilla.org/en-US/docs/Web/API/DOMRect
|
61
|
+
*/
|
62
|
+
left: number;
|
63
|
+
/**
|
64
|
+
* top is usually the same as y, but can differ if height is negative.
|
65
|
+
* See: https://developer.mozilla.org/en-US/docs/Web/API/DOMRect
|
66
|
+
*/
|
67
|
+
top: number;
|
68
|
+
width: number;
|
69
|
+
height: number;
|
70
|
+
bottom: number;
|
71
|
+
right: number;
|
72
|
+
x: number;
|
73
|
+
y: number;
|
74
|
+
};
|
75
|
+
/** Check if widget is above a breakpoint */
|
76
|
+
isAbove: (breakpoint: 'xs' | 'sm' | 'md' | 'lg' | 'xl') => boolean;
|
77
|
+
/** Check if widget is below a breakpoint */
|
78
|
+
isBelow: (breakpoint: 'xs' | 'sm' | 'md' | 'lg' | 'xl') => boolean;
|
79
|
+
}
|
80
|
+
/**
|
81
|
+
* Custom hook that measures widget dimensions and provides responsive breakpoints
|
82
|
+
* based on the actual widget size rather than viewport size.
|
83
|
+
*
|
84
|
+
* @param options Configuration options for the measurement
|
85
|
+
* @returns WidgetSizeInfo object with ref, dimensions, and breakpoints
|
86
|
+
*
|
87
|
+
* @example
|
88
|
+
* ```tsx
|
89
|
+
* const { ref, width, breakpoints } = useWidgetSize();
|
90
|
+
*
|
91
|
+
* return (
|
92
|
+
* <div ref={ref}>
|
93
|
+
* {breakpoints.isXs ? 'Compact view' : 'Full view'}
|
94
|
+
* <p>Widget width: {width}px</p>
|
95
|
+
* </div>
|
96
|
+
* );
|
97
|
+
* ```
|
98
|
+
*/
|
99
|
+
export declare const useWidgetSize: (options?: {
|
100
|
+
/** Debounce measurement updates (ms) */
|
101
|
+
debounce?: number;
|
102
|
+
/** Throttle measurement updates (ms) */
|
103
|
+
throttle?: number;
|
104
|
+
/** Scroll containers to observe */
|
105
|
+
scroll?: boolean;
|
106
|
+
/** Resize containers to observe */
|
107
|
+
resize?: boolean;
|
108
|
+
}) => WidgetSizeInfo;
|
109
|
+
export default useWidgetSize;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { useTheme } from '@mui/material';
|
2
2
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
3
|
+
import useMeasure from 'react-use-measure';
|
3
4
|
/**
|
4
5
|
* Custom hook for responsive design breakpoints using size terminology.
|
5
6
|
* Breakpoints based on MUI default theme:
|
@@ -33,3 +34,67 @@ export function useResponsive() {
|
|
33
34
|
between: (start, end) => useMediaQuery(theme.breakpoints.between(start, end)),
|
34
35
|
};
|
35
36
|
}
|
37
|
+
/**
|
38
|
+
* Custom hook that measures widget dimensions and provides responsive breakpoints
|
39
|
+
* based on the actual widget size rather than viewport size.
|
40
|
+
*
|
41
|
+
* @param options Configuration options for the measurement
|
42
|
+
* @returns WidgetSizeInfo object with ref, dimensions, and breakpoints
|
43
|
+
*
|
44
|
+
* @example
|
45
|
+
* ```tsx
|
46
|
+
* const { ref, width, breakpoints } = useWidgetSize();
|
47
|
+
*
|
48
|
+
* return (
|
49
|
+
* <div ref={ref}>
|
50
|
+
* {breakpoints.isXs ? 'Compact view' : 'Full view'}
|
51
|
+
* <p>Widget width: {width}px</p>
|
52
|
+
* </div>
|
53
|
+
* );
|
54
|
+
* ```
|
55
|
+
*/
|
56
|
+
export const useWidgetSize = (options) => {
|
57
|
+
const [ref, bounds] = useMeasure({
|
58
|
+
debounce: options?.debounce ?? 16,
|
59
|
+
scroll: options?.scroll ?? true,
|
60
|
+
offsetSize: true,
|
61
|
+
...options,
|
62
|
+
});
|
63
|
+
const width = bounds.width || 0;
|
64
|
+
const height = bounds.height || 0;
|
65
|
+
// Widget-specific breakpoints based on container width
|
66
|
+
const breakpoints = {
|
67
|
+
isXs: width < 800,
|
68
|
+
isSm: width >= 800 && width < 1000,
|
69
|
+
isMd: width >= 1000 && width < 1200,
|
70
|
+
isLg: width >= 1200 && width < 1400,
|
71
|
+
isXl: width >= 1400,
|
72
|
+
isCompact: height < 300,
|
73
|
+
isTall: height >= 600,
|
74
|
+
};
|
75
|
+
// Breakpoint thresholds
|
76
|
+
const breakpointThresholds = {
|
77
|
+
xs: 800,
|
78
|
+
sm: 1000,
|
79
|
+
md: 1200,
|
80
|
+
lg: 1400,
|
81
|
+
xl: Infinity,
|
82
|
+
};
|
83
|
+
// Utility functions for responsive checks
|
84
|
+
const isAbove = (breakpoint) => {
|
85
|
+
return width >= breakpointThresholds[breakpoint];
|
86
|
+
};
|
87
|
+
const isBelow = (breakpoint) => {
|
88
|
+
return width < breakpointThresholds[breakpoint];
|
89
|
+
};
|
90
|
+
return {
|
91
|
+
ref,
|
92
|
+
width,
|
93
|
+
height,
|
94
|
+
breakpoints,
|
95
|
+
bounds,
|
96
|
+
isAbove,
|
97
|
+
isBelow,
|
98
|
+
};
|
99
|
+
};
|
100
|
+
export default useWidgetSize;
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,187 @@
|
|
1
|
+
import { renderHook } from '@testing-library/react';
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
3
|
+
import { useWidgetSize } from '.';
|
4
|
+
// Shared mock bounds for useMeasure
|
5
|
+
let mockBounds = {
|
6
|
+
left: 0,
|
7
|
+
top: 0,
|
8
|
+
width: 0,
|
9
|
+
height: 0,
|
10
|
+
bottom: 0,
|
11
|
+
right: 0,
|
12
|
+
x: 0,
|
13
|
+
y: 0,
|
14
|
+
};
|
15
|
+
function setMockBounds(newBounds) {
|
16
|
+
mockBounds = { ...mockBounds, ...newBounds };
|
17
|
+
}
|
18
|
+
// Mock useMeasure from react-use-measure
|
19
|
+
vi.mock('react-use-measure', () => {
|
20
|
+
const useMeasure = () => [
|
21
|
+
vi.fn(),
|
22
|
+
mockBounds,
|
23
|
+
];
|
24
|
+
return { __esModule: true, default: useMeasure, useMeasure };
|
25
|
+
});
|
26
|
+
describe('useWidgetSize', () => {
|
27
|
+
beforeEach(() => {
|
28
|
+
// Reset bounds before each test
|
29
|
+
setMockBounds({
|
30
|
+
left: 0,
|
31
|
+
top: 0,
|
32
|
+
width: 0,
|
33
|
+
height: 0,
|
34
|
+
bottom: 0,
|
35
|
+
right: 0,
|
36
|
+
x: 0,
|
37
|
+
y: 0,
|
38
|
+
});
|
39
|
+
});
|
40
|
+
it('should provide ref and basic structure', () => {
|
41
|
+
setMockBounds({ width: 123, height: 456 });
|
42
|
+
const { result } = renderHook(() => useWidgetSize());
|
43
|
+
expect(result.current.ref).toBeDefined();
|
44
|
+
expect(typeof result.current.ref).toBe('function');
|
45
|
+
expect(result.current.width).toBe(123);
|
46
|
+
expect(result.current.height).toBe(456);
|
47
|
+
});
|
48
|
+
describe('breakpoints', () => {
|
49
|
+
it('should set isXs for width < 800', () => {
|
50
|
+
setMockBounds({ width: 799, height: 100 });
|
51
|
+
const { result } = renderHook(() => useWidgetSize());
|
52
|
+
expect(result.current.breakpoints.isXs).toBe(true);
|
53
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
54
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
55
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
56
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
57
|
+
});
|
58
|
+
it('should set isSm for 800 <= width < 1000', () => {
|
59
|
+
setMockBounds({ width: 800, height: 100 });
|
60
|
+
let { result } = renderHook(() => useWidgetSize());
|
61
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
62
|
+
expect(result.current.breakpoints.isSm).toBe(true);
|
63
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
64
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
65
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
66
|
+
setMockBounds({ width: 999, height: 100 });
|
67
|
+
result = renderHook(() => useWidgetSize()).result;
|
68
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
69
|
+
expect(result.current.breakpoints.isSm).toBe(true);
|
70
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
71
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
72
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
73
|
+
});
|
74
|
+
it('should set isMd for 1000 <= width < 1200', () => {
|
75
|
+
setMockBounds({ width: 1000, height: 100 });
|
76
|
+
let { result } = renderHook(() => useWidgetSize());
|
77
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
78
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
79
|
+
expect(result.current.breakpoints.isMd).toBe(true);
|
80
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
81
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
82
|
+
setMockBounds({ width: 1199, height: 100 });
|
83
|
+
result = renderHook(() => useWidgetSize()).result;
|
84
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
85
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
86
|
+
expect(result.current.breakpoints.isMd).toBe(true);
|
87
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
88
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
89
|
+
});
|
90
|
+
it('should set isLg for 1200 <= width < 1400', () => {
|
91
|
+
setMockBounds({ width: 1200, height: 100 });
|
92
|
+
let { result } = renderHook(() => useWidgetSize());
|
93
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
94
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
95
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
96
|
+
expect(result.current.breakpoints.isLg).toBe(true);
|
97
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
98
|
+
setMockBounds({ width: 1399, height: 100 });
|
99
|
+
result = renderHook(() => useWidgetSize()).result;
|
100
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
101
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
102
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
103
|
+
expect(result.current.breakpoints.isLg).toBe(true);
|
104
|
+
expect(result.current.breakpoints.isXl).toBe(false);
|
105
|
+
});
|
106
|
+
it('should set isXl for width >= 1400', () => {
|
107
|
+
setMockBounds({ width: 1400, height: 100 });
|
108
|
+
let { result } = renderHook(() => useWidgetSize());
|
109
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
110
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
111
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
112
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
113
|
+
expect(result.current.breakpoints.isXl).toBe(true);
|
114
|
+
setMockBounds({ width: 2000, height: 100 });
|
115
|
+
result = renderHook(() => useWidgetSize()).result;
|
116
|
+
expect(result.current.breakpoints.isXs).toBe(false);
|
117
|
+
expect(result.current.breakpoints.isSm).toBe(false);
|
118
|
+
expect(result.current.breakpoints.isMd).toBe(false);
|
119
|
+
expect(result.current.breakpoints.isLg).toBe(false);
|
120
|
+
expect(result.current.breakpoints.isXl).toBe(true);
|
121
|
+
});
|
122
|
+
it('should set isCompact for height < 300', () => {
|
123
|
+
setMockBounds({ width: 1000, height: 299 });
|
124
|
+
const { result } = renderHook(() => useWidgetSize());
|
125
|
+
expect(result.current.breakpoints.isCompact).toBe(true);
|
126
|
+
expect(result.current.breakpoints.isTall).toBe(false);
|
127
|
+
});
|
128
|
+
it('should set isTall for height >= 600', () => {
|
129
|
+
setMockBounds({ width: 1000, height: 600 });
|
130
|
+
const { result } = renderHook(() => useWidgetSize());
|
131
|
+
expect(result.current.breakpoints.isTall).toBe(true);
|
132
|
+
expect(result.current.breakpoints.isCompact).toBe(false);
|
133
|
+
setMockBounds({ width: 1000, height: 800 });
|
134
|
+
const { result: result2 } = renderHook(() => useWidgetSize());
|
135
|
+
expect(result2.current.breakpoints.isTall).toBe(true);
|
136
|
+
expect(result2.current.breakpoints.isCompact).toBe(false);
|
137
|
+
});
|
138
|
+
it('should not set isCompact or isTall for 300 <= height < 600', () => {
|
139
|
+
setMockBounds({ width: 1000, height: 300 });
|
140
|
+
let { result } = renderHook(() => useWidgetSize());
|
141
|
+
expect(result.current.breakpoints.isCompact).toBe(false);
|
142
|
+
expect(result.current.breakpoints.isTall).toBe(false);
|
143
|
+
setMockBounds({ width: 1000, height: 599 });
|
144
|
+
result = renderHook(() => useWidgetSize()).result;
|
145
|
+
expect(result.current.breakpoints.isCompact).toBe(false);
|
146
|
+
expect(result.current.breakpoints.isTall).toBe(false);
|
147
|
+
});
|
148
|
+
});
|
149
|
+
it('should provide bounds information', () => {
|
150
|
+
setMockBounds({
|
151
|
+
left: 1,
|
152
|
+
top: 2,
|
153
|
+
width: 300,
|
154
|
+
height: 400,
|
155
|
+
bottom: 402,
|
156
|
+
right: 301,
|
157
|
+
x: 1,
|
158
|
+
y: 2,
|
159
|
+
});
|
160
|
+
const { result } = renderHook(() => useWidgetSize());
|
161
|
+
expect(result.current.bounds).toBeDefined();
|
162
|
+
expect(result.current.bounds.left).toBe(1);
|
163
|
+
expect(result.current.bounds.top).toBe(2);
|
164
|
+
expect(result.current.bounds.width).toBe(300);
|
165
|
+
expect(result.current.bounds.height).toBe(400);
|
166
|
+
expect(result.current.bounds.bottom).toBe(402);
|
167
|
+
expect(result.current.bounds.right).toBe(301);
|
168
|
+
expect(result.current.bounds.x).toBe(1);
|
169
|
+
expect(result.current.bounds.y).toBe(2);
|
170
|
+
});
|
171
|
+
it('should provide responsive utility functions', () => {
|
172
|
+
setMockBounds({ width: 1200 });
|
173
|
+
const { result } = renderHook(() => useWidgetSize());
|
174
|
+
expect(result.current.isAbove).toBeDefined();
|
175
|
+
expect(typeof result.current.isAbove).toBe('function');
|
176
|
+
expect(result.current.isBelow).toBeDefined();
|
177
|
+
expect(typeof result.current.isBelow).toBe('function');
|
178
|
+
});
|
179
|
+
it('should calculate responsive utility functions correctly', () => {
|
180
|
+
setMockBounds({ width: 1100 });
|
181
|
+
const { result } = renderHook(() => useWidgetSize());
|
182
|
+
expect(result.current.isAbove('sm')).toBe(true); // 1100 >= 1000
|
183
|
+
expect(result.current.isBelow('lg')).toBe(true); // 1100 < 1400
|
184
|
+
expect(result.current.isAbove('xl')).toBe(false); // 1100 < Infinity
|
185
|
+
expect(result.current.isBelow('xs')).toBe(false); // 1100 >= 800
|
186
|
+
});
|
187
|
+
});
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { useMediaQuery, useTheme } from '@mui/material';
|
2
2
|
import UIThemeProvider from './UIThemeProvider';
|
3
|
-
import { useResponsive } from './hooks';
|
4
|
-
export { useMediaQuery, useResponsive, useTheme };
|
3
|
+
import { useResponsive, useWidgetSize, type WidgetSizeInfo } from './hooks';
|
4
|
+
export { useMediaQuery, useResponsive, useTheme, useWidgetSize, type WidgetSizeInfo };
|
5
5
|
export default UIThemeProvider;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { useMediaQuery, useTheme } from '@mui/material';
|
2
2
|
import UIThemeProvider from './UIThemeProvider';
|
3
|
-
import { useResponsive } from './hooks';
|
4
|
-
export { useMediaQuery, useResponsive, useTheme };
|
3
|
+
import { useResponsive, useWidgetSize } from './hooks';
|
4
|
+
export { useMediaQuery, useResponsive, useTheme, useWidgetSize };
|
5
5
|
export default UIThemeProvider;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@evoke-platform/ui-components",
|
3
|
-
"version": "1.6.0-dev.
|
3
|
+
"version": "1.6.0-dev.3",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/published/index.js",
|
6
6
|
"module": "dist/published/index.js",
|
@@ -128,6 +128,7 @@
|
|
128
128
|
"react-input-mask": "^2.0.4",
|
129
129
|
"react-number-format": "^4.9.3",
|
130
130
|
"react-querybuilder": "^6.0.2",
|
131
|
+
"react-use-measure": "^2.1.7",
|
131
132
|
"rtf.js": "^3.0.9",
|
132
133
|
"sift": "^17.1.3",
|
133
134
|
"small-date": "^2.0.0",
|