@geotab/zenith 3.11.0 → 3.11.1

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