wunderbaum 0.0.9 → 0.1.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.
package/src/types.ts CHANGED
@@ -23,11 +23,18 @@ export type NodeVisitResponse = "skip" | boolean | void;
23
23
  export type NodeVisitCallback = (node: WunderbaumNode) => NodeVisitResponse;
24
24
 
25
25
  // type WithWildcards<T> = T & { [key: string]: unknown };
26
+
27
+ /* -----------------------------------------------------------------------------
28
+ * EVENT CALLBACK TYPES
29
+ * ---------------------------------------------------------------------------*/
30
+
26
31
  export interface WbTreeEventType {
27
32
  /** Name of the event. */
28
33
  type: string;
29
- /** The affected tree. */
34
+ /** The affected tree instance. */
30
35
  tree: Wunderbaum;
36
+ /** Exposed utility module methods. */
37
+ util: any;
31
38
  /** Originating HTML event, e.g. `click` if any. */
32
39
  event?: Event;
33
40
  // [key: string]: unknown;
@@ -43,6 +50,63 @@ export interface WbNodeEventType extends WbTreeEventType {
43
50
  typeInfo: NodeTypeDefinition;
44
51
  }
45
52
 
53
+ export interface WbActivateEventType extends WbNodeEventType {
54
+ prevNode: WunderbaumNode;
55
+ /** The original event. */
56
+ event: Event;
57
+ }
58
+
59
+ export interface WbChangeEventType extends WbNodeEventType {
60
+ info: WbEventInfo;
61
+ inputElem: HTMLInputElement;
62
+ inputValue: any;
63
+ }
64
+
65
+ export interface WbClickEventType extends WbTreeEventType {
66
+ /** The original event. */
67
+ event: MouseEvent;
68
+ node: WunderbaumNode;
69
+ info: WbEventInfo;
70
+ }
71
+
72
+ export interface WbErrorEventType extends WbNodeEventType {
73
+ error: any;
74
+ }
75
+
76
+ export interface WbDeactivateEventType extends WbNodeEventType {
77
+ nextNode: WunderbaumNode;
78
+ /** The original event. */
79
+ event: Event;
80
+ }
81
+
82
+ export interface WbEnhanceTitleEventType extends WbNodeEventType {
83
+ titleSpan: HTMLSpanElement;
84
+ }
85
+
86
+ export interface WbFocusEventType extends WbTreeEventType {
87
+ /** The original event. */
88
+ event: FocusEvent;
89
+ /** True if `focusin`, false if `focusout`. */
90
+ flag: boolean;
91
+ }
92
+
93
+ export interface WbKeydownEventType extends WbTreeEventType {
94
+ /** The original event. */
95
+ event: KeyboardEvent;
96
+ node: WunderbaumNode;
97
+ info: WbEventInfo;
98
+ /** Canical name of the key including modifiers. @see {@link eventToString} */
99
+ eventName: string;
100
+ }
101
+
102
+ export interface WbInitEventType extends WbTreeEventType {
103
+ error?: any;
104
+ }
105
+
106
+ export interface WbReceiveEventType extends WbNodeEventType {
107
+ response: any;
108
+ }
109
+
46
110
  export interface WbRenderEventType extends WbNodeEventType {
47
111
  /**
48
112
  * True if the node's markup was not yet created. In this case the render
@@ -50,24 +114,22 @@ export interface WbRenderEventType extends WbNodeEventType {
50
114
  * values according to to current node data).
51
115
  */
52
116
  isNew: boolean;
53
- /** True if the node only displays the title and is stretched over all remaining columns. */
54
- isColspan: boolean;
55
- // /** */
56
- // isDataChange: boolean;
57
117
  /** The node's `<span class='wb-node'>` element. */
58
118
  nodeElem: HTMLSpanElement;
119
+ /** True if the node only displays the title and is stretched over all remaining columns. */
120
+ isColspan: boolean;
59
121
  /**
60
122
  * Array of node's `<span class='wb-col'>` elements.
61
123
  * The first element is `<span class='wb-node wb-col'>`, which contains the
62
124
  * node title and icon (`idx: 0`, id: '*'`).
63
125
  */
64
- allColInfosById: ColumnEventInfos;
126
+ allColInfosById: ColumnEventInfoMap;
65
127
  /**
66
128
  * Array of node's `<span class='wb-node'>` elements, *that should be rendered*.
67
129
  * In contrast to `allColInfosById`, the node title is not part of this array.
68
130
  * If node.isColspan() is true, this array is empty (`[]`).
69
131
  */
70
- renderColInfosById: ColumnEventInfos;
132
+ renderColInfosById: ColumnEventInfoMap;
71
133
  }
72
134
 
73
135
  /**
@@ -77,13 +139,13 @@ export interface WbRenderEventType extends WbNodeEventType {
77
139
  export interface NodeTypeDefinition {
78
140
  // /** Type ID that matches `node.type`. */
79
141
  // id: string;
80
- /** En/disable checkbox for matching nodes.*/
142
+ /** En/disable checkbox for matching nodes. */
81
143
  checkbox?: boolean | BoolOrStringOptionResolver;
82
- /** En/disable checkbox for matching nodes.*/
83
- colspan?: boolean | BoolOptionResolver;
84
- /** Optional class names that are added to all `div.wb-row` elements of matching nodes.*/
144
+ /** Optional class names that are added to all `div.wb-row` elements of matching nodes. */
85
145
  classes?: string;
86
- /**Default icon for matching nodes.*/
146
+ /** Only show title and hide other columns if any. */
147
+ colspan?: boolean | BoolOptionResolver;
148
+ /** Default icon for matching nodes. */
87
149
  icon?: boolean | string | BoolOrStringOptionResolver;
88
150
  /**
89
151
  * See also {@link WunderbaumNode.getOption|WunderbaumNode.getOption()}
@@ -94,26 +156,19 @@ export interface NodeTypeDefinition {
94
156
  // _any: any;
95
157
  }
96
158
 
97
- // /**
98
- // * Contains the node's type information, i.e. `tree.types[node.type]` if
99
- // * defined. @see {@link Wunderbaum.types}
100
- // */
101
- // export type NodeTypeInfo = {
102
- // icon?: string;
103
- // classes?: string;
104
- // // and more
105
- // [key: string]: unknown;
106
- // };
107
- export type NodeTypeDefinitions = { [type: string]: NodeTypeDefinition };
159
+ /* -----------------------------------------------------------------------------
160
+ * DATA TYPES
161
+ * ---------------------------------------------------------------------------*/
162
+
163
+ export type NodeTypeDefinitionMap = { [type: string]: NodeTypeDefinition };
108
164
 
109
165
  /**
166
+ * Column type definitions.
110
167
  * @see {@link `Wunderbaum.columns`}
111
168
  */
112
169
  export interface ColumnDefinition {
113
170
  /** Column ID as defined in `tree.columns` definition ("*" for title column). */
114
171
  id: string;
115
- // /** */
116
- // idx: number;
117
172
  /** Column header (defaults to id) */
118
173
  title: string;
119
174
  /** Column header tooltip (optional) */
@@ -137,8 +192,12 @@ export interface ColumnDefinition {
137
192
  _widthPx?: number;
138
193
  _ofsPx?: number;
139
194
  }
195
+
140
196
  export type ColumnDefinitionList = Array<ColumnDefinition>;
141
197
 
198
+ /**
199
+ * Column information (passed to the `render` event).
200
+ */
142
201
  export interface ColumnEventInfo {
143
202
  /** Column ID as defined in `tree.columns` definition ("*" for title column). */
144
203
  id: string;
@@ -149,11 +208,33 @@ export interface ColumnEventInfo {
149
208
  /** The value of `tree.columns[]` for the current index. */
150
209
  info: ColumnDefinition;
151
210
  }
152
- export type ColumnEventInfos = { [colId: string]: ColumnEventInfo };
153
211
 
154
- export type WbTreeCallbackType = (e: WbTreeEventType) => any;
155
- export type WbNodeCallbackType = (e: WbNodeEventType) => any;
156
- export type WbRenderCallbackType = (e: WbRenderEventType) => void;
212
+ export type ColumnEventInfoMap = { [colId: string]: ColumnEventInfo };
213
+
214
+ /**
215
+ * Additional inforation derived from mouse or keyboard events.
216
+ * @see {@link Wunderbaum.getEventInfo}
217
+ */
218
+ export interface WbEventInfo {
219
+ /** The tree instance. */
220
+ tree: Wunderbaum;
221
+ /** The affected node instance instance if any. */
222
+ node: WunderbaumNode | null;
223
+ /** The affected part of the node span (e.g. title, expander, ...). */
224
+ region: NodeRegion;
225
+ /** The definition of the affected column if any. */
226
+ colDef?: ColumnDefinition;
227
+ /** The index of affected column or -1. */
228
+ colIdx: number;
229
+ /** The column definition ID of affected column if any. */
230
+ colId?: string;
231
+ /** The affected column's span tag if any. */
232
+ colElem?: HTMLSpanElement;
233
+ }
234
+
235
+ // export type WbTreeCallbackType = (e: WbTreeEventType) => any;
236
+ // export type WbNodeCallbackType = (e: WbNodeEventType) => any;
237
+ // export type WbRenderCallbackType = (e: WbRenderEventType) => void;
157
238
 
158
239
  export type FilterModeType = null | "dim" | "hide";
159
240
  export type ApplyCommandType =
@@ -211,7 +292,7 @@ export enum NodeStatusType {
211
292
  }
212
293
 
213
294
  /** Define the subregion of a node, where an event occurred. */
214
- export enum TargetType {
295
+ export enum NodeRegion {
215
296
  unknown = "",
216
297
  checkbox = "checkbox",
217
298
  column = "column",
@@ -221,6 +302,18 @@ export enum TargetType {
221
302
  title = "title",
222
303
  }
223
304
 
305
+ /** Initial navigation mode and possible transition. */
306
+ export enum NavModeEnum {
307
+ startRow = "startRow", // Start with row mode, but allow cell-nav mode
308
+ cell = "cell", // Cell-nav mode only
309
+ startCell = "startCell", // Start in cell-nav mode, but allow row mode
310
+ row = "row", // Row mode only
311
+ }
312
+
313
+ /* -----------------------------------------------------------------------------
314
+ * METHOD OPTIONS TYPES
315
+ * ---------------------------------------------------------------------------*/
316
+
224
317
  /** Possible values for {@link WunderbaumNode.addChildren()}. */
225
318
  export interface AddChildrenOptions {
226
319
  /** Insert children before this node (or index)
@@ -237,6 +330,11 @@ export interface AddChildrenOptions {
237
330
  _level?: number;
238
331
  }
239
332
 
333
+ /** Possible values for {@link Wunderbaum.applyCommand()} and {@link WunderbaumNode.applyCommand()}. */
334
+ export interface ApplyCommandOptions {
335
+ [key: string]: unknown;
336
+ }
337
+
240
338
  /** Possible values for {@link Wunderbaum.expandAll()} and {@link WunderbaumNode.expandAll()}. */
241
339
  export interface ExpandAllOptions {
242
340
  /** Restrict expand level @default 99 */
@@ -247,6 +345,17 @@ export interface ExpandAllOptions {
247
345
  force?: boolean;
248
346
  }
249
347
 
348
+ /** Possible values for {@link Wunderbaum.filterNodes()} and {@link Wunderbaum.filterBranches()}. */
349
+ export interface FilterNodesOptions {
350
+ mode?: string;
351
+ leavesOnly?: boolean;
352
+ fuzzy?: boolean;
353
+ highlight?: boolean;
354
+ hideExpanders?: boolean;
355
+ autoExpand?: boolean;
356
+ noData?: boolean;
357
+ }
358
+
250
359
  /** Possible values for {@link WunderbaumNode.makeVisible()}. */
251
360
  export interface MakeVisibleOptions {
252
361
  /** Do not animate expand (currently not implemented). @default false */
@@ -257,12 +366,21 @@ export interface MakeVisibleOptions {
257
366
  noEvents?: boolean;
258
367
  }
259
368
 
260
- /** Initial navigation mode and possible transition. */
261
- export enum NavigationOptions {
262
- startRow = "startRow", // Start with row mode, but allow cell-nav mode
263
- cell = "cell", // Cell-nav mode only
264
- startCell = "startCell", // Start in cell-nav mode, but allow row mode
265
- row = "row", // Row mode only
369
+ /** Possible values for {@link Wunderbaum.navigate()}. */
370
+ export interface NavigateOptions {
371
+ activate?: boolean;
372
+ event?: Event;
373
+ }
374
+
375
+ /** Possible values for {@link WunderbaumNode.render()}. */
376
+ export interface RenderOptions {
377
+ change?: ChangeType;
378
+ after?: any;
379
+ isNew?: boolean;
380
+ preventScroll?: boolean;
381
+ isDataChange?: boolean;
382
+ top?: number;
383
+ resizeCols?: boolean;
266
384
  }
267
385
 
268
386
  /** Possible values for {@link scrollIntoView()}. */
@@ -337,9 +455,25 @@ export interface SetStatusOptions {
337
455
  details?: string;
338
456
  }
339
457
 
458
+ /** Possible values for {@link Wunderbaum.updateColumns()}. */
459
+ export interface UpdateColumnsOptions {
460
+ calculateCols?: boolean;
461
+ updateRows?: boolean;
462
+ }
463
+
464
+ /** Possible values for {@link Wunderbaum.visitRows()} and {@link Wunderbaum.visitRowsUp()}. */
465
+ export interface VisitRowsOptions {
466
+ reverse?: boolean;
467
+ includeSelf?: boolean;
468
+ includeHidden?: boolean;
469
+ wrap?: boolean;
470
+ start?: WunderbaumNode | null;
471
+ }
472
+
340
473
  /* -----------------------------------------------------------------------------
341
474
  * wb_ext_dnd
342
- */
475
+ * ---------------------------------------------------------------------------*/
476
+
343
477
  export type DropRegionType = "over" | "before" | "after";
344
478
  export type DropRegionTypeSet = Set<DropRegionType>;
345
479
  // type AllowedDropRegionType =
package/src/wb_ext_dnd.ts CHANGED
@@ -144,7 +144,7 @@ export class DndExtension extends WunderbaumExtension {
144
144
  protected autoScroll(event: DragEvent): number {
145
145
  let tree = this.tree,
146
146
  dndOpts = tree.options.dnd!,
147
- sp = tree.scrollContainerElement,
147
+ sp = tree.listContainerElement,
148
148
  sensitivity = dndOpts.scrollSensitivity,
149
149
  speed = dndOpts.scrollSpeed,
150
150
  scrolled = 0;
@@ -196,7 +196,7 @@ export class EditExtension extends WunderbaumExtension {
196
196
  // (we also treat a `true` return value as 'use default'):
197
197
  if (inputHtml === true || !inputHtml) {
198
198
  const title = escapeHtml(node.title);
199
- inputHtml = `<input type=text class="wb-input-edit" value="${title}" required autocorrect=off>`;
199
+ inputHtml = `<input type=text class="wb-input-edit" tabindex=-1 value="${title}" required autocorrect=off>`;
200
200
  }
201
201
  const titleSpan = node
202
202
  .getColElem(0)!
@@ -236,11 +236,11 @@ export class EditExtension extends WunderbaumExtension {
236
236
  * @param apply
237
237
  * @param opts.canKeepOpen
238
238
  */
239
- _stopEditTitle(apply: boolean, opts: any) {
239
+ _stopEditTitle(apply: boolean, options: any) {
240
240
  const focusElem = document.activeElement as HTMLInputElement;
241
241
  let newValue = focusElem ? getValueFromElem(focusElem) : null;
242
242
  const node = this.curEditNode;
243
- const forceClose = !!opts.forceClose;
243
+ const forceClose = !!options.forceClose;
244
244
  const validity = this.getPluginOption("validity");
245
245
 
246
246
  if (newValue && this.getPluginOption("trim")) {
@@ -250,7 +250,7 @@ export class EditExtension extends WunderbaumExtension {
250
250
  this.tree.logDebug("stopEditTitle: not in edit mode.");
251
251
  return;
252
252
  }
253
- node.logDebug(`stopEditTitle(${apply})`, opts, focusElem, newValue);
253
+ node.logDebug(`stopEditTitle(${apply})`, options, focusElem, newValue);
254
254
 
255
255
  if (apply && newValue !== null && newValue !== node.title) {
256
256
  const errMsg = focusElem.validationMessage;
@@ -283,21 +283,23 @@ export class EditExtension extends WunderbaumExtension {
283
283
  return;
284
284
  }
285
285
  node?.setTitle(newValue);
286
- this.curEditNode!.render();
286
+ // NOTE: At least on Safari, this render call triggers a scroll event
287
+ // probably because the focused input is replaced.
288
+ this.curEditNode!.render({ preventScroll: true });
287
289
  this.curEditNode = null;
288
290
  this.relatedNode = null;
289
291
  this.tree.setFocus(); // restore focus that was in the input element
290
292
  })
291
293
  .catch((err) => {
292
- // this.curEditNode!.render();
293
- // this.curEditNode = null;
294
- // this.relatedNode = null;
294
+ node.logError(err);
295
295
  });
296
296
  // Trigger 'change' event for embedded `<input>`
297
297
  // focusElem.blur();
298
298
  } else {
299
299
  // Discard the embedded `<input>`
300
- this.curEditNode!.render();
300
+ // NOTE: At least on Safari, this render call triggers a scroll event
301
+ // probably because the focused input is replaced.
302
+ this.curEditNode!.render({ preventScroll: true });
301
303
  this.curEditNode = null;
302
304
  this.relatedNode = null;
303
305
  // We discarded the <input>, so we have to acquire keyboard focus again
@@ -11,7 +11,11 @@ import {
11
11
  extend,
12
12
  onEvent,
13
13
  } from "./util";
14
- import { NodeFilterCallback, NodeStatusType } from "./types";
14
+ import {
15
+ FilterNodesOptions,
16
+ NodeFilterCallback,
17
+ NodeStatusType,
18
+ } from "./types";
15
19
  import { Wunderbaum } from "./wunderbaum";
16
20
  import { WunderbaumNode } from "./wb_node";
17
21
  import { WunderbaumExtension } from "./wb_extension_base";
@@ -243,19 +247,25 @@ export class FilterExtension extends WunderbaumExtension {
243
247
  /**
244
248
  * [ext-filter] Dim or hide nodes.
245
249
  *
246
- * @param {boolean} [opts={autoExpand: false, leavesOnly: false}]
250
+ * @param {boolean} [options={autoExpand: false, leavesOnly: false}]
247
251
  */
248
- filterNodes(filter: string | NodeFilterCallback, opts: any) {
249
- return this._applyFilterNoUpdate(filter, false, opts);
252
+ filterNodes(
253
+ filter: string | NodeFilterCallback,
254
+ options: FilterNodesOptions
255
+ ) {
256
+ return this._applyFilterNoUpdate(filter, false, options);
250
257
  }
251
258
 
252
259
  /**
253
260
  * [ext-filter] Dim or hide whole branches.
254
261
  *
255
- * @param {boolean} [opts={autoExpand: false}]
262
+ * @param {boolean} [options={autoExpand: false}]
256
263
  */
257
- filterBranches(filter: string | NodeFilterCallback, opts: any) {
258
- return this._applyFilterNoUpdate(filter, true, opts);
264
+ filterBranches(
265
+ filter: string | NodeFilterCallback,
266
+ options: FilterNodesOptions
267
+ ) {
268
+ return this._applyFilterNoUpdate(filter, true, options);
259
269
  }
260
270
 
261
271
  /**
@@ -4,7 +4,7 @@
4
4
  * @VERSION, @DATE (https://github.com/mar10/wunderbaum)
5
5
  */
6
6
 
7
- import { NavigationOptions } from "./types";
7
+ import { NavModeEnum } from "./types";
8
8
  import { eventToString } from "./util";
9
9
  import { Wunderbaum } from "./wunderbaum";
10
10
  import { WunderbaumNode } from "./wb_node";
@@ -47,7 +47,7 @@ export class KeynavExtension extends WunderbaumExtension {
47
47
  opts = data.options,
48
48
  activate = !event.ctrlKey || opts.autoActivate,
49
49
  curInput = this._getEmbeddedInputElem(event.target),
50
- navModeOption = opts.navigationModeOption as NavigationOptions;
50
+ navModeOption = opts.navigationModeOption as NavModeEnum;
51
51
  // isCellEditMode = tree.navMode === NavigationMode.cellEdit;
52
52
 
53
53
  let focusNode,
@@ -122,20 +122,30 @@ export class KeynavExtension extends WunderbaumExtension {
122
122
 
123
123
  // Pre-Evaluate expand/collapse action for LEFT/RIGHT
124
124
  switch (eventName) {
125
+ case "Enter":
126
+ if (node.isActive()) {
127
+ if (node.isExpanded()) {
128
+ eventName = "Subtract"; // callapse
129
+ } else if (node.isExpandable(true)) {
130
+ eventName = "Add"; // expand
131
+ }
132
+ }
133
+ break;
125
134
  case "ArrowLeft":
126
135
  if (node.expanded) {
127
136
  eventName = "Subtract"; // collapse
128
137
  }
129
138
  break;
130
139
  case "ArrowRight":
131
- if (!node.expanded && (node.children || node.lazy)) {
140
+ if (!node.expanded && node.isExpandable(true)) {
132
141
  eventName = "Add"; // expand
133
142
  } else if (
134
- navModeOption === NavigationOptions.startCell ||
135
- navModeOption === NavigationOptions.startRow
143
+ navModeOption === NavModeEnum.startCell ||
144
+ navModeOption === NavModeEnum.startRow
136
145
  ) {
146
+ event.preventDefault();
137
147
  tree.setCellNav();
138
- return;
148
+ return false;
139
149
  }
140
150
  break;
141
151
  }
@@ -151,7 +161,7 @@ export class KeynavExtension extends WunderbaumExtension {
151
161
  case "Subtract":
152
162
  node.setExpanded(false);
153
163
  break;
154
- case " ":
164
+ case " ": // Space
155
165
  // if (node.isPagingNode()) {
156
166
  // tree._triggerNodeEvent("clickPaging", ctx, event);
157
167
  // } else
@@ -231,7 +241,16 @@ export class KeynavExtension extends WunderbaumExtension {
231
241
  }
232
242
 
233
243
  switch (eventName) {
234
- case " ":
244
+ case "+":
245
+ case "Add":
246
+ // case "=": // 187: '+' @ Chrome, Safari
247
+ node.setExpanded(true);
248
+ break;
249
+ case "-":
250
+ case "Subtract":
251
+ node.setExpanded(false);
252
+ break;
253
+ case " ": // Space
235
254
  if (tree.activeColIdx === 0 && node.getOption("checkbox")) {
236
255
  node.setSelected(!node.isSelected());
237
256
  handled = true;
@@ -251,7 +270,7 @@ export class KeynavExtension extends WunderbaumExtension {
251
270
  break;
252
271
  case "Enter":
253
272
  tree.setFocus(); // Blur prev. input if any
254
- if (tree.activeColIdx === 0 && node.isExpandable()) {
273
+ if ((tree.activeColIdx === 0 || isColspan) && node.isExpandable()) {
255
274
  node.setExpanded(!node.isExpanded());
256
275
  handled = true;
257
276
  } else if (curInput && !inputHasFocus && inputCanFocus) {
@@ -261,7 +280,7 @@ export class KeynavExtension extends WunderbaumExtension {
261
280
  break;
262
281
  case "Escape":
263
282
  tree.setFocus(); // Blur prev. input if any
264
- if (tree.isCellNav() && navModeOption !== NavigationOptions.cell) {
283
+ if (tree.isCellNav() && navModeOption !== NavModeEnum.cell) {
265
284
  tree.setCellNav(false); // row-nav mode
266
285
  handled = true;
267
286
  }
@@ -272,7 +291,7 @@ export class KeynavExtension extends WunderbaumExtension {
272
291
  node.setExpanded(false);
273
292
  } else if (!isColspan && tree.activeColIdx > 0) {
274
293
  tree.setColumn(tree.activeColIdx - 1);
275
- } else if (navModeOption !== NavigationOptions.cell) {
294
+ } else if (navModeOption !== NavModeEnum.cell) {
276
295
  tree.setCellNav(false); // row-nav mode
277
296
  }
278
297
  handled = true;
@@ -289,16 +308,16 @@ export class KeynavExtension extends WunderbaumExtension {
289
308
  }
290
309
  handled = true;
291
310
  break;
292
- case "Home": // Generated by FN + ArrowLeft on Mac
293
- case "Meta+ArrowLeft":
311
+ case "Home": // Generated by [Fn] + ArrowLeft on Mac
312
+ // case "Meta+ArrowLeft":
294
313
  tree.setFocus(); // Blur prev. input if any
295
314
  if (!isColspan && tree.activeColIdx > 0) {
296
315
  tree.setColumn(0);
297
316
  }
298
317
  handled = true;
299
318
  break;
300
- case "End": // Generated by FN + ArrowRight on Mac
301
- case "Meta+ArrowRight":
319
+ case "End": // Generated by [Fn] + ArrowRight on Mac
320
+ // case "Meta+ArrowRight":
302
321
  tree.setFocus(); // Blur prev. input if any
303
322
  if (!isColspan && tree.activeColIdx < tree.columns.length - 1) {
304
323
  tree.setColumn(tree.columns.length - 1);
@@ -308,12 +327,12 @@ export class KeynavExtension extends WunderbaumExtension {
308
327
  case "ArrowDown":
309
328
  case "ArrowUp":
310
329
  case "Backspace":
311
- case "Control+End": // Generated by FN + Control + ArrowRight on Mac
312
- case "Control+Home": // Generated by FN + Control + Arrowleft on Mac
313
- case "Meta+ArrowDown":
314
- case "Meta+ArrowUp":
315
- case "PageDown": // Generated by FN + ArrowDown on Mac
316
- case "PageUp": // Generated by FN + ArrowUp on Mac
330
+ case "Control+End": // Generated by Control + [Fn] + ArrowRight on Mac
331
+ case "Control+Home": // Generated by Control + [Fn] + Arrowleft on Mac
332
+ case "Meta+ArrowDown": // [⌘] + ArrowDown on Mac
333
+ case "Meta+ArrowUp": // [⌘] + ArrowUp on Mac
334
+ case "PageDown": // Generated by [Fn] + ArrowDown on Mac
335
+ case "PageUp": // Generated by [Fn] + ArrowUp on Mac
317
336
  node.navigate(eventName, { activate: activate, event: event });
318
337
  // if (isCellEditMode) {
319
338
  // this._getEmbeddedInputElem(null, true); // set focus to input