@geotab/zenith 3.17.0-beta.0 → 3.17.0-beta.2
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 +26 -29
- package/dist/dataGrid/withSelectableRows/components/bulkActions/bulkActions.d.ts +1 -1
- package/dist/dropdownRaw/dropdownHelper.d.ts +20 -3
- package/dist/dropdownRaw/dropdownHelper.js +29 -6
- package/dist/dropdownRaw/dropdownRaw.js +22 -6
- package/dist/header/components/collapsedItemsControl/collapsedItemsControl.js +1 -1
- package/dist/header/headerButton.d.ts +1 -2
- package/dist/header/headerButton.js +1 -1
- package/dist/index.css +2 -2
- package/dist/pillExpandable/pillExpandable.js +3 -1
- package/dist/pillExpandable/pillExpandableSimple.d.ts +2 -1
- package/dist/pillExpandable/pillExpandableSimple.js +2 -2
- package/dist/table/selectable/interfaces.d.ts +6 -0
- package/dist/table/selectable/useDragSelection.d.ts +1 -1
- package/dist/table/selectable/useDragSelection.js +4 -4
- package/dist/table/selectable/useSelectableRows.d.ts +2 -0
- package/dist/table/selectable/useSelectableRows.js +88 -41
- package/dist/table/selectable/utils/calculateSelectionState.js +3 -2
- package/dist/table/selectable/utils/getCurrentPageSelection.js +9 -4
- package/dist/table/selectable/utils/groupExclusions.d.ts +7 -0
- package/dist/table/selectable/utils/groupExclusions.js +61 -0
- package/dist/table/selectable/utils/isRowChecked.js +1 -1
- package/dist/table/table.js +6 -5
- package/dist/waiting/waiting.js +3 -1
- package/esm/dataGrid/withSelectableRows/components/bulkActions/bulkActions.d.ts +1 -1
- package/esm/dropdownRaw/dropdownHelper.d.ts +20 -3
- package/esm/dropdownRaw/dropdownHelper.js +27 -5
- package/esm/dropdownRaw/dropdownRaw.js +23 -7
- package/esm/header/components/collapsedItemsControl/collapsedItemsControl.js +1 -1
- package/esm/header/headerButton.d.ts +1 -2
- package/esm/header/headerButton.js +1 -1
- package/esm/pillExpandable/pillExpandable.js +3 -1
- package/esm/pillExpandable/pillExpandableSimple.d.ts +2 -1
- package/esm/pillExpandable/pillExpandableSimple.js +2 -2
- package/esm/table/selectable/interfaces.d.ts +6 -0
- package/esm/table/selectable/useDragSelection.d.ts +1 -1
- package/esm/table/selectable/useDragSelection.js +4 -4
- package/esm/table/selectable/useSelectableRows.d.ts +2 -0
- package/esm/table/selectable/useSelectableRows.js +90 -43
- package/esm/table/selectable/utils/calculateSelectionState.js +3 -2
- package/esm/table/selectable/utils/getCurrentPageSelection.js +9 -4
- package/esm/table/selectable/utils/groupExclusions.d.ts +7 -0
- package/esm/table/selectable/utils/groupExclusions.js +55 -0
- package/esm/table/selectable/utils/isRowChecked.js +1 -1
- package/esm/table/table.js +6 -5
- package/esm/waiting/waiting.js +3 -1
- package/package.json +1 -4
- package/README.md.baseline +0 -1
package/README.md
CHANGED
|
@@ -45,39 +45,36 @@ Now components are ready for usage.
|
|
|
45
45
|
|
|
46
46
|
Zenith library provides components defined in Zenith Design System. It includes very basic blocks like colors, icons, font presets, atom components like buttons, checkboxes etc and high order components - header, table, filters bar etc. List of existing components can be found in [Storybook](https://developers.geotab.com/zenith-storybook/index.html).
|
|
47
47
|
|
|
48
|
-
## Translations
|
|
49
|
-
|
|
50
|
-
Zenith has English and 32 non-English locale dictionaries, including Arabic (`ar-001`) with right-to-left support. The [translation process guide](./docs/TRANSLATIONS.md) covers adding strings, Tech Content and Localization handoffs, spreadsheet sync, build-time injection, and validation. Read it before adding or changing a user-facing string, reviewing English copy, or running the sync. Locale availability does not imply that every string has a reviewed translation.
|
|
51
|
-
|
|
52
48
|
## Change log
|
|
53
49
|
|
|
54
50
|
### 3.17.0
|
|
55
51
|
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
-
|
|
52
|
+
- Add Primary, Destructive, and TertiaryDestructive trigger variants to `Dropdown` / `FilterButton`
|
|
53
|
+
- Add optional separators below single- and multi-select `Dropdown` items
|
|
54
|
+
- Add destructive styling to single-select `Dropdown` items
|
|
55
|
+
- Add `sortSelectedToTop` to float selected `Dropdown` options to the top when opened
|
|
56
|
+
- Show full single-select `Dropdown` option labels on hover
|
|
57
|
+
- Add loaded/total counts and an end-of-results message for desktop infinite-scroll tables; improve row-loading announcements
|
|
58
|
+
- Add progressive loading of nested `Table` rows with a +N more control, plus the `useShowMore` hook and `DEFAULT_SHOW_MORE_CAP` export
|
|
59
|
+
- Add seven sequential and seven diverging data-visualization color tokens
|
|
60
|
+
- Support destructive menu items and open-in-new-page indicators, including collapsed `Header` actions
|
|
61
|
+
- Export `PillBox`, `DEFAULT_MAX_PILLS`, `IPillData`, and `IPillBox` from the package entry point
|
|
62
|
+
- Add mouse-drag and Shift-click range selection to `Table` and selectable `DataGrid` rows, including expanded nested rows
|
|
63
|
+
- Add opt-in cross-page Select All exclusions when individual rows or the current-page header are unchecked
|
|
64
|
+
- Preserve cross-page Select All and existing exclusions during drag and Shift-click range selection; correct exclusion counts, childless nested-row selection, and global selection commands; exclude loading and show-more placeholders from fully loaded selection counts
|
|
65
|
+
- Make cross-page exclusions opt-in through `selectable.allowExclusions` while preserving the existing selection contract by default; correct selection feedback during reloads and empty-selection bulk actions
|
|
66
|
+
- Preserve `Table` selection during append loading and refreshes
|
|
67
|
+
- Keep `Waiting` overlays covering scrollable content, improve spinner positioning, and block keyboard interaction with sibling content while the overlay is visible
|
|
68
|
+
- Remove special bold styling from the first `Table` / `DataGrid` column header
|
|
69
|
+
- Reduce form label/control gaps and correct `Dropdown` form-field styling and width
|
|
70
|
+
- Close `PillExpandable` popovers on user scrolling while ignoring browser scroll-anchoring adjustments
|
|
71
|
+
- Fix RTL tab keyboard navigation, focus scrolling, and tab/pill/chip/accordion styling
|
|
72
|
+
- Allow `Tabs` to associate tabs with explicitly named panels through `ariaControls`, including panels outside the default tab layout
|
|
73
|
+
- Forward ARIA attributes to the appropriate input elements in `DropdownRaw` and `TextInputRaw`
|
|
74
|
+
- Make `FormLayout` positioning deterministic for fractional and invalid positions
|
|
75
|
+
- Keep disabled `Button` and related menu/header buttons keyboard-focusable while preventing activation
|
|
76
|
+
- Improve `PillExpandable` popover focus management and accessible trigger/content relationships
|
|
77
|
+
- Keep `Waiting` content interactive when `hideOverlay` is enabled while loading
|
|
81
78
|
|
|
82
79
|
### 3.16.0
|
|
83
80
|
|
|
@@ -12,7 +12,7 @@ export interface IBulkActionsProps extends IZenComponentProps {
|
|
|
12
12
|
* even when `selected` is 0 (i.e., cross-page "select all" is active).
|
|
13
13
|
*/
|
|
14
14
|
allSelected?: boolean;
|
|
15
|
-
/**
|
|
15
|
+
/** The selection spans unloaded rows and its total is not available. */
|
|
16
16
|
selectionCountUnknown?: boolean;
|
|
17
17
|
onClearSelection: () => void;
|
|
18
18
|
onSelectAll?: () => void;
|
|
@@ -12,12 +12,28 @@ export declare const isAllItemsHasOneParent: (listData: IDropdownRawItem[], chil
|
|
|
12
12
|
export declare function prepareComboOptionsForList(actionListData: Set<string>, translate: (s: string) => string, options: IDropdownRawItem[], getSelectedFn: () => string[], getSelectedChildFn: (optionId: any) => string[], isFlatList: boolean, getTitle?: (itemId: string) => string, isAllSelected?: boolean): ICheckboxListWithActionOption[];
|
|
13
13
|
export declare const createOptions: (stateObj: IDropdownState, translate: (s: string) => string, listItem: IDropdownRawItem[], isAllSelected?: boolean) => ICheckboxListWithActionOption[];
|
|
14
14
|
export declare const sortDropdownItemArray: (arr: IDropdownRawItem[], sortFn?: (a: IDropdownRawItem, b: IDropdownRawItem) => number) => IDropdownRawItem[];
|
|
15
|
+
/**
|
|
16
|
+
* An item is half selected when at least one of its direct children is selected — the state its checkbox
|
|
17
|
+
* shows as indeterminate (see `prepareComboOptionsForList`). `selectedSet` is passed in so the sort can use
|
|
18
|
+
* its own snapshot of the selection instead of the live one.
|
|
19
|
+
*/
|
|
20
|
+
export declare const hasSelectedChild: (groupsMap: IDropdownState["groupsMap"], itemId: string, selectedSet: Set<string>) => boolean;
|
|
21
|
+
interface ISortSelectedToTopOptions {
|
|
22
|
+
/** Items that count as selected although their own id is not, e.g. a half selected parent. */
|
|
23
|
+
isPartiallySelected?: (item: IDropdownRawItem) => boolean;
|
|
24
|
+
/** Disabled items cannot be toggled, so they follow the selectable ones. */
|
|
25
|
+
isDisabled?: (item: IDropdownRawItem) => boolean;
|
|
26
|
+
}
|
|
15
27
|
/**
|
|
16
28
|
* Floats selected items to the top of the list while preserving the relative order within each
|
|
17
|
-
* group
|
|
18
|
-
*
|
|
29
|
+
* group. The order is: selected items that can be toggled, then selected items that are disabled
|
|
30
|
+
* (so a newly selected item is never pushed down by disabled ones), then everything else. An item
|
|
31
|
+
* counts as selected when its own id is in `selectedIds` or when `isPartiallySelected` returns true
|
|
32
|
+
* for it, so half selected items sit with the selected ones. When `selectedIds` is empty the original
|
|
33
|
+
* array is returned unchanged (no allocation). Uses a single-pass partition to avoid traversing
|
|
34
|
+
* `items` more than once.
|
|
19
35
|
*/
|
|
20
|
-
export declare const applySortSelectedToTop: (items: IDropdownRawItem[], selectedIds: string[]) => IDropdownRawItem[];
|
|
36
|
+
export declare const applySortSelectedToTop: (items: IDropdownRawItem[], selectedIds: string[], { isPartiallySelected, isDisabled }?: ISortSelectedToTopOptions) => IDropdownRawItem[];
|
|
21
37
|
export declare const createSingleListOptions: (stateObj: IDropdownState, translate: (s: string) => string, listItem: IDropdownRawItem[]) => {
|
|
22
38
|
destructive: boolean | undefined;
|
|
23
39
|
divider?: boolean | undefined;
|
|
@@ -56,3 +72,4 @@ export declare const getAllyTriggerProps: (allyPattern: "selectOnlyCombobox" | "
|
|
|
56
72
|
readonly role: "button";
|
|
57
73
|
readonly "aria-haspopup": "menu";
|
|
58
74
|
};
|
|
75
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAllyTriggerProps = exports.getSelectedCount = exports.getStringFromAllSelected = exports.getStringFromSelected = exports.checkIsDataProblem = exports.prepareSelectedIdsToItems = exports.compareObjectsArrays = exports.compareStringsArrays = exports.createListDataOptions = exports.createSingleListOptions = exports.applySortSelectedToTop = exports.sortDropdownItemArray = exports.createOptions = exports.isAllItemsHasOneParent = exports.getDataForChange = exports.isEveryItemSelected = exports.isAllChildrenSelected = exports.getListDataWithDisabled = exports.getGroupsTreeItem = void 0;
|
|
3
|
+
exports.getAllyTriggerProps = exports.getSelectedCount = exports.getStringFromAllSelected = exports.getStringFromSelected = exports.checkIsDataProblem = exports.prepareSelectedIdsToItems = exports.compareObjectsArrays = exports.compareStringsArrays = exports.createListDataOptions = exports.createSingleListOptions = exports.applySortSelectedToTop = exports.hasSelectedChild = exports.sortDropdownItemArray = exports.createOptions = exports.isAllItemsHasOneParent = exports.getDataForChange = exports.isEveryItemSelected = exports.isAllChildrenSelected = exports.getListDataWithDisabled = exports.getGroupsTreeItem = void 0;
|
|
4
4
|
exports.prepareComboOptionsForList = prepareComboOptionsForList;
|
|
5
5
|
const groupsHelper_1 = require("../groupsFilterRaw/groupsHelper");
|
|
6
6
|
const stateReducerHelper_1 = require("./stateReducer/stateReducerHelper");
|
|
@@ -93,21 +93,44 @@ const sortDropdownItemArray = (arr, sortFn) => {
|
|
|
93
93
|
return arr;
|
|
94
94
|
};
|
|
95
95
|
exports.sortDropdownItemArray = sortDropdownItemArray;
|
|
96
|
+
/**
|
|
97
|
+
* An item is half selected when at least one of its direct children is selected — the state its checkbox
|
|
98
|
+
* shows as indeterminate (see `prepareComboOptionsForList`). `selectedSet` is passed in so the sort can use
|
|
99
|
+
* its own snapshot of the selection instead of the live one.
|
|
100
|
+
*/
|
|
101
|
+
const hasSelectedChild = (groupsMap, itemId, selectedSet) => {
|
|
102
|
+
const group = groupsMap[itemId];
|
|
103
|
+
return group ? (0, stateReducerHelper_1.getChildList)(group.children).some(child => selectedSet.has(child.id)) : false;
|
|
104
|
+
};
|
|
105
|
+
exports.hasSelectedChild = hasSelectedChild;
|
|
96
106
|
/**
|
|
97
107
|
* Floats selected items to the top of the list while preserving the relative order within each
|
|
98
|
-
* group
|
|
99
|
-
*
|
|
108
|
+
* group. The order is: selected items that can be toggled, then selected items that are disabled
|
|
109
|
+
* (so a newly selected item is never pushed down by disabled ones), then everything else. An item
|
|
110
|
+
* counts as selected when its own id is in `selectedIds` or when `isPartiallySelected` returns true
|
|
111
|
+
* for it, so half selected items sit with the selected ones. When `selectedIds` is empty the original
|
|
112
|
+
* array is returned unchanged (no allocation). Uses a single-pass partition to avoid traversing
|
|
113
|
+
* `items` more than once.
|
|
100
114
|
*/
|
|
101
|
-
const applySortSelectedToTop = (items, selectedIds) => {
|
|
115
|
+
const applySortSelectedToTop = (items, selectedIds, { isPartiallySelected, isDisabled } = {}) => {
|
|
102
116
|
if (!selectedIds.length)
|
|
103
117
|
return items;
|
|
104
118
|
const selectedSet = new Set(selectedIds);
|
|
105
119
|
const selected = [];
|
|
120
|
+
const selectedDisabled = [];
|
|
106
121
|
const unselected = [];
|
|
107
122
|
for (const item of items) {
|
|
108
|
-
(selectedSet.has(item.id) ?
|
|
123
|
+
if (!selectedSet.has(item.id) && !(isPartiallySelected === null || isPartiallySelected === void 0 ? void 0 : isPartiallySelected(item))) {
|
|
124
|
+
unselected.push(item);
|
|
125
|
+
}
|
|
126
|
+
else if (isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(item)) {
|
|
127
|
+
selectedDisabled.push(item);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
selected.push(item);
|
|
131
|
+
}
|
|
109
132
|
}
|
|
110
|
-
return [...selected, ...unselected];
|
|
133
|
+
return [...selected, ...selectedDisabled, ...unselected];
|
|
111
134
|
};
|
|
112
135
|
exports.applySortSelectedToTop = applySortSelectedToTop;
|
|
113
136
|
const createSingleListOptions = (stateObj, translate, listItem) => {
|
|
@@ -1155,20 +1155,36 @@ const DropdownRaw = props => {
|
|
|
1155
1155
|
// hasApplyButton=true: uses globalSelectedIds (committed selection) — reordering
|
|
1156
1156
|
// only takes effect after the user clicks "Apply".
|
|
1157
1157
|
const idsForSort = hasApplyButton ? state.globalSelectedIds : state.sortedTopSnapshot;
|
|
1158
|
-
const floated = sortSelectedToTop ? (0, dropdownHelper_1.applySortSelectedToTop)(children, idsForSort) : children;
|
|
1159
|
-
rawItems = floated.slice(0, listLimit);
|
|
1160
1158
|
if (sortSelectedToTop) {
|
|
1159
|
+
// Half selected items (a direct child is selected, shown as indeterminate) float with the selected ones.
|
|
1160
|
+
// Disabled selected items follow the selectable ones; in a nested list `disabled` is not enforced (see createOptions).
|
|
1161
1161
|
const selectedSet = new Set(idsForSort);
|
|
1162
|
-
|
|
1162
|
+
const isPartiallySelected = item => (0, dropdownHelper_1.hasSelectedChild)(state.groupsMap, item.id, selectedSet);
|
|
1163
|
+
const isDisabled = item => Boolean(item.disabled) && !state.isNestedList;
|
|
1164
|
+
rawItems = (0, dropdownHelper_1.applySortSelectedToTop)(children, idsForSort, {
|
|
1165
|
+
isPartiallySelected,
|
|
1166
|
+
isDisabled
|
|
1167
|
+
}).slice(0, listLimit);
|
|
1168
|
+
pinnedCount = rawItems.filter(item => selectedSet.has(item.id) || isPartiallySelected(item)).length;
|
|
1169
|
+
} else {
|
|
1170
|
+
rawItems = children.slice(0, listLimit);
|
|
1163
1171
|
}
|
|
1164
1172
|
}
|
|
1165
1173
|
const listData = (0, dropdownHelper_1.createListDataOptions)(state, translate, rawItems, multiselect, currentAllSelected);
|
|
1166
1174
|
// Explicit bounds check (rather than relying on CheckboxListWithAction's own
|
|
1167
1175
|
// `ind < optionsArr.length - 1` guard) keeps the "don't draw a trailing divider"
|
|
1168
1176
|
// intent local to where the boundary is computed.
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1177
|
+
// Floated items drop their own dividers, so the boundary divider is the only one drawn between them and the rest.
|
|
1178
|
+
const currentListData = multiselect && sortSelectedToTop && pinnedCount > 0 && pinnedCount < listData.length ? listData.map((opt, ind) => {
|
|
1179
|
+
if (ind === pinnedCount - 1) {
|
|
1180
|
+
return Object.assign(Object.assign({}, opt), {
|
|
1181
|
+
divider: true
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
return ind < pinnedCount && opt.divider ? Object.assign(Object.assign({}, opt), {
|
|
1185
|
+
divider: false
|
|
1186
|
+
}) : opt;
|
|
1187
|
+
}) : listData;
|
|
1172
1188
|
return (0, jsx_runtime_1.jsx)(dropdownList_1.DropdownList, {
|
|
1173
1189
|
onBackButtonClick: handleBackButtonClick,
|
|
1174
1190
|
onSelectAllClick: isSearchMode ? handleSelectAllInSearch : handleSelectAllClick,
|
|
@@ -111,7 +111,7 @@ const PageToolbarCollapsedItemsControl = ({
|
|
|
111
111
|
rel: child.props.rel,
|
|
112
112
|
icon: child.props.icon,
|
|
113
113
|
iconOpen: child.props.iconOpen,
|
|
114
|
-
destructive: child.props.
|
|
114
|
+
destructive: child.props.type === buttonType_1.ButtonType.Destructive || child.props.type === buttonType_1.ButtonType.TertiaryDestructive
|
|
115
115
|
});
|
|
116
116
|
items.push(el);
|
|
117
117
|
}
|
|
@@ -8,7 +8,6 @@ export interface IHeaderButton extends Omit<IButton, "onClick"> {
|
|
|
8
8
|
inContextMenu?: boolean;
|
|
9
9
|
icon?: React.FC<IIcon>;
|
|
10
10
|
iconOpen?: boolean;
|
|
11
|
-
destructive?: boolean;
|
|
12
11
|
iconPosition?: TButtonIconPosition;
|
|
13
12
|
iconClasses?: string;
|
|
14
13
|
iconSize?: TSvgIconSize;
|
|
@@ -16,6 +15,6 @@ export interface IHeaderButton extends Omit<IButton, "onClick"> {
|
|
|
16
15
|
}
|
|
17
16
|
export declare const HeaderButtonDisplayName = "HeaderButton";
|
|
18
17
|
export declare const HeaderButton: {
|
|
19
|
-
({ id, children, icon, iconOpen,
|
|
18
|
+
({ id, children, icon, iconOpen, iconPosition, className, important, onClick, inContextMenu, disabled, focusableWhenDisabled, ...restProps }: IHeaderButton): import("react/jsx-runtime").JSX.Element;
|
|
20
19
|
displayName: string;
|
|
21
20
|
};
|
|
@@ -18,7 +18,7 @@ const textIconButton_1 = require("../textIconButton/textIconButton");
|
|
|
18
18
|
const classNames_1 = require("../commonHelpers/classNames/classNames");
|
|
19
19
|
exports.HeaderButtonDisplayName = "HeaderButton";
|
|
20
20
|
const HeaderButton = (_a) => {
|
|
21
|
-
var { id, children, icon, iconOpen,
|
|
21
|
+
var { id, children, icon, iconOpen, iconPosition = textIconButton_1.ButtonIconPosition.Start, className = "", important, onClick, inContextMenu, disabled, focusableWhenDisabled } = _a, restProps = __rest(_a, ["id", "children", "icon", "iconOpen", "iconPosition", "className", "important", "onClick", "inContextMenu", "disabled", "focusableWhenDisabled"]);
|
|
22
22
|
const fullClassName = (0, classNames_1.classNames)(["zen-header-button", className]);
|
|
23
23
|
const props = Object.assign(Object.assign({}, restProps), { disabled, "data-important": important ? "1" : "0",
|
|
24
24
|
// Defaults on when disabled; pass `focusableWhenDisabled={false}` to opt back into native `disabled`.
|
package/dist/index.css
CHANGED
|
@@ -4931,8 +4931,8 @@ html:lang(ar) .zen-mobile-sheet__title {
|
|
|
4931
4931
|
gap: 1.5rem;
|
|
4932
4932
|
height: 100%;
|
|
4933
4933
|
}
|
|
4934
|
-
.zen-form-section .zen-form-field-label--top
|
|
4935
|
-
margin-block-
|
|
4934
|
+
.zen-form-section .zen-form-field-label--top {
|
|
4935
|
+
margin-block-end: -1.25rem;
|
|
4936
4936
|
}
|
|
4937
4937
|
.zen-form-section--desktop.zen-form-section--one-column {
|
|
4938
4938
|
grid-template-columns: repeat(8, 1fr);
|
|
@@ -428,6 +428,7 @@ const PillExpandableBase = ({
|
|
|
428
428
|
}) => {
|
|
429
429
|
const popupId = (0, react_1.useId)();
|
|
430
430
|
const descriptionId = (0, react_1.useId)();
|
|
431
|
+
const counterId = (0, react_1.useId)();
|
|
431
432
|
const [descriptionElement, setDescriptionElement] = (0, react_1.useState)(null);
|
|
432
433
|
const isDrive = (0, useDrive_1.useDrive)();
|
|
433
434
|
const [isMobile, setIsMobile] = (0, react_1.useState)(false);
|
|
@@ -596,10 +597,11 @@ const PillExpandableBase = ({
|
|
|
596
597
|
errorHandler: errorHandler,
|
|
597
598
|
isBeta: isBeta,
|
|
598
599
|
isMobile: isMobile,
|
|
599
|
-
descriptionId: isPopupOpen && descriptionElement ? descriptionId : undefined,
|
|
600
|
+
descriptionId: [uniqueChildren && !hideCounterNumber ? counterId : undefined, isPopupOpen && descriptionElement ? descriptionId : undefined].filter(Boolean).join(" ") || undefined,
|
|
600
601
|
ariaHasPopup: "dialog",
|
|
601
602
|
dataAnalyticsId: dataAnalyticsId
|
|
602
603
|
}), uniqueChildren && (0, jsx_runtime_1.jsx)(pillExpandableSimple_1.PillExpandableSimple, {
|
|
604
|
+
id: counterId,
|
|
603
605
|
icon: secondaryIcon || effectiveIcon,
|
|
604
606
|
text: hideCounterNumber ? "" : counterText,
|
|
605
607
|
includeExpandIcon: false,
|
|
@@ -2,6 +2,7 @@ import { FC, RefObject } from "react";
|
|
|
2
2
|
import { IPillExpandableBase, TPillType } from "./pillExpandable";
|
|
3
3
|
import { IIcon } from "../icons/icon";
|
|
4
4
|
interface IPillExpandableSimple extends IPillExpandableBase {
|
|
5
|
+
id?: string;
|
|
5
6
|
includeExpandIcon?: boolean;
|
|
6
7
|
expanded?: boolean;
|
|
7
8
|
onExpand?: () => void;
|
|
@@ -15,7 +16,7 @@ interface IPillExpandableSimple extends IPillExpandableBase {
|
|
|
15
16
|
type?: TPillType;
|
|
16
17
|
}
|
|
17
18
|
export declare const PillExpandableSimple: {
|
|
18
|
-
({ onExpand, text, expanded, includeExpandIcon, type, icon, isBeta, isMobile, ref, className, descriptionId, ariaHasPopup, isDecorative, dataAnalyticsId }: IPillExpandableSimple): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
({ id, onExpand, text, expanded, includeExpandIcon, type, icon, isBeta, isMobile, ref, className, descriptionId, ariaHasPopup, isDecorative, dataAnalyticsId }: IPillExpandableSimple): import("react/jsx-runtime").JSX.Element;
|
|
19
20
|
displayName: string;
|
|
20
21
|
};
|
|
21
22
|
export {};
|
|
@@ -8,7 +8,7 @@ const iconChevronTop_1 = require("../icons/iconChevronTop");
|
|
|
8
8
|
const iconChevronBottom_1 = require("../icons/iconChevronBottom");
|
|
9
9
|
const iconException_1 = require("../icons/iconException");
|
|
10
10
|
const classNames_1 = require("../commonHelpers/classNames/classNames");
|
|
11
|
-
const PillExpandableSimple = ({ onExpand, text, expanded, includeExpandIcon = true, type = "warning", icon = iconException_1.IconException, isBeta, isMobile, ref, className, descriptionId, ariaHasPopup, isDecorative, dataAnalyticsId
|
|
11
|
+
const PillExpandableSimple = ({ id, onExpand, text, expanded, includeExpandIcon = true, type = "warning", icon = iconException_1.IconException, isBeta, isMobile, ref, className, descriptionId, ariaHasPopup, isDecorative, dataAnalyticsId
|
|
12
12
|
// eslint-disable-next-line complexity
|
|
13
13
|
}) => {
|
|
14
14
|
const iconDriveClassName = (0, useDriveClassName_1.useDriveClassName)("icon");
|
|
@@ -37,7 +37,7 @@ const PillExpandableSimple = ({ onExpand, text, expanded, includeExpandIcon = tr
|
|
|
37
37
|
size: iconSize
|
|
38
38
|
}) }) }))] }));
|
|
39
39
|
if (isDecorative) {
|
|
40
|
-
return ((0, jsx_runtime_1.jsx)("span", { className: (0, classNames_1.classNames)([
|
|
40
|
+
return ((0, jsx_runtime_1.jsx)("span", { id: id, className: (0, classNames_1.classNames)([
|
|
41
41
|
"zen-status-pill__container",
|
|
42
42
|
`zen-status-pill__container--${type}`,
|
|
43
43
|
containerDriveClassName || "",
|
|
@@ -15,6 +15,12 @@ export interface ISelectionValue {
|
|
|
15
15
|
* Consumers opting in must resolve the effective selection before running bulk actions.
|
|
16
16
|
*/
|
|
17
17
|
selected: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Excluded nested groups, including children that have not loaded yet. Only used with
|
|
20
|
+
* allowExclusions and all: true. Preserve this field when saving controlled selection;
|
|
21
|
+
* resolve these groups as well as selected before running a bulk action.
|
|
22
|
+
*/
|
|
23
|
+
excludedGroupIds?: string[];
|
|
18
24
|
}
|
|
19
25
|
/**
|
|
20
26
|
* One checkbox row in the order it is rendered. Expanded nested rows are part of this list,
|
|
@@ -4,7 +4,7 @@ import { IDragSelectionRow } from "./interfaces";
|
|
|
4
4
|
* @param rows every checkbox row in render order, expanded nested rows included, so ranges can
|
|
5
5
|
* span nesting levels.
|
|
6
6
|
*/
|
|
7
|
-
export declare const useDragSelection: (rows: IDragSelectionRow[], gridRef: RefObject<HTMLElement | null> | undefined, onBatchSelect: (rangeIds: string[], select: boolean, base:
|
|
7
|
+
export declare const useDragSelection: <TSelection = Set<string>>(rows: IDragSelectionRow[], gridRef: RefObject<HTMLElement | null> | undefined, onBatchSelect: (rangeIds: string[], select: boolean, base: TSelection) => void, getBaseSelection: () => TSelection, isSelectable: (row: IDragSelectionRow) => boolean, isEnabled: boolean) => {
|
|
8
8
|
onCheckboxMouseDown: (id: string, checked: boolean, e: ReactMouseEvent) => void;
|
|
9
9
|
suppressNextChangeRef: RefObject<boolean>;
|
|
10
10
|
};
|
|
@@ -22,7 +22,7 @@ const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSele
|
|
|
22
22
|
isEnabledRef.current = isEnabled;
|
|
23
23
|
const anchorIdRef = (0, react_1.useRef)(null);
|
|
24
24
|
const anchorSelectRef = (0, react_1.useRef)(true);
|
|
25
|
-
const baseSelectedRef = (0, react_1.useRef)(
|
|
25
|
+
const baseSelectedRef = (0, react_1.useRef)(null);
|
|
26
26
|
const isDraggingRef = (0, react_1.useRef)(false);
|
|
27
27
|
const movedRef = (0, react_1.useRef)(false);
|
|
28
28
|
const lastResultKeyRef = (0, react_1.useRef)("");
|
|
@@ -31,7 +31,7 @@ const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSele
|
|
|
31
31
|
const attachedGridElementRef = (0, react_1.useRef)(null);
|
|
32
32
|
const emitRange = (0, react_1.useCallback)((currentId) => {
|
|
33
33
|
const anchorId = anchorIdRef.current;
|
|
34
|
-
if (anchorId === null) {
|
|
34
|
+
if (anchorId === null || baseSelectedRef.current === null) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
const range = (0, getRangeIds_1.getRangeIds)(rowsRef.current, anchorId, currentId, isSelectableRef.current);
|
|
@@ -85,7 +85,7 @@ const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSele
|
|
|
85
85
|
(_c = attachedGridElementRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener("scroll", onScroll);
|
|
86
86
|
(_d = attachedGridElementRef.current) === null || _d === void 0 ? void 0 : _d.classList.remove(DRAG_CLASS);
|
|
87
87
|
attachedGridElementRef.current = null;
|
|
88
|
-
}, [onMouseMove, onScroll]);
|
|
88
|
+
}, [onMouseMove, onScroll]);
|
|
89
89
|
const onCheckboxMouseDown = (0, react_1.useCallback)((id, checked, e) => {
|
|
90
90
|
var _a, _b, _c, _d, _e;
|
|
91
91
|
// Right-click between drag-end and the trailing click must not clear suppression.
|
|
@@ -95,7 +95,7 @@ const useDragSelection = (rows, gridRef, onBatchSelect, getBaseSelection, isSele
|
|
|
95
95
|
if (!isEnabledRef.current || e.button !== 0) {
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
|
-
if (e.shiftKey && anchorIdRef.current !== null) {
|
|
98
|
+
if (e.shiftKey && anchorIdRef.current !== null && baseSelectedRef.current !== null) {
|
|
99
99
|
e.preventDefault();
|
|
100
100
|
const anchorId = anchorIdRef.current;
|
|
101
101
|
const anchorInList = rowsRef.current.some(row => row.id === anchorId);
|
|
@@ -10,6 +10,8 @@ export interface ISelectableRowsOptions<T extends IRowEntity<N>, N extends IEnti
|
|
|
10
10
|
onSelect: (selection: ISelectionValue) => void;
|
|
11
11
|
/** Preserve cross-page Select All using excluded IDs. Consumers must resolve exclusions before running bulk actions. Defaults to false. */
|
|
12
12
|
allowExclusions?: boolean;
|
|
13
|
+
/** Changes when the dataset represented by the selection is replaced, rather than paged. */
|
|
14
|
+
selectionDatasetId?: string | number;
|
|
13
15
|
checkboxDisabled?: (entity: T | N, isNested?: boolean) => boolean;
|
|
14
16
|
checkboxVisible?: (entity: T | N, isNested?: boolean) => boolean;
|
|
15
17
|
checkboxInHeader?: boolean;
|