@geotab/zenith 3.16.0-beta.2 → 3.16.0-beta.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/README.md +15 -12
- package/dist/absolute/absolute.js +1 -1
- package/dist/chart/plugins/linePlugin/getInterpolatedValue.d.ts +2 -2
- package/dist/chart/plugins/linePlugin/getInterpolatedValue.js +3 -2
- package/dist/chart/plugins/linePlugin/linePlugin.js +2 -1
- package/dist/chart/utils/getFormattedLabel.js +5 -1
- package/dist/checkbox/checkbox.d.ts +2 -1
- package/dist/checkbox/checkbox.js +2 -2
- package/dist/checkboxListWithAction/checkboxListWithAction.js +1 -0
- package/dist/commonHelpers/hooks/useTrapFocus.d.ts +0 -9
- package/dist/commonHelpers/hooks/useTrapFocus.js +14 -66
- package/dist/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +2 -1
- package/dist/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
- package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +4 -2
- package/dist/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +10 -1
- package/dist/dataGrid/row/row.js +3 -2
- package/dist/dataGrid/withSelectableRows/withSelectableRows.js +73 -12
- package/dist/index.css +1 -1
- package/dist/table/selectable/interfaces.d.ts +9 -13
- package/dist/table/selectable/useDragSelection.d.ts +10 -0
- package/dist/table/selectable/useDragSelection.js +139 -0
- package/dist/table/selectable/useSelectableRows.d.ts +2 -2
- package/dist/table/selectable/useSelectableRows.js +59 -49
- package/dist/table/selectable/utils/calculateSelectionState.js +0 -35
- package/dist/table/selectable/utils/getDragSelectionRows.d.ts +15 -0
- package/dist/table/selectable/utils/getDragSelectionRows.js +28 -0
- package/dist/table/selectable/utils/getRangeIds.d.ts +2 -0
- package/dist/table/selectable/utils/getRangeIds.js +21 -0
- package/dist/table/selectable/utils/isRowChecked.js +1 -12
- package/dist/table/table.js +1 -1
- package/esm/absolute/absolute.js +1 -1
- package/esm/chart/plugins/linePlugin/getInterpolatedValue.d.ts +2 -2
- package/esm/chart/plugins/linePlugin/getInterpolatedValue.js +3 -2
- package/esm/chart/plugins/linePlugin/linePlugin.js +2 -1
- package/esm/chart/utils/getFormattedLabel.js +5 -1
- package/esm/checkbox/checkbox.d.ts +2 -1
- package/esm/checkbox/checkbox.js +2 -2
- package/esm/checkboxListWithAction/checkboxListWithAction.js +1 -0
- package/esm/commonHelpers/hooks/useTrapFocus.d.ts +0 -9
- package/esm/commonHelpers/hooks/useTrapFocus.js +15 -67
- package/esm/dataGrid/columns/checkboxColumn/checkboxCell.d.ts +2 -1
- package/esm/dataGrid/columns/checkboxColumn/checkboxCell.js +1 -1
- package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.d.ts +4 -2
- package/esm/dataGrid/columns/checkboxColumn/checkboxColumnWrapper.js +10 -1
- package/esm/dataGrid/row/row.js +3 -2
- package/esm/dataGrid/withSelectableRows/withSelectableRows.js +73 -12
- package/esm/table/selectable/interfaces.d.ts +9 -13
- package/esm/table/selectable/useDragSelection.d.ts +10 -0
- package/esm/table/selectable/useDragSelection.js +135 -0
- package/esm/table/selectable/useSelectableRows.d.ts +2 -2
- package/esm/table/selectable/useSelectableRows.js +59 -49
- package/esm/table/selectable/utils/calculateSelectionState.js +0 -35
- package/esm/table/selectable/utils/getDragSelectionRows.d.ts +15 -0
- package/esm/table/selectable/utils/getDragSelectionRows.js +24 -0
- package/esm/table/selectable/utils/getRangeIds.d.ts +2 -0
- package/esm/table/selectable/utils/getRangeIds.js +17 -0
- package/esm/table/selectable/utils/isRowChecked.js +1 -12
- package/esm/table/table.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,28 +49,31 @@ Zenith library provides components defined in Zenith Design System. It includes
|
|
|
49
49
|
|
|
50
50
|
### 3.16.0
|
|
51
51
|
|
|
52
|
-
- Add `Tooltip.
|
|
52
|
+
- Add `Tooltip.InlineTrigger` subcomponent for inline tooltip triggers
|
|
53
|
+
- Add `TrendIndicator` component, the `getTrendIndicatorDirection` helper, and `Table.TrendIndicator`
|
|
53
54
|
- Add popup button variant for `Nav` items
|
|
54
55
|
- Add integer-only mode prop to `Range` / `FilterBar.Range`
|
|
55
|
-
- Add Arabic language support
|
|
56
56
|
- Add experimental feature-flag infrastructure (`ZenithExperimentalProvider`, `useExperimentalFeature`)
|
|
57
57
|
- Expose `Tag` and `ProgressIndicator` as `Table` sub-components (`Table.Tag`, `Table.ProgressIndicator`)
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
58
|
+
- Add `MODAL_SCROLL_LOCK_CLASS` export to control scroll-lock release timing when a `Modal` closes
|
|
59
|
+
- Rename the Arabic locale from `ar` to `ar-001`; `ar` and any `ar-*` value still resolve to it
|
|
60
|
+
- Migrate component alignment defaults to logical direction values — `ControlledPopup` now defaults to `bottom-start` and `Tooltip` to `end`
|
|
61
|
+
- Complete RTL logical-direction support: `ControlledPopup` migration and `PillExpandable` alignment flipping
|
|
62
|
+
- Remove `isBannerTarget` from the side panel overlay target checks
|
|
63
|
+
- Apply `dataAnalyticsId` to nested `PillExpandable` child pill triggers
|
|
64
|
+
- Resolve 20 npm audit vulnerabilities in Zenith dependencies
|
|
65
|
+
- Add an `ariaLabel` prop to `Checkbox` and accessible names to `Dropdown` multi-select options
|
|
62
66
|
- Fix multiline `Banner` header spacing when there is no close button
|
|
63
67
|
- Fix scrolling in `Tabs` and `FiltersBar`
|
|
64
|
-
- Fix `Tabs` fading
|
|
68
|
+
- Fix `Tabs` fading in RTL layouts
|
|
69
|
+
- Fix side panel slide direction in RTL layouts
|
|
65
70
|
- Fix pills and chips scrolling the page to a blank area in RTL
|
|
66
|
-
- Fix icons ignoring their component's colour
|
|
67
71
|
- Fix mobile header overflow and `ReportsPopup` missing from the kebab menu in non-English languages
|
|
68
|
-
-
|
|
72
|
+
- Distinguish the `Tabs` focus ring from the active tab, and move focus to a tab only on user-initiated changes
|
|
69
73
|
- Fix `BetaPill` synthesising a Send feedback button when `feedbackAction` is undefined
|
|
70
|
-
-
|
|
71
|
-
- Fix Storybook brand URL to resolve based on the environment
|
|
74
|
+
- Fix `Nav` mobile search autofocusing when the search box is closed
|
|
72
75
|
- Fix `AutoFill` not selecting the chosen option on `DropdownRaw`
|
|
73
|
-
-
|
|
76
|
+
- Fix `LineChart` tooltip interpolation and accessible chart dates when a custom x-axis parser is used
|
|
74
77
|
|
|
75
78
|
### 3.15.0
|
|
76
79
|
|
|
@@ -111,7 +111,7 @@ const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, trigger
|
|
|
111
111
|
returnFocusToTrigger();
|
|
112
112
|
}
|
|
113
113
|
}, [isOpen, returnFocusToTrigger]);
|
|
114
|
-
const condition = (0, react_1.useCallback)((
|
|
114
|
+
const condition = (0, react_1.useCallback)(() => (useTrapFocusWithTrigger === "off" ? false : true), [useTrapFocusWithTrigger]);
|
|
115
115
|
(0, useTrapFocus_1.useTrapFocus)(popupRef, useTrapFocusWithTrigger === "withTrigger" ? triggerRef : undefined, isOpen, condition);
|
|
116
116
|
(0, useEscape_1.useEscape)(popupRef, handleEscape, isOpen);
|
|
117
117
|
(0, useArrowKey_1.useArrowKey)(popupRef, handleEscape, isOpen);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Scale } from "chart.js";
|
|
1
|
+
import { Scale, type ChartOptions } from "chart.js";
|
|
2
2
|
import { ILineChartData } from "../../lineChart/interfaces";
|
|
3
|
-
export declare function getInterpolatedValue(xScale: Scale, data: ILineChartData, datasetIndex: number, xPixel: number): number | null;
|
|
3
|
+
export declare function getInterpolatedValue(xScale: Scale, data: ILineChartData, datasetIndex: number, xPixel: number, parsing?: ChartOptions<"line">["parsing"]): number | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getInterpolatedValue = getInterpolatedValue;
|
|
4
|
-
function getInterpolatedValue(xScale, data, datasetIndex, xPixel) {
|
|
4
|
+
function getInterpolatedValue(xScale, data, datasetIndex, xPixel, parsing) {
|
|
5
5
|
const dataset = data.datasets[datasetIndex];
|
|
6
6
|
const dataPoints = dataset.data;
|
|
7
7
|
if (dataPoints.length < 2) {
|
|
@@ -18,7 +18,8 @@ function getInterpolatedValue(xScale, data, datasetIndex, xPixel) {
|
|
|
18
18
|
if (y === null) {
|
|
19
19
|
continue;
|
|
20
20
|
}
|
|
21
|
-
const
|
|
21
|
+
const parsedX = parsing === false ? x : xScale.parse(x, i);
|
|
22
|
+
const pointXPixel = xScale.getPixelForValue(parsedX);
|
|
22
23
|
if (pointXPixel <= xPixel && pointXPixel > lowerXPixel) {
|
|
23
24
|
lowerPoint = y;
|
|
24
25
|
lowerXPixel = pointXPixel;
|
|
@@ -60,6 +60,7 @@ const LinePlugin = (containerId, options, isDark) => ({
|
|
|
60
60
|
let lowestValueY = Infinity;
|
|
61
61
|
const items = datasets
|
|
62
62
|
.map((dataset, dsIndex) => {
|
|
63
|
+
var _a;
|
|
63
64
|
if (!chart.isDatasetVisible(dsIndex)) {
|
|
64
65
|
return undefined;
|
|
65
66
|
}
|
|
@@ -67,7 +68,7 @@ const LinePlugin = (containerId, options, isDark) => ({
|
|
|
67
68
|
return undefined;
|
|
68
69
|
}
|
|
69
70
|
const xScale = chart.scales.x;
|
|
70
|
-
const value = (0, getInterpolatedValue_1.getInterpolatedValue)(xScale, chart.data, dsIndex, x);
|
|
71
|
+
const value = (0, getInterpolatedValue_1.getInterpolatedValue)(xScale, chart.data, dsIndex, x, (_a = dataset.parsing) !== null && _a !== void 0 ? _a : chart.options.parsing);
|
|
71
72
|
const yAxisID = dataset.yAxisID || "y";
|
|
72
73
|
const yScale = chart.scales[yAxisID];
|
|
73
74
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -6,14 +6,18 @@ function getFormattedLabel(value, dateFormatter, options) {
|
|
|
6
6
|
var _a, _b, _c;
|
|
7
7
|
const scaleType = (_b = (_a = options === null || options === void 0 ? void 0 : options.scales) === null || _a === void 0 ? void 0 : _a.x) === null || _b === void 0 ? void 0 : _b.type;
|
|
8
8
|
let format;
|
|
9
|
+
let parser;
|
|
9
10
|
if (((_c = options === null || options === void 0 ? void 0 : options.scales) === null || _c === void 0 ? void 0 : _c.x) && scaleType) {
|
|
10
11
|
const scaleFormat = options.scales.x[scaleType];
|
|
11
12
|
if ((scaleFormat === null || scaleFormat === void 0 ? void 0 : scaleFormat.unit) && scaleFormat.displayFormats && scaleFormat.displayFormats[scaleFormat.unit]) {
|
|
12
13
|
format = scaleFormat.displayFormats[scaleFormat.unit];
|
|
13
14
|
}
|
|
15
|
+
if (options.parsing !== false && scaleFormat && "parser" in scaleFormat && typeof scaleFormat.parser === "function") {
|
|
16
|
+
parser = scaleFormat.parser;
|
|
17
|
+
}
|
|
14
18
|
}
|
|
15
19
|
if (value instanceof Date || (typeof value === "string" && (0, isDateString_1.isDateString)(value))) {
|
|
16
|
-
return dateFormatter(value, format);
|
|
20
|
+
return dateFormatter(parser ? new Date(parser(value)) : value, format);
|
|
17
21
|
}
|
|
18
22
|
return String(value);
|
|
19
23
|
}
|
|
@@ -8,6 +8,7 @@ export interface ICheckbox extends IZenComponentProps {
|
|
|
8
8
|
checked?: boolean;
|
|
9
9
|
indeterminate?: boolean;
|
|
10
10
|
title?: string;
|
|
11
|
+
ariaLabel?: string;
|
|
11
12
|
disabled?: boolean;
|
|
12
13
|
fullWidth?: boolean;
|
|
13
14
|
reverse?: boolean;
|
|
@@ -16,4 +17,4 @@ export interface ICheckbox extends IZenComponentProps {
|
|
|
16
17
|
tabIndex?: number;
|
|
17
18
|
describedBy?: string;
|
|
18
19
|
}
|
|
19
|
-
export declare const Checkbox: ({ reverse, fullWidth, id, checked, indeterminate, title, className, children, disabled, wrapped, describedBy, ...rest }: ICheckbox) => import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export declare const Checkbox: ({ reverse, fullWidth, id, checked, indeterminate, title, ariaLabel, className, children, disabled, wrapped, describedBy, ...rest }: ICheckbox) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -56,14 +56,14 @@ const checkboxIconCheckmark_1 = require("./checkboxIconCheckmark");
|
|
|
56
56
|
const checkboxIconMinus_1 = require("./checkboxIconMinus");
|
|
57
57
|
const useMobile_1 = require("../commonHelpers/hooks/useMobile");
|
|
58
58
|
const Checkbox = (_a) => {
|
|
59
|
-
var { reverse, fullWidth, id, checked, indeterminate, title, className = "", children, disabled, wrapped, describedBy } = _a, rest = __rest(_a, ["reverse", "fullWidth", "id", "checked", "indeterminate", "title", "className", "children", "disabled", "wrapped", "describedBy"]);
|
|
59
|
+
var { reverse, fullWidth, id, checked, indeterminate, title, ariaLabel, className = "", children, disabled, wrapped, describedBy } = _a, rest = __rest(_a, ["reverse", "fullWidth", "id", "checked", "indeterminate", "title", "ariaLabel", "className", "children", "disabled", "wrapped", "describedBy"]);
|
|
60
60
|
const state = (0, checkboxUtils_1.getCheckboxState)(checked, indeterminate);
|
|
61
61
|
const generatedId = react_1.default.useId();
|
|
62
62
|
const intId = id || generatedId;
|
|
63
63
|
const driveClasses = (0, useDriveClassName_1.useDriveClassName)("zen-checkbox");
|
|
64
64
|
const isMobile = (0, useMobile_1.useMobile)();
|
|
65
65
|
const checkboxIconClasses = (0, react_1.useMemo)(() => (0, classNames_1.classNames)(["zen-checkbox__icon", disabled ? "zen-checkbox__icon--disabled" : ""]), [disabled]);
|
|
66
|
-
const checkbox = ((0, jsx_runtime_1.jsx)(triStateCheckbox_1.TriStateCheckbox, Object.assign({ className: "zen-checkbox__input", id: intId, checked: checked, indeterminate: indeterminate, disabled: disabled, "aria-label": title, "aria-describedby": describedBy }, rest)));
|
|
66
|
+
const checkbox = ((0, jsx_runtime_1.jsx)(triStateCheckbox_1.TriStateCheckbox, Object.assign({ className: "zen-checkbox__input", id: intId, checked: checked, indeterminate: indeterminate, disabled: disabled, "aria-label": ariaLabel || title, "aria-describedby": describedBy }, rest)));
|
|
67
67
|
const iconAndLabel = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "zen-checkbox__box", "aria-hidden": true, children: state === checkboxState_1.CheckboxState.Indeterminate ? ((0, jsx_runtime_1.jsx)(checkboxIconMinus_1.CheckboxIconMinus, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" })) : state === checkboxState_1.CheckboxState.On ? ((0, jsx_runtime_1.jsx)(checkboxIconCheckmark_1.CheckboxIconCheckmark, { className: checkboxIconClasses, size: driveClasses ? "bigger" : "medium" })) : null }), children ? ((0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-checkbox__label-text", fullWidth ? "zen-checkbox__label-text--full-width" : ""]), children: children })) : null] }));
|
|
68
68
|
if (wrapped) {
|
|
69
69
|
return ((0, jsx_runtime_1.jsxs)("label", { className: (0, classNames_1.classNames)(["zen-checkbox", driveClasses || "", className]), title: title, children: [checkbox, (0, jsx_runtime_1.jsx)("div", { className: (0, classNames_1.classNames)(["zen-checkbox__label", reverse ? "zen-checkbox__label--reverse" : ""]), children: iconAndLabel })] }));
|
|
@@ -453,6 +453,7 @@ const CheckboxListWithAction = ({
|
|
|
453
453
|
checked: opt.checked,
|
|
454
454
|
disabled: opt.blocked,
|
|
455
455
|
title: translate("Toggle {groupName} filter").replace("{groupName}", titleForRender),
|
|
456
|
+
ariaLabel: titleForRender,
|
|
456
457
|
describedBy: opt.isWithAction ? navigationInstructionsId : undefined,
|
|
457
458
|
"data-indeterminate": opt.partialChecked,
|
|
458
459
|
tabIndex: getTabIndex(ind, "checkbox", opt.blocked),
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import { RefObject } from "react";
|
|
2
2
|
type TElementToBool = (element: HTMLElement) => boolean;
|
|
3
|
-
/**
|
|
4
|
-
* Traps keyboard (Tab) focus within `containerRef` (and optionally its `triggerRef`).
|
|
5
|
-
*
|
|
6
|
-
* Nested-popup contract: for correct nested-popup behaviour, a focused element that triggers an
|
|
7
|
-
* open child popup must expose a `data-popup-id` attribute whose value is the `id` of the child
|
|
8
|
-
* popup element rendered in the DOM. When present, focus is deferred to that child popup's trap.
|
|
9
|
-
* This contract is fulfilled automatically by `ControlledPopup`; callers using `useTrapFocus`
|
|
10
|
-
* directly must set `data-popup-id` themselves or nested popups will silently lose focus handling.
|
|
11
|
-
*/
|
|
12
3
|
export declare const useTrapFocus: (containerRef: RefObject<HTMLElement | null>, triggerRef: RefObject<HTMLElement | null> | undefined, subscriptionTrigger: unknown, condition?: (t: unknown) => boolean, isElementVisible?: TElementToBool) => void;
|
|
13
4
|
export {};
|
|
@@ -9,38 +9,18 @@ const isChildOf_1 = require("../../utils/isChildOf");
|
|
|
9
9
|
const isElementHidden_1 = require("../../utils/isElementHidden");
|
|
10
10
|
const zen_1 = require("../../utils/zen");
|
|
11
11
|
const findFirstVisible = (elems, isElementVisible) => elems.find(elem => isElementVisible(elem));
|
|
12
|
-
/**
|
|
13
|
-
* Traps keyboard (Tab) focus within `containerRef` (and optionally its `triggerRef`).
|
|
14
|
-
*
|
|
15
|
-
* Nested-popup contract: for correct nested-popup behaviour, a focused element that triggers an
|
|
16
|
-
* open child popup must expose a `data-popup-id` attribute whose value is the `id` of the child
|
|
17
|
-
* popup element rendered in the DOM. When present, focus is deferred to that child popup's trap.
|
|
18
|
-
* This contract is fulfilled automatically by `ControlledPopup`; callers using `useTrapFocus`
|
|
19
|
-
* directly must set `data-popup-id` themselves or nested popups will silently lose focus handling.
|
|
20
|
-
*/
|
|
21
12
|
const useTrapFocus = (containerRef, triggerRef, subscriptionTrigger, condition, isElementVisible) => {
|
|
22
13
|
/* eslint-disable complexity */
|
|
23
14
|
const handleKeyDown = (0, react_1.useCallback)(e => {
|
|
24
|
-
var _a, _b, _c, _d, _e, _f
|
|
15
|
+
var _a, _b, _c, _d, _e, _f;
|
|
25
16
|
/* eslint-enable complexity */
|
|
26
17
|
const getChildCondition = () => {
|
|
27
|
-
var _a, _b
|
|
28
|
-
const targetEl = e.target;
|
|
29
|
-
// If the target is a trigger for an open child popup, defer to that popup's
|
|
30
|
-
// focus trap. Key on data-popup-id + DOM presence so this works even when
|
|
31
|
-
// preventAttributesAutoSet suppresses aria-expanded.
|
|
32
|
-
const dataPopupId = targetEl.getAttribute("data-popup-id");
|
|
33
|
-
if (dataPopupId &&
|
|
34
|
-
((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.getElementById(dataPopupId)) &&
|
|
35
|
-
(0, isChildOf_1.isChildOf)(targetEl, containerRef.current) &&
|
|
36
|
-
targetEl !== (triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current)) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
18
|
+
var _a, _b;
|
|
39
19
|
return triggerRef
|
|
40
|
-
? !(0, isChildOf_1.isChildOf)(
|
|
41
|
-
|
|
42
|
-
!(0, isChildOf_1.isChildOf)(
|
|
43
|
-
: !(0, isChildOf_1.isChildOf)(
|
|
20
|
+
? !(0, isChildOf_1.isChildOf)(e.target, containerRef.current) &&
|
|
21
|
+
e.target !== ((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.body) &&
|
|
22
|
+
!(0, isChildOf_1.isChildOf)(e.target, triggerRef.current)
|
|
23
|
+
: !(0, isChildOf_1.isChildOf)(e.target, containerRef.current) && e.target !== ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body);
|
|
44
24
|
};
|
|
45
25
|
if (!containerRef.current || getChildCondition()) {
|
|
46
26
|
return;
|
|
@@ -50,14 +30,9 @@ const useTrapFocus = (containerRef, triggerRef, subscriptionTrigger, condition,
|
|
|
50
30
|
: !(0, dialogHelpers_1.isElementInsideContainer)(target, containerEl.current) &&
|
|
51
31
|
!(0, dialogHelpers_1.isElementInsideContainer)(target, triggerEl.current);
|
|
52
32
|
const isTargetOutside = e.target ? checkIsElementOutside(e.target, containerRef, triggerRef) : undefined;
|
|
53
|
-
const
|
|
54
|
-
const triggerSelf = (triggerElement === null || triggerElement === void 0 ? void 0 : triggerElement.matches(focusableSelector_1.FOCUSABLE_SELECTOR)) ? [triggerElement] : [];
|
|
55
|
-
const triggerChildren = Array.from((_b = triggerElement === null || triggerElement === void 0 ? void 0 : triggerElement.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR)) !== null && _b !== void 0 ? _b : []);
|
|
56
|
-
// querySelectorAll only returns descendants (never the element itself), so triggerSelf
|
|
57
|
-
// and triggerChildren are disjoint by definition and need no deduplication.
|
|
58
|
-
const triggerSelectors = [...triggerSelf, ...triggerChildren];
|
|
33
|
+
const triggerSelectors = ((_a = triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR)) || [];
|
|
59
34
|
const containerSelectors = containerRef.current.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR);
|
|
60
|
-
const focusable = triggerRef ? [...triggerSelectors, ...Array.from(containerSelectors)] : [...Array.from(containerSelectors)];
|
|
35
|
+
const focusable = triggerRef ? [...Array.from(triggerSelectors), ...Array.from(containerSelectors)] : [...Array.from(containerSelectors)];
|
|
61
36
|
if (!focusable.length) {
|
|
62
37
|
return;
|
|
63
38
|
}
|
|
@@ -74,59 +49,32 @@ const useTrapFocus = (containerRef, triggerRef, subscriptionTrigger, condition,
|
|
|
74
49
|
return;
|
|
75
50
|
}
|
|
76
51
|
if (e.shiftKey) {
|
|
77
|
-
if (((
|
|
52
|
+
if (((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.activeElement) === first) {
|
|
78
53
|
e.preventDefault();
|
|
79
54
|
last === null || last === void 0 ? void 0 : last.focus();
|
|
80
55
|
return;
|
|
81
56
|
}
|
|
82
|
-
if (firstContainerFocusable && ((
|
|
57
|
+
if (firstContainerFocusable && ((_c = zen_1.zen.document) === null || _c === void 0 ? void 0 : _c.activeElement) === firstContainerFocusable) {
|
|
83
58
|
e.preventDefault();
|
|
84
59
|
lastTriggerFocusable === null || lastTriggerFocusable === void 0 ? void 0 : lastTriggerFocusable.focus();
|
|
85
60
|
}
|
|
86
61
|
return;
|
|
87
62
|
}
|
|
88
|
-
if (((
|
|
63
|
+
if (((_d = zen_1.zen.document) === null || _d === void 0 ? void 0 : _d.activeElement) === last) {
|
|
89
64
|
e.preventDefault();
|
|
90
65
|
first === null || first === void 0 ? void 0 : first.focus();
|
|
91
66
|
return;
|
|
92
67
|
}
|
|
93
|
-
if (lastTriggerFocusable && ((
|
|
68
|
+
if (lastTriggerFocusable && ((_e = zen_1.zen.document) === null || _e === void 0 ? void 0 : _e.activeElement) === lastTriggerFocusable) {
|
|
94
69
|
e.preventDefault();
|
|
95
70
|
firstContainerFocusable === null || firstContainerFocusable === void 0 ? void 0 : firstContainerFocusable.focus();
|
|
96
71
|
}
|
|
97
|
-
else if (isLastChildOfFirst && first && (0, isChildOf_1.isChildOf)((
|
|
72
|
+
else if (isLastChildOfFirst && first && (0, isChildOf_1.isChildOf)((_f = zen_1.zen.document) === null || _f === void 0 ? void 0 : _f.activeElement, first)) {
|
|
98
73
|
e.preventDefault();
|
|
99
74
|
}
|
|
100
75
|
return;
|
|
101
76
|
}
|
|
102
|
-
},
|
|
103
|
-
// condition is consumed by useKeydown below, not read by handleKeyDown directly; its absence from deps is intentional.
|
|
104
|
-
[containerRef, triggerRef, isElementVisible]);
|
|
77
|
+
}, [containerRef, triggerRef, isElementVisible]);
|
|
105
78
|
(0, useKeydown_1.useKeydown)(handleKeyDown, subscriptionTrigger, condition);
|
|
106
|
-
// When withTrigger mode closes (condition goes false), restore focus to the trigger
|
|
107
|
-
// if focus landed on body (which happens when the popup's focused element is unmounted).
|
|
108
|
-
// This restoration is intentionally scoped to the "focused element unmounted → body" case;
|
|
109
|
-
// the general close case (e.g. click-outside, item selection) is handled separately by the
|
|
110
|
-
// returnFocusToTrigger effect in absolute.tsx. Both are idempotent, so overlap is harmless.
|
|
111
|
-
// Initialized to false because popups mount closed; the guard below reconciles the first
|
|
112
|
-
// active/inactive edge, so a popup that mounts already open still resolves correctly.
|
|
113
|
-
const isActiveRef = (0, react_1.useRef)(false);
|
|
114
|
-
(0, react_1.useEffect)(() => {
|
|
115
|
-
var _a, _b;
|
|
116
|
-
const isActive = condition ? condition(subscriptionTrigger) : !!subscriptionTrigger;
|
|
117
|
-
// Guard: short-circuit when the raw open/close state is unchanged to avoid spurious
|
|
118
|
-
// focus restoration if an unstable condition reference re-fires this effect.
|
|
119
|
-
if (!!subscriptionTrigger === isActiveRef.current) {
|
|
120
|
-
isActiveRef.current = isActive;
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
if (!isActive && isActiveRef.current && (triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current)) {
|
|
124
|
-
const active = (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.activeElement;
|
|
125
|
-
if (!active || active === ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body)) {
|
|
126
|
-
triggerRef.current.focus();
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
isActiveRef.current = isActive;
|
|
130
|
-
}, [condition, subscriptionTrigger, triggerRef]);
|
|
131
79
|
};
|
|
132
80
|
exports.useTrapFocus = useTrapFocus;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FC, PropsWithChildren, ReactElement } from "react";
|
|
1
|
+
import { FC, MouseEvent as ReactMouseEvent, PropsWithChildren, ReactElement } from "react";
|
|
2
2
|
import { IZenIdComponentProps } from "../../../commonHelpers/zenComponent";
|
|
3
3
|
import "./checkboxColumn.less";
|
|
4
4
|
interface ICheckboxCellProps extends IZenIdComponentProps {
|
|
@@ -8,6 +8,7 @@ interface ICheckboxCellProps extends IZenIdComponentProps {
|
|
|
8
8
|
disabled?: boolean;
|
|
9
9
|
children?: ReactElement<typeof CheckboxCell.Content>;
|
|
10
10
|
onChange?: (id: string, checked: boolean) => void;
|
|
11
|
+
onMouseDown?: (id: string, checked: boolean, e: ReactMouseEvent) => void;
|
|
11
12
|
}
|
|
12
13
|
interface ICheckboxCell extends FC<ICheckboxCellProps> {
|
|
13
14
|
Content: FC<PropsWithChildren>;
|
|
@@ -4,7 +4,7 @@ exports.CheckboxCell = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const checkbox_1 = require("../../../checkbox/checkbox");
|
|
6
6
|
const classNames_1 = require("../../../commonHelpers/classNames/classNames");
|
|
7
|
-
const CheckboxCell = ({ id, checked, indeterminate, label, disabled, className, onChange, children }) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-checkbox-column", className || ""]), children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { className: "zen-checkbox-column__checkbox", checked: checked, indeterminate: indeterminate, disabled: disabled, title: label, onChange: e => onChange && onChange(id, e.target.checked), wrapped: true }), children] }));
|
|
7
|
+
const CheckboxCell = ({ id, checked, indeterminate, label, disabled, className, onChange, onMouseDown, children }) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-checkbox-column", className || ""]), onMouseDown: onMouseDown ? e => onMouseDown(id, checked, e) : undefined, children: [(0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { className: "zen-checkbox-column__checkbox", checked: checked, indeterminate: indeterminate, disabled: disabled, title: label, onChange: e => onChange && onChange(id, e.target.checked), wrapped: true }), children] }));
|
|
8
8
|
exports.CheckboxCell = CheckboxCell;
|
|
9
9
|
exports.CheckboxCell.Content = function content({ children }) {
|
|
10
10
|
return (0, jsx_runtime_1.jsx)("div", { className: "zen-checkbox-column__content", children: children });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode, RefObject } from "react";
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, ReactNode, RefObject } from "react";
|
|
2
2
|
import { IListColumnWrapper } from "../../listColumn";
|
|
3
3
|
import "./checkboxColumn.less";
|
|
4
4
|
import { SimpleEventHandler } from "../../../commonHelpers/simpleEventHandler";
|
|
@@ -17,7 +17,8 @@ export interface ICheckboxColumnWrapper<T extends object> extends IListColumnWra
|
|
|
17
17
|
attach(event: "toggle", handler: (state: [Event, HTMLButtonElement]) => void): this;
|
|
18
18
|
attach(event: "change", handler: (state: [string, boolean]) => void): this;
|
|
19
19
|
attach(event: "change-all", handler: (state: [boolean]) => void): this;
|
|
20
|
-
|
|
20
|
+
attach(event: "mousedown", handler: (state: [string, boolean, ReactMouseEvent]) => void): this;
|
|
21
|
+
detach(event: "change" | "toggle" | "change-all" | "mousedown", handler?: (state: unknown) => void): this;
|
|
21
22
|
}
|
|
22
23
|
export declare enum SelectionState {
|
|
23
24
|
All = 0,
|
|
@@ -34,6 +35,7 @@ export declare class CheckboxColumnWrapper<T extends IEntityWithId> extends Simp
|
|
|
34
35
|
private state;
|
|
35
36
|
private readonly actionsClickHandler;
|
|
36
37
|
private readonly changeHandler;
|
|
38
|
+
private readonly mouseDownHandler;
|
|
37
39
|
private readonly changeHandlerAll;
|
|
38
40
|
constructor(selections: Set<string>, options: ICheckboxColumnOptions<T>, menuTriggerRef: RefObject<HTMLButtonElement | null>);
|
|
39
41
|
get selectionState(): SelectionState;
|
|
@@ -67,6 +67,15 @@ class CheckboxColumnWrapper extends simpleEventHandler_1.SimpleEventHandler {
|
|
|
67
67
|
this.fire("change", [id, checked]);
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
|
+
// Only fired for enabled checkboxes, so a disabled row can never become a drag anchor.
|
|
71
|
+
Object.defineProperty(this, "mouseDownHandler", {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
configurable: true,
|
|
74
|
+
writable: true,
|
|
75
|
+
value: (id, checked, e) => {
|
|
76
|
+
this.fire("mousedown", [id, checked, e]);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
70
79
|
Object.defineProperty(this, "changeHandlerAll", {
|
|
71
80
|
enumerable: true,
|
|
72
81
|
configurable: true,
|
|
@@ -92,7 +101,7 @@ class CheckboxColumnWrapper extends simpleEventHandler_1.SimpleEventHandler {
|
|
|
92
101
|
}
|
|
93
102
|
const allowed = this.condition(entity);
|
|
94
103
|
const isDisable = this.disabled ? this.disabled(entity) : this.state === SelectionState.All;
|
|
95
|
-
const cell = ((0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell, { id: entity.id, className: allowed ? "" : "zen-checkbox-column--no-checkbox", checked: this.state === SelectionState.All || this.selections.has(entity.id), indeterminate: false, disabled: isDisable, label: this.options.createTitle(entity), onChange: this.changeHandler, children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, { children: value }) }));
|
|
104
|
+
const cell = ((0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell, { id: entity.id, className: allowed ? "" : "zen-checkbox-column--no-checkbox", checked: this.state === SelectionState.All || this.selections.has(entity.id), indeterminate: false, disabled: isDisable, label: this.options.createTitle(entity), onChange: this.changeHandler, onMouseDown: isDisable ? undefined : this.mouseDownHandler, children: (0, jsx_runtime_1.jsx)(checkboxCell_1.CheckboxCell.Content, { children: value }) }));
|
|
96
105
|
return cell;
|
|
97
106
|
}
|
|
98
107
|
renderHeader(title) {
|
package/dist/dataGrid/row/row.js
CHANGED
|
@@ -60,7 +60,8 @@ const Row = ({ id, entity, columns, visibleRows, flexibleColumnWidth, isLastRow,
|
|
|
60
60
|
return acc;
|
|
61
61
|
}, { cells: [], colspan: 0 }).cells, [columns, expanded, getCellParams, isVisible, onExpandedChange, isActive, active, onClick]);
|
|
62
62
|
const cells = (0, react_1.useMemo)(() => renderCells(entity, false), [entity, renderCells]);
|
|
63
|
-
const
|
|
64
|
-
|
|
63
|
+
const nestedEntities = (0, react_1.useMemo)(() => (expanded && entity.children ? entity.children : []), [entity.children, expanded]);
|
|
64
|
+
const nestedCells = (0, react_1.useMemo)(() => nestedEntities.map(nestedEntity => renderCells(nestedEntity, true)), [nestedEntities, renderCells]);
|
|
65
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("tr", { "data-row-id": id, id: mainRowId, role: "row", "aria-level": isTreeGrid ? 1 : undefined, "aria-posinset": isTreeGrid ? ariaPosinset : undefined, "aria-setsize": isTreeGrid ? ariaSetsize : undefined, "aria-expanded": isTreeGrid ? expanded : undefined, className: (0, classNames_1.classNames)(["zen-data-grid__row", className || "", isLastRow ? "zen-data-grid__row--last" : ""]), children: cells }, mainRowId), nestedCells.map((nestedRow, index) => ((0, jsx_runtime_1.jsx)("tr", { "data-row-id": nestedEntities[index].id, id: `${mainRowId}_child_${index}`, role: "row", "aria-level": 2, "aria-posinset": index + 1, "aria-setsize": nestedCells.length, className: "zen-data-grid__row zen-data-grid__row--nested", children: nestedRow }, `${mainRowId}_child_${index}`)))] }));
|
|
65
66
|
};
|
|
66
67
|
exports.DataGridRow = (0, react_1.memo)(Row);
|
|
@@ -15,6 +15,8 @@ const selectList_1 = require("../../selectList/selectList");
|
|
|
15
15
|
const checkboxState_1 = require("../../checkbox/checkboxState");
|
|
16
16
|
const selectableRowsColumnWrapper_1 = require("./columns/selectableRowsColumnWrapper");
|
|
17
17
|
const useLanguage_1 = require("../../utils/localization/useLanguage");
|
|
18
|
+
const useDragSelection_1 = require("../../table/selectable/useDragSelection");
|
|
19
|
+
const getDragSelectionRows_1 = require("../../table/selectable/utils/getDragSelectionRows");
|
|
18
20
|
injectString("cs", "Select all", "Vybrat v\u0161e");
|
|
19
21
|
injectString("da-DK", "Select all", "V\xE6lg alle");
|
|
20
22
|
injectString("de", "Select all", "Alle ausw\xE4hlen");
|
|
@@ -209,13 +211,29 @@ const withSelectableRows = DataGridComponent => {
|
|
|
209
211
|
const selectMenuRef = (0, react_1.useRef)(null);
|
|
210
212
|
const selections = (0, exports.getSelections)(selection);
|
|
211
213
|
const allSelected = selection !== undefined && selection.allSelected;
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
214
|
+
const isCheckboxVisible = (0, react_1.useCallback)(entity => {
|
|
215
|
+
const condition = options.condition || options.checkboxVisible;
|
|
216
|
+
return condition ? condition(entity) : true;
|
|
217
|
+
}, [options.condition, options.checkboxVisible]);
|
|
218
|
+
const isCheckboxDisabled = (0, react_1.useCallback)(entity => {
|
|
219
|
+
if (options.checkboxDisabled) {
|
|
220
|
+
return options.checkboxDisabled(entity);
|
|
221
|
+
}
|
|
222
|
+
if (options.selectionLimit !== undefined) {
|
|
223
|
+
return !selections.has(entity.id) && selections.size >= options.selectionLimit;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}, [options, selections]);
|
|
227
|
+
const wrapper = (0, react_1.useMemo)(() => {
|
|
228
|
+
var _a;
|
|
229
|
+
return selectMode ? new selectableRowsColumnWrapper_1.SelectableRowsColumnWrapper(selections, {
|
|
230
|
+
createTitle: options.createTitle,
|
|
231
|
+
headerTitle: options.headerTitle,
|
|
232
|
+
condition: options.condition || options.checkboxVisible,
|
|
233
|
+
disabled: (_a = options.checkboxDisabled) !== null && _a !== void 0 ? _a : isCheckboxDisabled,
|
|
234
|
+
header: options.selectionLimit === undefined && options.checkboxDisabled === undefined && options.checkboxVisible === undefined && options.condition === undefined || options.checkboxInHeader === true && !options.selectionLimit
|
|
235
|
+
}, selectMenuRef) : null;
|
|
236
|
+
}, [selectMode, selections, options.createTitle, options.headerTitle, options.condition, options.checkboxVisible, options.checkboxDisabled, options.selectionLimit, options.checkboxInHeader, isCheckboxDisabled]);
|
|
219
237
|
if (wrapper) {
|
|
220
238
|
wrapper.selectionState = calculateSelectionState(entities, selections, allSelected, options);
|
|
221
239
|
}
|
|
@@ -223,9 +241,10 @@ const withSelectableRows = DataGridComponent => {
|
|
|
223
241
|
const newSelections = new Set(selections);
|
|
224
242
|
entities.forEach(entity => {
|
|
225
243
|
if (checked) {
|
|
226
|
-
|
|
244
|
+
// Intentionally not isCheckboxDisabled: "select all" ignores the selection
|
|
245
|
+
// limit, it only skips rows the consumer explicitly disabled.
|
|
227
246
|
const isEnabled = !options.checkboxDisabled || !options.checkboxDisabled(entity);
|
|
228
|
-
if (
|
|
247
|
+
if (isCheckboxVisible(entity) && isEnabled) {
|
|
229
248
|
newSelections.add(entity.id);
|
|
230
249
|
}
|
|
231
250
|
return;
|
|
@@ -238,8 +257,49 @@ const withSelectableRows = DataGridComponent => {
|
|
|
238
257
|
allSelected: newState === checkboxColumnWrapper_1.SelectionState.All,
|
|
239
258
|
turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
|
|
240
259
|
});
|
|
241
|
-
}, [selections, entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
|
|
260
|
+
}, [selections, entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll, isCheckboxVisible]);
|
|
261
|
+
const {
|
|
262
|
+
rows: dragRows,
|
|
263
|
+
entityById
|
|
264
|
+
} = (0, react_1.useMemo)(() => (0, getDragSelectionRows_1.getDragSelectionRows)(entities), [entities]);
|
|
265
|
+
const isRowSelectable = (0, react_1.useCallback)(row => {
|
|
266
|
+
const entity = entityById.get(row.id);
|
|
267
|
+
return !!entity && isCheckboxVisible(entity) && !isCheckboxDisabled(entity);
|
|
268
|
+
}, [entityById, isCheckboxVisible, isCheckboxDisabled]);
|
|
269
|
+
// "Select all" is held as a flag rather than a list of ids, so materialise the page before
|
|
270
|
+
// a range starts editing it — otherwise the range would be applied to an empty selection.
|
|
271
|
+
const getBaseSelection = (0, react_1.useCallback)(() => allSelected ? new Set(entities.map(entity => entity.id)) : new Set(selections), [allSelected, entities, selections]);
|
|
272
|
+
const onBatchSelect = (0, react_1.useCallback)((rangeIds, select, base) => {
|
|
273
|
+
const result = new Set(base);
|
|
274
|
+
const limit = options.selectionLimit;
|
|
275
|
+
for (const id of rangeIds) {
|
|
276
|
+
if (select) {
|
|
277
|
+
if (limit !== undefined && result.size >= limit) {
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
result.add(id);
|
|
281
|
+
} else {
|
|
282
|
+
result.delete(id);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const newState = calculateSelectionState(entities, result, false, options);
|
|
286
|
+
onSelect({
|
|
287
|
+
selected: [...result],
|
|
288
|
+
allSelected: newState === checkboxColumnWrapper_1.SelectionState.All,
|
|
289
|
+
turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
|
|
290
|
+
});
|
|
291
|
+
}, [entities, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
|
|
292
|
+
const {
|
|
293
|
+
onCheckboxMouseDown,
|
|
294
|
+
suppressNextChangeRef
|
|
295
|
+
} = (0, useDragSelection_1.useDragSelection)(dragRows, props.ref, onBatchSelect, getBaseSelection, isRowSelectable, selectMode);
|
|
242
296
|
const onSelectListener = (0, react_1.useCallback)(([id, checked]) => {
|
|
297
|
+
// A drag or shift-click has already emitted the whole range; swallow the click that
|
|
298
|
+
// ends it so the row it landed on is not toggled back.
|
|
299
|
+
if (suppressNextChangeRef.current) {
|
|
300
|
+
suppressNextChangeRef.current = false;
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
243
303
|
if (allSelected) {
|
|
244
304
|
const newSelection = new Set(entities.map(entity => entity.id));
|
|
245
305
|
newSelection.delete(id);
|
|
@@ -261,7 +321,7 @@ const withSelectableRows = DataGridComponent => {
|
|
|
261
321
|
allSelected: newState === checkboxColumnWrapper_1.SelectionState.All,
|
|
262
322
|
turnOffSelectAll: selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll
|
|
263
323
|
});
|
|
264
|
-
}, [entities, selections, allSelected, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll]);
|
|
324
|
+
}, [entities, selections, allSelected, options, onSelect, selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll, suppressNextChangeRef]);
|
|
265
325
|
const onSelectAll = (0, react_1.useCallback)(([checked]) => {
|
|
266
326
|
if (checked && ((selection === null || selection === void 0 ? void 0 : selection.turnOffSelectAll) || options.turnOffSelectAll)) {
|
|
267
327
|
selectAll(true);
|
|
@@ -310,10 +370,11 @@ const withSelectableRows = DataGridComponent => {
|
|
|
310
370
|
wrapper.attach("change", onSelectListener);
|
|
311
371
|
wrapper.attach("change-all", onSelectAll);
|
|
312
372
|
wrapper.attach("toggle", onTriggerClick);
|
|
373
|
+
wrapper.attach("mousedown", ([id, checked, e]) => onCheckboxMouseDown(id, checked, e));
|
|
313
374
|
return () => {
|
|
314
375
|
wrapper.detach();
|
|
315
376
|
};
|
|
316
|
-
}, [wrapper, onSelectListener, onSelectAll, onTriggerClick]);
|
|
377
|
+
}, [wrapper, onSelectListener, onSelectAll, onTriggerClick, onCheckboxMouseDown]);
|
|
317
378
|
const listColumns = (0, react_1.useMemo)(() => {
|
|
318
379
|
const newColumns = columns.map(c => Object.assign({}, c));
|
|
319
380
|
// Remove CheckboxColumnWrappers from wrappers list
|
package/dist/index.css
CHANGED
|
@@ -13083,7 +13083,7 @@ html:lang(ar) .zen-radio__wrapper--mobile .zen-radio__label {
|
|
|
13083
13083
|
.zen-waiting--inline {
|
|
13084
13084
|
position: relative;
|
|
13085
13085
|
width: 2.5rem;
|
|
13086
|
-
height:
|
|
13086
|
+
height: 2.5rem;
|
|
13087
13087
|
}
|
|
13088
13088
|
.zen-waiting__spinner-text {
|
|
13089
13089
|
font-family: Roboto, "Segoe UI", Segoe, "Helvetica Neue", Helvetica, sans-serif;
|
|
@@ -5,19 +5,15 @@ export declare enum SelectionState {
|
|
|
5
5
|
None = "none"
|
|
6
6
|
}
|
|
7
7
|
export interface ISelectionValue {
|
|
8
|
-
/**
|
|
9
|
-
* Whether every selectable row across every page is selected.
|
|
10
|
-
*/
|
|
11
8
|
all: boolean;
|
|
12
|
-
/**
|
|
13
|
-
* The meaning of this list depends on `all`:
|
|
14
|
-
* - when `all` is `false`, it is the ids explicitly *included* in the selection.
|
|
15
|
-
* - when `all` is `true`, it is the ids explicitly *excluded* from the otherwise
|
|
16
|
-
* fully-selected set (e.g. rows unchecked after a "select all" across paginated data).
|
|
17
|
-
*
|
|
18
|
-
* This lets `all: true` represent "all except these ids" without needing to know the
|
|
19
|
-
* full id universe (MYG-142234) - unchecking a row while `all` is true only ever adds
|
|
20
|
-
* to this exclusion list; it must never be rebuilt from the currently rendered page.
|
|
21
|
-
*/
|
|
22
9
|
selected: string[];
|
|
23
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* One checkbox row in the order it is rendered. Expanded nested rows are part of this list,
|
|
13
|
+
* directly after their parent, so a drag or shift-click range can span nesting levels the
|
|
14
|
+
* same way it spans sibling rows.
|
|
15
|
+
*/
|
|
16
|
+
export interface IDragSelectionRow {
|
|
17
|
+
id: string;
|
|
18
|
+
isNested: boolean;
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MouseEvent as ReactMouseEvent, RefObject } from "react";
|
|
2
|
+
import { IDragSelectionRow } from "./interfaces";
|
|
3
|
+
/**
|
|
4
|
+
* @param rows every checkbox row in render order, expanded nested rows included, so ranges can
|
|
5
|
+
* span nesting levels.
|
|
6
|
+
*/
|
|
7
|
+
export declare const useDragSelection: (rows: IDragSelectionRow[], gridRef: RefObject<HTMLElement | null> | undefined, onBatchSelect: (rangeIds: string[], select: boolean, base: Set<string>) => void, getBaseSelection: () => Set<string>, isSelectable: (row: IDragSelectionRow) => boolean, isEnabled: boolean) => {
|
|
8
|
+
onCheckboxMouseDown: (id: string, checked: boolean, e: ReactMouseEvent) => void;
|
|
9
|
+
suppressNextChangeRef: RefObject<boolean>;
|
|
10
|
+
};
|