handsontable 0.0.0-next-8c1a357-20240805 → 0.0.0-next-121e5b4-20240807

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.

package/helpers/a11y.js CHANGED
@@ -21,6 +21,8 @@ const A11Y_MENU = () => ['role', 'menu'];
21
21
  exports.A11Y_MENU = A11Y_MENU;
22
22
  const A11Y_MENU_ITEM = () => ['role', 'menuitem'];
23
23
  exports.A11Y_MENU_ITEM = A11Y_MENU_ITEM;
24
+ const A11Y_MENU_ITEM_CHECKBOX = () => ['role', 'menuitemcheckbox'];
25
+ exports.A11Y_MENU_ITEM_CHECKBOX = A11Y_MENU_ITEM_CHECKBOX;
24
26
  const A11Y_COMBOBOX = () => ['role', 'combobox'];
25
27
  exports.A11Y_COMBOBOX = A11Y_COMBOBOX;
26
28
  const A11Y_LISTBOX = () => ['role', 'listbox'];
package/helpers/a11y.mjs CHANGED
@@ -8,6 +8,7 @@ export const A11Y_COLUMNHEADER = () => ['role', 'columnheader'];
8
8
  export const A11Y_ROW = () => ['role', 'row'];
9
9
  export const A11Y_MENU = () => ['role', 'menu'];
10
10
  export const A11Y_MENU_ITEM = () => ['role', 'menuitem'];
11
+ export const A11Y_MENU_ITEM_CHECKBOX = () => ['role', 'menuitemcheckbox'];
11
12
  export const A11Y_COMBOBOX = () => ['role', 'combobox'];
12
13
  export const A11Y_LISTBOX = () => ['role', 'listbox'];
13
14
  export const A11Y_OPTION = () => ['role', 'option'];
package/helpers/mixed.js CHANGED
@@ -134,7 +134,7 @@ const domMessages = {
134
134
  function _injectProductInfo(key, element) {
135
135
  const hasValidType = !isEmpty(key);
136
136
  const isNonCommercial = typeof key === 'string' && key.toLowerCase() === 'non-commercial-and-evaluation';
137
- const hotVersion = "0.0.0-next-8c1a357-20240805";
137
+ const hotVersion = "0.0.0-next-121e5b4-20240807";
138
138
  let keyValidityDate;
139
139
  let consoleMessageState = 'invalid';
140
140
  let domMessageState = 'invalid';
package/helpers/mixed.mjs CHANGED
@@ -124,7 +124,7 @@ const domMessages = {
124
124
  export function _injectProductInfo(key, element) {
125
125
  const hasValidType = !isEmpty(key);
126
126
  const isNonCommercial = typeof key === 'string' && key.toLowerCase() === 'non-commercial-and-evaluation';
127
- const hotVersion = "0.0.0-next-8c1a357-20240805";
127
+ const hotVersion = "0.0.0-next-121e5b4-20240807";
128
128
  let keyValidityDate;
129
129
  let consoleMessageState = 'invalid';
130
130
  let domMessageState = 'invalid';
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "url": "https://github.com/handsontable/handsontable/issues"
11
11
  },
12
12
  "author": "Handsoncode <hello@handsontable.com>",
13
- "version": "0.0.0-next-8c1a357-20240805",
13
+ "version": "0.0.0-next-121e5b4-20240807",
14
14
  "main": "index",
15
15
  "module": "index.mjs",
16
16
  "jsnext:main": "index.mjs",
@@ -31,11 +31,13 @@ function createMenuItemRenderer(mainTableHot) {
31
31
  const item = menuHot.getSourceDataAtRow(row);
32
32
  const wrapper = mainTableHot.rootDocument.createElement('div');
33
33
  const itemValue = typeof value === 'function' ? value.call(mainTableHot) : value;
34
+ const ariaLabel = typeof item.ariaLabel === 'function' ? item.ariaLabel.call(mainTableHot) : item.ariaLabel;
35
+ const ariaChecked = typeof item.ariaChecked === 'function' ? item.ariaChecked.call(mainTableHot) : item.ariaChecked;
34
36
  (0, _element.empty)(TD);
35
37
  (0, _element.addClass)(wrapper, 'htItemWrapper');
36
38
  if (mainTableHot.getSettings().ariaTags) {
37
39
  const isFocusable = !(0, _utils.isItemDisabled)(item, mainTableHot) && !(0, _utils.isItemSelectionDisabled)(item) && !(0, _utils.isItemSeparator)(item);
38
- (0, _element.setAttribute)(TD, [(0, _a11y.A11Y_MENU_ITEM)(), (0, _a11y.A11Y_LABEL)(itemValue), ...(isFocusable ? [(0, _a11y.A11Y_TABINDEX)(-1)] : []), ...((0, _utils.isItemDisabled)(item, mainTableHot) ? [(0, _a11y.A11Y_DISABLED)()] : []), ...((0, _utils.isItemSubMenu)(item) ? [(0, _a11y.A11Y_EXPANDED)(false)] : [])]);
40
+ (0, _element.setAttribute)(TD, [...((0, _utils.isItemCheckable)(item) ? [(0, _a11y.A11Y_MENU_ITEM_CHECKBOX)(), (0, _a11y.A11Y_LABEL)(ariaLabel), (0, _a11y.A11Y_CHECKED)(ariaChecked)] : [(0, _a11y.A11Y_MENU_ITEM)(), (0, _a11y.A11Y_LABEL)(itemValue)]), ...(isFocusable ? [(0, _a11y.A11Y_TABINDEX)(-1)] : []), ...((0, _utils.isItemDisabled)(item, mainTableHot) ? [(0, _a11y.A11Y_DISABLED)()] : []), ...((0, _utils.isItemSubMenu)(item) ? [(0, _a11y.A11Y_EXPANDED)(false)] : [])]);
39
41
  }
40
42
  TD.className = '';
41
43
  TD.appendChild(wrapper);
@@ -1,6 +1,6 @@
1
- import { isItemSubMenu, isItemDisabled, isItemSelectionDisabled, isItemSeparator } from "./utils.mjs";
1
+ import { isItemSubMenu, isItemDisabled, isItemSelectionDisabled, isItemSeparator, isItemCheckable } from "./utils.mjs";
2
2
  import { addClass, empty, fastInnerHTML, setAttribute } from "../../../helpers/dom/element.mjs";
3
- import { A11Y_DISABLED, A11Y_EXPANDED, A11Y_LABEL, A11Y_MENU_ITEM, A11Y_TABINDEX } from "../../../helpers/a11y.mjs";
3
+ import { A11Y_MENU_ITEM_CHECKBOX, A11Y_DISABLED, A11Y_EXPANDED, A11Y_LABEL, A11Y_MENU_ITEM, A11Y_TABINDEX, A11Y_CHECKED } from "../../../helpers/a11y.mjs";
4
4
  /**
5
5
  * Creates the menu renderer function.
6
6
  *
@@ -27,11 +27,13 @@ export function createMenuItemRenderer(mainTableHot) {
27
27
  const item = menuHot.getSourceDataAtRow(row);
28
28
  const wrapper = mainTableHot.rootDocument.createElement('div');
29
29
  const itemValue = typeof value === 'function' ? value.call(mainTableHot) : value;
30
+ const ariaLabel = typeof item.ariaLabel === 'function' ? item.ariaLabel.call(mainTableHot) : item.ariaLabel;
31
+ const ariaChecked = typeof item.ariaChecked === 'function' ? item.ariaChecked.call(mainTableHot) : item.ariaChecked;
30
32
  empty(TD);
31
33
  addClass(wrapper, 'htItemWrapper');
32
34
  if (mainTableHot.getSettings().ariaTags) {
33
35
  const isFocusable = !isItemDisabled(item, mainTableHot) && !isItemSelectionDisabled(item) && !isItemSeparator(item);
34
- setAttribute(TD, [A11Y_MENU_ITEM(), A11Y_LABEL(itemValue), ...(isFocusable ? [A11Y_TABINDEX(-1)] : []), ...(isItemDisabled(item, mainTableHot) ? [A11Y_DISABLED()] : []), ...(isItemSubMenu(item) ? [A11Y_EXPANDED(false)] : [])]);
36
+ setAttribute(TD, [...(isItemCheckable(item) ? [A11Y_MENU_ITEM_CHECKBOX(), A11Y_LABEL(ariaLabel), A11Y_CHECKED(ariaChecked)] : [A11Y_MENU_ITEM(), A11Y_LABEL(itemValue)]), ...(isFocusable ? [A11Y_TABINDEX(-1)] : []), ...(isItemDisabled(item, mainTableHot) ? [A11Y_DISABLED()] : []), ...(isItemSubMenu(item) ? [A11Y_EXPANDED(false)] : [])]);
35
37
  }
36
38
  TD.className = '';
37
39
  TD.appendChild(wrapper);
@@ -4,6 +4,7 @@ exports.__esModule = true;
4
4
  exports.filterSeparators = filterSeparators;
5
5
  exports.hasSubMenu = hasSubMenu;
6
6
  exports.isDisabled = isDisabled;
7
+ exports.isItemCheckable = isItemCheckable;
7
8
  exports.isItemDisabled = isItemDisabled;
8
9
  exports.isItemHidden = isItemHidden;
9
10
  exports.isItemSelectionDisabled = isItemSelectionDisabled;
@@ -174,4 +175,14 @@ function filterSeparators(items) {
174
175
  result = popSeparators(result, separator);
175
176
  result = removeDuplicatedSeparators(result);
176
177
  return result;
178
+ }
179
+
180
+ /**
181
+ * Check if the provided element presents the checkboxable menu item.
182
+ *
183
+ * @param {object} itemToTest Item element.
184
+ * @returns {boolean}
185
+ */
186
+ function isItemCheckable(itemToTest) {
187
+ return itemToTest.checkable === true;
177
188
  }
@@ -160,4 +160,14 @@ export function filterSeparators(items) {
160
160
  result = popSeparators(result, separator);
161
161
  result = removeDuplicatedSeparators(result);
162
162
  return result;
163
+ }
164
+
165
+ /**
166
+ * Check if the provided element presents the checkboxable menu item.
167
+ *
168
+ * @param {object} itemToTest Item element.
169
+ * @returns {boolean}
170
+ */
171
+ export function isItemCheckable(itemToTest) {
172
+ return itemToTest.checkable === true;
163
173
  }
@@ -9,6 +9,17 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
9
9
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
10
  const KEY = exports.KEY = 'alignment';
11
11
 
12
+ /**
13
+ * @param {object} hot The current Handsontable instance.
14
+ * @param {string} rawName The raw name of the menu item.
15
+ * @param {string} htClassName The class name to check.
16
+ * @returns {string} The value of aria-label parameter.
17
+ */
18
+ function ariaLabel(hot, rawName, htClassName) {
19
+ const checkboxState = (0, _utils.hasSelectionAClass)(hot, htClassName) ? hot.getTranslatedPhrase(C.CHECKBOX_CHECKED) : hot.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
20
+ return `${rawName} ${checkboxState.toLowerCase()}`;
21
+ }
22
+
12
23
  /**
13
24
  * @returns {object}
14
25
  */
@@ -34,15 +45,16 @@ function alignmentItem() {
34
45
  submenu: {
35
46
  items: [{
36
47
  key: `${KEY}:left`,
48
+ checkable: true,
49
+ ariaLabel() {
50
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT), 'htLeft');
51
+ },
52
+ ariaChecked() {
53
+ return (0, _utils.hasSelectionAClass)(this, 'htLeft');
54
+ },
37
55
  name() {
38
56
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT);
39
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
40
- const className = this.getCellMeta(row, col).className;
41
- if (className && className.indexOf('htLeft') !== -1) {
42
- return true;
43
- }
44
- });
45
- if (hasClass) {
57
+ if ((0, _utils.hasSelectionAClass)(this, 'htLeft')) {
46
58
  label = (0, _utils.markLabelAsSelected)(label);
47
59
  }
48
60
  return label;
@@ -59,15 +71,16 @@ function alignmentItem() {
59
71
  disabled: false
60
72
  }, {
61
73
  key: `${KEY}:center`,
74
+ checkable: true,
75
+ ariaLabel() {
76
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER), 'htCenter');
77
+ },
78
+ ariaChecked() {
79
+ return (0, _utils.hasSelectionAClass)(this, 'htCenter');
80
+ },
62
81
  name() {
63
82
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER);
64
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
65
- const className = this.getCellMeta(row, col).className;
66
- if (className && className.indexOf('htCenter') !== -1) {
67
- return true;
68
- }
69
- });
70
- if (hasClass) {
83
+ if ((0, _utils.hasSelectionAClass)(this, 'htCenter')) {
71
84
  label = (0, _utils.markLabelAsSelected)(label);
72
85
  }
73
86
  return label;
@@ -84,15 +97,16 @@ function alignmentItem() {
84
97
  disabled: false
85
98
  }, {
86
99
  key: `${KEY}:right`,
100
+ checkable: true,
101
+ ariaLabel() {
102
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT), 'htRight');
103
+ },
104
+ ariaChecked() {
105
+ return (0, _utils.hasSelectionAClass)(this, 'htRight');
106
+ },
87
107
  name() {
88
108
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT);
89
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
90
- const className = this.getCellMeta(row, col).className;
91
- if (className && className.indexOf('htRight') !== -1) {
92
- return true;
93
- }
94
- });
95
- if (hasClass) {
109
+ if ((0, _utils.hasSelectionAClass)(this, 'htRight')) {
96
110
  label = (0, _utils.markLabelAsSelected)(label);
97
111
  }
98
112
  return label;
@@ -109,15 +123,16 @@ function alignmentItem() {
109
123
  disabled: false
110
124
  }, {
111
125
  key: `${KEY}:justify`,
126
+ checkable: true,
127
+ ariaLabel() {
128
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY), 'htJustify');
129
+ },
130
+ ariaChecked() {
131
+ return (0, _utils.hasSelectionAClass)(this, 'htJustify');
132
+ },
112
133
  name() {
113
134
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY);
114
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
115
- const className = this.getCellMeta(row, col).className;
116
- if (className && className.indexOf('htJustify') !== -1) {
117
- return true;
118
- }
119
- });
120
- if (hasClass) {
135
+ if ((0, _utils.hasSelectionAClass)(this, 'htJustify')) {
121
136
  label = (0, _utils.markLabelAsSelected)(label);
122
137
  }
123
138
  return label;
@@ -136,15 +151,16 @@ function alignmentItem() {
136
151
  name: _separator.KEY
137
152
  }, {
138
153
  key: `${KEY}:top`,
154
+ checkable: true,
155
+ ariaLabel() {
156
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP), 'htTop');
157
+ },
158
+ ariaChecked() {
159
+ return (0, _utils.hasSelectionAClass)(this, 'htTop');
160
+ },
139
161
  name() {
140
162
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP);
141
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
142
- const className = this.getCellMeta(row, col).className;
143
- if (className && className.indexOf('htTop') !== -1) {
144
- return true;
145
- }
146
- });
147
- if (hasClass) {
163
+ if ((0, _utils.hasSelectionAClass)(this, 'htTop')) {
148
164
  label = (0, _utils.markLabelAsSelected)(label);
149
165
  }
150
166
  return label;
@@ -161,15 +177,16 @@ function alignmentItem() {
161
177
  disabled: false
162
178
  }, {
163
179
  key: `${KEY}:middle`,
180
+ checkable: true,
181
+ ariaLabel() {
182
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE), 'htMiddle');
183
+ },
184
+ ariaChecked() {
185
+ return (0, _utils.hasSelectionAClass)(this, 'htMiddle');
186
+ },
164
187
  name() {
165
188
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE);
166
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
167
- const className = this.getCellMeta(row, col).className;
168
- if (className && className.indexOf('htMiddle') !== -1) {
169
- return true;
170
- }
171
- });
172
- if (hasClass) {
189
+ if ((0, _utils.hasSelectionAClass)(this, 'htMiddle')) {
173
190
  label = (0, _utils.markLabelAsSelected)(label);
174
191
  }
175
192
  return label;
@@ -186,15 +203,16 @@ function alignmentItem() {
186
203
  disabled: false
187
204
  }, {
188
205
  key: `${KEY}:bottom`,
206
+ checkable: true,
207
+ ariaLabel() {
208
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM), 'htBottom');
209
+ },
210
+ ariaChecked() {
211
+ return (0, _utils.hasSelectionAClass)(this, 'htBottom');
212
+ },
189
213
  name() {
190
214
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM);
191
- const hasClass = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => {
192
- const className = this.getCellMeta(row, col).className;
193
- if (className && className.indexOf('htBottom') !== -1) {
194
- return true;
195
- }
196
- });
197
- if (hasClass) {
215
+ if ((0, _utils.hasSelectionAClass)(this, 'htBottom')) {
198
216
  label = (0, _utils.markLabelAsSelected)(label);
199
217
  }
200
218
  return label;
@@ -1,8 +1,19 @@
1
- import { align, getAlignmentClasses, checkSelectionConsistency, markLabelAsSelected } from "../utils.mjs";
1
+ import { align, getAlignmentClasses, markLabelAsSelected, hasSelectionAClass } from "../utils.mjs";
2
2
  import { KEY as SEPARATOR } from "./separator.mjs";
3
3
  import * as C from "../../../i18n/constants.mjs";
4
4
  export const KEY = 'alignment';
5
5
 
6
+ /**
7
+ * @param {object} hot The current Handsontable instance.
8
+ * @param {string} rawName The raw name of the menu item.
9
+ * @param {string} htClassName The class name to check.
10
+ * @returns {string} The value of aria-label parameter.
11
+ */
12
+ function ariaLabel(hot, rawName, htClassName) {
13
+ const checkboxState = hasSelectionAClass(hot, htClassName) ? hot.getTranslatedPhrase(C.CHECKBOX_CHECKED) : hot.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
14
+ return `${rawName} ${checkboxState.toLowerCase()}`;
15
+ }
16
+
6
17
  /**
7
18
  * @returns {object}
8
19
  */
@@ -28,15 +39,16 @@ export default function alignmentItem() {
28
39
  submenu: {
29
40
  items: [{
30
41
  key: `${KEY}:left`,
42
+ checkable: true,
43
+ ariaLabel() {
44
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT), 'htLeft');
45
+ },
46
+ ariaChecked() {
47
+ return hasSelectionAClass(this, 'htLeft');
48
+ },
31
49
  name() {
32
50
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_LEFT);
33
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
34
- const className = this.getCellMeta(row, col).className;
35
- if (className && className.indexOf('htLeft') !== -1) {
36
- return true;
37
- }
38
- });
39
- if (hasClass) {
51
+ if (hasSelectionAClass(this, 'htLeft')) {
40
52
  label = markLabelAsSelected(label);
41
53
  }
42
54
  return label;
@@ -53,15 +65,16 @@ export default function alignmentItem() {
53
65
  disabled: false
54
66
  }, {
55
67
  key: `${KEY}:center`,
68
+ checkable: true,
69
+ ariaLabel() {
70
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER), 'htCenter');
71
+ },
72
+ ariaChecked() {
73
+ return hasSelectionAClass(this, 'htCenter');
74
+ },
56
75
  name() {
57
76
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_CENTER);
58
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
59
- const className = this.getCellMeta(row, col).className;
60
- if (className && className.indexOf('htCenter') !== -1) {
61
- return true;
62
- }
63
- });
64
- if (hasClass) {
77
+ if (hasSelectionAClass(this, 'htCenter')) {
65
78
  label = markLabelAsSelected(label);
66
79
  }
67
80
  return label;
@@ -78,15 +91,16 @@ export default function alignmentItem() {
78
91
  disabled: false
79
92
  }, {
80
93
  key: `${KEY}:right`,
94
+ checkable: true,
95
+ ariaLabel() {
96
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT), 'htRight');
97
+ },
98
+ ariaChecked() {
99
+ return hasSelectionAClass(this, 'htRight');
100
+ },
81
101
  name() {
82
102
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_RIGHT);
83
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
84
- const className = this.getCellMeta(row, col).className;
85
- if (className && className.indexOf('htRight') !== -1) {
86
- return true;
87
- }
88
- });
89
- if (hasClass) {
103
+ if (hasSelectionAClass(this, 'htRight')) {
90
104
  label = markLabelAsSelected(label);
91
105
  }
92
106
  return label;
@@ -103,15 +117,16 @@ export default function alignmentItem() {
103
117
  disabled: false
104
118
  }, {
105
119
  key: `${KEY}:justify`,
120
+ checkable: true,
121
+ ariaLabel() {
122
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY), 'htJustify');
123
+ },
124
+ ariaChecked() {
125
+ return hasSelectionAClass(this, 'htJustify');
126
+ },
106
127
  name() {
107
128
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_JUSTIFY);
108
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
109
- const className = this.getCellMeta(row, col).className;
110
- if (className && className.indexOf('htJustify') !== -1) {
111
- return true;
112
- }
113
- });
114
- if (hasClass) {
129
+ if (hasSelectionAClass(this, 'htJustify')) {
115
130
  label = markLabelAsSelected(label);
116
131
  }
117
132
  return label;
@@ -130,15 +145,16 @@ export default function alignmentItem() {
130
145
  name: SEPARATOR
131
146
  }, {
132
147
  key: `${KEY}:top`,
148
+ checkable: true,
149
+ ariaLabel() {
150
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP), 'htTop');
151
+ },
152
+ ariaChecked() {
153
+ return hasSelectionAClass(this, 'htTop');
154
+ },
133
155
  name() {
134
156
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_TOP);
135
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
136
- const className = this.getCellMeta(row, col).className;
137
- if (className && className.indexOf('htTop') !== -1) {
138
- return true;
139
- }
140
- });
141
- if (hasClass) {
157
+ if (hasSelectionAClass(this, 'htTop')) {
142
158
  label = markLabelAsSelected(label);
143
159
  }
144
160
  return label;
@@ -155,15 +171,16 @@ export default function alignmentItem() {
155
171
  disabled: false
156
172
  }, {
157
173
  key: `${KEY}:middle`,
174
+ checkable: true,
175
+ ariaLabel() {
176
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE), 'htMiddle');
177
+ },
178
+ ariaChecked() {
179
+ return hasSelectionAClass(this, 'htMiddle');
180
+ },
158
181
  name() {
159
182
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_MIDDLE);
160
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
161
- const className = this.getCellMeta(row, col).className;
162
- if (className && className.indexOf('htMiddle') !== -1) {
163
- return true;
164
- }
165
- });
166
- if (hasClass) {
183
+ if (hasSelectionAClass(this, 'htMiddle')) {
167
184
  label = markLabelAsSelected(label);
168
185
  }
169
186
  return label;
@@ -180,15 +197,16 @@ export default function alignmentItem() {
180
197
  disabled: false
181
198
  }, {
182
199
  key: `${KEY}:bottom`,
200
+ checkable: true,
201
+ ariaLabel() {
202
+ return ariaLabel(this, this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM), 'htBottom');
203
+ },
204
+ ariaChecked() {
205
+ return hasSelectionAClass(this, 'htBottom');
206
+ },
183
207
  name() {
184
208
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_ALIGNMENT_BOTTOM);
185
- const hasClass = checkSelectionConsistency(this.getSelectedRange(), (row, col) => {
186
- const className = this.getCellMeta(row, col).className;
187
- if (className && className.indexOf('htBottom') !== -1) {
188
- return true;
189
- }
190
- });
191
- if (hasClass) {
209
+ if (hasSelectionAClass(this, 'htBottom')) {
192
210
  label = markLabelAsSelected(label);
193
211
  }
194
212
  return label;
@@ -15,6 +15,17 @@ const KEY = exports.KEY = 'make_read_only';
15
15
  function readOnlyItem() {
16
16
  return {
17
17
  key: KEY,
18
+ checkable: true,
19
+ ariaChecked() {
20
+ const atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
21
+ return atLeastOneReadOnly;
22
+ },
23
+ ariaLabel() {
24
+ const rawName = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
25
+ const atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
26
+ const checkboxState = atLeastOneReadOnly ? this.getTranslatedPhrase(C.CHECKBOX_CHECKED) : this.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
27
+ return `${rawName} ${checkboxState.toLowerCase()}`;
28
+ },
18
29
  name() {
19
30
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
20
31
  const atLeastOneReadOnly = (0, _utils.checkSelectionConsistency)(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
@@ -9,6 +9,17 @@ export const KEY = 'make_read_only';
9
9
  export default function readOnlyItem() {
10
10
  return {
11
11
  key: KEY,
12
+ checkable: true,
13
+ ariaChecked() {
14
+ const atLeastOneReadOnly = checkSelectionConsistency(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
15
+ return atLeastOneReadOnly;
16
+ },
17
+ ariaLabel() {
18
+ const rawName = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
19
+ const atLeastOneReadOnly = checkSelectionConsistency(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
20
+ const checkboxState = atLeastOneReadOnly ? this.getTranslatedPhrase(C.CHECKBOX_CHECKED) : this.getTranslatedPhrase(C.CHECKBOX_UNCHECKED);
21
+ return `${rawName} ${checkboxState.toLowerCase()}`;
22
+ },
12
23
  name() {
13
24
  let label = this.getTranslatedPhrase(C.CONTEXTMENU_ITEMS_READ_ONLY);
14
25
  const atLeastOneReadOnly = checkSelectionConsistency(this.getSelectedRange(), (row, col) => this.getCellMeta(row, col).readOnly);
@@ -4,7 +4,9 @@ exports.__esModule = true;
4
4
  exports.align = align;
5
5
  exports.checkSelectionConsistency = checkSelectionConsistency;
6
6
  exports.getAlignmentClasses = getAlignmentClasses;
7
+ exports.getAlignmentComparatorByClass = getAlignmentComparatorByClass;
7
8
  exports.getDocumentOffsetByElement = getDocumentOffsetByElement;
9
+ exports.hasSelectionAClass = hasSelectionAClass;
8
10
  exports.markLabelAsSelected = markLabelAsSelected;
9
11
  exports.prepareHorizontalAlignClass = prepareHorizontalAlignClass;
10
12
  exports.prepareVerticalAlignClass = prepareVerticalAlignClass;
@@ -151,4 +153,28 @@ function getDocumentOffsetByElement(elementToCheck, baseDocument) {
151
153
  offset.left = left;
152
154
  }
153
155
  return offset;
156
+ }
157
+
158
+ /**
159
+ * Prepares comparator function consumable by checkSelectionConsistency
160
+ * Comparator function checks if the cell has the provided class name.
161
+ *
162
+ * @param {string} htClassName The class name to check.
163
+ * @returns {Function} Returns the comparator function.
164
+ * Use with .bind, .call or .apply to pass the Handsontable instance.
165
+ */
166
+ function getAlignmentComparatorByClass(htClassName) {
167
+ return function (row, col) {
168
+ const className = this.getCellMeta(row, col).className;
169
+ return className && className.indexOf(htClassName) !== -1;
170
+ };
171
+ }
172
+
173
+ /**
174
+ * @param {object} hot Handsontable instance.
175
+ * @param {string} htClassName The class name to check.
176
+ * @returns {boolean} Returns true if at least one cell has the provided class name.
177
+ */
178
+ function hasSelectionAClass(hot, htClassName) {
179
+ return checkSelectionConsistency(hot.getSelectedRange(), getAlignmentComparatorByClass(htClassName).bind(hot));
154
180
  }
@@ -141,4 +141,28 @@ export function getDocumentOffsetByElement(elementToCheck, baseDocument) {
141
141
  offset.left = left;
142
142
  }
143
143
  return offset;
144
+ }
145
+
146
+ /**
147
+ * Prepares comparator function consumable by checkSelectionConsistency
148
+ * Comparator function checks if the cell has the provided class name.
149
+ *
150
+ * @param {string} htClassName The class name to check.
151
+ * @returns {Function} Returns the comparator function.
152
+ * Use with .bind, .call or .apply to pass the Handsontable instance.
153
+ */
154
+ export function getAlignmentComparatorByClass(htClassName) {
155
+ return function (row, col) {
156
+ const className = this.getCellMeta(row, col).className;
157
+ return className && className.indexOf(htClassName) !== -1;
158
+ };
159
+ }
160
+
161
+ /**
162
+ * @param {object} hot Handsontable instance.
163
+ * @param {string} htClassName The class name to check.
164
+ * @returns {boolean} Returns true if at least one cell has the provided class name.
165
+ */
166
+ export function hasSelectionAClass(hot, htClassName) {
167
+ return checkSelectionConsistency(hot.getSelectedRange(), getAlignmentComparatorByClass(htClassName).bind(hot));
144
168
  }