handsontable 0.0.0-next-ff8465d-20231006 → 0.0.0-next-b0a4ea2-20231024

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of handsontable might be problematic. Click here for more details.

Files changed (117) hide show
  1. package/base.js +2 -2
  2. package/base.mjs +2 -2
  3. package/cellTypes/dateType/dateType.d.ts +3 -3
  4. package/cellTypes/dateType/dateType.js +2 -2
  5. package/cellTypes/dateType/dateType.mjs +2 -2
  6. package/cellTypes/handsontableType/handsontableType.d.ts +3 -3
  7. package/cellTypes/handsontableType/handsontableType.js +2 -2
  8. package/cellTypes/handsontableType/handsontableType.mjs +2 -2
  9. package/core.d.ts +1 -1
  10. package/core.js +10 -5
  11. package/core.mjs +10 -5
  12. package/dataMap/metaManager/metaSchema.js +1 -1
  13. package/dataMap/metaManager/metaSchema.mjs +1 -1
  14. package/dist/handsontable.css +13 -12
  15. package/dist/handsontable.full.css +13 -12
  16. package/dist/handsontable.full.js +2260 -1403
  17. package/dist/handsontable.full.min.css +5 -5
  18. package/dist/handsontable.full.min.js +10 -10
  19. package/dist/handsontable.js +2260 -1403
  20. package/dist/handsontable.min.css +5 -5
  21. package/dist/handsontable.min.js +24 -24
  22. package/dist/languages/all.js +6 -2
  23. package/dist/languages/all.min.js +1 -1
  24. package/dist/languages/en-US.js +3 -1
  25. package/dist/languages/en-US.min.js +1 -1
  26. package/dist/languages/pl-PL.js +3 -1
  27. package/dist/languages/pl-PL.min.js +1 -1
  28. package/editors/autocompleteEditor/autocompleteEditor.js +1 -1
  29. package/editors/autocompleteEditor/autocompleteEditor.mjs +1 -1
  30. package/editors/dateEditor/dateEditor.js +26 -7
  31. package/editors/dateEditor/dateEditor.mjs +27 -8
  32. package/editors/handsontableEditor/handsontableEditor.js +7 -0
  33. package/editors/handsontableEditor/handsontableEditor.mjs +8 -1
  34. package/helpers/a11y.js +3 -1
  35. package/helpers/a11y.mjs +2 -1
  36. package/helpers/mixed.js +1 -1
  37. package/helpers/mixed.mjs +1 -1
  38. package/i18n/constants.js +7 -1
  39. package/i18n/constants.mjs +4 -1
  40. package/i18n/languages/en-US.js +3 -1
  41. package/i18n/languages/en-US.mjs +3 -1
  42. package/i18n/languages/pl-PL.js +3 -1
  43. package/i18n/languages/pl-PL.mjs +3 -1
  44. package/languages/all.js +6 -2
  45. package/languages/en-US.js +3 -1
  46. package/languages/en-US.mjs +3 -1
  47. package/languages/index.js +6 -2
  48. package/languages/pl-PL.js +3 -1
  49. package/languages/pl-PL.mjs +3 -1
  50. package/package.json +11 -1
  51. package/pluginHooks.js +1 -1
  52. package/pluginHooks.mjs +1 -1
  53. package/plugins/contextMenu/menu/defaultShortcutsList.js +88 -0
  54. package/plugins/contextMenu/menu/defaultShortcutsList.mjs +84 -0
  55. package/plugins/contextMenu/menu/menu.js +87 -151
  56. package/plugins/contextMenu/menu/menu.mjs +90 -154
  57. package/plugins/contextMenu/menu/menuItemRenderer.js +58 -0
  58. package/plugins/contextMenu/menu/menuItemRenderer.mjs +54 -0
  59. package/plugins/contextMenu/menu/navigator.js +19 -144
  60. package/plugins/contextMenu/menu/navigator.mjs +18 -143
  61. package/plugins/contextMenu/menu/shortcuts.js +114 -0
  62. package/plugins/contextMenu/menu/shortcuts.mjs +110 -0
  63. package/plugins/dropdownMenu/dropdownMenu.js +32 -4
  64. package/plugins/dropdownMenu/dropdownMenu.mjs +33 -5
  65. package/plugins/filters/component/_base.js +23 -8
  66. package/plugins/filters/component/_base.mjs +23 -8
  67. package/plugins/filters/component/actionBar.js +29 -27
  68. package/plugins/filters/component/actionBar.mjs +26 -23
  69. package/plugins/filters/component/condition.js +46 -59
  70. package/plugins/filters/component/condition.mjs +40 -52
  71. package/plugins/filters/component/operators.js +21 -22
  72. package/plugins/filters/component/operators.mjs +18 -18
  73. package/plugins/filters/component/value.js +35 -26
  74. package/plugins/filters/component/value.mjs +32 -22
  75. package/plugins/filters/filters.js +75 -48
  76. package/plugins/filters/filters.mjs +68 -41
  77. package/plugins/filters/menu/focusController.js +123 -0
  78. package/plugins/filters/menu/focusController.mjs +119 -0
  79. package/plugins/filters/menu/focusNavigator.js +30 -0
  80. package/plugins/filters/menu/focusNavigator.mjs +26 -0
  81. package/plugins/filters/ui/_base.js +35 -13
  82. package/plugins/filters/ui/_base.mjs +35 -13
  83. package/plugins/filters/ui/input.js +43 -32
  84. package/plugins/filters/ui/input.mjs +42 -30
  85. package/plugins/filters/ui/link.js +44 -12
  86. package/plugins/filters/ui/link.mjs +44 -11
  87. package/plugins/filters/ui/multipleSelect.js +234 -129
  88. package/plugins/filters/ui/multipleSelect.mjs +232 -127
  89. package/plugins/filters/ui/radioInput.js +42 -18
  90. package/plugins/filters/ui/radioInput.mjs +42 -17
  91. package/plugins/filters/ui/select.js +144 -75
  92. package/plugins/filters/ui/select.mjs +140 -70
  93. package/renderers/autocompleteRenderer/autocompleteRenderer.js +1 -1
  94. package/renderers/autocompleteRenderer/autocompleteRenderer.mjs +1 -1
  95. package/renderers/checkboxRenderer/checkboxRenderer.js +3 -3
  96. package/renderers/checkboxRenderer/checkboxRenderer.mjs +4 -4
  97. package/renderers/dateRenderer/dateRenderer.d.ts +5 -0
  98. package/renderers/dateRenderer/dateRenderer.js +29 -0
  99. package/renderers/dateRenderer/dateRenderer.mjs +24 -0
  100. package/renderers/dateRenderer/index.d.ts +1 -0
  101. package/renderers/dateRenderer/index.js +6 -0
  102. package/renderers/dateRenderer/index.mjs +1 -0
  103. package/renderers/handsontableRenderer/handsontableRenderer.d.ts +5 -0
  104. package/renderers/handsontableRenderer/handsontableRenderer.js +29 -0
  105. package/renderers/handsontableRenderer/handsontableRenderer.mjs +24 -0
  106. package/renderers/handsontableRenderer/index.d.ts +1 -0
  107. package/renderers/handsontableRenderer/index.js +6 -0
  108. package/renderers/handsontableRenderer/index.mjs +1 -0
  109. package/renderers/index.d.ts +6 -0
  110. package/renderers/selectRenderer/selectRenderer.js +2 -1
  111. package/renderers/selectRenderer/selectRenderer.mjs +2 -1
  112. package/selection/selection.js +2 -2
  113. package/selection/selection.mjs +2 -2
  114. package/shortcuts/context.js +3 -2
  115. package/shortcuts/context.mjs +3 -2
  116. package/utils/paginator.js +151 -0
  117. package/utils/paginator.mjs +147 -0
@@ -1,21 +1,34 @@
1
+ import "core-js/modules/es.array.unscopables.flat.js";
1
2
  import "core-js/modules/es.array.push.js";
3
+ import "core-js/modules/es.error.cause.js";
4
+ function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
5
+ function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
6
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
7
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
8
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
9
+ function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
10
+ function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
11
+ function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
12
+ function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
13
+ function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
2
14
  import { BasePlugin } from "../base/index.mjs";
3
15
  import { arrayEach, arrayMap } from "../../helpers/array.mjs";
4
16
  import { toSingleLine } from "../../helpers/templateLiteralTag.mjs";
5
17
  import { warn } from "../../helpers/console.mjs";
6
18
  import { rangeEach } from "../../helpers/number.mjs";
7
- import EventManager from "../../eventManager.mjs";
8
19
  import { addClass, removeClass } from "../../helpers/dom/element.mjs";
20
+ import { isKey } from "../../helpers/unicode.mjs";
9
21
  import { SEPARATOR } from "../contextMenu/predefinedItems/index.mjs";
10
22
  import * as constants from "../../i18n/constants.mjs";
11
- import ConditionComponent from "./component/condition.mjs";
12
- import OperatorsComponent from "./component/operators.mjs";
13
- import ValueComponent from "./component/value.mjs";
14
- import ActionBarComponent from "./component/actionBar.mjs";
23
+ import { ConditionComponent } from "./component/condition.mjs";
24
+ import { OperatorsComponent } from "./component/operators.mjs";
25
+ import { ValueComponent } from "./component/value.mjs";
26
+ import { ActionBarComponent } from "./component/actionBar.mjs";
15
27
  import ConditionCollection from "./conditionCollection.mjs";
16
28
  import DataFilter from "./dataFilter.mjs";
17
29
  import ConditionUpdateObserver from "./conditionUpdateObserver.mjs";
18
30
  import { createArrayAssertion, toEmptyString, unifyColumnValues } from "./utils.mjs";
31
+ import { createMenuFocusController } from "./menu/focusController.mjs";
19
32
  import { CONDITION_NONE, CONDITION_BY_VALUE, OPERATION_AND, OPERATION_OR, OPERATION_OR_THEN_VARIABLE } from "./constants.mjs";
20
33
  import { TrimmingMap } from "../../translations/index.mjs";
21
34
  export const PLUGIN_KEY = 'filters';
@@ -57,6 +70,7 @@ const SHORTCUTS_GROUP = PLUGIN_KEY;
57
70
  * ```
58
71
  * :::
59
72
  */
73
+ var _menuFocusNavigator = /*#__PURE__*/new WeakMap();
60
74
  export class Filters extends BasePlugin {
61
75
  static get PLUGIN_KEY() {
62
76
  return PLUGIN_KEY;
@@ -67,52 +81,55 @@ export class Filters extends BasePlugin {
67
81
  static get PLUGIN_DEPS() {
68
82
  return ['plugin:DropdownMenu', 'plugin:HiddenRows', 'cell-type:checkbox'];
69
83
  }
84
+
85
+ /**
86
+ * Instance of {@link DropdownMenu}.
87
+ *
88
+ * @private
89
+ * @type {DropdownMenu}
90
+ */
91
+
70
92
  constructor(hotInstance) {
71
93
  super(hotInstance);
72
- /**
73
- * Instance of {@link EventManager}.
74
- *
75
- * @private
76
- * @type {EventManager}
77
- */
78
- this.eventManager = new EventManager(this);
79
- /**
80
- * Instance of {@link DropdownMenu}.
81
- *
82
- * @private
83
- * @type {DropdownMenu}
84
- */
85
- this.dropdownMenuPlugin = null;
94
+ // One listener for the enable/disable functionality
95
+ _defineProperty(this, "dropdownMenuPlugin", null);
86
96
  /**
87
97
  * Instance of {@link ConditionCollection}.
88
98
  *
89
99
  * @private
90
100
  * @type {ConditionCollection}
91
101
  */
92
- this.conditionCollection = null;
102
+ _defineProperty(this, "conditionCollection", null);
93
103
  /**
94
104
  * Instance of {@link ConditionUpdateObserver}.
95
105
  *
96
106
  * @private
97
107
  * @type {ConditionUpdateObserver}
98
108
  */
99
- this.conditionUpdateObserver = null;
109
+ _defineProperty(this, "conditionUpdateObserver", null);
100
110
  /**
101
111
  * Map, where key is component identifier and value represent `BaseComponent` element or it derivatives.
102
112
  *
103
113
  * @private
104
114
  * @type {Map}
105
115
  */
106
- this.components = new Map([['filter_by_condition', null], ['filter_operators', null], ['filter_by_condition2', null], ['filter_by_value', null], ['filter_action_bar', null]]);
116
+ _defineProperty(this, "components", new Map([['filter_by_condition', null], ['filter_operators', null], ['filter_by_condition2', null], ['filter_by_value', null], ['filter_action_bar', null]]));
107
117
  /**
108
118
  * Map of skipped rows by plugin.
109
119
  *
110
120
  * @private
111
121
  * @type {null|TrimmingMap}
112
122
  */
113
- this.filtersRowsMap = null;
114
-
115
- // One listener for the enable/disable functionality
123
+ _defineProperty(this, "filtersRowsMap", null);
124
+ /**
125
+ * Menu focus navigator allows switching the focus position through Tab and Shift Tab keys.
126
+ *
127
+ * @type {MenuFocusNavigator|undefined}
128
+ */
129
+ _classPrivateFieldInitSpec(this, _menuFocusNavigator, {
130
+ writable: true,
131
+ value: void 0
132
+ });
116
133
  this.hot.addHook('afterGetColHeader', (col, TH) => this.onAfterGetColHeader(col, TH));
117
134
  }
118
135
 
@@ -192,7 +209,6 @@ export class Filters extends BasePlugin {
192
209
  this.conditionUpdateObserver.addLocalHook('update', conditionState => this.updateComponents(conditionState));
193
210
  }
194
211
  this.components.forEach(component => component.show());
195
- this.addHook('beforeDropdownMenuSetItems', items => this.onBeforeDropdownMenuSetItems(items));
196
212
  this.addHook('afterDropdownMenuDefaultOptions', defaultOptions => this.onAfterDropdownMenuDefaultOptions(defaultOptions));
197
213
  this.addHook('afterDropdownMenuShow', () => this.onAfterDropdownMenuShow());
198
214
  this.addHook('afterDropdownMenuHide', () => this.onAfterDropdownMenuHide());
@@ -203,6 +219,32 @@ export class Filters extends BasePlugin {
203
219
  this.dropdownMenuPlugin.disablePlugin();
204
220
  this.dropdownMenuPlugin.enablePlugin();
205
221
  }
222
+ if (!_classPrivateFieldGet(this, _menuFocusNavigator) && this.dropdownMenuPlugin.enabled) {
223
+ const mainMenu = this.dropdownMenuPlugin.menu;
224
+ const focusableItems = [
225
+ // A fake menu item that once focused allows escaping from the focus navigation (using Tab keys)
226
+ // to the menu navigation using arrow keys.
227
+ {
228
+ focus: () => mainMenu.focus()
229
+ }, ...Array.from(this.components).map(_ref => {
230
+ let [, component] = _ref;
231
+ return component.getElements();
232
+ }).flat()];
233
+ _classPrivateFieldSet(this, _menuFocusNavigator, createMenuFocusController(mainMenu, focusableItems));
234
+ const forwardToFocusNavigation = event => {
235
+ _classPrivateFieldGet(this, _menuFocusNavigator).listen();
236
+ event.preventDefault();
237
+ if (isKey(event.keyCode, 'TAB')) {
238
+ if (event.shiftKey) {
239
+ _classPrivateFieldGet(this, _menuFocusNavigator).toPreviousItem();
240
+ } else {
241
+ _classPrivateFieldGet(this, _menuFocusNavigator).toNextItem();
242
+ }
243
+ }
244
+ };
245
+ this.components.get('filter_by_value').addLocalHook('listTabKeydown', forwardToFocusNavigation);
246
+ this.components.get('filter_by_condition').addLocalHook('selectTabKeydown', forwardToFocusNavigation);
247
+ }
206
248
  this.registerShortcuts();
207
249
  super.enablePlugin();
208
250
  }
@@ -570,21 +612,6 @@ export class Filters extends BasePlugin {
570
612
  this.components.get('filter_by_condition2').getSelectElement().closeOptions();
571
613
  }
572
614
 
573
- /**
574
- * Before dropdown menu set menu items listener.
575
- *
576
- * @private
577
- */
578
- onBeforeDropdownMenuSetItems() {
579
- if (this.dropdownMenuPlugin) {
580
- this.dropdownMenuPlugin.menu.addLocalHook('afterOpen', () => {
581
- this.dropdownMenuPlugin.menu.hotMenu.updateSettings({
582
- hiddenRows: true
583
- });
584
- });
585
- }
586
- }
587
-
588
615
  /**
589
616
  * After dropdown menu default options listener.
590
617
  *
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.createMenuFocusController = createMenuFocusController;
5
+ var _focusNavigator = require("./focusNavigator");
6
+ var _select = require("../ui/select");
7
+ var _base = require("../ui/_base");
8
+ var _link = require("../ui/link");
9
+ const SHORTCUTS_MENU_CONTEXT = 'filters';
10
+
11
+ /**
12
+ * @typedef MenuFocusNavigator
13
+ * @property {function(number): void} setCurrentPage Sets the current index of the selected focus.
14
+ * @property {function(): number} getCurrentPage Gets the index of currently focus element.
15
+ * @property {function(): void} toFirstItem Move the focus index to the first element in the list.
16
+ * @property {function(): void} toLastItem Move the focus index to the last element in the list.
17
+ * @property {function(): void} toNextItem Move the focus index to the next element in the list.
18
+ * @property {function(): void} toPreviousItem Move the focus index to the previous element in the list.
19
+ * @property {function(): void} clear Clear the internal state of the navigator.
20
+ * @property {function(): void} listen Activate the navigator by listening the keyboard shortcuts.
21
+ */
22
+ /**
23
+ * Creates navigator controller for filter subcomponents in the menu.
24
+ *
25
+ * @param {Menu} mainMenu The main Menu instance.
26
+ * @param {BaseUI[]} menuItems The list of the component's elements to paginate to.
27
+ * @returns {Paginator}
28
+ */
29
+ function createMenuFocusController(mainMenu, menuItems) {
30
+ const navigator = (0, _focusNavigator.createFocusNavigator)(menuItems);
31
+ const updateNavigatorPosition = element => () => {
32
+ if (mainMenu.isOpened()) {
33
+ mainMenu.getKeyboardShortcutsCtrl().listen(SHORTCUTS_MENU_CONTEXT);
34
+ }
35
+ navigator.setCurrentPage(menuItems.indexOf(element));
36
+ };
37
+
38
+ // update navigator position (internal state) to element that was recently clicked or focused
39
+ menuItems.forEach(element => {
40
+ if (element instanceof _base.BaseUI) {
41
+ element.addLocalHook('click', updateNavigatorPosition(element));
42
+ element.addLocalHook('focus', updateNavigatorPosition(element));
43
+ element.addLocalHook('afterClose', updateNavigatorPosition(element));
44
+ }
45
+ });
46
+ mainMenu.addLocalHook('afterSelectionChange', selectedItem => {
47
+ if (!selectedItem.key.startsWith('filter_')) {
48
+ navigator.clear();
49
+ }
50
+ });
51
+
52
+ /**
53
+ * Extends the menu and submenus with new keyboard shortcuts.
54
+ *
55
+ * @param {*} menu The menu (as main menu or submenu) instance.
56
+ */
57
+ function addKeyboardShortcuts(menu) {
58
+ const mainMenuShortcutsCtrl = mainMenu.getKeyboardShortcutsCtrl();
59
+ const currentMenuShortcutsCtrl = menu.getKeyboardShortcutsCtrl();
60
+ navigator.clear();
61
+ currentMenuShortcutsCtrl.addCustomShortcuts([{
62
+ keys: [['Tab'], ['Shift', 'Tab']],
63
+ forwardToContext: mainMenuShortcutsCtrl.getContext(SHORTCUTS_MENU_CONTEXT),
64
+ callback: () => {
65
+ if (menu.isSubMenu()) {
66
+ menu.close();
67
+ }
68
+ mainMenuShortcutsCtrl.listen(SHORTCUTS_MENU_CONTEXT);
69
+ }
70
+ }]);
71
+ if (menu.isSubMenu()) {
72
+ return;
73
+ }
74
+ mainMenuShortcutsCtrl.addCustomShortcuts([{
75
+ keys: [['Tab'], ['Shift', 'Tab']],
76
+ callback: event => {
77
+ mainMenu.getNavigator().clear();
78
+ if (event.shiftKey) {
79
+ navigator.toPreviousItem();
80
+ } else {
81
+ navigator.toNextItem();
82
+ }
83
+ }
84
+ }, {
85
+ keys: [['Escape']],
86
+ callback: () => {
87
+ mainMenu.close();
88
+ }
89
+ }, {
90
+ keys: [['Enter'], ['Space']],
91
+ preventDefault: false,
92
+ callback: event => {
93
+ const element = menuItems[navigator.getCurrentPage()];
94
+ if (element instanceof _select.SelectUI) {
95
+ element.openOptions();
96
+ event.preventDefault();
97
+ }
98
+ if (element instanceof _link.LinkUI) {
99
+ element.activate();
100
+ event.preventDefault();
101
+ }
102
+ if (!(element instanceof _base.BaseUI)) {
103
+ event.preventDefault();
104
+ }
105
+ }
106
+ }], SHORTCUTS_MENU_CONTEXT);
107
+ }
108
+ mainMenu.addLocalHook('afterSubmenuOpen', addKeyboardShortcuts);
109
+ mainMenu.addLocalHook('afterOpen', addKeyboardShortcuts);
110
+
111
+ /**
112
+ * Focuses the menu and switches its shortcut context to that one which controls
113
+ * the focus navigation.
114
+ */
115
+ function listen() {
116
+ mainMenu.focus();
117
+ mainMenu.getKeyboardShortcutsCtrl().listen(SHORTCUTS_MENU_CONTEXT);
118
+ }
119
+ return {
120
+ ...navigator,
121
+ listen
122
+ };
123
+ }
@@ -0,0 +1,119 @@
1
+ import { createFocusNavigator } from "./focusNavigator.mjs";
2
+ import { SelectUI } from "../ui/select.mjs";
3
+ import { BaseUI } from "../ui/_base.mjs";
4
+ import { LinkUI } from "../ui/link.mjs";
5
+ const SHORTCUTS_MENU_CONTEXT = 'filters';
6
+
7
+ /**
8
+ * @typedef MenuFocusNavigator
9
+ * @property {function(number): void} setCurrentPage Sets the current index of the selected focus.
10
+ * @property {function(): number} getCurrentPage Gets the index of currently focus element.
11
+ * @property {function(): void} toFirstItem Move the focus index to the first element in the list.
12
+ * @property {function(): void} toLastItem Move the focus index to the last element in the list.
13
+ * @property {function(): void} toNextItem Move the focus index to the next element in the list.
14
+ * @property {function(): void} toPreviousItem Move the focus index to the previous element in the list.
15
+ * @property {function(): void} clear Clear the internal state of the navigator.
16
+ * @property {function(): void} listen Activate the navigator by listening the keyboard shortcuts.
17
+ */
18
+ /**
19
+ * Creates navigator controller for filter subcomponents in the menu.
20
+ *
21
+ * @param {Menu} mainMenu The main Menu instance.
22
+ * @param {BaseUI[]} menuItems The list of the component's elements to paginate to.
23
+ * @returns {Paginator}
24
+ */
25
+ export function createMenuFocusController(mainMenu, menuItems) {
26
+ const navigator = createFocusNavigator(menuItems);
27
+ const updateNavigatorPosition = element => () => {
28
+ if (mainMenu.isOpened()) {
29
+ mainMenu.getKeyboardShortcutsCtrl().listen(SHORTCUTS_MENU_CONTEXT);
30
+ }
31
+ navigator.setCurrentPage(menuItems.indexOf(element));
32
+ };
33
+
34
+ // update navigator position (internal state) to element that was recently clicked or focused
35
+ menuItems.forEach(element => {
36
+ if (element instanceof BaseUI) {
37
+ element.addLocalHook('click', updateNavigatorPosition(element));
38
+ element.addLocalHook('focus', updateNavigatorPosition(element));
39
+ element.addLocalHook('afterClose', updateNavigatorPosition(element));
40
+ }
41
+ });
42
+ mainMenu.addLocalHook('afterSelectionChange', selectedItem => {
43
+ if (!selectedItem.key.startsWith('filter_')) {
44
+ navigator.clear();
45
+ }
46
+ });
47
+
48
+ /**
49
+ * Extends the menu and submenus with new keyboard shortcuts.
50
+ *
51
+ * @param {*} menu The menu (as main menu or submenu) instance.
52
+ */
53
+ function addKeyboardShortcuts(menu) {
54
+ const mainMenuShortcutsCtrl = mainMenu.getKeyboardShortcutsCtrl();
55
+ const currentMenuShortcutsCtrl = menu.getKeyboardShortcutsCtrl();
56
+ navigator.clear();
57
+ currentMenuShortcutsCtrl.addCustomShortcuts([{
58
+ keys: [['Tab'], ['Shift', 'Tab']],
59
+ forwardToContext: mainMenuShortcutsCtrl.getContext(SHORTCUTS_MENU_CONTEXT),
60
+ callback: () => {
61
+ if (menu.isSubMenu()) {
62
+ menu.close();
63
+ }
64
+ mainMenuShortcutsCtrl.listen(SHORTCUTS_MENU_CONTEXT);
65
+ }
66
+ }]);
67
+ if (menu.isSubMenu()) {
68
+ return;
69
+ }
70
+ mainMenuShortcutsCtrl.addCustomShortcuts([{
71
+ keys: [['Tab'], ['Shift', 'Tab']],
72
+ callback: event => {
73
+ mainMenu.getNavigator().clear();
74
+ if (event.shiftKey) {
75
+ navigator.toPreviousItem();
76
+ } else {
77
+ navigator.toNextItem();
78
+ }
79
+ }
80
+ }, {
81
+ keys: [['Escape']],
82
+ callback: () => {
83
+ mainMenu.close();
84
+ }
85
+ }, {
86
+ keys: [['Enter'], ['Space']],
87
+ preventDefault: false,
88
+ callback: event => {
89
+ const element = menuItems[navigator.getCurrentPage()];
90
+ if (element instanceof SelectUI) {
91
+ element.openOptions();
92
+ event.preventDefault();
93
+ }
94
+ if (element instanceof LinkUI) {
95
+ element.activate();
96
+ event.preventDefault();
97
+ }
98
+ if (!(element instanceof BaseUI)) {
99
+ event.preventDefault();
100
+ }
101
+ }
102
+ }], SHORTCUTS_MENU_CONTEXT);
103
+ }
104
+ mainMenu.addLocalHook('afterSubmenuOpen', addKeyboardShortcuts);
105
+ mainMenu.addLocalHook('afterOpen', addKeyboardShortcuts);
106
+
107
+ /**
108
+ * Focuses the menu and switches its shortcut context to that one which controls
109
+ * the focus navigation.
110
+ */
111
+ function listen() {
112
+ mainMenu.focus();
113
+ mainMenu.getKeyboardShortcutsCtrl().listen(SHORTCUTS_MENU_CONTEXT);
114
+ }
115
+ return {
116
+ ...navigator,
117
+ listen
118
+ };
119
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.createFocusNavigator = createFocusNavigator;
5
+ var _paginator = require("../../../utils/paginator");
6
+ var _element = require("../../../helpers/dom/element");
7
+ var _multipleSelect = require("../ui/multipleSelect");
8
+ /**
9
+ * Creates navigator for switching the focus of the filter's elements.
10
+ *
11
+ * @param {BaseUI[]} elements The elements to paginate to.
12
+ * @returns {Paginator}
13
+ */
14
+ function createFocusNavigator(elements) {
15
+ const navigator = (0, _paginator.createPaginator)({
16
+ initialPage: 0,
17
+ size: () => elements.length,
18
+ onItemSelect: (currentIndex, directItemChange) => {
19
+ const element = elements[currentIndex];
20
+ if (element instanceof _multipleSelect.MultipleSelectUI) {
21
+ return directItemChange;
22
+ }
23
+ if (element.element && !(0, _element.isVisible)(element.element)) {
24
+ return false;
25
+ }
26
+ element.focus();
27
+ }
28
+ });
29
+ return navigator;
30
+ }
@@ -0,0 +1,26 @@
1
+ import { createPaginator } from "../../../utils/paginator.mjs";
2
+ import { isVisible } from "../../../helpers/dom/element.mjs";
3
+ import { MultipleSelectUI } from "../ui/multipleSelect.mjs";
4
+ /**
5
+ * Creates navigator for switching the focus of the filter's elements.
6
+ *
7
+ * @param {BaseUI[]} elements The elements to paginate to.
8
+ * @returns {Paginator}
9
+ */
10
+ export function createFocusNavigator(elements) {
11
+ const navigator = createPaginator({
12
+ initialPage: 0,
13
+ size: () => elements.length,
14
+ onItemSelect: (currentIndex, directItemChange) => {
15
+ const element = elements[currentIndex];
16
+ if (element instanceof MultipleSelectUI) {
17
+ return directItemChange;
18
+ }
19
+ if (element.element && !isVisible(element.element)) {
20
+ return false;
21
+ }
22
+ element.focus();
23
+ }
24
+ });
25
+ return navigator;
26
+ }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
+ require("core-js/modules/es.error.cause.js");
4
5
  var _object = require("../../../helpers/object");
5
6
  var _localHooks = _interopRequireDefault(require("../../../mixins/localHooks"));
6
7
  var _eventManager = _interopRequireDefault(require("../../../eventManager"));
@@ -10,6 +11,9 @@ var C = _interopRequireWildcard(require("../../../i18n/constants"));
10
11
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
11
12
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
15
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
16
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
13
17
  const STATE_BUILT = 'built';
14
18
  const STATE_BUILDING = 'building';
15
19
  const EVENTS_TO_REGISTER = ['click', 'input', 'keydown', 'keypress', 'keyup', 'focus', 'blur', 'change'];
@@ -27,38 +31,43 @@ class BaseUI {
27
31
  wrapIt: true
28
32
  });
29
33
  }
34
+
35
+ /**
36
+ * Instance of Handsontable.
37
+ *
38
+ * @type {Core}
39
+ */
40
+
30
41
  constructor(hotInstance, options) {
31
- /**
32
- * Instance of Handsontable.
33
- *
34
- * @type {Core}
35
- */
36
- this.hot = hotInstance;
42
+ _defineProperty(this, "hot", void 0);
37
43
  /**
38
44
  * Instance of EventManager.
39
45
  *
40
46
  * @type {EventManager}
41
47
  */
42
- this.eventManager = new _eventManager.default(this);
48
+ _defineProperty(this, "eventManager", new _eventManager.default(this));
43
49
  /**
44
50
  * List of element options.
45
51
  *
46
52
  * @type {object}
47
53
  */
48
- this.options = (0, _object.extend)(BaseUI.DEFAULTS, options);
54
+ _defineProperty(this, "options", void 0);
49
55
  /**
50
56
  * Build root DOM element.
51
57
  *
52
58
  * @type {Element}
53
59
  * @private
54
60
  */
55
- this._element = this.hot.rootDocument.createElement(this.options.wrapIt ? 'div' : this.options.tagName);
61
+ _defineProperty(this, "_element", void 0);
56
62
  /**
57
63
  * Flag which determines build state of element.
58
64
  *
59
65
  * @type {string}
60
66
  */
61
- this.buildState = null;
67
+ _defineProperty(this, "buildState", void 0);
68
+ this.hot = hotInstance;
69
+ this.options = (0, _object.extend)(BaseUI.DEFAULTS, options);
70
+ this._element = this.hot.rootDocument.createElement(this.options.wrapIt ? 'div' : this.options.tagName);
62
71
  }
63
72
 
64
73
  /**
@@ -131,6 +140,16 @@ class BaseUI {
131
140
  if (!this.buildState) {
132
141
  this.buildState = STATE_BUILDING;
133
142
  }
143
+
144
+ // prevents "hot.unlisten()" call when clicked
145
+ // (https://github.com/handsontable/handsontable/blob/master/handsontable/src/tableView.js#L317-L321)
146
+ this._element.setAttribute('data-hot-input', true);
147
+ if (this.options.tabIndex !== undefined) {
148
+ this._element.setAttribute('tabindex', this.options.tabIndex);
149
+ }
150
+ if (this.options.role !== undefined) {
151
+ this._element.setAttribute('role', this.options.role);
152
+ }
134
153
  if (this.options.className) {
135
154
  (0, _element.addClass)(this._element, this.options.className);
136
155
  }
@@ -138,6 +157,10 @@ class BaseUI {
138
157
  (0, _array.arrayEach)(this.options.children, element => this._element.appendChild(element.element));
139
158
  } else if (this.options.wrapIt) {
140
159
  const element = this.hot.rootDocument.createElement(this.options.tagName);
160
+
161
+ // prevents "hot.unlisten()" call when clicked
162
+ // (https://github.com/handsontable/handsontable/blob/master/handsontable/src/tableView.js#L317-L321)
163
+ element.setAttribute('data-hot-input', true);
141
164
  (0, _object.objectEach)(this.options, (value, key) => {
142
165
  if (element[key] !== void 0 && key !== 'className' && key !== 'tagName' && key !== 'children') {
143
166
  element[key] = this.translateIfPossible(value);
@@ -191,6 +214,5 @@ class BaseUI {
191
214
  this._element = null;
192
215
  }
193
216
  }
194
- (0, _object.mixin)(BaseUI, _localHooks.default);
195
- var _default = BaseUI;
196
- exports.default = _default;
217
+ exports.BaseUI = BaseUI;
218
+ (0, _object.mixin)(BaseUI, _localHooks.default);