@angular/aria 21.0.0-rc.0 → 21.0.0-rc.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/_adev_assets/aria-accordion.json +14 -14
- package/_adev_assets/aria-combobox.json +10 -10
- package/_adev_assets/aria-grid.json +81 -12
- package/_adev_assets/aria-listbox.json +3 -3
- package/_adev_assets/aria-menu.json +174 -74
- package/_adev_assets/aria-tabs.json +22 -22
- package/_adev_assets/aria-toolbar.json +99 -120
- package/_adev_assets/aria-tree.json +20 -16
- package/fesm2022/_widget-chunk.mjs +266 -144
- package/fesm2022/_widget-chunk.mjs.map +1 -1
- package/fesm2022/accordion.mjs +12 -13
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/aria.mjs +1 -1
- package/fesm2022/aria.mjs.map +1 -1
- package/fesm2022/combobox.mjs +9 -7
- package/fesm2022/combobox.mjs.map +1 -1
- package/fesm2022/grid.mjs +61 -12
- package/fesm2022/grid.mjs.map +1 -1
- package/fesm2022/listbox.mjs +14 -15
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/menu.mjs +117 -61
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/private.mjs +390 -399
- package/fesm2022/private.mjs.map +1 -1
- package/fesm2022/tabs.mjs +16 -17
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +79 -44
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tree.mjs +22 -19
- package/fesm2022/tree.mjs.map +1 -1
- package/package.json +2 -10
- package/types/_grid-chunk.d.ts +115 -53
- package/types/accordion.d.ts +4 -4
- package/types/combobox.d.ts +2 -2
- package/types/grid.d.ts +12 -3
- package/types/listbox.d.ts +3 -4
- package/types/menu.d.ts +33 -21
- package/types/private.d.ts +263 -341
- package/types/tabs.d.ts +4 -4
- package/types/toolbar.d.ts +29 -26
- package/types/tree.d.ts +5 -6
- package/_adev_assets/aria-radio-group.json +0 -389
- package/fesm2022/deferred-content.mjs +0 -99
- package/fesm2022/deferred-content.mjs.map +0 -1
- package/fesm2022/radio-group.mjs +0 -338
- package/fesm2022/radio-group.mjs.map +0 -1
- package/types/deferred-content.d.ts +0 -38
- package/types/radio-group.d.ts +0 -84
|
@@ -46,23 +46,28 @@ class KeyboardEventManager extends EventManager {
|
|
|
46
46
|
const {
|
|
47
47
|
modifiers,
|
|
48
48
|
key,
|
|
49
|
-
handler
|
|
49
|
+
handler,
|
|
50
|
+
options
|
|
50
51
|
} = this._normalizeInputs(...args);
|
|
51
52
|
this.configs.push({
|
|
52
53
|
handler: handler,
|
|
53
54
|
matcher: event => this._isMatch(event, key, modifiers),
|
|
54
|
-
...this.options
|
|
55
|
+
...this.options,
|
|
56
|
+
...options
|
|
55
57
|
});
|
|
56
58
|
return this;
|
|
57
59
|
}
|
|
58
60
|
_normalizeInputs(...args) {
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
const
|
|
61
|
+
const withModifiers = Array.isArray(args[0]) || args[0] in Modifier;
|
|
62
|
+
const modifiers = withModifiers ? args[0] : Modifier.None;
|
|
63
|
+
const key = withModifiers ? args[1] : args[0];
|
|
64
|
+
const handler = withModifiers ? args[2] : args[1];
|
|
65
|
+
const options = withModifiers ? args[3] : args[2];
|
|
62
66
|
return {
|
|
63
67
|
key: key,
|
|
64
68
|
handler: handler,
|
|
65
|
-
modifiers: modifiers
|
|
69
|
+
modifiers: modifiers,
|
|
70
|
+
options: options ?? {}
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
_isMatch(event, key, modifiers) {
|
|
@@ -130,7 +135,6 @@ class PointerEventManager extends EventManager {
|
|
|
130
135
|
class GridData {
|
|
131
136
|
inputs;
|
|
132
137
|
cells;
|
|
133
|
-
rowCount = computed(() => this.cells().length);
|
|
134
138
|
maxRowCount = computed(() => Math.max(...this._rowCountByCol().values(), 0));
|
|
135
139
|
maxColCount = computed(() => Math.max(...this._colCountsByRow().values(), 0));
|
|
136
140
|
_coordsMap = computed(() => {
|
|
@@ -280,7 +284,7 @@ class GridFocus {
|
|
|
280
284
|
constructor(inputs) {
|
|
281
285
|
this.inputs = inputs;
|
|
282
286
|
}
|
|
283
|
-
|
|
287
|
+
getCellTabIndex(cell) {
|
|
284
288
|
if (this.gridDisabled()) {
|
|
285
289
|
return -1;
|
|
286
290
|
}
|
|
@@ -290,7 +294,7 @@ class GridFocus {
|
|
|
290
294
|
return this.activeCell() === cell ? 0 : -1;
|
|
291
295
|
}
|
|
292
296
|
isFocusable(cell) {
|
|
293
|
-
return !cell.disabled() ||
|
|
297
|
+
return !cell.disabled() || this.inputs.softDisabled();
|
|
294
298
|
}
|
|
295
299
|
focusCell(cell) {
|
|
296
300
|
if (this.gridDisabled()) {
|
|
@@ -349,37 +353,38 @@ class GridNavigation {
|
|
|
349
353
|
gotoCoords(coords) {
|
|
350
354
|
return this.inputs.gridFocus.focusCoordinates(coords);
|
|
351
355
|
}
|
|
352
|
-
peek(direction, fromCoords, wrap) {
|
|
356
|
+
peek(direction, fromCoords, wrap, allowDisabled) {
|
|
353
357
|
wrap = wrap ?? (direction.row !== undefined ? this.inputs.rowWrap() : this.inputs.colWrap());
|
|
354
|
-
return this._peekDirectional(direction, fromCoords, wrap);
|
|
358
|
+
return this._peekDirectional(direction, fromCoords, wrap, allowDisabled);
|
|
355
359
|
}
|
|
356
360
|
advance(direction) {
|
|
357
361
|
const nextCoords = this.peek(direction, this.inputs.gridFocus.activeCoords());
|
|
358
362
|
return !!nextCoords && this.gotoCoords(nextCoords);
|
|
359
363
|
}
|
|
360
|
-
peekFirst(row) {
|
|
364
|
+
peekFirst(row, allowDisabled) {
|
|
361
365
|
const fromCoords = {
|
|
362
366
|
row: row ?? 0,
|
|
363
367
|
col: -1
|
|
364
368
|
};
|
|
365
|
-
return row === undefined ? this._peekDirectional(direction.Right, fromCoords, 'continuous') : this._peekDirectional(direction.Right, fromCoords, 'nowrap');
|
|
369
|
+
return row === undefined ? this._peekDirectional(direction.Right, fromCoords, 'continuous', allowDisabled) : this._peekDirectional(direction.Right, fromCoords, 'nowrap', allowDisabled);
|
|
366
370
|
}
|
|
367
371
|
first(row) {
|
|
368
372
|
const nextCoords = this.peekFirst(row);
|
|
369
373
|
return !!nextCoords && this.gotoCoords(nextCoords);
|
|
370
374
|
}
|
|
371
|
-
peekLast(row) {
|
|
375
|
+
peekLast(row, allowDisabled) {
|
|
372
376
|
const fromCoords = {
|
|
373
377
|
row: row ?? this.inputs.grid.maxRowCount() - 1,
|
|
374
378
|
col: this.inputs.grid.maxColCount()
|
|
375
379
|
};
|
|
376
|
-
return row === undefined ? this._peekDirectional(direction.Left, fromCoords, 'continuous') : this._peekDirectional(direction.Left, fromCoords, 'nowrap');
|
|
380
|
+
return row === undefined ? this._peekDirectional(direction.Left, fromCoords, 'continuous', allowDisabled) : this._peekDirectional(direction.Left, fromCoords, 'nowrap', allowDisabled);
|
|
377
381
|
}
|
|
378
382
|
last(row) {
|
|
379
383
|
const nextCoords = this.peekLast(row);
|
|
380
384
|
return !!nextCoords && this.gotoCoords(nextCoords);
|
|
381
385
|
}
|
|
382
|
-
_peekDirectional(delta, fromCoords, wrap) {
|
|
386
|
+
_peekDirectional(delta, fromCoords, wrap, allowDisabled = false) {
|
|
387
|
+
if (this.inputs.gridFocus.gridDisabled()) return undefined;
|
|
383
388
|
const fromCell = this.inputs.grid.getCell(fromCoords);
|
|
384
389
|
const maxRowCount = this.inputs.grid.maxRowCount();
|
|
385
390
|
const maxColCount = this.inputs.grid.maxColCount();
|
|
@@ -406,11 +411,17 @@ class GridNavigation {
|
|
|
406
411
|
col: (nextCoords.col + colDelta + maxColCount) % maxColCount
|
|
407
412
|
};
|
|
408
413
|
}
|
|
414
|
+
if (wrap === 'nowrap') {
|
|
415
|
+
nextCoords = {
|
|
416
|
+
row: nextCoords.row + rowDelta,
|
|
417
|
+
col: nextCoords.col + colDelta
|
|
418
|
+
};
|
|
419
|
+
}
|
|
409
420
|
if (nextCoords.row === fromCoords.row && nextCoords.col === fromCoords.col) {
|
|
410
421
|
return undefined;
|
|
411
422
|
}
|
|
412
423
|
const nextCell = this.inputs.grid.getCell(nextCoords);
|
|
413
|
-
if (nextCell !== undefined && nextCell !== fromCell && this.inputs.gridFocus.isFocusable(nextCell)) {
|
|
424
|
+
if (nextCell !== undefined && nextCell !== fromCell && (allowDisabled || this.inputs.gridFocus.isFocusable(nextCell))) {
|
|
414
425
|
return nextCoords;
|
|
415
426
|
}
|
|
416
427
|
}
|
|
@@ -420,45 +431,45 @@ class GridNavigation {
|
|
|
420
431
|
|
|
421
432
|
class GridSelection {
|
|
422
433
|
inputs;
|
|
434
|
+
_undoList = signal([]);
|
|
423
435
|
constructor(inputs) {
|
|
424
436
|
this.inputs = inputs;
|
|
425
437
|
}
|
|
426
|
-
|
|
427
|
-
for (const cell of this.
|
|
428
|
-
cell.selected.set(
|
|
438
|
+
undo() {
|
|
439
|
+
for (const [cell, oldState] of this._undoList()) {
|
|
440
|
+
cell.selected.set(oldState);
|
|
429
441
|
}
|
|
442
|
+
this._undoList.set([]);
|
|
443
|
+
}
|
|
444
|
+
select(fromCoords, toCoords) {
|
|
445
|
+
this._updateState(fromCoords, toCoords ?? fromCoords, () => true);
|
|
430
446
|
}
|
|
431
447
|
deselect(fromCoords, toCoords) {
|
|
432
|
-
|
|
433
|
-
cell.selected.set(false);
|
|
434
|
-
}
|
|
448
|
+
this._updateState(fromCoords, toCoords ?? fromCoords, () => false);
|
|
435
449
|
}
|
|
436
450
|
toggle(fromCoords, toCoords) {
|
|
437
|
-
|
|
438
|
-
cell.selected.update(state => !state);
|
|
439
|
-
}
|
|
451
|
+
this._updateState(fromCoords, toCoords ?? fromCoords, oldState => !oldState);
|
|
440
452
|
}
|
|
441
453
|
selectAll() {
|
|
442
|
-
|
|
454
|
+
this._updateState({
|
|
443
455
|
row: 0,
|
|
444
456
|
col: 0
|
|
445
457
|
}, {
|
|
446
458
|
row: this.inputs.grid.maxRowCount(),
|
|
447
459
|
col: this.inputs.grid.maxColCount()
|
|
448
|
-
}))
|
|
449
|
-
cell.selected.set(true);
|
|
450
|
-
}
|
|
460
|
+
}, () => true);
|
|
451
461
|
}
|
|
452
462
|
deselectAll() {
|
|
453
|
-
|
|
463
|
+
this._updateState({
|
|
454
464
|
row: 0,
|
|
455
465
|
col: 0
|
|
456
466
|
}, {
|
|
457
467
|
row: this.inputs.grid.maxRowCount(),
|
|
458
468
|
col: this.inputs.grid.maxColCount()
|
|
459
|
-
}))
|
|
460
|
-
|
|
461
|
-
|
|
469
|
+
}, () => false);
|
|
470
|
+
}
|
|
471
|
+
isSelectable(cell) {
|
|
472
|
+
return cell.selectable() && !cell.disabled();
|
|
462
473
|
}
|
|
463
474
|
*_validCells(fromCoords, toCoords) {
|
|
464
475
|
const startRow = Math.min(fromCoords.row, toCoords.row);
|
|
@@ -473,14 +484,22 @@ class GridSelection {
|
|
|
473
484
|
col
|
|
474
485
|
});
|
|
475
486
|
if (cell === undefined) continue;
|
|
476
|
-
if (!
|
|
477
|
-
if (cell.disabled()) continue;
|
|
487
|
+
if (!this.isSelectable(cell)) continue;
|
|
478
488
|
if (visited.has(cell)) continue;
|
|
479
489
|
visited.add(cell);
|
|
480
490
|
yield cell;
|
|
481
491
|
}
|
|
482
492
|
}
|
|
483
493
|
}
|
|
494
|
+
_updateState(fromCoords, toCoords, stateFn) {
|
|
495
|
+
const undoList = [];
|
|
496
|
+
for (const cell of this._validCells(fromCoords, toCoords)) {
|
|
497
|
+
const oldState = cell.selected();
|
|
498
|
+
undoList.push([cell, oldState]);
|
|
499
|
+
cell.selected.set(stateFn(oldState));
|
|
500
|
+
}
|
|
501
|
+
this._undoList.set(undoList);
|
|
502
|
+
}
|
|
484
503
|
}
|
|
485
504
|
|
|
486
505
|
class Grid {
|
|
@@ -490,9 +509,12 @@ class Grid {
|
|
|
490
509
|
navigationBehavior;
|
|
491
510
|
selectionBehavior;
|
|
492
511
|
selectionAnchor = linkedSignal(() => this.focusBehavior.activeCoords());
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
512
|
+
selectionAnchorCell = computed(() => this.data.getCell(this.selectionAnchor()));
|
|
513
|
+
selectionStabled = signal(true);
|
|
514
|
+
allSelected = computed(() => this.data.cells().flat().filter(c => this.selectionBehavior.isSelectable(c)).every(c => c.selected()));
|
|
515
|
+
gridTabIndex = () => this.focusBehavior.gridTabIndex();
|
|
516
|
+
gridDisabled = () => this.focusBehavior.gridDisabled();
|
|
517
|
+
activeDescendant = () => this.focusBehavior.activeDescendant();
|
|
496
518
|
constructor(inputs) {
|
|
497
519
|
this.inputs = inputs;
|
|
498
520
|
this.data = new GridData(inputs);
|
|
@@ -520,51 +542,33 @@ class Grid {
|
|
|
520
542
|
return index !== undefined ? index + 1 : undefined;
|
|
521
543
|
}
|
|
522
544
|
cellTabIndex(cell) {
|
|
523
|
-
return this.focusBehavior.
|
|
524
|
-
}
|
|
525
|
-
up() {
|
|
526
|
-
return this.navigationBehavior.advance(direction.Up);
|
|
527
|
-
}
|
|
528
|
-
rangeSelectUp() {
|
|
529
|
-
const coords = this.navigationBehavior.peek(direction.Up, this.selectionAnchor());
|
|
530
|
-
if (coords === undefined) return;
|
|
531
|
-
this._rangeSelectCoords(coords);
|
|
532
|
-
}
|
|
533
|
-
down() {
|
|
534
|
-
return this.navigationBehavior.advance(direction.Down);
|
|
545
|
+
return this.focusBehavior.getCellTabIndex(cell);
|
|
535
546
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
if (coords === undefined) return;
|
|
539
|
-
this._rangeSelectCoords(coords);
|
|
547
|
+
up(opts = {}) {
|
|
548
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peek(direction.Up, this.selectionAnchor(), 'nowrap', true)) : this.navigationBehavior.advance(direction.Up), opts);
|
|
540
549
|
}
|
|
541
|
-
|
|
542
|
-
return this.navigationBehavior.advance(direction.
|
|
550
|
+
down(opts = {}) {
|
|
551
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peek(direction.Down, this.selectionAnchor(), 'nowrap', true)) : this.navigationBehavior.advance(direction.Down), opts);
|
|
543
552
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
if (coords === undefined) return;
|
|
547
|
-
this._rangeSelectCoords(coords);
|
|
553
|
+
left(opts = {}) {
|
|
554
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peek(direction.Left, this.selectionAnchor(), 'nowrap', true)) : this.navigationBehavior.advance(direction.Left), opts);
|
|
548
555
|
}
|
|
549
|
-
right() {
|
|
550
|
-
return this.navigationBehavior.advance(direction.Right);
|
|
556
|
+
right(opts = {}) {
|
|
557
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peek(direction.Right, this.selectionAnchor(), 'nowrap', true)) : this.navigationBehavior.advance(direction.Right), opts);
|
|
551
558
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
if (coords === undefined) return;
|
|
555
|
-
this._rangeSelectCoords(coords);
|
|
559
|
+
first(opts = {}) {
|
|
560
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peekFirst(undefined, true)) : this.navigationBehavior.first(), opts);
|
|
556
561
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
firstInRow() {
|
|
561
|
-
return this.navigationBehavior.first(this.focusBehavior.activeCoords().row);
|
|
562
|
+
firstInRow(opts = {}) {
|
|
563
|
+
const row = this.focusBehavior.activeCoords().row;
|
|
564
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peekFirst(row, true)) : this.navigationBehavior.first(row), opts);
|
|
562
565
|
}
|
|
563
|
-
last() {
|
|
564
|
-
return this.navigationBehavior.last();
|
|
566
|
+
last(opts = {}) {
|
|
567
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peekLast(undefined, true)) : this.navigationBehavior.last(), opts);
|
|
565
568
|
}
|
|
566
|
-
lastInRow() {
|
|
567
|
-
|
|
569
|
+
lastInRow(opts = {}) {
|
|
570
|
+
const row = this.focusBehavior.activeCoords().row;
|
|
571
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.navigationBehavior.peekLast(row, true)) : this.navigationBehavior.last(row), opts);
|
|
568
572
|
}
|
|
569
573
|
selectRow() {
|
|
570
574
|
const row = this.focusBehavior.activeCoords().row;
|
|
@@ -588,50 +592,48 @@ class Grid {
|
|
|
588
592
|
col
|
|
589
593
|
});
|
|
590
594
|
}
|
|
591
|
-
|
|
592
|
-
this.selectionBehavior.
|
|
595
|
+
select() {
|
|
596
|
+
this.selectionBehavior.select(this.focusBehavior.activeCoords());
|
|
593
597
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if (coords === undefined) return;
|
|
605
|
-
this._rangeSelectCoords(coords);
|
|
606
|
-
}
|
|
607
|
-
_rangeSelectCoords(coords) {
|
|
608
|
-
const activeCell = this.focusBehavior.activeCell();
|
|
609
|
-
const anchorCell = this.data.getCell(coords);
|
|
610
|
-
if (activeCell === undefined || anchorCell === undefined) {
|
|
598
|
+
deselect() {
|
|
599
|
+
this.selectionBehavior.deselect(this.focusBehavior.activeCoords());
|
|
600
|
+
}
|
|
601
|
+
toggle() {
|
|
602
|
+
this.selectionBehavior.toggle(this.focusBehavior.activeCoords());
|
|
603
|
+
}
|
|
604
|
+
toggleOne() {
|
|
605
|
+
const selected = !!this.focusBehavior.activeCell()?.selected();
|
|
606
|
+
if (selected) {
|
|
607
|
+
this.deselect();
|
|
611
608
|
return;
|
|
612
609
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
const toCoords = {
|
|
621
|
-
row: Math.max(...allRows),
|
|
622
|
-
col: Math.max(...allCols)
|
|
623
|
-
};
|
|
610
|
+
this.deselectAll();
|
|
611
|
+
this.select();
|
|
612
|
+
}
|
|
613
|
+
selectAll() {
|
|
614
|
+
this.selectionBehavior.selectAll();
|
|
615
|
+
}
|
|
616
|
+
deselectAll() {
|
|
624
617
|
this.selectionBehavior.deselectAll();
|
|
625
|
-
|
|
626
|
-
|
|
618
|
+
}
|
|
619
|
+
gotoCell(cell, opts = {}) {
|
|
620
|
+
return this._navigateWithSelection(() => opts.anchor ? this._updateSelectionAnchor(() => this.data.getCoords(cell)) : this.navigationBehavior.gotoCell(cell), opts);
|
|
621
|
+
}
|
|
622
|
+
setDefaultState() {
|
|
623
|
+
const focusableSelectedCell = this.data.cells().flat().filter(c => this.focusBehavior.isFocusable(c)).find(c => c.selected());
|
|
624
|
+
if (focusableSelectedCell !== undefined) {
|
|
625
|
+
this.focusBehavior.focusCell(focusableSelectedCell);
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
const firstFocusableCoords = this.navigationBehavior.peekFirst();
|
|
629
|
+
if (firstFocusableCoords !== undefined) {
|
|
630
|
+
return this.focusBehavior.focusCoordinates(firstFocusableCoords);
|
|
631
|
+
}
|
|
632
|
+
return false;
|
|
627
633
|
}
|
|
628
634
|
resetState() {
|
|
629
635
|
if (this.focusBehavior.stateEmpty()) {
|
|
630
|
-
|
|
631
|
-
if (firstFocusableCoords === undefined) {
|
|
632
|
-
return false;
|
|
633
|
-
}
|
|
634
|
-
return this.focusBehavior.focusCoordinates(firstFocusableCoords);
|
|
636
|
+
return this.setDefaultState();
|
|
635
637
|
}
|
|
636
638
|
if (this.focusBehavior.stateStale()) {
|
|
637
639
|
if (this.focusBehavior.focusCell(this.focusBehavior.activeCell())) {
|
|
@@ -646,6 +648,67 @@ class Grid {
|
|
|
646
648
|
}
|
|
647
649
|
return false;
|
|
648
650
|
}
|
|
651
|
+
_updateSelectionAnchor(peekFn) {
|
|
652
|
+
const coords = peekFn();
|
|
653
|
+
const success = coords !== undefined;
|
|
654
|
+
if (!success) return false;
|
|
655
|
+
this.selectionAnchor.set(coords);
|
|
656
|
+
return success;
|
|
657
|
+
}
|
|
658
|
+
_updateRangeSelection() {
|
|
659
|
+
if (!this.selectionStabled()) {
|
|
660
|
+
this.selectionBehavior.undo();
|
|
661
|
+
}
|
|
662
|
+
this.selectionBehavior.select(...this._getSelectionCoords(this.focusBehavior.activeCoords(), this.selectionAnchor()));
|
|
663
|
+
}
|
|
664
|
+
_getSelectionCoords(startCoords, endCoords) {
|
|
665
|
+
const startCell = this.data.getCell(startCoords);
|
|
666
|
+
const endCell = this.data.getCell(endCoords);
|
|
667
|
+
const allCoords = [...this.data.getAllCoords(startCell), ...this.data.getAllCoords(endCell)];
|
|
668
|
+
const allRows = allCoords.map(c => c.row);
|
|
669
|
+
const allCols = allCoords.map(c => c.col);
|
|
670
|
+
const fromCoords = {
|
|
671
|
+
row: Math.min(...allRows),
|
|
672
|
+
col: Math.min(...allCols)
|
|
673
|
+
};
|
|
674
|
+
const toCoords = {
|
|
675
|
+
row: Math.max(...allRows),
|
|
676
|
+
col: Math.max(...allCols)
|
|
677
|
+
};
|
|
678
|
+
return [fromCoords, toCoords];
|
|
679
|
+
}
|
|
680
|
+
_navigateWithSelection(op, opts = {}) {
|
|
681
|
+
const success = op();
|
|
682
|
+
if (!success) return false;
|
|
683
|
+
if (opts.anchor) {
|
|
684
|
+
this._updateRangeSelection();
|
|
685
|
+
this.selectionStabled.set(false);
|
|
686
|
+
return success;
|
|
687
|
+
}
|
|
688
|
+
this.selectionStabled.set(true);
|
|
689
|
+
if (opts.select) {
|
|
690
|
+
this.select();
|
|
691
|
+
return success;
|
|
692
|
+
}
|
|
693
|
+
if (opts.selectOne) {
|
|
694
|
+
this.deselectAll();
|
|
695
|
+
this.select();
|
|
696
|
+
return success;
|
|
697
|
+
}
|
|
698
|
+
if (opts.toggle) {
|
|
699
|
+
this.toggle();
|
|
700
|
+
return success;
|
|
701
|
+
}
|
|
702
|
+
if (opts.toggleOne) {
|
|
703
|
+
const selected = !!this.focusBehavior.activeCell()?.selected();
|
|
704
|
+
this.deselectAll();
|
|
705
|
+
if (!selected) {
|
|
706
|
+
this.select();
|
|
707
|
+
}
|
|
708
|
+
return success;
|
|
709
|
+
}
|
|
710
|
+
return success;
|
|
711
|
+
}
|
|
649
712
|
}
|
|
650
713
|
|
|
651
714
|
class GridPattern {
|
|
@@ -656,53 +719,110 @@ class GridPattern {
|
|
|
656
719
|
disabled = computed(() => this.gridBehavior.gridDisabled());
|
|
657
720
|
activeDescendant = computed(() => this.gridBehavior.activeDescendant());
|
|
658
721
|
activeCell = computed(() => this.gridBehavior.focusBehavior.activeCell());
|
|
722
|
+
anchorCell = computed(() => this.inputs.enableSelection() && this.inputs.multi() ? this.gridBehavior.selectionAnchorCell() : undefined);
|
|
659
723
|
pauseNavigation = computed(() => this.gridBehavior.data.cells().flat().reduce((res, c) => res || c.widgetActivated(), false));
|
|
660
724
|
isFocused = signal(false);
|
|
725
|
+
hasBeenFocused = signal(false);
|
|
661
726
|
dragging = signal(false);
|
|
727
|
+
prevColKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft');
|
|
728
|
+
nextColKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
|
|
662
729
|
keydown = computed(() => {
|
|
663
730
|
const manager = new KeyboardEventManager();
|
|
664
731
|
if (this.pauseNavigation()) {
|
|
665
732
|
return manager;
|
|
666
733
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
734
|
+
const opts = {
|
|
735
|
+
selectOne: this.inputs.enableSelection() && this.inputs.selectionMode() === 'follow'
|
|
736
|
+
};
|
|
737
|
+
manager.on('ArrowUp', () => this.gridBehavior.up(opts)).on('ArrowDown', () => this.gridBehavior.down(opts)).on(this.prevColKey(), () => this.gridBehavior.left(opts)).on(this.nextColKey(), () => this.gridBehavior.right(opts)).on('Home', () => this.gridBehavior.firstInRow(opts)).on('End', () => this.gridBehavior.lastInRow(opts)).on([Modifier.Ctrl], 'Home', () => this.gridBehavior.first(opts)).on([Modifier.Ctrl], 'End', () => this.gridBehavior.last(opts));
|
|
738
|
+
if (this.inputs.enableSelection() && this.inputs.selectionMode() === 'explicit') {
|
|
739
|
+
manager.on('Enter', () => this.inputs.multi() ? this.gridBehavior.toggle() : this.gridBehavior.toggleOne()).on(' ', () => this.inputs.multi() ? this.gridBehavior.toggle() : this.gridBehavior.toggleOne());
|
|
740
|
+
}
|
|
741
|
+
if (this.inputs.enableSelection() && this.inputs.enableRangeSelection()) {
|
|
742
|
+
manager.on(Modifier.Shift, 'ArrowUp', () => this.gridBehavior.up({
|
|
743
|
+
anchor: true
|
|
744
|
+
})).on(Modifier.Shift, 'ArrowDown', () => this.gridBehavior.down({
|
|
745
|
+
anchor: true
|
|
746
|
+
})).on(Modifier.Shift, this.prevColKey(), () => this.gridBehavior.left({
|
|
747
|
+
anchor: true
|
|
748
|
+
})).on(Modifier.Shift, this.nextColKey(), () => this.gridBehavior.right({
|
|
749
|
+
anchor: true
|
|
750
|
+
})).on(Modifier.Shift, 'Home', () => this.gridBehavior.firstInRow({
|
|
751
|
+
anchor: true
|
|
752
|
+
})).on(Modifier.Shift, 'End', () => this.gridBehavior.lastInRow({
|
|
753
|
+
anchor: true
|
|
754
|
+
})).on([Modifier.Ctrl | Modifier.Shift], 'Home', () => this.gridBehavior.first({
|
|
755
|
+
anchor: true
|
|
756
|
+
})).on([Modifier.Ctrl | Modifier.Shift], 'End', () => this.gridBehavior.last({
|
|
757
|
+
anchor: true
|
|
758
|
+
})).on([Modifier.Ctrl, Modifier.Meta], 'A', () => {
|
|
759
|
+
if (this.gridBehavior.allSelected()) {
|
|
760
|
+
this.gridBehavior.deselectAll();
|
|
761
|
+
} else {
|
|
762
|
+
this.gridBehavior.selectAll();
|
|
763
|
+
}
|
|
764
|
+
}).on([Modifier.Shift], ' ', () => this.gridBehavior.selectRow()).on([Modifier.Ctrl, Modifier.Meta], ' ', () => this.gridBehavior.selectCol());
|
|
670
765
|
}
|
|
671
766
|
return manager;
|
|
672
767
|
});
|
|
673
768
|
pointerdown = computed(() => {
|
|
674
769
|
const manager = new PointerEventManager();
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
if (!cell) return;
|
|
678
|
-
this.gridBehavior.gotoCell(cell);
|
|
679
|
-
if (this.inputs.enableSelection()) {
|
|
680
|
-
this.dragging.set(true);
|
|
681
|
-
}
|
|
682
|
-
});
|
|
683
|
-
if (this.inputs.enableSelection()) {
|
|
684
|
-
manager.on([Modifier.Ctrl, Modifier.Meta], e => {
|
|
770
|
+
if (!this.inputs.enableSelection()) {
|
|
771
|
+
manager.on(e => {
|
|
685
772
|
const cell = this.inputs.getCell(e.target);
|
|
686
|
-
if (!cell) return;
|
|
687
|
-
this.gridBehavior.
|
|
688
|
-
})
|
|
773
|
+
if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return;
|
|
774
|
+
this.gridBehavior.gotoCell(cell);
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
if (this.inputs.enableSelection()) {
|
|
778
|
+
manager.on(e => {
|
|
689
779
|
const cell = this.inputs.getCell(e.target);
|
|
690
|
-
if (!cell) return;
|
|
691
|
-
this.gridBehavior.
|
|
692
|
-
|
|
780
|
+
if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return;
|
|
781
|
+
this.gridBehavior.gotoCell(cell, {
|
|
782
|
+
selectOne: this.inputs.selectionMode() === 'follow',
|
|
783
|
+
toggleOne: this.inputs.selectionMode() === 'explicit' && !this.inputs.multi(),
|
|
784
|
+
toggle: this.inputs.selectionMode() === 'explicit' && this.inputs.multi()
|
|
785
|
+
});
|
|
786
|
+
if (this.inputs.multi() && this.inputs.enableRangeSelection()) {
|
|
787
|
+
this.dragging.set(true);
|
|
788
|
+
}
|
|
693
789
|
});
|
|
790
|
+
if (this.inputs.multi()) {
|
|
791
|
+
manager.on([Modifier.Ctrl, Modifier.Meta], e => {
|
|
792
|
+
const cell = this.inputs.getCell(e.target);
|
|
793
|
+
if (!cell || !this.gridBehavior.focusBehavior.isFocusable(cell)) return;
|
|
794
|
+
this.gridBehavior.gotoCell(cell, {
|
|
795
|
+
toggle: true
|
|
796
|
+
});
|
|
797
|
+
if (this.inputs.enableRangeSelection()) {
|
|
798
|
+
this.dragging.set(true);
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
if (this.inputs.enableRangeSelection()) {
|
|
802
|
+
manager.on(Modifier.Shift, e => {
|
|
803
|
+
const cell = this.inputs.getCell(e.target);
|
|
804
|
+
if (!cell) return;
|
|
805
|
+
this.gridBehavior.gotoCell(cell, {
|
|
806
|
+
anchor: true
|
|
807
|
+
});
|
|
808
|
+
this.dragging.set(true);
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
}
|
|
694
812
|
}
|
|
695
813
|
return manager;
|
|
696
814
|
});
|
|
697
815
|
pointerup = computed(() => {
|
|
698
816
|
const manager = new PointerEventManager();
|
|
699
|
-
if (this.inputs.enableSelection()) {
|
|
700
|
-
manager.on([Modifier.Shift, Modifier.None], () => {
|
|
817
|
+
if (this.inputs.enableSelection() && this.inputs.enableRangeSelection()) {
|
|
818
|
+
manager.on([Modifier.Shift, Modifier.Ctrl, Modifier.Meta, Modifier.None], () => {
|
|
701
819
|
this.dragging.set(false);
|
|
702
820
|
});
|
|
703
821
|
}
|
|
704
822
|
return manager;
|
|
705
823
|
});
|
|
824
|
+
_maybeDeletion = signal(false);
|
|
825
|
+
_deletion = signal(false);
|
|
706
826
|
constructor(inputs) {
|
|
707
827
|
this.inputs = inputs;
|
|
708
828
|
this.gridBehavior = new Grid({
|
|
@@ -723,23 +843,23 @@ class GridPattern {
|
|
|
723
843
|
onPointermove(event) {
|
|
724
844
|
if (this.disabled()) return;
|
|
725
845
|
if (!this.inputs.enableSelection()) return;
|
|
846
|
+
if (!this.inputs.enableRangeSelection()) return;
|
|
726
847
|
if (!this.dragging()) return;
|
|
727
848
|
const cell = this.inputs.getCell(event.target);
|
|
728
849
|
if (!cell) return;
|
|
729
|
-
this.gridBehavior.
|
|
850
|
+
this.gridBehavior.gotoCell(cell, {
|
|
851
|
+
anchor: true
|
|
852
|
+
});
|
|
730
853
|
}
|
|
731
854
|
onPointerup(event) {
|
|
732
855
|
if (!this.disabled()) {
|
|
733
856
|
this.pointerup().handle(event);
|
|
734
857
|
}
|
|
735
858
|
}
|
|
736
|
-
onFocusIn(
|
|
859
|
+
onFocusIn() {
|
|
737
860
|
this.isFocused.set(true);
|
|
738
|
-
|
|
739
|
-
if (!cell) return;
|
|
740
|
-
this.gridBehavior.gotoCell(cell);
|
|
861
|
+
this.hasBeenFocused.set(true);
|
|
741
862
|
}
|
|
742
|
-
_maybeDeletion = signal(false);
|
|
743
863
|
onFocusOut(event) {
|
|
744
864
|
const parentEl = this.inputs.element();
|
|
745
865
|
const targetEl = event.relatedTarget;
|
|
@@ -749,15 +869,16 @@ class GridPattern {
|
|
|
749
869
|
if (parentEl.contains(targetEl)) return;
|
|
750
870
|
this.isFocused.set(false);
|
|
751
871
|
}
|
|
752
|
-
|
|
872
|
+
setDefaultStateEffect() {
|
|
873
|
+
if (this.hasBeenFocused()) return;
|
|
874
|
+
this.gridBehavior.setDefaultState();
|
|
875
|
+
}
|
|
753
876
|
resetStateEffect() {
|
|
754
877
|
const hasReset = this.gridBehavior.resetState();
|
|
755
878
|
if (hasReset && this._maybeDeletion()) {
|
|
756
879
|
this._deletion.set(true);
|
|
757
880
|
}
|
|
758
|
-
|
|
759
|
-
this._maybeDeletion.set(false);
|
|
760
|
-
}
|
|
881
|
+
this._maybeDeletion.set(false);
|
|
761
882
|
}
|
|
762
883
|
focusEffect() {
|
|
763
884
|
const activeCell = this.activeCell();
|
|
@@ -795,6 +916,7 @@ class GridCellPattern {
|
|
|
795
916
|
ariaColIndex = computed(() => this.inputs.colIndex() ?? this.inputs.grid().gridBehavior.colIndex(this));
|
|
796
917
|
element = computed(() => this.inputs.widget()?.element() ?? this.inputs.element());
|
|
797
918
|
active = computed(() => this.inputs.grid().activeCell() === this);
|
|
919
|
+
anchor = computed(() => this.inputs.grid().anchorCell() === this ? true : undefined);
|
|
798
920
|
_tabIndex = computed(() => this.inputs.grid().gridBehavior.cellTabIndex(this));
|
|
799
921
|
tabIndex = computed(() => this.inputs.widget() !== undefined ? -1 : this._tabIndex());
|
|
800
922
|
widgetActivated = computed(() => this.inputs.widget()?.inputs.activate() ?? false);
|