@addev-be/ui 0.2.7 → 0.2.9

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.
Files changed (26) hide show
  1. package/dist/components/data/DataGrid/DataGridFilterMenu/index.js +6 -5
  2. package/dist/components/data/DataGrid/FilterValuesScroller.js +4 -3
  3. package/dist/components/data/DataGrid/helpers/columns.js +1 -1
  4. package/dist/components/data/DataGrid/helpers/filters.d.ts +1 -1
  5. package/dist/components/data/DataGrid/helpers/filters.js +23 -12
  6. package/dist/components/data/DataGrid/index.js +1 -1
  7. package/dist/components/data/DataGrid/styles.d.ts +5 -0
  8. package/dist/components/data/DataGrid/styles.js +8 -4
  9. package/dist/components/data/DataGrid/types.d.ts +4 -3
  10. package/dist/components/data/SqlRequestDataGrid/helpers/columns.js +1 -1
  11. package/dist/components/data/SqlRequestDataGrid/index.js +1 -1
  12. package/dist/components/ui/ContextMenu/index.js +7 -2
  13. package/dist/components/ui/ContextMenu/styles.js +2 -2
  14. package/package.json +1 -1
  15. package/src/components/data/DataGrid/DataGridFilterMenu/index.tsx +7 -13
  16. package/src/components/data/DataGrid/FilterValuesScroller.tsx +33 -27
  17. package/src/components/data/DataGrid/helpers/columns.tsx +5 -1
  18. package/src/components/data/DataGrid/helpers/filters.ts +29 -19
  19. package/src/components/data/DataGrid/hooks/useDataGrid.tsx +2 -1
  20. package/src/components/data/DataGrid/index.tsx +1 -0
  21. package/src/components/data/DataGrid/styles.ts +22 -2
  22. package/src/components/data/DataGrid/types.ts +4 -2
  23. package/src/components/data/SqlRequestDataGrid/helpers/columns.tsx +1 -0
  24. package/src/components/data/SqlRequestDataGrid/index.tsx +1 -1
  25. package/src/components/ui/ContextMenu/index.tsx +7 -1
  26. package/src/components/ui/ContextMenu/styles.ts +4 -0
@@ -79,6 +79,7 @@ var sortDesc = {
79
79
  };
80
80
  var footerFunctionsTexts = {
81
81
  average: 'Moyenne',
82
+ avg: 'Moyenne',
82
83
  count: 'Nombre',
83
84
  max: 'Maximum',
84
85
  min: 'Minimum',
@@ -86,6 +87,7 @@ var footerFunctionsTexts = {
86
87
  };
87
88
  var footerFunctionsIcons = {
88
89
  average: Icons_1.XBarIcon,
90
+ avg: Icons_1.XBarIcon,
89
91
  count: Icons_1.TallyIcon,
90
92
  max: Icons_1.ArrowUpBigSmallIcon,
91
93
  min: Icons_1.ArrowDownBigSmallIcon,
@@ -165,11 +167,10 @@ var DataGridFilterMenu = function (_a) {
165
167
  }
166
168
  }, []);
167
169
  var checkboxesComponent = (0, react_1.useMemo)(function () {
168
- if (column.type === 'date') {
169
- var groups = (0, helpers_1.getDateGroups)(filteredAvailableValues);
170
- return ((0, jsx_runtime_1.jsx)(FilterValuesScroller_1.FilterValuesScroller, { values: filteredAvailableValues, selectedValues: selectedValues, onToggle: toggleValues, formatter: formatter, renderer: renderer, groups: groups }));
171
- }
172
- return ((0, jsx_runtime_1.jsx)(FilterValuesScroller_1.FilterValuesScroller, { values: filteredAvailableValues, selectedValues: selectedValues, onToggle: toggleValues, formatter: formatter, renderer: renderer }));
170
+ var groups = column.type === 'date'
171
+ ? (0, helpers_1.getDateGroups)(filteredAvailableValues)
172
+ : undefined;
173
+ return ((0, jsx_runtime_1.jsx)(FilterValuesScroller_1.FilterValuesScroller, { values: filteredAvailableValues, selectedValues: selectedValues, onToggle: toggleValues, formatter: formatter, renderer: renderer, groups: groups }));
173
174
  }, [
174
175
  column.type,
175
176
  filteredAvailableValues,
@@ -44,10 +44,11 @@ var react_1 = require("react");
44
44
  var hooks_1 = require("../../../hooks");
45
45
  var CheckboxTemplate = function (_a) {
46
46
  var selectedValues = _a.selectedValues, value = _a.value, index = _a.index, className = _a.className, style = _a.style, onToggle = _a.onToggle;
47
- return ((0, jsx_runtime_1.jsxs)("div", { className: (0, lodash_1.join)([
47
+ var checked = (0, react_1.useMemo)(function () { return value.values.every(function (v) { return selectedValues.includes(v); }); }, [selectedValues, value.values]);
48
+ return ((0, jsx_runtime_1.jsxs)(styles.FilterValueContainer, { className: (0, lodash_1.join)([
48
49
  // 'absolute left-0 right-0 flex flex-row cursor-pointer hover:bg-gray-50',
49
50
  className,
50
- ], ' '), style: __assign(__assign({}, style), { paddingLeft: "".concat(value.level, "rem") }), title: value.title, onClick: function () { return onToggle === null || onToggle === void 0 ? void 0 : onToggle([value.value]); }, children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: selectedValues.includes(value.value), readOnly: true }), (0, jsx_runtime_1.jsx)("span", { children: value.displayValue || '(Vides)' })] }, index));
51
+ ], ' '), style: __assign(__assign({}, style), { paddingLeft: "".concat(value.level, "rem") }), title: value.title, onClick: function () { return onToggle === null || onToggle === void 0 ? void 0 : onToggle(value.values); }, children: [(0, jsx_runtime_1.jsx)("input", { type: "checkbox", checked: checked, readOnly: true }), (0, jsx_runtime_1.jsx)("span", { children: value.displayValue || '(Vides)' })] }, index));
51
52
  };
52
53
  var FilterValuesScroller = function (_a) {
53
54
  var values = _a.values, _b = _a.rowHeight, rowHeight = _b === void 0 ? styles.DEFAULT_FILTER_ROW_HEIGHT : _b, onRangeChange = _a.onRangeChange, onToggle = _a.onToggle, _c = _a.formatter, formatter = _c === void 0 ? helpers_1.defaultRendererAndFormatter : _c, _d = _a.renderer, renderer = _d === void 0 ? helpers_1.defaultRendererAndFormatter : _d, _e = _a.selectedValues, selectedValues = _e === void 0 ? [] : _e, groups = _a.groups;
@@ -62,7 +63,7 @@ var FilterValuesScroller = function (_a) {
62
63
  var target = e.target;
63
64
  setScrollTop(function () { return target.scrollTop; });
64
65
  }, 50), []);
65
- var checkboxes = (0, react_1.useMemo)(function () { return (0, helpers_1.getCheckboxes)(values, renderer, formatter, groups); }, [values, groups, renderer, formatter]);
66
+ var checkboxes = (0, react_1.useMemo)(function () { return (0, helpers_1.getCheckboxes)(values, '', renderer, formatter, groups); }, [values, groups, renderer, formatter]);
66
67
  var visibleCheckboxes = checkboxes.slice(Math.max(0, index - tolerance), index + length + 1 + tolerance);
67
68
  var firstCheckboxTop = Math.max(0, index - tolerance) * rowHeight;
68
69
  (0, react_1.useEffect)(function () {
@@ -61,7 +61,7 @@ exports.phoneColumn = phoneColumn;
61
61
  var dateColumn = function (key, title, options) {
62
62
  var _a;
63
63
  return (_a = {},
64
- _a[key] = __assign({ name: title, render: function (row) { var _a; return (_a = (0, moment_1.default)(row[key]).format('DD/MM/YYYY')) !== null && _a !== void 0 ? _a : ''; }, getter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, sortGetter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, footer: function (_, filteredRows) { return "".concat(filteredRows.length, " \u00E9l\u00E9ments"); }, filter: (0, filters_1.textFilter)(key) }, options),
64
+ _a[key] = __assign({ name: title, type: 'date', render: function (row) { var _a; return (_a = (0, moment_1.default)(row[key]).format('DD/MM/YYYY')) !== null && _a !== void 0 ? _a : ''; }, getter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, sortGetter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, footer: function (_, filteredRows) { return "".concat(filteredRows.length, " \u00E9l\u00E9ments"); }, filter: __assign(__assign({}, (0, filters_1.textFilter)(key)), { renderer: function (value) { var _a; return (_a = (0, moment_1.default)(value).format('DD/MM/YYYY')) !== null && _a !== void 0 ? _a : ''; } }) }, options),
65
65
  _a);
66
66
  };
67
67
  exports.dateColumn = dateColumn;
@@ -12,6 +12,6 @@ export declare const defaultValueParsers: {
12
12
  export declare const groupDatesByYearAndMonth: (dates: any[]) => Record<string, Record<string, any[]>>;
13
13
  export declare const getDateGroups: (dates: any[]) => DataGridFilterGroup[];
14
14
  export declare const defaultRendererAndFormatter: (value: any) => string;
15
- export declare const getCheckboxes: (values: DataGridFilterValue[], renderer: DataGridFilterRenderer, formatter: DataGridFilterFormatter, groups?: DataGridFilterGroup[], level?: number) => DataGridFilterCheckbox[];
15
+ export declare const getCheckboxes: (values: DataGridFilterValue[], displayValue: DataGridFilterValue, renderer: DataGridFilterRenderer, formatter: DataGridFilterFormatter, groups?: DataGridFilterGroup[], level?: number) => DataGridFilterCheckbox[];
16
16
  export declare const textFilter: (key: string) => DataGridFilter<"text">;
17
17
  export declare const numberFilter: (key: string) => DataGridFilter<"number">;
@@ -207,10 +207,12 @@ var getDateGroups = function (dates) {
207
207
  var year = _a[0], months = _a[1];
208
208
  return ({
209
209
  name: year,
210
+ displayValue: year,
210
211
  values: Object.values(months).flat(),
211
212
  groups: Object.entries(months).map(function (_a) {
212
213
  var month = _a[0], dates = _a[1];
213
214
  return ({
215
+ displayValue: month,
214
216
  name: month,
215
217
  values: dates,
216
218
  });
@@ -223,19 +225,28 @@ var defaultRendererAndFormatter = function (value) {
223
225
  return String(value !== null && value !== void 0 ? value : '').trim() || '(Vides)';
224
226
  };
225
227
  exports.defaultRendererAndFormatter = defaultRendererAndFormatter;
226
- var getCheckboxes = function (values, renderer, formatter, groups, level) {
228
+ var getCheckboxes = function (values, displayValue, renderer, formatter, groups, level) {
227
229
  if (level === void 0) { level = 0; }
228
- return __spreadArray(__spreadArray([], (groups !== null && groups !== void 0 ? groups : [])
229
- .map(function (group) {
230
- var _a;
231
- return (0, exports.getCheckboxes)((_a = group.values) !== null && _a !== void 0 ? _a : [], renderer, formatter, group.groups, level + 1);
232
- })
233
- .flat(), true), values.map(function (value) { return ({
234
- displayValue: renderer(value),
235
- title: formatter(value),
236
- value: value !== null && value !== void 0 ? value : '',
237
- level: level,
238
- }); }), true);
230
+ return groups
231
+ ? groups
232
+ .map(function (group) {
233
+ var _a, _b;
234
+ return __spreadArray([
235
+ {
236
+ displayValue: group.displayValue,
237
+ title: formatter(group.displayValue),
238
+ values: (_a = group.values) !== null && _a !== void 0 ? _a : [],
239
+ level: level,
240
+ }
241
+ ], (0, exports.getCheckboxes)((_b = group.values) !== null && _b !== void 0 ? _b : [], group.displayValue, renderer, formatter, group.groups, level + 1), true);
242
+ })
243
+ .flat()
244
+ : values.map(function (value) { return ({
245
+ displayValue: renderer(value),
246
+ title: formatter(value),
247
+ values: [value !== null && value !== void 0 ? value : ''],
248
+ level: level,
249
+ }); });
239
250
  };
240
251
  exports.getCheckboxes = getCheckboxes;
241
252
  var textFilter = function (key) { return ({
@@ -103,6 +103,6 @@ var DataGrid = function (_a) {
103
103
  toggleSelection,
104
104
  visibleColumns,
105
105
  ]);
106
- return ((0, jsx_runtime_1.jsx)(DataGridContext.Provider, { value: contextProps, children: (0, jsx_runtime_1.jsxs)(styles.DataGridContainer, { ref: scrollableRef, onScroll: onScroll, "$headerRowHeight": headerRowHeight, "$rowHeight": rowHeight, "$rowsCount": contextProps.sortedRows.length, className: className, children: [(0, jsx_runtime_1.jsx)(DataGridHeader_1.DataGridHeader, { context: DataGridContext }), (0, jsx_runtime_1.jsx)(VirtualScroller_1.VirtualScroller, { onRangeChange: onVisibleRowsChange, hasFooter: hasFooter, rowTemplate: rowTemplate, context: DataGridContext }), hasFooter && (0, jsx_runtime_1.jsx)(DataGridFooter_1.DataGridFooter, { context: DataGridContext })] }) }));
106
+ return ((0, jsx_runtime_1.jsx)(DataGridContext.Provider, { value: contextProps, children: (0, jsx_runtime_1.jsxs)(styles.DataGridContainer, { ref: scrollableRef, onScroll: onScroll, "$headerRowHeight": headerRowHeight, "$rowHeight": rowHeight, "$rowsCount": contextProps.sortedRows.length, "$withFooter": hasFooter, className: className, children: [(0, jsx_runtime_1.jsx)(DataGridHeader_1.DataGridHeader, { context: DataGridContext }), (0, jsx_runtime_1.jsx)(VirtualScroller_1.VirtualScroller, { onRangeChange: onVisibleRowsChange, hasFooter: hasFooter, rowTemplate: rowTemplate, context: DataGridContext }), hasFooter && (0, jsx_runtime_1.jsx)(DataGridFooter_1.DataGridFooter, { context: DataGridContext })] }) }));
107
107
  };
108
108
  exports.DataGrid = DataGrid;
@@ -2,6 +2,7 @@ import { ThemeColor } from '../../../providers/ThemeProvider/types';
2
2
  export declare const VIRTUAL_SCROLL_TOLERANCE = 20;
3
3
  export declare const TOOLBAR_HEIGHT = 40;
4
4
  export declare const DEFAULT_HEADER_ROW_HEIGHT = 40;
5
+ export declare const DEFAULT_FOOTER_ROW_HEIGHT = 40;
5
6
  export declare const DEFAULT_ROW_HEIGHT = 32;
6
7
  export declare const DEFAULT_FILTER_ROW_HEIGHT = 24;
7
8
  export declare const TopPaddingRow: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
@@ -31,6 +32,7 @@ export declare const DataGridContainer: import("styled-components/dist/types").I
31
32
  $rowHeight?: number;
32
33
  $rowsCount: number;
33
34
  $showToolsHeader?: boolean;
35
+ $withFooter?: boolean;
34
36
  }>> & string;
35
37
  type DataGridHeaderOrFooterRowProps = {
36
38
  $headerRowHeight?: number;
@@ -61,4 +63,7 @@ export declare const FilterValuesScrollerContainer: import("styled-components/di
61
63
  }>, never>, {
62
64
  $rowHeight?: number;
63
65
  }>> & string;
66
+ export declare const FilterValueContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
67
+ ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
68
+ }>, never>, never>> & string;
64
69
  export {};
@@ -27,11 +27,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
27
27
  return result;
28
28
  };
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.FilterValuesScrollerContainer = exports.ResizeBackdrop = exports.HeaderSelectionCell = exports.SelectionCell = exports.LoadingCell = exports.DataGridRow = exports.DataGridFooterRow = exports.DataGridHeaderRow = exports.DataGridContainer = exports.DataGridToolsRow = exports.DataGridCell = exports.DataGridHeaderCellContainer = exports.DataGridResizeGrip = exports.VirtualScrollerRowsContainer = exports.VirtualScrollerContainer = exports.BottomPaddingRow = exports.TopPaddingRow = exports.DEFAULT_FILTER_ROW_HEIGHT = exports.DEFAULT_ROW_HEIGHT = exports.DEFAULT_HEADER_ROW_HEIGHT = exports.TOOLBAR_HEIGHT = exports.VIRTUAL_SCROLL_TOLERANCE = void 0;
30
+ exports.FilterValueContainer = exports.FilterValuesScrollerContainer = exports.ResizeBackdrop = exports.HeaderSelectionCell = exports.SelectionCell = exports.LoadingCell = exports.DataGridRow = exports.DataGridFooterRow = exports.DataGridHeaderRow = exports.DataGridContainer = exports.DataGridToolsRow = exports.DataGridCell = exports.DataGridHeaderCellContainer = exports.DataGridResizeGrip = exports.VirtualScrollerRowsContainer = exports.VirtualScrollerContainer = exports.BottomPaddingRow = exports.TopPaddingRow = exports.DEFAULT_FILTER_ROW_HEIGHT = exports.DEFAULT_ROW_HEIGHT = exports.DEFAULT_FOOTER_ROW_HEIGHT = exports.DEFAULT_HEADER_ROW_HEIGHT = exports.TOOLBAR_HEIGHT = exports.VIRTUAL_SCROLL_TOLERANCE = void 0;
31
31
  var styled_components_1 = __importStar(require("styled-components"));
32
32
  exports.VIRTUAL_SCROLL_TOLERANCE = 20;
33
33
  exports.TOOLBAR_HEIGHT = 40;
34
34
  exports.DEFAULT_HEADER_ROW_HEIGHT = 40;
35
+ exports.DEFAULT_FOOTER_ROW_HEIGHT = 40;
35
36
  exports.DEFAULT_ROW_HEIGHT = 32;
36
37
  exports.DEFAULT_FILTER_ROW_HEIGHT = 24;
37
38
  exports.TopPaddingRow = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject([""], [""])));
@@ -70,8 +71,8 @@ exports.DataGridCell.displayName = 'DataGridCell';
70
71
  exports.DataGridToolsRow = styled_components_1.default.div(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n grid-column-start: 1;\n grid-column-end: -1;\n grid-row: 1;\n display: flex;\n gap: var(--space-1);\n padding: 0 var(--space-1);\n align-items: center;\n background-color: var(--color-neutral-200);\n position: sticky;\n top: 0;\n left: 0;\n z-index: 10;\n"], ["\n grid-column-start: 1;\n grid-column-end: -1;\n grid-row: 1;\n display: flex;\n gap: var(--space-1);\n padding: 0 var(--space-1);\n align-items: center;\n background-color: var(--color-neutral-200);\n position: sticky;\n top: 0;\n left: 0;\n z-index: 10;\n"])));
71
72
  exports.DataGridToolsRow.displayName = 'DataGridToolsRow';
72
73
  exports.DataGridContainer = styled_components_1.default.div(templateObject_13 || (templateObject_13 = __makeTemplateObject(["\n display: grid;\n width: 100%;\n height: 100%;\n background-color: var(--color-neutral-50);\n font-size: var(--text-base);\n overflow: scroll;\n grid-template-rows: ", ";\n\n ", " {\n height: ", "px;\n }\n ", " {\n position: sticky;\n top: ", ";\n height: ", ";\n }\n ", " {\n height: ", ";\n line-height: ", ";\n }\n\n ", " {\n grid-column-start: 1;\n grid-column-end: -1;\n grid-row: 3;\n }\n"], ["\n display: grid;\n width: 100%;\n height: 100%;\n background-color: var(--color-neutral-50);\n font-size: var(--text-base);\n overflow: scroll;\n grid-template-rows: ", ";\n\n ", " {\n height: ", "px;\n }\n ", " {\n position: sticky;\n top: ", ";\n height: ", ";\n }\n ", " {\n height: ", ";\n line-height: ", ";\n }\n\n ", " {\n grid-column-start: 1;\n grid-column-end: -1;\n grid-row: 3;\n }\n"])), function (_a) {
73
- var _b = _a.$headerRowHeight, $headerRowHeight = _b === void 0 ? exports.DEFAULT_HEADER_ROW_HEIGHT : _b;
74
- return "".concat(exports.TOOLBAR_HEIGHT, "px ").concat($headerRowHeight, "px auto");
74
+ var _b = _a.$headerRowHeight, $headerRowHeight = _b === void 0 ? exports.DEFAULT_HEADER_ROW_HEIGHT : _b, _c = _a.$withFooter, $withFooter = _c === void 0 ? false : _c;
75
+ return "".concat(exports.TOOLBAR_HEIGHT, "px ").concat($headerRowHeight, "px auto ").concat($withFooter ? exports.DEFAULT_FOOTER_ROW_HEIGHT + 'px' : '');
75
76
  }, exports.DataGridToolsRow, exports.TOOLBAR_HEIGHT, exports.DataGridHeaderCellContainer, function (_a) {
76
77
  var _b = _a.$headerRowHeight, $headerRowHeight = _b === void 0 ? exports.DEFAULT_HEADER_ROW_HEIGHT : _b;
77
78
  return "".concat($headerRowHeight, "px");
@@ -131,4 +132,7 @@ exports.FilterValuesScrollerContainer = styled_components_1.default.div.attrs({
131
132
  var _b = _a.$rowHeight, $rowHeight = _b === void 0 ? exports.DEFAULT_FILTER_ROW_HEIGHT : _b;
132
133
  return "".concat($rowHeight, "px");
133
134
  });
134
- var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25;
135
+ exports.FilterValueContainer = styled_components_1.default.div.attrs({
136
+ className: 'FilterValueContainer',
137
+ })(templateObject_26 || (templateObject_26 = __makeTemplateObject(["\n position: absolute;\n display: flex;\n flex-direction: row;\n align-items: center;\n cursor: pointer;\n &:hover {\n background-color: var(--color-neutral-50);\n }\n"], ["\n position: absolute;\n display: flex;\n flex-direction: row;\n align-items: center;\n cursor: pointer;\n &:hover {\n background-color: var(--color-neutral-50);\n }\n"])));
138
+ var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25, templateObject_26;
@@ -6,7 +6,7 @@ export type DataGridCellFC = FC<{
6
6
  onDoubleClick?: MouseEventHandler;
7
7
  style?: CSSProperties;
8
8
  }>;
9
- export type DataGridFooterPredefinedFunction = 'average' | 'count' | 'max' | 'min' | 'sum';
9
+ export type DataGridFooterPredefinedFunction = 'average' | 'avg' | 'count' | 'max' | 'min' | 'sum';
10
10
  export type DataGridFooterFunction<R> = (allRows: R[], filteredRows: R[], selectedRows: R[]) => ReactNode;
11
11
  export type DataGridColumn<R> = {
12
12
  component?: DataGridCellFC;
@@ -150,13 +150,14 @@ export type DataGridFilter<T extends string = DataGridFilterType> = T extends Da
150
150
  } : never;
151
151
  export type DataGridFilterGroup = {
152
152
  name: string;
153
- values?: (string | number | null)[];
153
+ displayValue: DataGridFilterValue;
154
+ values?: DataGridFilterValue[];
154
155
  groups?: DataGridFilterGroup[];
155
156
  };
156
157
  export type DataGridFilterValue = string | number | null;
157
158
  export type DataGridFilterCheckbox = {
158
159
  displayValue: ReactNode;
159
160
  title: string;
160
- value: DataGridFilterValue;
161
+ values: DataGridFilterValue[];
161
162
  level: number;
162
163
  };
@@ -58,7 +58,7 @@ exports.sqlPhoneColumn = sqlPhoneColumn;
58
58
  var sqlDateColumn = function (key, title, options) {
59
59
  var _a;
60
60
  return (_a = {},
61
- _a[key] = __assign({ name: title, render: function (row) { return (0, dates_1.formatDate)(row[key]); }, getter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, sortGetter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, filter: __assign(__assign({}, (0, helpers_1.textFilter)(key)), { getter: function (value) { var _a; return (_a = value[key]) !== null && _a !== void 0 ? _a : ''; } }), footer: function (rows) { return "".concat(rows[0][key], " \u00E9l\u00E9ments"); } }, options),
61
+ _a[key] = __assign({ name: title, type: 'date', render: function (row) { return (0, dates_1.formatDate)(row[key]); }, getter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, sortGetter: function (row) { var _a; return (_a = row[key]) !== null && _a !== void 0 ? _a : ''; }, filter: __assign(__assign({}, (0, helpers_1.textFilter)(key)), { getter: function (value) { var _a; return (_a = value[key]) !== null && _a !== void 0 ? _a : ''; } }), footer: function (rows) { return "".concat(rows[0][key], " \u00E9l\u00E9ments"); } }, options),
62
62
  _a);
63
63
  };
64
64
  exports.sqlDateColumn = sqlDateColumn;
@@ -91,7 +91,7 @@ var SqlRequestDataGrid = function (_a) {
91
91
  ];
92
92
  }, [props.columns, props.hiddenColumns]), columnsKeys = _l[0], visibleColumnsKeys = _l[1];
93
93
  var columnTypes = (0, react_1.useMemo)(function () {
94
- return visibleColumnsKeys.map(function (key) { var _a; return String((_a = props.columns[key].type) !== null && _a !== void 0 ? _a : 'text'); });
94
+ return visibleColumnsKeys.map(function (key) { var _a, _b; return String((_b = (_a = props.columns[key]) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'text'); });
95
95
  }, [visibleColumnsKeys, props.columns]);
96
96
  var refresh = (0, react_1.useCallback)(function () {
97
97
  setRows([]);
@@ -34,7 +34,9 @@ exports.ContextMenu = ContextMenu;
34
34
  var ParentMenuItem = function (_a) {
35
35
  var children = _a.children, props = __rest(_a, ["children"]);
36
36
  var _b = (0, react_1.useState)(false), isOpened = _b[0], setIsOpened = _b[1];
37
- var _c = (0, react_1.useState)(null), currentTimeout = _c[0], setCurrentTimeout = _c[1];
37
+ var _c = (0, react_1.useState)(false), isSubMenuLeft = _c[0], setIsSubMenuLeft = _c[1];
38
+ var _d = (0, react_1.useState)(null), currentTimeout = _d[0], setCurrentTimeout = _d[1];
39
+ var containerRef = (0, react_1.useRef)(null);
38
40
  var stopTimeout = (0, react_1.useCallback)(function () {
39
41
  if (currentTimeout) {
40
42
  clearTimeout(currentTimeout);
@@ -44,12 +46,15 @@ var ParentMenuItem = function (_a) {
44
46
  var startTimeout = (0, react_1.useCallback)(function (open) {
45
47
  stopTimeout();
46
48
  setCurrentTimeout(window.setTimeout(function () {
49
+ var _a;
50
+ var rect = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
51
+ setIsSubMenuLeft(!!rect && rect.right + 280 > window.innerWidth);
47
52
  setIsOpened(open);
48
53
  }, open ? 100 : 300));
49
54
  }, [stopTimeout]);
50
55
  var open = (0, react_1.useCallback)(function () { return startTimeout(true); }, [startTimeout]);
51
56
  var close = (0, react_1.useCallback)(function () { return startTimeout(false); }, [startTimeout]);
52
- return ((0, jsx_runtime_1.jsx)(styles_1.MenuItemContainer, __assign({}, props, { className: isOpened ? 'opened' : '', onMouseEnter: open, onMouseLeave: close, "$withArrow": true, children: children })));
57
+ return ((0, jsx_runtime_1.jsx)(styles_1.MenuItemContainer, __assign({ ref: containerRef }, props, { className: "".concat(isOpened ? 'opened' : '', " ").concat(isSubMenuLeft ? 'left' : ''), onMouseEnter: open, onMouseLeave: close, "$withArrow": true, children: children })));
53
58
  };
54
59
  exports.ParentMenuItem = ParentMenuItem;
55
60
  exports.ContextMenu.Item = styles_1.MenuItemContainer;
@@ -40,7 +40,7 @@ exports.SubMenu = styled_components_1.default.div.attrs({
40
40
  exports.SubMenu.displayName = 'SubMenu';
41
41
  exports.MenuItemContainer = styled_components_1.default.div.attrs({
42
42
  className: 'MenuItemContainer',
43
- })(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n position: relative;\n display: flex;\n align-items: center;\n font-family: var(--font-sans);\n font-weight: normal;\n text-align: left;\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-base);\n line-height: var(--leading-6);\n border: none;\n cursor: pointer;\n\n ", "\n\n ", "\n\n svg {\n fill: currentColor;\n width: var(--space-4);\n height: var(--space-4);\n margin-right: var(--space-2);\n }\n\n & > ", " {\n display: none;\n margin-top: calc(0px - var(--space-1));\n }\n &.opened > ", " {\n display: block;\n }\n"], ["\n position: relative;\n display: flex;\n align-items: center;\n font-family: var(--font-sans);\n font-weight: normal;\n text-align: left;\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-base);\n line-height: var(--leading-6);\n border: none;\n cursor: pointer;\n\n ", "\n\n ", "\n\n svg {\n fill: currentColor;\n width: var(--space-4);\n height: var(--space-4);\n margin-right: var(--space-2);\n }\n\n & > ", " {\n display: none;\n margin-top: calc(0px - var(--space-1));\n }\n &.opened > ", " {\n display: block;\n }\n"])), function (_a) {
43
+ })(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n position: relative;\n display: flex;\n align-items: center;\n font-family: var(--font-sans);\n font-weight: normal;\n text-align: left;\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-base);\n line-height: var(--leading-6);\n border: none;\n cursor: pointer;\n\n ", "\n\n ", "\n\n svg {\n fill: currentColor;\n width: var(--space-4);\n height: var(--space-4);\n margin-right: var(--space-2);\n }\n\n & > ", " {\n display: none;\n margin-top: calc(0px - var(--space-1));\n }\n &.opened > ", " {\n display: block;\n }\n &.opened.left > ", " {\n left: auto;\n right: 100%;\n }\n"], ["\n position: relative;\n display: flex;\n align-items: center;\n font-family: var(--font-sans);\n font-weight: normal;\n text-align: left;\n padding: var(--space-1) var(--space-2);\n font-size: var(--text-base);\n line-height: var(--leading-6);\n border: none;\n cursor: pointer;\n\n ", "\n\n ", "\n\n svg {\n fill: currentColor;\n width: var(--space-4);\n height: var(--space-4);\n margin-right: var(--space-2);\n }\n\n & > ", " {\n display: none;\n margin-top: calc(0px - var(--space-1));\n }\n &.opened > ", " {\n display: block;\n }\n &.opened.left > ", " {\n left: auto;\n right: 100%;\n }\n"])), function (_a) {
44
44
  var $withArrow = _a.$withArrow;
45
45
  return $withArrow && (0, styled_components_1.css)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n &::after {\n content: '';\n position: absolute;\n right: var(--space-2);\n top: 50%;\n transform: translateY(-50%);\n border: 4px solid transparent;\n border-left-color: var(--color-neutral-600);\n }\n "], ["\n &::after {\n content: '';\n position: absolute;\n right: var(--space-2);\n top: 50%;\n transform: translateY(-50%);\n border: 4px solid transparent;\n border-left-color: var(--color-neutral-600);\n }\n "])));
46
46
  }, function (_a) {
@@ -48,7 +48,7 @@ exports.MenuItemContainer = styled_components_1.default.div.attrs({
48
48
  return disabled
49
49
  ? (0, styled_components_1.css)(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n color: var(--color-neutral-300);\n background-color: var(--color-neutral-100);\n cursor: default;\n "], ["\n color: var(--color-neutral-300);\n background-color: var(--color-neutral-100);\n cursor: default;\n "]))) : $color
50
50
  ? (0, styled_components_1.css)(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n color: var(--color-", "-600);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-", "-200);\n }\n "], ["\n color: var(--color-", "-600);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-", "-200);\n }\n "])), $color, $color) : (0, styled_components_1.css)(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n color: var(--color-neutral-900);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-neutral-200);\n }\n "], ["\n color: var(--color-neutral-900);\n background-color: var(--color-neutral-100);\n &:hover {\n background-color: var(--color-neutral-200);\n }\n "])));
51
- }, exports.SubMenu, exports.SubMenu);
51
+ }, exports.SubMenu, exports.SubMenu, exports.SubMenu);
52
52
  exports.MenuItemContainer.displayName = 'MenuItemContainer';
53
53
  exports.Divider = styled_components_1.default.div.attrs({
54
54
  className: 'Divider',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@addev-be/ui",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "watch": "tsc -b --watch",
@@ -66,6 +66,7 @@ const sortDesc: Record<DataGridFilterType, [string, IconFC]> = {
66
66
 
67
67
  const footerFunctionsTexts: Record<DataGridFooterPredefinedFunction, string> = {
68
68
  average: 'Moyenne',
69
+ avg: 'Moyenne',
69
70
  count: 'Nombre',
70
71
  max: 'Maximum',
71
72
  min: 'Minimum',
@@ -73,6 +74,7 @@ const footerFunctionsTexts: Record<DataGridFooterPredefinedFunction, string> = {
73
74
  };
74
75
  const footerFunctionsIcons: Record<DataGridFooterPredefinedFunction, IconFC> = {
75
76
  average: XBarIcon,
77
+ avg: XBarIcon,
76
78
  count: TallyIcon,
77
79
  max: ArrowUpBigSmallIcon,
78
80
  min: ArrowDownBigSmallIcon,
@@ -195,19 +197,10 @@ export const DataGridFilterMenu = <R,>({
195
197
  }, []);
196
198
 
197
199
  const checkboxesComponent = useMemo(() => {
198
- if (column.type === 'date') {
199
- const groups = getDateGroups(filteredAvailableValues);
200
- return (
201
- <FilterValuesScroller
202
- values={filteredAvailableValues}
203
- selectedValues={selectedValues}
204
- onToggle={toggleValues}
205
- formatter={formatter}
206
- renderer={renderer}
207
- groups={groups}
208
- />
209
- );
210
- }
200
+ const groups =
201
+ column.type === 'date'
202
+ ? getDateGroups(filteredAvailableValues)
203
+ : undefined;
211
204
  return (
212
205
  <FilterValuesScroller
213
206
  values={filteredAvailableValues}
@@ -215,6 +208,7 @@ export const DataGridFilterMenu = <R,>({
215
208
  onToggle={toggleValues}
216
209
  formatter={formatter}
217
210
  renderer={renderer}
211
+ groups={groups}
218
212
  />
219
213
  );
220
214
  }, [
@@ -29,33 +29,39 @@ const CheckboxTemplate = ({
29
29
  className?: string;
30
30
  style?: React.CSSProperties;
31
31
  onToggle?: (values: DataGridFilterValue[]) => void;
32
- }) => (
33
- <div
34
- key={index}
35
- className={join(
36
- [
37
- // 'absolute left-0 right-0 flex flex-row cursor-pointer hover:bg-gray-50',
38
- className,
39
- ],
40
- ' '
41
- )}
42
- style={{ ...style, paddingLeft: `${value.level}rem` }}
43
- title={value.title}
44
- onClick={() => onToggle?.([value.value])}
45
- >
46
- <input
47
- type="checkbox"
48
- checked={selectedValues.includes(value.value)}
49
- readOnly
50
- // className="inline-block mr-2"
51
- />
52
- <span
53
- // className="mr-2 truncate"
32
+ }) => {
33
+ const checked = useMemo(
34
+ () => value.values.every((v) => selectedValues.includes(v)),
35
+ [selectedValues, value.values]
36
+ );
37
+ return (
38
+ <styles.FilterValueContainer
39
+ key={index}
40
+ className={join(
41
+ [
42
+ // 'absolute left-0 right-0 flex flex-row cursor-pointer hover:bg-gray-50',
43
+ className,
44
+ ],
45
+ ' '
46
+ )}
47
+ style={{ ...style, paddingLeft: `${value.level}rem` }}
48
+ title={value.title}
49
+ onClick={() => onToggle?.(value.values)}
54
50
  >
55
- {value.displayValue || '(Vides)'}
56
- </span>
57
- </div>
58
- );
51
+ <input
52
+ type="checkbox"
53
+ checked={checked}
54
+ readOnly
55
+ // className="inline-block mr-2"
56
+ />
57
+ <span
58
+ // className="mr-2 truncate"
59
+ >
60
+ {value.displayValue || '(Vides)'}
61
+ </span>
62
+ </styles.FilterValueContainer>
63
+ );
64
+ };
59
65
 
60
66
  type FilterValuesScrollerProps = {
61
67
  values: DataGridFilterValue[];
@@ -96,7 +102,7 @@ export const FilterValuesScroller = ({
96
102
  );
97
103
 
98
104
  const checkboxes = useMemo(
99
- () => getCheckboxes(values, renderer, formatter, groups),
105
+ () => getCheckboxes(values, '', renderer, formatter, groups),
100
106
  [values, groups, renderer, formatter]
101
107
  );
102
108
  const visibleCheckboxes = checkboxes.slice(
@@ -87,11 +87,15 @@ export const dateColumn = <R extends Record<string, any>>(
87
87
  ): DataGridColumns<R> => ({
88
88
  [key]: {
89
89
  name: title,
90
+ type: 'date',
90
91
  render: (row) => moment(row[key]).format('DD/MM/YYYY') ?? '',
91
92
  getter: (row) => row[key] ?? '',
92
93
  sortGetter: (row) => row[key] ?? '',
93
94
  footer: (_, filteredRows) => `${filteredRows.length} éléments`,
94
- filter: textFilter(key),
95
+ filter: {
96
+ ...textFilter(key),
97
+ renderer: (value) => moment(value).format('DD/MM/YYYY') ?? '',
98
+ },
95
99
  ...options,
96
100
  },
97
101
  });
@@ -168,8 +168,10 @@ export const getDateGroups = (dates: any[]): DataGridFilterGroup[] => {
168
168
  const grouperDates = groupDatesByYearAndMonth(dates);
169
169
  return Object.entries(grouperDates).map(([year, months]) => ({
170
170
  name: year,
171
+ displayValue: year,
171
172
  values: Object.values(months).flat(),
172
173
  groups: Object.entries(months).map(([month, dates]) => ({
174
+ displayValue: month,
173
175
  name: month,
174
176
  values: dates,
175
177
  })),
@@ -181,29 +183,37 @@ export const defaultRendererAndFormatter = (value: any) =>
181
183
 
182
184
  export const getCheckboxes = (
183
185
  values: DataGridFilterValue[],
186
+ displayValue: DataGridFilterValue,
184
187
  renderer: DataGridFilterRenderer,
185
188
  formatter: DataGridFilterFormatter,
186
189
  groups?: DataGridFilterGroup[],
187
190
  level = 0
188
- ): DataGridFilterCheckbox[] => [
189
- ...(groups ?? [])
190
- .map<DataGridFilterCheckbox[]>((group) =>
191
- getCheckboxes(
192
- group.values ?? [],
193
- renderer,
194
- formatter,
195
- group.groups,
196
- level + 1
197
- )
198
- )
199
- .flat(),
200
- ...values.map<DataGridFilterCheckbox>((value) => ({
201
- displayValue: renderer(value),
202
- title: formatter(value),
203
- value: value ?? '',
204
- level,
205
- })),
206
- ];
191
+ ): DataGridFilterCheckbox[] =>
192
+ groups
193
+ ? groups
194
+ .map<DataGridFilterCheckbox[]>((group) => [
195
+ {
196
+ displayValue: group.displayValue,
197
+ title: formatter(group.displayValue),
198
+ values: group.values ?? [],
199
+ level,
200
+ },
201
+ ...getCheckboxes(
202
+ group.values ?? [],
203
+ group.displayValue,
204
+ renderer,
205
+ formatter,
206
+ group.groups,
207
+ level + 1
208
+ ),
209
+ ])
210
+ .flat()
211
+ : values.map<DataGridFilterCheckbox>((value) => ({
212
+ displayValue: renderer(value),
213
+ title: formatter(value),
214
+ values: [value ?? ''],
215
+ level,
216
+ }));
207
217
 
208
218
  export const textFilter = (key: string): DataGridFilter<'text'> => ({
209
219
  type: 'text',
@@ -191,7 +191,8 @@ export const useDataGrid = <R,>(
191
191
  acc[columnKey] = column.footer;
192
192
  } else if (
193
193
  typeof column.footer === 'object' &&
194
- typeof column.footer[footerKey] === 'function'
194
+ typeof column.footer[footerKey] === 'function' &&
195
+ column.footer[footerKey] !== null
195
196
  ) {
196
197
  acc[columnKey] = column.footer[footerKey];
197
198
  }
@@ -123,6 +123,7 @@ export const DataGrid = <R,>({
123
123
  $headerRowHeight={headerRowHeight}
124
124
  $rowHeight={rowHeight}
125
125
  $rowsCount={contextProps.sortedRows.length}
126
+ $withFooter={hasFooter}
126
127
  className={className}
127
128
  >
128
129
  <DataGridHeader context={DataGridContext} />
@@ -5,6 +5,7 @@ import { ThemeColor } from '../../../providers/ThemeProvider/types';
5
5
  export const VIRTUAL_SCROLL_TOLERANCE = 20;
6
6
  export const TOOLBAR_HEIGHT = 40;
7
7
  export const DEFAULT_HEADER_ROW_HEIGHT = 40;
8
+ export const DEFAULT_FOOTER_ROW_HEIGHT = 40;
8
9
  export const DEFAULT_ROW_HEIGHT = 32;
9
10
  export const DEFAULT_FILTER_ROW_HEIGHT = 24;
10
11
 
@@ -175,6 +176,7 @@ export const DataGridContainer = styled.div<{
175
176
  $rowHeight?: number;
176
177
  $rowsCount: number;
177
178
  $showToolsHeader?: boolean;
179
+ $withFooter?: boolean;
178
180
  }>`
179
181
  display: grid;
180
182
  width: 100%;
@@ -182,8 +184,13 @@ export const DataGridContainer = styled.div<{
182
184
  background-color: var(--color-neutral-50);
183
185
  font-size: var(--text-base);
184
186
  overflow: scroll;
185
- grid-template-rows: ${({ $headerRowHeight = DEFAULT_HEADER_ROW_HEIGHT }) =>
186
- `${TOOLBAR_HEIGHT}px ${$headerRowHeight}px auto`};
187
+ grid-template-rows: ${({
188
+ $headerRowHeight = DEFAULT_HEADER_ROW_HEIGHT,
189
+ $withFooter = false,
190
+ }) =>
191
+ `${TOOLBAR_HEIGHT}px ${$headerRowHeight}px auto ${
192
+ $withFooter ? DEFAULT_FOOTER_ROW_HEIGHT + 'px' : ''
193
+ }`};
187
194
 
188
195
  ${DataGridToolsRow} {
189
196
  height: ${TOOLBAR_HEIGHT}px;
@@ -345,3 +352,16 @@ export const FilterValuesScrollerContainer = styled.div.attrs({
345
352
  }
346
353
  }
347
354
  `;
355
+
356
+ export const FilterValueContainer = styled.div.attrs({
357
+ className: 'FilterValueContainer',
358
+ })`
359
+ position: absolute;
360
+ display: flex;
361
+ flex-direction: row;
362
+ align-items: center;
363
+ cursor: pointer;
364
+ &:hover {
365
+ background-color: var(--color-neutral-50);
366
+ }
367
+ `;
@@ -23,6 +23,7 @@ export type DataGridCellFC = FC<{
23
23
 
24
24
  export type DataGridFooterPredefinedFunction =
25
25
  | 'average'
26
+ | 'avg'
26
27
  | 'count'
27
28
  | 'max'
28
29
  | 'min'
@@ -246,7 +247,8 @@ export type DataGridFilter<T extends string = DataGridFilterType> =
246
247
 
247
248
  export type DataGridFilterGroup = {
248
249
  name: string;
249
- values?: (string | number | null)[];
250
+ displayValue: DataGridFilterValue;
251
+ values?: DataGridFilterValue[];
250
252
  groups?: DataGridFilterGroup[];
251
253
  };
252
254
 
@@ -255,6 +257,6 @@ export type DataGridFilterValue = string | number | null;
255
257
  export type DataGridFilterCheckbox = {
256
258
  displayValue: ReactNode;
257
259
  title: string;
258
- value: DataGridFilterValue;
260
+ values: DataGridFilterValue[];
259
261
  level: number;
260
262
  };
@@ -99,6 +99,7 @@ export const sqlDateColumn = <R extends Record<string, any>>(
99
99
  ): SqlRequestDataGridColumns<R> => ({
100
100
  [key]: {
101
101
  name: title,
102
+ type: 'date',
102
103
  render: (row) => formatDate(row[key]),
103
104
  getter: (row) => row[key] ?? '',
104
105
  sortGetter: (row) => row[key] ?? '',
@@ -59,7 +59,7 @@ export const SqlRequestDataGrid = <R,>({
59
59
  const columnTypes = useMemo(
60
60
  () =>
61
61
  visibleColumnsKeys.map((key) =>
62
- String(props.columns[key].type ?? 'text')
62
+ String(props.columns[key]?.type ?? 'text')
63
63
  ),
64
64
  [visibleColumnsKeys, props.columns]
65
65
  );
@@ -4,6 +4,7 @@ import {
4
4
  HTMLAttributes,
5
5
  PropsWithChildren,
6
6
  useCallback,
7
+ useRef,
7
8
  useState,
8
9
  } from 'react';
9
10
 
@@ -27,7 +28,9 @@ export const ParentMenuItem: FC<HTMLAttributes<HTMLDivElement>> = ({
27
28
  ...props
28
29
  }) => {
29
30
  const [isOpened, setIsOpened] = useState(false);
31
+ const [isSubMenuLeft, setIsSubMenuLeft] = useState(false);
30
32
  const [currentTimeout, setCurrentTimeout] = useState<number | null>(null);
33
+ const containerRef = useRef<HTMLDivElement | null>(null);
31
34
 
32
35
  const stopTimeout = useCallback(() => {
33
36
  if (currentTimeout) {
@@ -42,6 +45,8 @@ export const ParentMenuItem: FC<HTMLAttributes<HTMLDivElement>> = ({
42
45
  setCurrentTimeout(
43
46
  window.setTimeout(
44
47
  () => {
48
+ const rect = containerRef.current?.getBoundingClientRect();
49
+ setIsSubMenuLeft(!!rect && rect.right + 280 > window.innerWidth);
45
50
  setIsOpened(open);
46
51
  },
47
52
  open ? 100 : 300
@@ -56,8 +61,9 @@ export const ParentMenuItem: FC<HTMLAttributes<HTMLDivElement>> = ({
56
61
 
57
62
  return (
58
63
  <MenuItemContainer
64
+ ref={containerRef}
59
65
  {...props}
60
- className={isOpened ? 'opened' : ''}
66
+ className={`${isOpened ? 'opened' : ''} ${isSubMenuLeft ? 'left' : ''}`}
61
67
  onMouseEnter={open}
62
68
  onMouseLeave={close}
63
69
  $withArrow
@@ -104,6 +104,10 @@ export const MenuItemContainer = styled.div.attrs({
104
104
  &.opened > ${SubMenu} {
105
105
  display: block;
106
106
  }
107
+ &.opened.left > ${SubMenu} {
108
+ left: auto;
109
+ right: 100%;
110
+ }
107
111
  `;
108
112
  MenuItemContainer.displayName = 'MenuItemContainer';
109
113