@iyulab/flex-table 0.49.1 → 0.50.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/CHANGELOG.md +37 -0
- package/README.md +12 -4
- package/dist/{flex-table-CpAhHipx.js → flex-table-Hx-xTm0e.js} +167 -46
- package/dist/flex-table.d.ts +47 -0
- package/dist/flex-table.js +1 -1
- package/dist/react.js +1 -1
- package/package.json +1 -1
- package/skills/iyulab-flex-table/references/styling.md +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.50.1] - 2026-10-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **Screen readers hear the active cell.** The table kept the focus on itself and marked the active cell
|
|
8
|
+
with a class only, so assistive technology announced the grid and nothing as the arrow keys moved
|
|
9
|
+
(the host cannot point `aria-activedescendant` into its own shadow tree). The focus now sits on the
|
|
10
|
+
active cell — or the active header cell — while the table has it (roving focus): each move is announced
|
|
11
|
+
with the cell's row, column and content. `document.activeElement` is still the table.
|
|
12
|
+
- When scrolling moves the focused cell out of the rendered window, the focus waits on the table instead
|
|
13
|
+
of staying on a recycled cell that now shows another row; the next key brings it back onto the active
|
|
14
|
+
cell.
|
|
15
|
+
|
|
16
|
+
## [0.50.0] - 2026-10-06
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **Tab no longer traps the focus in the table.** Tab past the last cell (Shift+Tab before the first)
|
|
21
|
+
stayed on that cell, so keyboard focus could never leave the table (WCAG 2.1.2). Tab still walks the
|
|
22
|
+
cells; at either end it now moves on to the next (previous) control on the page.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **The header row is reachable by keyboard.** ArrowUp from the first row moves onto the column's header
|
|
27
|
+
cell; ArrowLeft / ArrowRight / Home / End move along the header and ArrowDown returns to the body. On a
|
|
28
|
+
header cell, Enter or Space sorts (Shift adds the column to the sort), Alt+ArrowDown or the context-menu
|
|
29
|
+
key opens the column menu, and Alt+ArrowLeft / Alt+ArrowRight resize the column. Escape from that menu
|
|
30
|
+
returns to the same header cell. An empty table keeps the header row reachable.
|
|
31
|
+
- Keyboard focus arriving on a table with nothing active activates the first cell, so the first arrow
|
|
32
|
+
key already moves and no Tab is spent entering.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **The column menu buttons are no longer Tab stops** (`tabindex="-1"`, like the row checkboxes) — the
|
|
37
|
+
table is one Tab stop and the header row reaches each column's menu. Pages that relied on tabbing to a
|
|
38
|
+
menu button reach it from the header row instead.
|
|
39
|
+
|
|
3
40
|
## [0.49.1] - 2026-10-06
|
|
4
41
|
|
|
5
42
|
### Fixed
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ npm install @iyulab/flex-table
|
|
|
67
67
|
- **Data Mode** — Client-side or server-side sorting/filtering (`dataMode`)
|
|
68
68
|
- **Context Menu** — `context-menu` event for custom right-click menus
|
|
69
69
|
- **React Wrapper** — `@iyulab/flex-table/react` subpath for idiomatic React usage
|
|
70
|
-
- **ARIA** — `role="grid"
|
|
70
|
+
- **ARIA** — `role="grid"` with roving focus (the focus sits on the active cell or header cell, so screen readers announce each move), `aria-sort`, `aria-selected`, `aria-readonly`, `aria-invalid`, `aria-rowcount`, `aria-colcount`, `aria-rowindex`, `aria-colindex`
|
|
71
71
|
|
|
72
72
|
## Sizing
|
|
73
73
|
|
|
@@ -437,8 +437,8 @@ package dependency; CSS custom properties are resolved at render time, not impor
|
|
|
437
437
|
|
|
438
438
|
| Key | Action |
|
|
439
439
|
|-----|--------|
|
|
440
|
-
| Arrow keys | Navigate cells |
|
|
441
|
-
| Tab / Shift+Tab | Move to next/previous cell |
|
|
440
|
+
| Arrow keys | Navigate cells (ArrowUp from the first row moves onto the header row) |
|
|
441
|
+
| Tab / Shift+Tab | Move to next/previous cell; past the last (before the first) cell, leave the table |
|
|
442
442
|
| Enter / F2 | Start editing (Enter on a non-editable cell fires `row-activate`) |
|
|
443
443
|
| Typing a printable character | Start editing an editable cell with that character |
|
|
444
444
|
| Escape | Cancel edit / clear selection / close the find panel |
|
|
@@ -455,9 +455,17 @@ package dependency; CSS custom properties are resolved at render time, not impor
|
|
|
455
455
|
| Ctrl+Shift+Z / Ctrl+Y | Redo |
|
|
456
456
|
| Alt+ArrowLeft / Alt+ArrowRight | Resize current column (±20px) |
|
|
457
457
|
| Ctrl+Click header | Select entire column |
|
|
458
|
+
| ArrowLeft / ArrowRight / Home / End (header row) | Move along the header; ArrowDown returns to the first row |
|
|
459
|
+
| Enter / Space (header row) | Sort the column (ascending → descending → none); with Shift, add it to the sort |
|
|
460
|
+
| Alt+ArrowDown or the context-menu key (header row) | Open the column menu |
|
|
458
461
|
| Enter / Space on a column menu button | Open the column menu |
|
|
459
462
|
| ArrowUp / ArrowDown / Home / End (column menu) | Move between menu items |
|
|
460
|
-
| Escape (column menu) | Close the menu and return focus to
|
|
463
|
+
| Escape (column menu) | Close the menu and return focus to where it was opened from |
|
|
464
|
+
|
|
465
|
+
The table is one Tab stop: keyboard focus arriving on it activates the first cell (the first header cell
|
|
466
|
+
when there are no rows), and the column menu buttons and row checkboxes are reached by keys, not Tab.
|
|
467
|
+
While the table has the focus, the focus sits on the active cell (or header cell) itself — `document.activeElement`
|
|
468
|
+
is the table, and its `shadowRoot.activeElement` is that cell.
|
|
461
469
|
|
|
462
470
|
## Localization
|
|
463
471
|
|
|
@@ -159,6 +159,11 @@ var x = r`
|
|
|
159
159
|
|
|
160
160
|
.ft-header-cell.ft-sortable { cursor: pointer; }
|
|
161
161
|
.ft-header-cell.ft-sortable:hover { background: var(--ft-header-hover-bg); }
|
|
162
|
+
/* The header cell the keyboard is on (ArrowUp from the first row) — same ring as the active body cell. */
|
|
163
|
+
.ft-header-cell.ft-header-active {
|
|
164
|
+
outline: 2px solid var(--ft-active-color);
|
|
165
|
+
outline-offset: -2px;
|
|
166
|
+
}
|
|
162
167
|
|
|
163
168
|
.ft-header-cell.ft-header-align-center { justify-content: center; }
|
|
164
169
|
.ft-header-cell.ft-header-align-end { justify-content: flex-end; }
|
|
@@ -1887,7 +1892,23 @@ var K = {
|
|
|
1887
1892
|
lte: "≤"
|
|
1888
1893
|
}, q = 120, J = 40, Y = 20, X = 32, Z = 5, Ze = 200, Q = class extends n {
|
|
1889
1894
|
constructor(...e) {
|
|
1890
|
-
super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = X, this._targetFloor = 0, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._editingCell = null, this._sortCriteria = [], this._selection = new oe(), this._editing = new se(), this._rowSelection = new A(), this._undo = new j(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._warnedUnconstrained = !1, this.
|
|
1895
|
+
super(...e), this.columns = [], this._data = [], this._inUndoRedo = !1, this.clearUndoOnDataChange = !1, this.clearSelectionOnDataChange = !1, this._rowHeightFromCss = X, this._targetFloor = 0, this.showRowNumbers = !1, this.theme = void 0, this.maxRows = 0, this.editable = !0, this.showFilters = !1, this.showContextMenu = !1, this.frozenRows = 0, this.emptyMessage = "No data", this.noMatchingMessage = "No matching data", this.loading = !1, this.importEnabled = !1, this.selectable = !1, this.dataMode = "client", this.footerData = null, this.stylesheets = [], this._scrollTop = 0, this._scrollLeft = 0, this._viewportHeight = 0, this._viewportWidth = 0, this._colLeftOffsets = [], this._totalRowWidth = 0, this._baseStyleSheets = [], this._activeCell = null, this._headerCol = null, this._focusedCellEl = null, this._editingCell = null, this._sortCriteria = [], this._selection = new oe(), this._editing = new se(), this._rowSelection = new A(), this._undo = new j(), this._filters = [], this._filteredIndices = [], this._sortedIndices = [], this._openFilterKey = null, this._rowSelectionVersion = 0, this._lastCheckboxRowIndex = null, this._checkboxShiftPending = !1, this._autocompleteState = null, this._headerMenu = null, this._bodyContextMenu = null, this._commentPopup = null, this._viewDirty = !0, this._isDragging = !1, this._wasDrag = !1, this._resizing = null, this._resizeCleanup = null, this._wasHeaderDrag = !1, this._wasRowDrag = !1, this._colDrag = null, this._colDragIndicatorLeft = null, this._fillDrag = null, this._rowDrag = null, this._rowDragIndicatorY = null, this._findState = null, this._columnWidths = /* @__PURE__ */ new Map(), this._hostResizeObserver = null, this._comments = /* @__PURE__ */ new Map(), this._isDragOver = !1, this._warnedUnconstrained = !1, this._onHostFocus = (e) => {
|
|
1896
|
+
e.composedPath()[0] !== this || this._activeCell || this._headerCol !== null || this.visibleColumns.length !== 0 && this.matches(":focus-visible") && (this._visibleRowCount > 0 ? (this._selection.setActive(0, 0), this._syncActiveCell()) : this._headerCol = 0);
|
|
1897
|
+
}, this._onFocusIn = (e) => {
|
|
1898
|
+
let t = e.composedPath()[0];
|
|
1899
|
+
t !== this && this._isGridSurface(t) && (this._focusedCellEl = t, this.tabIndex === 0 && (this._hostTabIndexLowered = !0, this.tabIndex = -1));
|
|
1900
|
+
}, this._onFocusOut = (e) => {
|
|
1901
|
+
let t = e.relatedTarget;
|
|
1902
|
+
if (t && (t === this || this.contains(t) || this.shadowRoot?.contains(t))) return;
|
|
1903
|
+
let n = e.composedPath()[0];
|
|
1904
|
+
requestAnimationFrame(() => {
|
|
1905
|
+
if (n instanceof HTMLElement && n === this._focusedCellEl && !n.isConnected) {
|
|
1906
|
+
this._syncGridFocus();
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
document.activeElement !== this && (this._focusedCellEl = null, this._hostTabIndexLowered && (this._hostTabIndexLowered = !1, this.tabIndex = 0));
|
|
1910
|
+
});
|
|
1911
|
+
}, this._hostTabIndexLowered = !1, this._onCommentPopupOutsideClick = () => {
|
|
1891
1912
|
this._commitCommentPopup();
|
|
1892
1913
|
}, this._invalidCells = /* @__PURE__ */ new Map(), this._textFilterState = /* @__PURE__ */ new Map(), this._numberFilterState = /* @__PURE__ */ new Map(), this._dateFilterState = /* @__PURE__ */ new Map(), this._emptyFilterState = /* @__PURE__ */ new Map();
|
|
1893
1914
|
}
|
|
@@ -2418,10 +2439,10 @@ var K = {
|
|
|
2418
2439
|
};
|
|
2419
2440
|
}
|
|
2420
2441
|
connectedCallback() {
|
|
2421
|
-
super.connectedCallback(), this._onScroll = this._onScroll.bind(this), this._onKeyDown = this._onKeyDown.bind(this), this._onDocumentClick = this._onDocumentClick.bind(this), this._onContextMenu = this._onContextMenu.bind(this), this._onDragover = this._onDragover.bind(this), this._onDragleave = this._onDragleave.bind(this), this._onDrop = this._onDrop.bind(this), this.addEventListener("scroll", this._onScroll, { passive: !0 }), this.addEventListener("keydown", this._onKeyDown), this.addEventListener("contextmenu", this._onContextMenu), this.addEventListener("dragover", this._onDragover), this.addEventListener("dragleave", this._onDragleave), this.addEventListener("drop", this._onDrop), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "grid"), typeof ResizeObserver < "u" && (this._hostResizeObserver = new ResizeObserver(() => this._measureViewport()), this._hostResizeObserver.observe(this));
|
|
2442
|
+
super.connectedCallback(), this._onScroll = this._onScroll.bind(this), this._onKeyDown = this._onKeyDown.bind(this), this._onDocumentClick = this._onDocumentClick.bind(this), this._onContextMenu = this._onContextMenu.bind(this), this._onDragover = this._onDragover.bind(this), this._onDragleave = this._onDragleave.bind(this), this._onDrop = this._onDrop.bind(this), this.addEventListener("scroll", this._onScroll, { passive: !0 }), this.addEventListener("keydown", this._onKeyDown), this.addEventListener("focus", this._onHostFocus), this.renderRoot.addEventListener("focusin", this._onFocusIn), this.renderRoot.addEventListener("focusout", this._onFocusOut), this.addEventListener("contextmenu", this._onContextMenu), this.addEventListener("dragover", this._onDragover), this.addEventListener("dragleave", this._onDragleave), this.addEventListener("drop", this._onDrop), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "grid"), typeof ResizeObserver < "u" && (this._hostResizeObserver = new ResizeObserver(() => this._measureViewport()), this._hostResizeObserver.observe(this));
|
|
2422
2443
|
}
|
|
2423
2444
|
disconnectedCallback() {
|
|
2424
|
-
super.disconnectedCallback(), this.removeEventListener("scroll", this._onScroll), this.removeEventListener("keydown", this._onKeyDown), this.removeEventListener("contextmenu", this._onContextMenu), this.removeEventListener("dragover", this._onDragover), this.removeEventListener("dragleave", this._onDragleave), this.removeEventListener("drop", this._onDrop), document.removeEventListener("click", this._onDocumentClick), document.removeEventListener("mousedown", this._onCommentPopupOutsideClick), this._isDragging = !1, this._wasDrag = !1, this._resizeCleanup &&= (this._resizeCleanup(), null), this._hostResizeObserver &&= (this._hostResizeObserver.disconnect(), null);
|
|
2445
|
+
super.disconnectedCallback(), this.removeEventListener("scroll", this._onScroll), this.removeEventListener("keydown", this._onKeyDown), this.removeEventListener("focus", this._onHostFocus), this.renderRoot.removeEventListener("focusin", this._onFocusIn), this.renderRoot.removeEventListener("focusout", this._onFocusOut), this.removeEventListener("contextmenu", this._onContextMenu), this.removeEventListener("dragover", this._onDragover), this.removeEventListener("dragleave", this._onDragleave), this.removeEventListener("drop", this._onDrop), document.removeEventListener("click", this._onDocumentClick), document.removeEventListener("mousedown", this._onCommentPopupOutsideClick), this._isDragging = !1, this._wasDrag = !1, this._resizeCleanup &&= (this._resizeCleanup(), null), this._hostResizeObserver &&= (this._hostResizeObserver.disconnect(), null);
|
|
2425
2446
|
}
|
|
2426
2447
|
firstUpdated() {
|
|
2427
2448
|
this._readDensityTokens(), this._measureViewport(), this.shadowRoot && Array.isArray(this.shadowRoot.adoptedStyleSheets) && (this._baseStyleSheets = [...this.shadowRoot.adoptedStyleSheets]), this._syncStylesheets();
|
|
@@ -2472,7 +2493,7 @@ var K = {
|
|
|
2472
2493
|
(!(e.size <= 2 && !e.has("data") && !e.has("columns") && !e.has("_openFilterKey") && !e.has("_editingCell") && !e.has("_activeCell") && (e.has("_scrollTop") || e.has("_scrollLeft"))) || this._viewDirty) && (this._recomputeView(), this._viewDirty = !1), this._updateColOffsets(), this._selection.setDimensions(this._visibleRowCount, this.visibleColumns.length), this._rowSelection.setRowCount(this._visibleRowCount);
|
|
2473
2494
|
}
|
|
2474
2495
|
updated(e) {
|
|
2475
|
-
this._focusEditor(), this._adjustFilterDropdown(), e.has("_headerMenu") && this._keepMenuInView(".ft-header-menu"), e.has("_bodyContextMenu") && this._bodyContextMenu && (this._keepMenuInView(".ft-body-context-menu"), this.shadowRoot?.querySelector(".ft-body-context-menu [role=\"menuitem\"]")?.focus()), e.has("stylesheets") && this._syncStylesheets();
|
|
2496
|
+
this._focusEditor(), this._syncGridFocus(), this._adjustFilterDropdown(), e.has("_headerMenu") && this._keepMenuInView(".ft-header-menu"), e.has("_bodyContextMenu") && this._bodyContextMenu && (this._keepMenuInView(".ft-body-context-menu"), this.shadowRoot?.querySelector(".ft-body-context-menu [role=\"menuitem\"]")?.focus()), e.has("stylesheets") && this._syncStylesheets();
|
|
2476
2497
|
let t = String(1 + this._visibleRowCount + +!!this.footerData), n = String(this.visibleColumns.length);
|
|
2477
2498
|
if (this.getAttribute("aria-rowcount") !== t && this.setAttribute("aria-rowcount", t), this.getAttribute("aria-colcount") !== n && this.setAttribute("aria-colcount", n), this.loading ? this.getAttribute("aria-busy") !== "true" && this.setAttribute("aria-busy", "true") : this.hasAttribute("aria-busy") && this.removeAttribute("aria-busy"), e.has("_commentPopup") && this._commentPopup) {
|
|
2478
2499
|
let e = this.shadowRoot?.querySelector(".ft-comment-popup textarea");
|
|
@@ -2528,28 +2549,34 @@ var K = {
|
|
|
2528
2549
|
this._openFilterKey &&= null, this._headerMenu &&= null, this._bodyContextMenu &&= null;
|
|
2529
2550
|
}
|
|
2530
2551
|
_onContextMenu(e) {
|
|
2531
|
-
let t = e.composedPath().find((e) => e instanceof HTMLElement && e.classList.contains("ft-cell"));
|
|
2532
|
-
if (!
|
|
2552
|
+
let t = e.composedPath(), n = t.find((e) => e instanceof HTMLElement && e.classList.contains("ft-cell"));
|
|
2553
|
+
if (!n) {
|
|
2554
|
+
if (t[0] === this && this._headerCol !== null) {
|
|
2555
|
+
let t = this.visibleColumns[this._headerCol];
|
|
2556
|
+
t && (e.preventDefault(), this._openColumnMenu(t));
|
|
2557
|
+
}
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2533
2560
|
e.preventDefault();
|
|
2534
|
-
let
|
|
2535
|
-
if (!
|
|
2536
|
-
let
|
|
2537
|
-
if (
|
|
2538
|
-
let
|
|
2539
|
-
if (!
|
|
2540
|
-
let
|
|
2561
|
+
let r = n.parentElement;
|
|
2562
|
+
if (!r || !r.classList.contains("ft-row")) return;
|
|
2563
|
+
let i = parseInt(n.dataset.colIndex ?? "-1", 10), a = r.style.top, o = Math.round(parseInt(a, 10) / this.rowHeight);
|
|
2564
|
+
if (i < 0 || o < 0) return;
|
|
2565
|
+
let s = this._toDataIndex(o), c = this.visibleColumns[i];
|
|
2566
|
+
if (!c) return;
|
|
2567
|
+
let l = this._emit("context-menu", {
|
|
2541
2568
|
x: e.clientX,
|
|
2542
2569
|
y: e.clientY,
|
|
2543
|
-
row:
|
|
2544
|
-
col:
|
|
2545
|
-
key:
|
|
2546
|
-
value: this.data[
|
|
2547
|
-
rowData: this.data[
|
|
2570
|
+
row: s,
|
|
2571
|
+
col: i,
|
|
2572
|
+
key: c.key,
|
|
2573
|
+
value: this.data[s]?.[c.key],
|
|
2574
|
+
rowData: this.data[s]
|
|
2548
2575
|
}, { cancelable: !0 });
|
|
2549
|
-
this._cancelCommentPopup(), this.showContextMenu && !
|
|
2550
|
-
rowIndex:
|
|
2551
|
-
colIndex:
|
|
2552
|
-
dataIndex:
|
|
2576
|
+
this._cancelCommentPopup(), this.showContextMenu && !l.defaultPrevented && (this._bodyContextMenu = {
|
|
2577
|
+
rowIndex: o,
|
|
2578
|
+
colIndex: i,
|
|
2579
|
+
dataIndex: s,
|
|
2553
2580
|
x: e.clientX,
|
|
2554
2581
|
y: e.clientY
|
|
2555
2582
|
}, requestAnimationFrame(() => {
|
|
@@ -2775,7 +2802,7 @@ var K = {
|
|
|
2775
2802
|
this._autocompleteState = null, this._applyEdit(e), this._selection.moveDown(), this._syncActiveCell();
|
|
2776
2803
|
}
|
|
2777
2804
|
_syncActiveCell() {
|
|
2778
|
-
this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._scrollToActiveCell(), this._dispatchSelectionEvent();
|
|
2805
|
+
this._activeCell = this._selection.activeCell ? { ...this._selection.activeCell } : null, this._activeCell && (this._headerCol = null), this._scrollToActiveCell(), this._dispatchSelectionEvent();
|
|
2779
2806
|
}
|
|
2780
2807
|
_onKeyDown(e) {
|
|
2781
2808
|
if (this._editing.current || this._openFilterKey && e.composedPath().some((e) => e instanceof Element && e.classList.contains("ft-filter-dropdown"))) return;
|
|
@@ -2789,7 +2816,22 @@ var K = {
|
|
|
2789
2816
|
"y"
|
|
2790
2817
|
].includes(t) && this._handleCtrlKey(e)) return;
|
|
2791
2818
|
}
|
|
2792
|
-
if (t.length !== 0 && this.
|
|
2819
|
+
if (t.length !== 0 && (this._isGridSurface(e.composedPath()[0]) || e.ctrlKey || e.metaKey)) {
|
|
2820
|
+
if (this._headerCol !== null) {
|
|
2821
|
+
this._onHeaderKeyDown(e, t);
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
if (this._visibleRowCount === 0) {
|
|
2825
|
+
[
|
|
2826
|
+
"ArrowDown",
|
|
2827
|
+
"ArrowUp",
|
|
2828
|
+
"ArrowLeft",
|
|
2829
|
+
"ArrowRight",
|
|
2830
|
+
"Home",
|
|
2831
|
+
"End"
|
|
2832
|
+
].includes(e.key) && (e.preventDefault(), this._headerCol = 0);
|
|
2833
|
+
return;
|
|
2834
|
+
}
|
|
2793
2835
|
if ((e.key === "Enter" || e.key === "F2") && this._activeCell && !_(e)) {
|
|
2794
2836
|
e.preventDefault();
|
|
2795
2837
|
let n = t[this._activeCell.col];
|
|
@@ -2802,7 +2844,6 @@ var K = {
|
|
|
2802
2844
|
"ArrowUp",
|
|
2803
2845
|
"ArrowLeft",
|
|
2804
2846
|
"ArrowRight",
|
|
2805
|
-
"Tab",
|
|
2806
2847
|
"Home",
|
|
2807
2848
|
"End"
|
|
2808
2849
|
].includes(e.key)) {
|
|
@@ -2825,10 +2866,69 @@ var K = {
|
|
|
2825
2866
|
e && this._isCellEditable(e) && this._startEdit();
|
|
2826
2867
|
return;
|
|
2827
2868
|
}
|
|
2869
|
+
if (e.key === "ArrowUp" && !e.shiftKey && !e.altKey && this._activeCell?.row === 0) {
|
|
2870
|
+
e.preventDefault(), this._enterHeader(this._activeCell.col);
|
|
2871
|
+
return;
|
|
2872
|
+
}
|
|
2828
2873
|
this._handleNavigation(e) && (e.preventDefault(), this._syncActiveCell());
|
|
2829
2874
|
}
|
|
2830
2875
|
}
|
|
2831
2876
|
}
|
|
2877
|
+
_onHeaderKeyDown(e, t) {
|
|
2878
|
+
if (e.ctrlKey || e.metaKey) return;
|
|
2879
|
+
let n = Math.min(this._headerCol ?? 0, t.length - 1), r = t[n], i;
|
|
2880
|
+
switch (e.key) {
|
|
2881
|
+
case "ArrowLeft":
|
|
2882
|
+
case "ArrowRight":
|
|
2883
|
+
if (e.altKey) {
|
|
2884
|
+
e.preventDefault(), this._resizeColumnBy(r.key, e.key === "ArrowRight" ? Y : -20);
|
|
2885
|
+
return;
|
|
2886
|
+
}
|
|
2887
|
+
i = e.key === "ArrowLeft" ? Math.max(0, n - 1) : Math.min(t.length - 1, n + 1);
|
|
2888
|
+
break;
|
|
2889
|
+
case "Home":
|
|
2890
|
+
i = 0;
|
|
2891
|
+
break;
|
|
2892
|
+
case "End":
|
|
2893
|
+
i = t.length - 1;
|
|
2894
|
+
break;
|
|
2895
|
+
case "ArrowDown":
|
|
2896
|
+
e.preventDefault(), e.altKey ? this._openColumnMenu(r) : this._visibleRowCount > 0 && (this._selection.setActive(0, n), this._syncActiveCell());
|
|
2897
|
+
return;
|
|
2898
|
+
case "Enter":
|
|
2899
|
+
case " ":
|
|
2900
|
+
if (_(e)) return;
|
|
2901
|
+
e.preventDefault(), r.sortable !== !1 && this._toggleSort(r, e.shiftKey);
|
|
2902
|
+
return;
|
|
2903
|
+
default: return;
|
|
2904
|
+
}
|
|
2905
|
+
e.preventDefault(), this._headerCol = i, this._scrollColumnIntoView(i);
|
|
2906
|
+
}
|
|
2907
|
+
_enterHeader(e) {
|
|
2908
|
+
this._selection.clear(), this._syncActiveCell(), this._headerCol = e, this._scrollColumnIntoView(e);
|
|
2909
|
+
}
|
|
2910
|
+
_isGridSurface(e) {
|
|
2911
|
+
return e === this || e instanceof HTMLElement && (e.classList.contains("ft-cell") || e.classList.contains("ft-header-cell")) && !e.classList.contains("ft-editing");
|
|
2912
|
+
}
|
|
2913
|
+
_keyboardCellEl() {
|
|
2914
|
+
let e = this.shadowRoot;
|
|
2915
|
+
if (!e) return null;
|
|
2916
|
+
if (this._headerCol !== null) return e.querySelector(`.ft-header-cell[data-col-index="${this._headerCol}"]`);
|
|
2917
|
+
let t = this._activeCell;
|
|
2918
|
+
return t ? e.querySelector(`.ft-row[aria-rowindex="${t.row + 2}"] .ft-cell[data-col-index="${t.col}"]`) : null;
|
|
2919
|
+
}
|
|
2920
|
+
_syncGridFocus() {
|
|
2921
|
+
let e = this.shadowRoot;
|
|
2922
|
+
if (!e) return;
|
|
2923
|
+
let t = e.activeElement;
|
|
2924
|
+
if (document.activeElement !== this) {
|
|
2925
|
+
this._focusedCellEl && !this._focusedCellEl.isConnected && (document.activeElement === document.body || document.activeElement === null) && (this._focusedCellEl = null, (this._keyboardCellEl() ?? this).focus({ preventScroll: !0 }));
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2928
|
+
if (t && !this._isGridSurface(t)) return;
|
|
2929
|
+
let n = this._keyboardCellEl() ?? this;
|
|
2930
|
+
n !== (t ?? this) && n.focus({ preventScroll: !0 });
|
|
2931
|
+
}
|
|
2832
2932
|
_handleCtrlKey(e) {
|
|
2833
2933
|
if (!(e.ctrlKey || e.metaKey) || e.altKey) return !1;
|
|
2834
2934
|
switch (e.key.toLowerCase()) {
|
|
@@ -2874,7 +2974,10 @@ var K = {
|
|
|
2874
2974
|
case "ArrowDown": return e.shiftKey ? this._selection.shiftMoveDown() : this._selection.moveDown(), !0;
|
|
2875
2975
|
case "ArrowLeft": return e.shiftKey ? this._selection.shiftMoveLeft() : this._selection.moveLeft(), !0;
|
|
2876
2976
|
case "ArrowRight": return e.shiftKey ? this._selection.shiftMoveRight() : this._selection.moveRight(), !0;
|
|
2877
|
-
case "Tab":
|
|
2977
|
+
case "Tab": {
|
|
2978
|
+
let t = this._selection.activeCell, n = e.shiftKey ? this._selection.movePrev() : this._selection.moveNext();
|
|
2979
|
+
return !(t && n && t.row === n.row && t.col === n.col);
|
|
2980
|
+
}
|
|
2878
2981
|
case "Home": return e.ctrlKey ? this._selection.moveToStart() : this._selection.moveToRowStart(), !0;
|
|
2879
2982
|
case "End": return e.ctrlKey ? this._selection.moveToEnd() : this._selection.moveToRowEnd(), !0;
|
|
2880
2983
|
case "Escape": return this._findState ? (this._closeFindPanel(), !0) : (this._selection.clear(), !0);
|
|
@@ -3102,24 +3205,29 @@ var K = {
|
|
|
3102
3205
|
_scrollToActiveCell() {
|
|
3103
3206
|
if (!this._activeCell) return;
|
|
3104
3207
|
let e = this._activeCell.row * this.rowHeight + this.headerHeight, t = e + this.rowHeight;
|
|
3105
|
-
this._activeCell.row < this._frozenRowCount || (e < this.scrollTop + this.headerHeight + this.frozenRowsHeight ? this.scrollTop = e - this.headerHeight - this.frozenRowsHeight : t > this.scrollTop + this.clientHeight && (this.scrollTop = t - this.clientHeight));
|
|
3106
|
-
|
|
3107
|
-
|
|
3208
|
+
this._activeCell.row < this._frozenRowCount || (e < this.scrollTop + this.headerHeight + this.frozenRowsHeight ? this.scrollTop = e - this.headerHeight - this.frozenRowsHeight : t > this.scrollTop + this.clientHeight && (this.scrollTop = t - this.clientHeight)), this._scrollColumnIntoView(this._activeCell.col);
|
|
3209
|
+
}
|
|
3210
|
+
_scrollColumnIntoView(e) {
|
|
3211
|
+
let t = this.visibleColumns, n = this._colLeftOffsets[e] ?? 0, r = n + this._getColWidth(t[e]);
|
|
3212
|
+
n < this.scrollLeft ? this.scrollLeft = n : r > this.scrollLeft + this.clientWidth && (this.scrollLeft = r - this.clientWidth);
|
|
3108
3213
|
}
|
|
3109
3214
|
_dispatchSelectionEvent() {
|
|
3110
3215
|
this._emit("cell-select", this._activeCell ? { ...this._activeCell } : null);
|
|
3111
3216
|
}
|
|
3112
|
-
_onHeaderClick(
|
|
3217
|
+
_onHeaderClick(e, t) {
|
|
3113
3218
|
if (this._wasHeaderDrag) {
|
|
3114
3219
|
this._wasHeaderDrag = !1;
|
|
3115
3220
|
return;
|
|
3116
3221
|
}
|
|
3117
|
-
let
|
|
3118
|
-
if (
|
|
3119
|
-
this._selectColumn(
|
|
3222
|
+
let n = this.visibleColumns.indexOf(t);
|
|
3223
|
+
if (e.ctrlKey || e.metaKey) {
|
|
3224
|
+
this._selectColumn(n);
|
|
3120
3225
|
return;
|
|
3121
3226
|
}
|
|
3122
|
-
|
|
3227
|
+
t.sortable !== !1 && this._toggleSort(t, e.shiftKey);
|
|
3228
|
+
}
|
|
3229
|
+
_toggleSort(t, n) {
|
|
3230
|
+
this._sortCriteria = e(this._sortCriteria, t.key, n), this.dataMode !== "server" && this._recomputeView(), this.requestUpdate(), this._emit("sort-change", { criteria: [...this._sortCriteria] });
|
|
3123
3231
|
}
|
|
3124
3232
|
_selectColumn(e) {
|
|
3125
3233
|
let t = this._visibleRowCount;
|
|
@@ -3158,7 +3266,8 @@ var K = {
|
|
|
3158
3266
|
n ? "ft-sortable" : "",
|
|
3159
3267
|
u ? "ft-pinned" : "",
|
|
3160
3268
|
d === "center" ? "ft-header-align-center" : "",
|
|
3161
|
-
d === "end" ? "ft-header-align-end" : ""
|
|
3269
|
+
d === "end" ? "ft-header-align-end" : "",
|
|
3270
|
+
this._headerCol === t ? "ft-header-active" : ""
|
|
3162
3271
|
].filter(Boolean).join(" "), p = n ? r ? r.direction === "asc" ? "ascending" : "descending" : "none" : void 0, m = this._getColWidth(e), h = this.headerHeight, g = this._colLeftOffsets[t] ?? 0, _;
|
|
3163
3272
|
_ = c ? `position: absolute; top: 0; left: ${this._scrollLeft + this._getPinnedLeft(t)}px; width: ${m}px; height: ${h}px; z-index: 4;` : l ? `position: absolute; top: 0; left: ${this._getPinnedRightLeft(t)}px; width: ${m}px; height: ${h}px; z-index: 4;` : `left: ${g}px; width: ${m}px; height: ${h}px;`;
|
|
3164
3273
|
let v = this._colDrag?.active && this._colDrag.colIndex === t, y = [...f.split(" "), v ? "ft-col-dragging" : ""].filter(Boolean).join(" "), b = this.columns, x = b.findIndex((t) => t.key === e.key), S = [];
|
|
@@ -3167,6 +3276,7 @@ var K = {
|
|
|
3167
3276
|
return i`
|
|
3168
3277
|
<div class=${y}
|
|
3169
3278
|
role="columnheader"
|
|
3279
|
+
tabindex="-1"
|
|
3170
3280
|
aria-colindex=${t + 1}
|
|
3171
3281
|
data-col-index=${t}
|
|
3172
3282
|
style=${_}
|
|
@@ -3175,7 +3285,7 @@ var K = {
|
|
|
3175
3285
|
@mousedown=${(n) => this._onHeaderMouseDown(n, e, t)}
|
|
3176
3286
|
@click=${n ? (t) => this._onHeaderClick(t, e) : void 0}>
|
|
3177
3287
|
${C ? i`
|
|
3178
|
-
<button class="ft-hidden-col-indicator"
|
|
3288
|
+
<button class="ft-hidden-col-indicator" tabindex="-1"
|
|
3179
3289
|
title=${k("showHiddenColumns")}
|
|
3180
3290
|
@click=${(t) => {
|
|
3181
3291
|
t.stopPropagation(), this._showHiddenBefore(e);
|
|
@@ -3186,6 +3296,7 @@ var K = {
|
|
|
3186
3296
|
${o >= 0 ? i`<span class="ft-sort-order">${o + 1}</span>` : ""}
|
|
3187
3297
|
<button class="ft-column-menu-btn ${s ? "ft-filter-active" : ""}"
|
|
3188
3298
|
type="button"
|
|
3299
|
+
tabindex="-1"
|
|
3189
3300
|
data-key=${e.key}
|
|
3190
3301
|
title=${k("columnMenu")}
|
|
3191
3302
|
aria-label=${k("columnMenuFor", { header: e.label })}
|
|
@@ -3232,12 +3343,15 @@ var K = {
|
|
|
3232
3343
|
this._headerMenu = null;
|
|
3233
3344
|
return;
|
|
3234
3345
|
}
|
|
3235
|
-
|
|
3346
|
+
this._openColumnMenu(t, e.currentTarget);
|
|
3347
|
+
}
|
|
3348
|
+
_openColumnMenu(e, t = this._columnMenuButton(e.key)) {
|
|
3349
|
+
let n = t?.getBoundingClientRect();
|
|
3236
3350
|
this._openFilterKey = null, this._headerMenu = {
|
|
3237
|
-
key:
|
|
3238
|
-
x: n
|
|
3239
|
-
y: n
|
|
3240
|
-
hiddenNeighbors: this._hiddenNeighbors(
|
|
3351
|
+
key: e.key,
|
|
3352
|
+
x: n?.left ?? 0,
|
|
3353
|
+
y: n?.bottom ?? 0,
|
|
3354
|
+
hiddenNeighbors: this._hiddenNeighbors(e)
|
|
3241
3355
|
}, requestAnimationFrame(() => {
|
|
3242
3356
|
document.addEventListener("click", this._onDocumentClick, { once: !0 });
|
|
3243
3357
|
}), this.updateComplete.then(() => this._menuItems()[0]?.focus());
|
|
@@ -3251,7 +3365,7 @@ var K = {
|
|
|
3251
3365
|
}
|
|
3252
3366
|
_closeHeaderMenu(e) {
|
|
3253
3367
|
let t = this._headerMenu?.key;
|
|
3254
|
-
this._headerMenu = null, e && t && this._columnMenuButton(t)?.focus();
|
|
3368
|
+
this._headerMenu = null, e && t && (this._headerCol === null ? this._columnMenuButton(t)?.focus() : this.focus());
|
|
3255
3369
|
}
|
|
3256
3370
|
_onHeaderMenuKeydown(e) {
|
|
3257
3371
|
this._onMenuKeydown(e, ".ft-header-menu", (e) => this._closeHeaderMenu(e));
|
|
@@ -3427,9 +3541,15 @@ var K = {
|
|
|
3427
3541
|
}
|
|
3428
3542
|
_closeFilterDropdown(e = !0) {
|
|
3429
3543
|
let t = this._openFilterKey;
|
|
3430
|
-
this._openFilterKey = null, e && t !== null
|
|
3431
|
-
|
|
3432
|
-
|
|
3544
|
+
if (this._openFilterKey = null, e && t !== null) {
|
|
3545
|
+
if (this._headerCol !== null) {
|
|
3546
|
+
this.focus();
|
|
3547
|
+
return;
|
|
3548
|
+
}
|
|
3549
|
+
this.updateComplete.then(() => {
|
|
3550
|
+
[...this.shadowRoot?.querySelectorAll(".ft-column-menu-btn") ?? []].find((e) => e.dataset.key === t)?.focus();
|
|
3551
|
+
});
|
|
3552
|
+
}
|
|
3433
3553
|
}
|
|
3434
3554
|
_onFilterDialogKeydown(e) {
|
|
3435
3555
|
if (e.key !== "Tab") return;
|
|
@@ -4350,6 +4470,7 @@ var K = {
|
|
|
4350
4470
|
return i`
|
|
4351
4471
|
<div class=${E ? C + " ft-has-comment" : C}
|
|
4352
4472
|
role="gridcell"
|
|
4473
|
+
tabindex="-1"
|
|
4353
4474
|
aria-colindex=${r + 1}
|
|
4354
4475
|
data-col-index=${r}
|
|
4355
4476
|
aria-selected=${v ? "true" : "false"}
|
|
@@ -4486,7 +4607,7 @@ G([s({ type: Array })], Q.prototype, "columns", void 0), G([s({
|
|
|
4486
4607
|
})], Q.prototype, "footerData", void 0), G([s({ attribute: !1 })], Q.prototype, "stylesheets", void 0), G([s({
|
|
4487
4608
|
type: Number,
|
|
4488
4609
|
attribute: "max-undo-size"
|
|
4489
|
-
})], Q.prototype, "maxUndoSize", null), G([c()], Q.prototype, "_scrollTop", void 0), G([c()], Q.prototype, "_scrollLeft", void 0), G([c()], Q.prototype, "_viewportHeight", void 0), G([c()], Q.prototype, "_viewportWidth", void 0), G([c()], Q.prototype, "_activeCell", void 0), G([c()], Q.prototype, "_editingCell", void 0), G([c()], Q.prototype, "_sortCriteria", void 0), G([c()], Q.prototype, "_openFilterKey", void 0), G([c()], Q.prototype, "_rowSelectionVersion", void 0), G([c()], Q.prototype, "_autocompleteState", void 0), G([c()], Q.prototype, "_headerMenu", void 0), G([c()], Q.prototype, "_bodyContextMenu", void 0), G([c()], Q.prototype, "_commentPopup", void 0), G([c()], Q.prototype, "_isDragOver", void 0), Q = G([o("flex-table")], Q);
|
|
4610
|
+
})], Q.prototype, "maxUndoSize", null), G([c()], Q.prototype, "_scrollTop", void 0), G([c()], Q.prototype, "_scrollLeft", void 0), G([c()], Q.prototype, "_viewportHeight", void 0), G([c()], Q.prototype, "_viewportWidth", void 0), G([c()], Q.prototype, "_activeCell", void 0), G([c()], Q.prototype, "_headerCol", void 0), G([c()], Q.prototype, "_editingCell", void 0), G([c()], Q.prototype, "_sortCriteria", void 0), G([c()], Q.prototype, "_openFilterKey", void 0), G([c()], Q.prototype, "_rowSelectionVersion", void 0), G([c()], Q.prototype, "_autocompleteState", void 0), G([c()], Q.prototype, "_headerMenu", void 0), G([c()], Q.prototype, "_bodyContextMenu", void 0), G([c()], Q.prototype, "_commentPopup", void 0), G([c()], Q.prototype, "_isDragOver", void 0), Q = G([o("flex-table")], Q);
|
|
4490
4611
|
function Qe(e, t) {
|
|
4491
4612
|
if (t) {
|
|
4492
4613
|
let t = fe(e);
|
package/dist/flex-table.d.ts
CHANGED
|
@@ -108,6 +108,13 @@ export declare class FlexTable extends LitElement {
|
|
|
108
108
|
/** The grid's own compiled styles, captured once so `stylesheets` merges without dropping them. */
|
|
109
109
|
private _baseStyleSheets;
|
|
110
110
|
private _activeCell;
|
|
111
|
+
/**
|
|
112
|
+
* The header cell the keyboard is on — the header row sits above the first body row (ArrowUp from
|
|
113
|
+
* it). Exclusive with an active body cell: entering one leaves the other.
|
|
114
|
+
*/
|
|
115
|
+
private _headerCol;
|
|
116
|
+
/** The cell (body or header) that last held the keyboard focus — to take it back if a re-render drops it. */
|
|
117
|
+
private _focusedCellEl;
|
|
111
118
|
private _editingCell;
|
|
112
119
|
private _sortCriteria;
|
|
113
120
|
private _selection;
|
|
@@ -394,6 +401,40 @@ export declare class FlexTable extends LitElement {
|
|
|
394
401
|
private _selectAutocompleteCandidate;
|
|
395
402
|
private _syncActiveCell;
|
|
396
403
|
private _onKeyDown;
|
|
404
|
+
/**
|
|
405
|
+
* The keyboard on the header row: arrows / Home / End move along it, ArrowDown returns to the body,
|
|
406
|
+
* Enter or Space sorts (Shift adds to the sort), Alt+ArrowDown opens the column menu, Alt+Arrow
|
|
407
|
+
* resizes. Tab leaves the grid.
|
|
408
|
+
*/
|
|
409
|
+
private _onHeaderKeyDown;
|
|
410
|
+
/** Move the keyboard from the body onto the header cell of visible column `colIndex`. */
|
|
411
|
+
private _enterHeader;
|
|
412
|
+
/**
|
|
413
|
+
* Keyboard focus arriving on a grid with nothing active places it on the first cell (the first header
|
|
414
|
+
* cell when the body is empty), so the first arrow already moves and Tab is not spent entering. A
|
|
415
|
+
* pointer focus places the cell it pressed instead.
|
|
416
|
+
*/
|
|
417
|
+
private _onHostFocus;
|
|
418
|
+
/**
|
|
419
|
+
* The grid's own keyboard surface: the host, the active body cell, the active header cell. Keys on
|
|
420
|
+
* anything else inside it (an editor, a menu, a button a cell renders) belong to that control.
|
|
421
|
+
*/
|
|
422
|
+
private _isGridSurface;
|
|
423
|
+
/**
|
|
424
|
+
* The element the keyboard is on — the active header cell, else the active body cell — when it is
|
|
425
|
+
* rendered (the body scrolls it out of the virtual window), else `null`.
|
|
426
|
+
*/
|
|
427
|
+
private _keyboardCellEl;
|
|
428
|
+
/**
|
|
429
|
+
* Roving focus: while the grid holds the focus, the focus sits on the cell the keyboard is on, so
|
|
430
|
+
* assistive technology announces each move (the host cannot point `aria-activedescendant` into its
|
|
431
|
+
* own shadow tree). It moves only between the host and the grid's cells — never out of an editor,
|
|
432
|
+
* a menu or a control that holds it.
|
|
433
|
+
*/
|
|
434
|
+
private _syncGridFocus;
|
|
435
|
+
private _onFocusIn;
|
|
436
|
+
private _onFocusOut;
|
|
437
|
+
private _hostTabIndexLowered;
|
|
397
438
|
private _handleCtrlKey;
|
|
398
439
|
private _handleAltKey;
|
|
399
440
|
/** Widen (positive) or narrow (negative) a visible column by `delta` px, never below its minimum. */
|
|
@@ -423,8 +464,12 @@ export declare class FlexTable extends LitElement {
|
|
|
423
464
|
private _clearRanges;
|
|
424
465
|
private _clearRange;
|
|
425
466
|
private _scrollToActiveCell;
|
|
467
|
+
/** Scroll horizontally so the visible column at `colIndex` is in view — cached column offsets. */
|
|
468
|
+
private _scrollColumnIntoView;
|
|
426
469
|
private _dispatchSelectionEvent;
|
|
427
470
|
private _onHeaderClick;
|
|
471
|
+
/** Cycle `col`'s sort (asc → desc → none); `multi` adds it to the existing criteria (Shift). */
|
|
472
|
+
private _toggleSort;
|
|
428
473
|
private _selectColumn;
|
|
429
474
|
/** Public API: select an entire column by index. */
|
|
430
475
|
selectColumn(colIndex: number): void;
|
|
@@ -456,6 +501,8 @@ export declare class FlexTable extends LitElement {
|
|
|
456
501
|
* and resizing without dragging the 6px handle (WCAG 2.2 SC 2.5.7 / 2.5.8).
|
|
457
502
|
*/
|
|
458
503
|
private _onColumnMenuBtnClick;
|
|
504
|
+
/** Open `col`'s column menu under `anchor` (its menu button by default) and focus the first item. */
|
|
505
|
+
private _openColumnMenu;
|
|
459
506
|
private _menuItems;
|
|
460
507
|
private _columnMenuButton;
|
|
461
508
|
private _closeHeaderMenu;
|
package/dist/flex-table.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "./flex-table-Hx-xTm0e.js";
|
|
2
2
|
export { o as FlexTable, e as RowSelectionState, t as UndoStack, n as effectiveAlign, i as exportData, r as flexTableLocale, a as renderCell };
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "./flex-table-
|
|
1
|
+
import { t as e } from "./flex-table-Hx-xTm0e.js";
|
|
2
2
|
import { i as t, t as n } from "./query-Dw4iO0ir.js";
|
|
3
3
|
import { t as r } from "./view-DiLr-TdY.js";
|
|
4
4
|
import i, { useCallback as a, useEffect as o, useMemo as s, useRef as c, useState as l } from "react";
|
package/package.json
CHANGED
|
@@ -68,7 +68,10 @@ flex-table {
|
|
|
68
68
|
|
|
69
69
|
| Key | Action |
|
|
70
70
|
|---|---|
|
|
71
|
-
| Arrows / Tab / Shift+Tab | Move between cells |
|
|
71
|
+
| Arrows / Tab / Shift+Tab | Move between cells; Tab past the last (Shift+Tab before the first) leaves the table |
|
|
72
|
+
| ArrowUp on the first row | Move onto the header row (arrows / Home / End along it, ArrowDown back) |
|
|
73
|
+
| Enter / Space on a header cell | Sort (Shift adds to the sort) |
|
|
74
|
+
| Alt+ArrowDown or context-menu key on a header cell | Open the column menu |
|
|
72
75
|
| Home / End, Ctrl+Home / Ctrl+End | Row start/end, table start/end |
|
|
73
76
|
| Shift+Arrow, Shift+Click | Extend range selection |
|
|
74
77
|
| Shift+Space | Select / deselect the active cell's row (`selectable`; row checkboxes are not Tab stops) |
|
|
@@ -84,6 +87,10 @@ flex-table {
|
|
|
84
87
|
| Alt+ArrowLeft / Alt+ArrowRight | Resize current column |
|
|
85
88
|
| Enter / Space on a column menu button | Open the column menu (arrows, Home/End navigate; Escape closes) |
|
|
86
89
|
|
|
90
|
+
The table is one Tab stop with roving focus — the focus sits on the active cell or header cell (screen
|
|
91
|
+
readers announce each move); keyboard focus arriving on it activates the first cell; the column menu
|
|
92
|
+
buttons are not Tab stops (the header row reaches them).
|
|
93
|
+
|
|
87
94
|
Ctrl also matches Cmd on macOS. Editing shortcuts are ignored when `editable` is `false`.
|
|
88
95
|
|
|
89
96
|
## Localization
|