@geotab/zenith 3.11.0-beta.1 → 3.11.1-beta.0

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 (95) hide show
  1. package/README.md +8 -0
  2. package/dist/checkboxListWithAction/checkboxListWithAction.js +26 -27
  3. package/dist/dataGrid/withFlexibleColumns/components/columnSettingsList.js +116 -44
  4. package/dist/index.css +4 -1
  5. package/dist/menu/utils/useMenuItemCore.js +3 -1
  6. package/dist/pillExpandable/pillExpandable.js +1 -36
  7. package/dist/pillExpandable/pillExpandableSimple.d.ts +1 -2
  8. package/dist/pillExpandable/pillExpandableSimple.js +5 -3
  9. package/dist/selectList/selectList.actionTypes.d.ts +6 -1
  10. package/dist/selectList/selectList.actionTypes.js +1 -0
  11. package/dist/selectList/selectList.d.ts +1 -1
  12. package/dist/selectList/selectList.helpers.d.ts +1 -1
  13. package/dist/selectList/selectList.helpers.js +29 -4
  14. package/dist/selectList/selectList.js +464 -125
  15. package/dist/selectList/selectList.reducer.js +3 -2
  16. package/dist/selectList/selectListItem.d.ts +2 -1
  17. package/dist/selectList/selectListItem.js +19 -2
  18. package/dist/sortControl/sortControl.js +58 -2
  19. package/dist/summaryTile/summaryTile.d.ts +3 -1
  20. package/dist/summaryTile/summaryTile.js +2 -1
  21. package/dist/table/flexible/columnsList.js +4 -2
  22. package/dist/utils/localization/translations/ar.json +5 -1
  23. package/dist/utils/localization/translations/cs.json +5 -1
  24. package/dist/utils/localization/translations/da-DK.json +5 -1
  25. package/dist/utils/localization/translations/de.json +5 -1
  26. package/dist/utils/localization/translations/en.json +5 -1
  27. package/dist/utils/localization/translations/es.json +5 -1
  28. package/dist/utils/localization/translations/fi-FI.json +5 -1
  29. package/dist/utils/localization/translations/fr-FR.json +5 -1
  30. package/dist/utils/localization/translations/fr.json +5 -1
  31. package/dist/utils/localization/translations/hu-HU.json +5 -1
  32. package/dist/utils/localization/translations/id.json +5 -1
  33. package/dist/utils/localization/translations/it.json +5 -1
  34. package/dist/utils/localization/translations/ja.json +5 -1
  35. package/dist/utils/localization/translations/ko-KR.json +5 -1
  36. package/dist/utils/localization/translations/ms.json +5 -1
  37. package/dist/utils/localization/translations/nb-NO.json +5 -1
  38. package/dist/utils/localization/translations/nl.json +5 -1
  39. package/dist/utils/localization/translations/pl.json +5 -1
  40. package/dist/utils/localization/translations/pt-BR.json +5 -1
  41. package/dist/utils/localization/translations/pt-PT.json +5 -1
  42. package/dist/utils/localization/translations/ro-RO.json +5 -1
  43. package/dist/utils/localization/translations/sk-SK.json +5 -1
  44. package/dist/utils/localization/translations/sv.json +5 -1
  45. package/dist/utils/localization/translations/th.json +5 -1
  46. package/dist/utils/localization/translations/tr.json +5 -1
  47. package/dist/utils/localization/translations/zh-Hans.json +5 -1
  48. package/dist/utils/localization/translations/zh-TW.json +5 -1
  49. package/esm/checkboxListWithAction/checkboxListWithAction.js +26 -27
  50. package/esm/dataGrid/withFlexibleColumns/components/columnSettingsList.js +110 -43
  51. package/esm/menu/utils/useMenuItemCore.js +3 -1
  52. package/esm/pillExpandable/pillExpandable.js +1 -36
  53. package/esm/pillExpandable/pillExpandableSimple.d.ts +1 -2
  54. package/esm/pillExpandable/pillExpandableSimple.js +5 -3
  55. package/esm/selectList/selectList.actionTypes.d.ts +6 -1
  56. package/esm/selectList/selectList.actionTypes.js +1 -0
  57. package/esm/selectList/selectList.d.ts +1 -1
  58. package/esm/selectList/selectList.helpers.d.ts +1 -1
  59. package/esm/selectList/selectList.helpers.js +29 -4
  60. package/esm/selectList/selectList.js +460 -126
  61. package/esm/selectList/selectList.reducer.js +3 -2
  62. package/esm/selectList/selectListItem.d.ts +2 -1
  63. package/esm/selectList/selectListItem.js +19 -2
  64. package/esm/sortControl/sortControl.js +58 -2
  65. package/esm/summaryTile/summaryTile.d.ts +3 -1
  66. package/esm/summaryTile/summaryTile.js +2 -1
  67. package/esm/table/flexible/columnsList.js +4 -2
  68. package/esm/utils/localization/translations/ar.json +5 -1
  69. package/esm/utils/localization/translations/cs.json +5 -1
  70. package/esm/utils/localization/translations/da-DK.json +5 -1
  71. package/esm/utils/localization/translations/de.json +5 -1
  72. package/esm/utils/localization/translations/en.json +5 -1
  73. package/esm/utils/localization/translations/es.json +5 -1
  74. package/esm/utils/localization/translations/fi-FI.json +5 -1
  75. package/esm/utils/localization/translations/fr-FR.json +5 -1
  76. package/esm/utils/localization/translations/fr.json +5 -1
  77. package/esm/utils/localization/translations/hu-HU.json +5 -1
  78. package/esm/utils/localization/translations/id.json +5 -1
  79. package/esm/utils/localization/translations/it.json +5 -1
  80. package/esm/utils/localization/translations/ja.json +5 -1
  81. package/esm/utils/localization/translations/ko-KR.json +5 -1
  82. package/esm/utils/localization/translations/ms.json +5 -1
  83. package/esm/utils/localization/translations/nb-NO.json +5 -1
  84. package/esm/utils/localization/translations/nl.json +5 -1
  85. package/esm/utils/localization/translations/pl.json +5 -1
  86. package/esm/utils/localization/translations/pt-BR.json +5 -1
  87. package/esm/utils/localization/translations/pt-PT.json +5 -1
  88. package/esm/utils/localization/translations/ro-RO.json +5 -1
  89. package/esm/utils/localization/translations/sk-SK.json +5 -1
  90. package/esm/utils/localization/translations/sv.json +5 -1
  91. package/esm/utils/localization/translations/th.json +5 -1
  92. package/esm/utils/localization/translations/tr.json +5 -1
  93. package/esm/utils/localization/translations/zh-Hans.json +5 -1
  94. package/esm/utils/localization/translations/zh-TW.json +5 -1
  95. package/package.json +1 -1
@@ -1,149 +1,483 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
1
+ import { injectString } from "../utils/localization/translationsDictionary";
2
+ var __rest = this && this.__rest || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
6
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
7
+ }
8
+ return t;
11
9
  };
12
- import { jsx as _jsx } from "react/jsx-runtime";
10
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
11
  import { createElement as _createElement } from "react";
14
12
  import { CheckboxState } from "../checkbox/checkboxState";
15
13
  import { classNames } from "../commonHelpers/classNames/classNames";
16
14
  import { getKeysPressed, isKeyForSearch } from "../commonHelpers/keyboard";
17
15
  import { ListAction } from "./selectList.actionTypes";
18
- import { getInitialState, getItemIdByIndex } from "./selectList.helpers";
16
+ import { getFirstIndex, getInitialState, getItemIdByIndex } from "./selectList.helpers";
19
17
  import { selectListReducer } from "./selectList.reducer";
20
18
  import { SelectListItem } from "./selectListItem";
21
19
  import { isChildOf } from "../utils/isChildOf";
22
20
  import { useDriveClassName } from "../utils/theme/useDriveClassName";
23
- import { memo, useCallback, useEffect, useMemo, useReducer, useRef } from "react";
21
+ import { memo, useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
24
22
  import { getScrollableParent } from "../utils/getScrollableParent";
25
23
  import { zen } from "../utils/zen";
24
+ import { useLanguage } from "../utils/localization/useLanguage";
25
+ import { getComponentText } from "../commonHelpers/reactHelpers/reactHelpers";
26
+ injectString("cs", "Checked", "Za\u0161krtnuto");
27
+ injectString("da-DK", "Checked", "Markeret");
28
+ injectString("de", "Checked", "Aktiviert");
29
+ injectString("en", "Checked", "Checked");
30
+ injectString("es", "Checked", "Marcado");
31
+ injectString("fi-FI", "Checked", "Valittu");
32
+ injectString("fr", "Checked", "Coch\xE9");
33
+ injectString("fr-FR", "Checked", "Coch\xE9");
34
+ injectString("hu-HU", "Checked", "Bejel\xF6lve");
35
+ injectString("id", "Checked", "Dicentang");
36
+ injectString("it", "Checked", "Selezionato");
37
+ injectString("ja", "Checked", "\u30C1\u30A7\u30C3\u30AF\u6E08\u307F");
38
+ injectString("ko-KR", "Checked", "\uC120\uD0DD\uB428");
39
+ injectString("ms", "Checked", "Ditanda");
40
+ injectString("nb-NO", "Checked", "Merket");
41
+ injectString("nl", "Checked", "Aangevinkt");
42
+ injectString("pl", "Checked", "Zaznaczono");
43
+ injectString("pt-BR", "Checked", "Marcado");
44
+ injectString("pt-PT", "Checked", "Marcado");
45
+ injectString("sk-SK", "Checked", "Za\u0161krtnut\xE9");
46
+ injectString("sv", "Checked", "Markerad");
47
+ injectString("th", "Checked", "\u0E17\u0E33\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E2B\u0E21\u0E32\u0E22\u0E41\u0E25\u0E49\u0E27");
48
+ injectString("tr", "Checked", "\u0130\u015Faretlendi");
49
+ injectString("zh-Hans", "Checked", "\u5DF2\u9009\u4E2D");
50
+ injectString("zh-TW", "Checked", "\u5DF2\u52FE\u9078");
51
+ injectString("ro-RO", "Checked", "Bifat");
52
+ injectString("ar-SA", "Checked", "\u0645\u062D\u062F\u062F");
53
+ injectString("cs", "Unchecked", "Neza\u0161krtnuto");
54
+ injectString("da-DK", "Unchecked", "Ikke markeret");
55
+ injectString("de", "Unchecked", "Deaktiviert");
56
+ injectString("en", "Unchecked", "Unchecked");
57
+ injectString("es", "Unchecked", "Sin marcar");
58
+ injectString("fi-FI", "Unchecked", "Ei valittu");
59
+ injectString("fr", "Unchecked", "Non coch\xE9");
60
+ injectString("fr-FR", "Unchecked", "Non coch\xE9");
61
+ injectString("hu-HU", "Unchecked", "Nincs bejel\xF6lve");
62
+ injectString("id", "Unchecked", "Tidak dicentang");
63
+ injectString("it", "Unchecked", "Non selezionato");
64
+ injectString("ja", "Unchecked", "\u672A\u30C1\u30A7\u30C3\u30AF");
65
+ injectString("ko-KR", "Unchecked", "\uC120\uD0DD \uC548 \uB428");
66
+ injectString("ms", "Unchecked", "Tidak ditanda");
67
+ injectString("nb-NO", "Unchecked", "Ikke merket");
68
+ injectString("nl", "Unchecked", "Niet aangevinkt");
69
+ injectString("pl", "Unchecked", "Odznaczono");
70
+ injectString("pt-BR", "Unchecked", "Desmarcado");
71
+ injectString("pt-PT", "Unchecked", "Desmarcado");
72
+ injectString("sk-SK", "Unchecked", "Neza\u0161krtnut\xE9");
73
+ injectString("sv", "Unchecked", "Avmarkerad");
74
+ injectString("th", "Unchecked", "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E17\u0E33\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E2B\u0E21\u0E32\u0E22");
75
+ injectString("tr", "Unchecked", "\u0130\u015Faretlenmedi");
76
+ injectString("zh-Hans", "Unchecked", "\u672A\u9009\u4E2D");
77
+ injectString("zh-TW", "Unchecked", "\u672A\u52FE\u9078");
78
+ injectString("ro-RO", "Unchecked", "Nebifat");
79
+ injectString("ar-SA", "Unchecked", "\u063A\u064A\u0631 \u0645\u062D\u062F\u062F");
26
80
  export const defaultListItemHeight = 40;
27
81
  const MemoizedSelectListItem = memo(SelectListItem);
28
- const SelectListInnerComp = ({ id, items, value, disabled, activeIndex = -1, title, multiselect = false, showCheckbox = false, standalone, className = "", onClickItem, onChangeItem, onKeyDown, onFocus, onBlur, style = {}, ref: listRef }) => {
29
- var _a;
30
- const driveComponentClass = useDriveClassName("zen-select-list");
31
- const state = getInitialState({ items, value, multiselect });
32
- state.activeIndex = activeIndex;
33
- return (_jsx("ul", { id: id, ref: listRef, className: classNames(["zen-select-list", driveComponentClass || "", className]), role: "listbox", "aria-multiselectable": multiselect, "aria-activedescendant": standalone ? getItemIdByIndex(state.itemsState, state.activeIndex) || ((_a = items.find(el => !el.disabled)) === null || _a === void 0 ? void 0 : _a.id) : undefined, "aria-label": title, "aria-disabled": disabled, tabIndex: standalone && !disabled ? 0 : -1, onKeyDown: onKeyDown, onFocus: onFocus, onBlur: onBlur, style: style, children: items.map((item, index) => (_createElement(MemoizedSelectListItem, Object.assign({}, item, { className: classNames(["zen-select-list__item", item.className || ""]), key: item.id, showCheckbox: showCheckbox, state: state.itemsState.get(item.id), focused: state.activeIndex === index, onChange: onChangeItem, onClick: onClickItem }), item.children))) }));
82
+ const SelectListInnerComp = ({
83
+ id,
84
+ items,
85
+ value,
86
+ disabled,
87
+ activeIndex = -1,
88
+ title,
89
+ multiselect = false,
90
+ showCheckbox = false,
91
+ standalone,
92
+ className = "",
93
+ onClickItem,
94
+ onChangeItem,
95
+ onFocusItem,
96
+ onKeyDown,
97
+ onFocus,
98
+ onBlur,
99
+ style = {},
100
+ ref: listRef
101
+ }) => {
102
+ var _a;
103
+ const driveComponentClass = useDriveClassName("zen-select-list");
104
+ const state = getInitialState({
105
+ items,
106
+ value,
107
+ multiselect
108
+ });
109
+ state.activeIndex = activeIndex;
110
+ return _jsx("ul", {
111
+ id: id,
112
+ ref: listRef,
113
+ className: classNames(["zen-select-list", driveComponentClass || "", className]),
114
+ role: showCheckbox ? "menu" : "listbox",
115
+ "aria-multiselectable": showCheckbox ? undefined : multiselect,
116
+ "aria-activedescendant": standalone && !showCheckbox ? getItemIdByIndex(state.itemsState, state.activeIndex) || ((_a = items.find(el => !el.disabled)) === null || _a === void 0 ? void 0 : _a.id) : undefined,
117
+ "aria-label": title,
118
+ "aria-disabled": disabled,
119
+ tabIndex: standalone && !disabled && !showCheckbox ? 0 : -1,
120
+ onKeyDown: onKeyDown,
121
+ onFocus: onFocus,
122
+ onBlur: onBlur,
123
+ style: style,
124
+ children: items.map((item, index) => _createElement(MemoizedSelectListItem, Object.assign({}, item, {
125
+ className: classNames(["zen-select-list__item", item.className || ""]),
126
+ key: item.id,
127
+ showCheckbox: showCheckbox,
128
+ state: state.itemsState.get(item.id),
129
+ focused: state.activeIndex === index,
130
+ onChange: onChangeItem,
131
+ onClick: onClickItem,
132
+ onFocusItem: onFocusItem
133
+ }), item.children))
134
+ });
34
135
  };
35
136
  SelectListInnerComp.displayName = "SelectListInnerComp";
36
137
  const SelectListInner = memo(SelectListInnerComp);
37
- export const SelectList = (_a) => {
38
- var { items: outerItems, value = new Map(), multiselect = false, selectItemOnFocus = true, forceSelection = false, disabled, onChange, onClick } = _a, rest = __rest(_a, ["items", "value", "multiselect", "selectItemOnFocus", "forceSelection", "disabled", "onChange", "onClick"]);
39
- const items = useMemo(() => outerItems, [outerItems]);
40
- const listRef = useRef(null);
41
- const [state, dispatchState] = useReducer(selectListReducer, { items, value, multiselect }, getInitialState);
42
- const innerValue = useMemo(() => JSON.stringify(Array.from(getInitialState({ items, value, multiselect }).itemsState)), [items, value, multiselect]);
43
- useEffect(() => {
44
- const parsedValue = JSON.parse(innerValue);
45
- dispatchState({ type: ListAction.Reset, payload: { items, value: new Map(parsedValue), multiselect } });
46
- }, [innerValue, multiselect, items]);
47
- useEffect(() => {
48
- if (!multiselect && selectItemOnFocus) {
49
- dispatchState({ type: ListAction.FocusFirst, payload: { items } });
50
- }
51
- dispatchState({ type: ListAction.Focus, payload: { items, multiselect } });
52
- }, [multiselect, items, selectItemOnFocus]);
53
- useEffect(() => {
54
- onChange && state.isItemsStateChanged && onChange(new Map(state.itemsState));
55
- }, [state.isItemsStateChanged, state.itemsState, onChange]);
56
- const onChangeItem = useCallback((updatedId, updatedState) => {
57
- dispatchState({ type: ListAction.ChangeItemState, payload: { updatedId, updatedState, multiselect } });
58
- }, [multiselect]);
59
- const hasScrolledToInitial = useRef(false);
60
- useEffect(() => {
61
- var _a;
62
- if (state.activeIndex >= 0 && listRef.current) {
63
- const isFocusInList = ((_a = zen.document) === null || _a === void 0 ? void 0 : _a.activeElement) && isChildOf(zen.document.activeElement, listRef.current);
64
- if (isFocusInList || !hasScrolledToInitial.current) {
65
- const itemEl = listRef.current.querySelector(`.zen-select-list__item:nth-child(${state.activeIndex + 1})`);
66
- itemEl === null || itemEl === void 0 ? void 0 : itemEl.scrollIntoView({ block: "nearest" });
67
- if (itemEl) {
68
- hasScrolledToInitial.current = true;
69
- }
138
+ export const SelectList = _a => {
139
+ var {
140
+ items: outerItems,
141
+ value = new Map(),
142
+ multiselect = false,
143
+ selectItemOnFocus = true,
144
+ forceSelection = false,
145
+ showCheckbox = false,
146
+ disabled,
147
+ onChange,
148
+ onClick
149
+ } = _a,
150
+ rest = __rest(_a, ["items", "value", "multiselect", "selectItemOnFocus", "forceSelection", "showCheckbox", "disabled", "onChange", "onClick"]);
151
+ const items = useMemo(() => outerItems, [outerItems]);
152
+ const listRef = useRef(null);
153
+ const {
154
+ translate
155
+ } = useLanguage();
156
+ const [announcement, setAnnouncement] = useState("");
157
+ const [state, dispatchState] = useReducer(selectListReducer, showCheckbox, isCheckbox => {
158
+ const initial = getInitialState({
159
+ items,
160
+ value,
161
+ multiselect
162
+ });
163
+ if (isCheckbox) {
164
+ initial.activeIndex = getFirstIndex(items);
165
+ }
166
+ return initial;
167
+ });
168
+ const innerValue = useMemo(() => JSON.stringify(Array.from(getInitialState({
169
+ items,
170
+ value,
171
+ multiselect
172
+ }).itemsState)), [items, value, multiselect]);
173
+ useEffect(() => {
174
+ const parsedValue = JSON.parse(innerValue);
175
+ dispatchState({
176
+ type: ListAction.Reset,
177
+ payload: {
178
+ items,
179
+ value: new Map(parsedValue),
180
+ multiselect
181
+ }
182
+ });
183
+ }, [innerValue, multiselect, items]);
184
+ useEffect(() => {
185
+ if (showCheckbox) {
186
+ dispatchState({
187
+ type: ListAction.FocusFirst,
188
+ payload: {
189
+ items
190
+ }
191
+ });
192
+ }
193
+ // eslint-disable-next-line react-hooks/exhaustive-deps
194
+ }, [showCheckbox]);
195
+ useEffect(() => {
196
+ if (!showCheckbox) {
197
+ if (!multiselect && selectItemOnFocus) {
198
+ dispatchState({
199
+ type: ListAction.FocusFirst,
200
+ payload: {
201
+ items
202
+ }
203
+ });
204
+ }
205
+ if (!multiselect) {
206
+ dispatchState({
207
+ type: ListAction.Focus,
208
+ payload: {
209
+ items,
210
+ multiselect
211
+ }
212
+ });
213
+ }
214
+ }
215
+ }, [multiselect, items, selectItemOnFocus, showCheckbox]);
216
+ useEffect(() => {
217
+ onChange && state.isItemsStateChanged && onChange(new Map(state.itemsState));
218
+ }, [state.isItemsStateChanged, state.itemsState, onChange]);
219
+ // VoiceOver does not announce aria-checked changes on role="menuitemcheckbox" (neither
220
+ // on toggle nor on navigation). Use a polite live region to announce the focused item's
221
+ // label + state whenever focus moves or state is toggled. The label is included so
222
+ // consecutive announcements of the same state still differ and get re-spoken.
223
+ useEffect(() => {
224
+ if (!showCheckbox || state.activeIndex < 0) {
225
+ return;
226
+ }
227
+ const itemId = getItemIdByIndex(state.itemsState, state.activeIndex);
228
+ if (!itemId) {
229
+ return;
230
+ }
231
+ const isChecked = state.itemsState.get(itemId) === CheckboxState.On;
232
+ const label = getComponentText(items[state.activeIndex].children);
233
+ setAnnouncement(`${label} ${isChecked ? translate("Checked") : translate("Unchecked")}`);
234
+ }, [showCheckbox, state.itemsState, state.activeIndex, items, translate]);
235
+ const onChangeItem = useCallback((updatedId, updatedState) => {
236
+ dispatchState({
237
+ type: ListAction.ChangeItemState,
238
+ payload: {
239
+ updatedId,
240
+ updatedState,
241
+ multiselect
242
+ }
243
+ });
244
+ }, [multiselect]);
245
+ const onFocusItem = useCallback(id => {
246
+ const index = items.findIndex(item => item.id === id);
247
+ if (index >= 0) {
248
+ dispatchState({
249
+ type: ListAction.FocusItem,
250
+ payload: {
251
+ index
252
+ }
253
+ });
254
+ }
255
+ }, [items]);
256
+ const hasScrolledToInitial = useRef(false);
257
+ useEffect(() => {
258
+ var _a, _b;
259
+ if (state.activeIndex >= 0 && listRef.current) {
260
+ const isFocusInList = ((_a = zen.document) === null || _a === void 0 ? void 0 : _a.activeElement) && isChildOf(zen.document.activeElement, listRef.current);
261
+ if (isFocusInList || !hasScrolledToInitial.current) {
262
+ const itemEl = listRef.current.querySelector(`.zen-select-list__item:nth-child(${state.activeIndex + 1})`);
263
+ itemEl === null || itemEl === void 0 ? void 0 : itemEl.scrollIntoView({
264
+ block: "nearest"
265
+ });
266
+ if (showCheckbox && isFocusInList && ((_b = zen.document) === null || _b === void 0 ? void 0 : _b.activeElement) !== itemEl) {
267
+ itemEl === null || itemEl === void 0 ? void 0 : itemEl.focus();
268
+ }
269
+ if (itemEl) {
270
+ hasScrolledToInitial.current = true;
271
+ }
272
+ }
273
+ }
274
+ }, [state.activeIndex, showCheckbox]);
275
+ useEffect(() => {
276
+ if (!state.level || !onClick) {
277
+ return;
278
+ }
279
+ onClick(state.level);
280
+ dispatchState({
281
+ type: ListAction.SetLevel,
282
+ payload: undefined
283
+ });
284
+ }, [onClick, state.level]);
285
+ const onKeyDown = e => {
286
+ const handlers = {
287
+ ArrowUp: () => multiselect || !selectItemOnFocus ? dispatchState({
288
+ type: ListAction.FocusPrev,
289
+ payload: {
290
+ items
291
+ }
292
+ }) : dispatchState({
293
+ type: ListAction.SelectPrev,
294
+ payload: {
295
+ items,
296
+ multiselect
297
+ }
298
+ }),
299
+ ArrowDown: () => multiselect || !selectItemOnFocus ? dispatchState({
300
+ type: ListAction.FocusNext,
301
+ payload: {
302
+ items
303
+ }
304
+ }) : dispatchState({
305
+ type: ListAction.SelectNext,
306
+ payload: {
307
+ items,
308
+ multiselect
309
+ }
310
+ }),
311
+ Enter: () => {
312
+ const item = items[state.activeIndex];
313
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
314
+ if (!item || item.disabled) {
315
+ return;
316
+ }
317
+ if (item.multiLevel) {
318
+ dispatchState({
319
+ type: ListAction.SetLevel,
320
+ payload: {
321
+ items
70
322
  }
323
+ });
324
+ } else {
325
+ dispatchState({
326
+ type: ListAction.ChangeItemState,
327
+ payload: {
328
+ updatedId: item.id,
329
+ updatedState: item.state === CheckboxState.On ? CheckboxState.Off : CheckboxState.On,
330
+ multiselect: multiselect
331
+ }
332
+ });
71
333
  }
72
- }, [state.activeIndex]);
73
- useEffect(() => {
74
- if (!state.level || !onClick) {
75
- return;
76
- }
77
- onClick(state.level);
78
- dispatchState({ type: ListAction.SetLevel, payload: undefined });
79
- }, [onClick, state.level]);
80
- const onKeyDown = (e) => {
81
- const handlers = {
82
- ArrowUp: () => multiselect || !selectItemOnFocus
83
- ? dispatchState({ type: ListAction.FocusPrev, payload: { items } })
84
- : dispatchState({ type: ListAction.SelectPrev, payload: { items, multiselect } }),
85
- ArrowDown: () => multiselect || !selectItemOnFocus
86
- ? dispatchState({ type: ListAction.FocusNext, payload: { items } })
87
- : dispatchState({ type: ListAction.SelectNext, payload: { items, multiselect } }),
88
- Enter: () => {
89
- const item = items[state.activeIndex];
90
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
91
- if (!item || item.disabled) {
92
- return;
93
- }
94
- if (item.multiLevel) {
95
- dispatchState({ type: ListAction.SetLevel, payload: { items } });
96
- }
97
- else {
98
- dispatchState({
99
- type: ListAction.ChangeItemState,
100
- payload: {
101
- updatedId: item.id,
102
- updatedState: item.state === CheckboxState.On ? CheckboxState.Off : CheckboxState.On,
103
- multiselect: multiselect
104
- }
105
- });
106
- }
107
- },
108
- Home: () => multiselect || !selectItemOnFocus
109
- ? dispatchState({ type: ListAction.FocusFirst, payload: { items } })
110
- : dispatchState({ type: ListAction.SelectFirst, payload: { items, multiselect } }),
111
- End: () => multiselect || !selectItemOnFocus
112
- ? dispatchState({ type: ListAction.FocusLast, payload: { items } })
113
- : dispatchState({ type: ListAction.SelectLast, payload: { items, multiselect } }),
114
- Space: () => {
115
- const item = items[state.activeIndex];
116
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
117
- if (item === null || item === void 0 ? void 0 : item.disabled) {
118
- return;
119
- }
120
- dispatchState({ type: ListAction.ToggleCurrent, payload: { multiselect } });
121
- },
122
- "Shift+ArrowUp": () => multiselect && dispatchState({ type: ListAction.SelectPrev, payload: { items, multiselect } }),
123
- "Shift+ArrowDown": () => multiselect && dispatchState({ type: ListAction.SelectNext, payload: { items, multiselect } }),
124
- "Ctrl+Shift+Home": () => multiselect && dispatchState({ type: ListAction.SelectAllToTheBeginning, payload: { items, multiselect } }),
125
- "Ctrl+Shift+End": () => multiselect && dispatchState({ type: ListAction.SelectAllToTheEnd, payload: { items, multiselect } }),
126
- "Ctrl+KeyA": () => multiselect && dispatchState({ type: ListAction.ToggleAll, payload: { items, multiselect } }),
127
- default: () => dispatchState({ type: ListAction.SearchItem, payload: { items, key: e.key } })
128
- };
129
- const handlerName = getKeysPressed(e);
130
- const handler = handlers[handlerName] || (isKeyForSearch(e.code) && handlers["default"]);
131
- if (handler) {
132
- handler();
133
- e.preventDefault();
134
- e.stopPropagation();
334
+ },
335
+ Home: () => multiselect || !selectItemOnFocus ? dispatchState({
336
+ type: ListAction.FocusFirst,
337
+ payload: {
338
+ items
135
339
  }
136
- };
137
- const onFocus = () => {
138
- const scrollableParent = getScrollableParent(listRef.current);
139
- if (!scrollableParent || scrollableParent.scrollTop === 0) {
140
- dispatchState({ type: ListAction.Focus, payload: { items, multiselect } });
340
+ }) : dispatchState({
341
+ type: ListAction.SelectFirst,
342
+ payload: {
343
+ items,
344
+ multiselect
141
345
  }
346
+ }),
347
+ End: () => multiselect || !selectItemOnFocus ? dispatchState({
348
+ type: ListAction.FocusLast,
349
+ payload: {
350
+ items
351
+ }
352
+ }) : dispatchState({
353
+ type: ListAction.SelectLast,
354
+ payload: {
355
+ items,
356
+ multiselect
357
+ }
358
+ }),
359
+ Space: () => {
360
+ const item = items[state.activeIndex];
361
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
362
+ if (item === null || item === void 0 ? void 0 : item.disabled) {
363
+ return;
364
+ }
365
+ dispatchState({
366
+ type: ListAction.ToggleCurrent,
367
+ payload: {
368
+ multiselect
369
+ }
370
+ });
371
+ },
372
+ "Shift+ArrowUp": () => multiselect && dispatchState({
373
+ type: ListAction.SelectPrev,
374
+ payload: {
375
+ items,
376
+ multiselect
377
+ }
378
+ }),
379
+ "Shift+ArrowDown": () => multiselect && dispatchState({
380
+ type: ListAction.SelectNext,
381
+ payload: {
382
+ items,
383
+ multiselect
384
+ }
385
+ }),
386
+ "Ctrl+Shift+Home": () => multiselect && dispatchState({
387
+ type: ListAction.SelectAllToTheBeginning,
388
+ payload: {
389
+ items,
390
+ multiselect
391
+ }
392
+ }),
393
+ "Ctrl+Shift+End": () => multiselect && dispatchState({
394
+ type: ListAction.SelectAllToTheEnd,
395
+ payload: {
396
+ items,
397
+ multiselect
398
+ }
399
+ }),
400
+ "Ctrl+KeyA": () => multiselect && dispatchState({
401
+ type: ListAction.ToggleAll,
402
+ payload: {
403
+ items,
404
+ multiselect
405
+ }
406
+ }),
407
+ default: () => dispatchState({
408
+ type: ListAction.SearchItem,
409
+ payload: {
410
+ items,
411
+ key: e.key
412
+ }
413
+ })
142
414
  };
143
- const onBlur = () => {
144
- multiselect && dispatchState({ type: ListAction.Blur, payload: { multiselect } });
145
- !multiselect && forceSelection && dispatchState({ type: ListAction.Blur, payload: { multiselect } });
146
- };
147
- return (_jsx(SelectListInner, Object.assign({}, rest, { ref: listRef, value: state.itemsState, items: items, activeIndex: state.activeIndex, multiselect: multiselect, standalone: true, disabled: disabled, onChangeItem: onChangeItem, onClickItem: onClick, onKeyDown: onKeyDown, onFocus: onFocus, onBlur: onBlur })));
415
+ const handlerName = getKeysPressed(e);
416
+ const handler = handlers[handlerName] || isKeyForSearch(e.code) && handlers["default"];
417
+ if (handler) {
418
+ handler();
419
+ e.preventDefault();
420
+ e.stopPropagation();
421
+ }
422
+ };
423
+ const onFocus = () => {
424
+ const scrollableParent = getScrollableParent(listRef.current);
425
+ if (!scrollableParent || scrollableParent.scrollTop === 0) {
426
+ dispatchState({
427
+ type: ListAction.Focus,
428
+ payload: {
429
+ items,
430
+ multiselect
431
+ }
432
+ });
433
+ }
434
+ };
435
+ const onBlur = () => {
436
+ // In showCheckbox mode, activeIndex must stay stable while focus cycles between
437
+ // list items and sibling controls (e.g. Reset button) via Tab/Shift+Tab.
438
+ // Resetting activeIndex to -1 would drop all li tabIndex values to -1, making
439
+ // Shift+Tab unable to re-enter the list.
440
+ if (showCheckbox) {
441
+ return;
442
+ }
443
+ multiselect && dispatchState({
444
+ type: ListAction.Blur,
445
+ payload: {
446
+ multiselect
447
+ }
448
+ });
449
+ !multiselect && forceSelection && dispatchState({
450
+ type: ListAction.Blur,
451
+ payload: {
452
+ multiselect
453
+ }
454
+ });
455
+ };
456
+ return _jsxs(_Fragment, {
457
+ children: [_jsx(SelectListInner, Object.assign({}, rest, {
458
+ ref: listRef,
459
+ value: state.itemsState,
460
+ items: items,
461
+ activeIndex: state.activeIndex,
462
+ multiselect: multiselect,
463
+ showCheckbox: showCheckbox,
464
+ standalone: true,
465
+ disabled: disabled,
466
+ onChangeItem: onChangeItem,
467
+ onClickItem: onClick,
468
+ onFocusItem: onFocusItem,
469
+ onKeyDown: onKeyDown,
470
+ onFocus: onFocus,
471
+ onBlur: onBlur
472
+ })), showCheckbox ? _jsx("div", {
473
+ className: "zen-visually-hidden",
474
+ "aria-live": "polite",
475
+ "aria-atomic": "true",
476
+ role: "status",
477
+ children: announcement
478
+ }) : null]
479
+ });
148
480
  };
149
- export const PassiveSelectList = props => _jsx(SelectListInnerComp, Object.assign({}, props, { standalone: false }));
481
+ export const PassiveSelectList = props => _jsx(SelectListInnerComp, Object.assign({}, props, {
482
+ standalone: false
483
+ }));
@@ -57,6 +57,8 @@ export const selectListReducer = (state, action) => {
57
57
  return Object.assign(Object.assign({}, state), { activeIndex: getNextIndex(state.activeIndex, payload.items), isItemsStateChanged: false, searchStr: "" });
58
58
  case ListAction.FocusPrev:
59
59
  return Object.assign(Object.assign({}, state), { activeIndex: getPrevIndex(state.activeIndex, payload.items), isItemsStateChanged: false, searchStr: "" });
60
+ case ListAction.FocusItem:
61
+ return Object.assign(Object.assign({}, state), { activeIndex: payload.index, isItemsStateChanged: false, searchStr: "" });
60
62
  case ListAction.SelectFirst: {
61
63
  const index = getFirstIndex(payload.items);
62
64
  return selectItem(state, index, payload.multiselect, (_a = payload.items[index]) === null || _a === void 0 ? void 0 : _a.disabled);
@@ -117,8 +119,7 @@ export const selectListReducer = (state, action) => {
117
119
  newItemsState = updatedState;
118
120
  });
119
121
  const prevActiveItemId = getItemIdByIndex(state.itemsState, state.activeIndex);
120
- const newActiveItemIndex = !!prevActiveItemId && getItemIndexById(newItemsState, prevActiveItemId);
121
- const activeIndex = newActiveItemIndex ? newActiveItemIndex : -1;
122
+ const activeIndex = prevActiveItemId !== undefined ? getItemIndexById(newItemsState, prevActiveItemId) : -1;
122
123
  return Object.assign(Object.assign({}, state), { itemsState: newItemsState, activeIndex, isItemsStateChanged: false });
123
124
  }
124
125
  case ListAction.SetLevel: {
@@ -8,6 +8,7 @@ export interface ISelectListItem extends IZenIdComponentProps {
8
8
  focused?: boolean;
9
9
  onChange?: (id: string, state: CheckboxState) => void;
10
10
  onClick?: (id: string) => void;
11
+ onFocusItem?: (id: string) => void;
11
12
  multiLevel?: boolean;
12
13
  }
13
- export declare const SelectListItem: ({ id, disabled, state, showCheckbox, focused, onChange, onClick, multiLevel, className, children }: ISelectListItem) => import("react/jsx-runtime").JSX.Element;
14
+ export declare const SelectListItem: ({ id, disabled, state, showCheckbox, focused, onChange, onClick, onFocusItem, multiLevel, className, children }: ISelectListItem) => import("react/jsx-runtime").JSX.Element;