@pingux/astro 2.214.0 → 2.216.0-alpha.0

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.
Files changed (35) hide show
  1. package/lib/cjs/components/OverlayPanel/OverlayPanel.js +6 -0
  2. package/lib/cjs/components/OverlayPanel/OverlayPanel.test.js +64 -0
  3. package/lib/cjs/components/Table/Table.mdx +2 -3
  4. package/lib/cjs/components/TableBase/Convenience/TableBaseEmptyState.stories.js +73 -0
  5. package/lib/cjs/components/TableBase/Customization/CustomEmptyState.stories.js +62 -0
  6. package/lib/cjs/components/TableBase/TableBase.js +179 -37
  7. package/lib/cjs/components/TableBase/TableBase.stories.js +217 -26
  8. package/lib/cjs/components/TableBase/TableBase.styles.d.ts +3 -0
  9. package/lib/cjs/components/TableBase/TableBase.styles.js +3 -0
  10. package/lib/cjs/components/TableBase/TableBase.test.js +557 -66
  11. package/lib/cjs/components/TableBase/TableBaseEmptyState.d.ts +4 -0
  12. package/lib/cjs/components/TableBase/TableBaseEmptyState.js +72 -0
  13. package/lib/cjs/components/TableBase/TableBaseEmptyState.test.js +54 -0
  14. package/lib/cjs/components/TableBase/index.d.ts +1 -0
  15. package/lib/cjs/components/TableBase/index.js +8 -1
  16. package/lib/cjs/components/TableBase/tableBaseAttributes.d.ts +21 -0
  17. package/lib/cjs/components/TableBase/tableBaseAttributes.js +24 -1
  18. package/lib/cjs/index.d.ts +1 -0
  19. package/lib/cjs/index.js +8 -0
  20. package/lib/cjs/types/tableBase.d.ts +16 -1
  21. package/lib/components/OverlayPanel/OverlayPanel.js +7 -1
  22. package/lib/components/OverlayPanel/OverlayPanel.test.js +64 -0
  23. package/lib/components/Table/Table.mdx +2 -3
  24. package/lib/components/TableBase/Convenience/TableBaseEmptyState.stories.js +65 -0
  25. package/lib/components/TableBase/Customization/CustomEmptyState.stories.js +54 -0
  26. package/lib/components/TableBase/TableBase.js +179 -35
  27. package/lib/components/TableBase/TableBase.stories.js +220 -28
  28. package/lib/components/TableBase/TableBase.styles.js +3 -0
  29. package/lib/components/TableBase/TableBase.test.js +557 -66
  30. package/lib/components/TableBase/TableBaseEmptyState.js +60 -0
  31. package/lib/components/TableBase/TableBaseEmptyState.test.js +51 -0
  32. package/lib/components/TableBase/index.js +2 -1
  33. package/lib/components/TableBase/tableBaseAttributes.js +23 -0
  34. package/lib/index.js +1 -0
  35. package/package.json +1 -1
@@ -22,6 +22,7 @@ function _regeneratorDefine2(e, r, n, t) { var i = _Object$defineProperty; try {
22
22
  function _OverloadYield(e, d) { this.v = e, this.k = d; }
23
23
  import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each";
24
24
  import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
25
+ import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
25
26
  import _sortInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/sort";
26
27
  import _parseInt from "@babel/runtime-corejs3/core-js-stable/parse-int";
27
28
  import React from 'react';
@@ -556,6 +557,101 @@ test('Arrow Left move the focus to next cell', /*#__PURE__*/_asyncToGenerator(/*
556
557
  }
557
558
  }, _callee10);
558
559
  })));
560
+ var renderWithLoadingState = function renderWithLoadingState(loadingState) {
561
+ return render(___EmotionJSX(TableBase, {
562
+ "aria-label": "table",
563
+ loadingState: loadingState
564
+ }, ___EmotionJSX(THead, {
565
+ columns: headers
566
+ }, function (head) {
567
+ return ___EmotionJSX(Column, {
568
+ key: head.key
569
+ }, head.name);
570
+ }), ___EmotionJSX(TBody, {
571
+ items: []
572
+ }, function () {
573
+ return ___EmotionJSX(Row, null, ___EmotionJSX(Cell, null, "A"), ___EmotionJSX(Cell, null, "B"), ___EmotionJSX(Cell, null, "C"));
574
+ })));
575
+ };
576
+ describe('Loading state', function () {
577
+ test('renders Loader when loadingState is "loading"', function () {
578
+ renderWithLoadingState('loading');
579
+ expect(screen.getByRole('alert')).toBeInTheDocument();
580
+ });
581
+ test('renders Loader when loadingState is "sorting"', function () {
582
+ renderWithLoadingState('sorting');
583
+ expect(screen.getByRole('alert')).toBeInTheDocument();
584
+ });
585
+ test('does not render Loader when loadingState is absent', function () {
586
+ renderWithLoadingState();
587
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
588
+ });
589
+ test('does not render Loader when loadingState is "loadingMore", renders empty state instead (Constraint #6)', function () {
590
+ renderWithLoadingState('loadingMore');
591
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
592
+ expect(screen.getByText('No items exist')).toBeInTheDocument();
593
+ });
594
+ });
595
+ describe('Empty state', function () {
596
+ test('renders default empty state when items is empty and no loadingState', function () {
597
+ render(___EmotionJSX(TableBase, {
598
+ "aria-label": "table"
599
+ }, ___EmotionJSX(THead, {
600
+ columns: headers
601
+ }, function (head) {
602
+ return ___EmotionJSX(Column, {
603
+ key: head.key
604
+ }, head.name);
605
+ }), ___EmotionJSX(TBody, {
606
+ items: []
607
+ }, function () {
608
+ return ___EmotionJSX(Row, null, ___EmotionJSX(Cell, null), ___EmotionJSX(Cell, null), ___EmotionJSX(Cell, null));
609
+ })));
610
+ expect(screen.getByText('No items exist')).toBeInTheDocument();
611
+ });
612
+ test('renders custom renderEmptyState and not default empty state', function () {
613
+ render(___EmotionJSX(TableBase, {
614
+ "aria-label": "table",
615
+ renderEmptyState: function renderEmptyState() {
616
+ return ___EmotionJSX("div", null, "Custom");
617
+ }
618
+ }, ___EmotionJSX(THead, {
619
+ columns: headers
620
+ }, function (head) {
621
+ return ___EmotionJSX(Column, {
622
+ key: head.key
623
+ }, head.name);
624
+ }), ___EmotionJSX(TBody, {
625
+ items: []
626
+ }, function () {
627
+ return ___EmotionJSX(Row, null, ___EmotionJSX(Cell, null), ___EmotionJSX(Cell, null), ___EmotionJSX(Cell, null));
628
+ })));
629
+ expect(screen.getByText('Custom')).toBeInTheDocument();
630
+ expect(screen.queryByText('No items exist')).not.toBeInTheDocument();
631
+ });
632
+ test('renders Loader and not empty state when loadingState is "loading" and items is empty', function () {
633
+ render(___EmotionJSX(TableBase, {
634
+ "aria-label": "table",
635
+ loadingState: "loading",
636
+ renderEmptyState: function renderEmptyState() {
637
+ return ___EmotionJSX("div", null, "Custom");
638
+ }
639
+ }, ___EmotionJSX(THead, {
640
+ columns: headers
641
+ }, function (head) {
642
+ return ___EmotionJSX(Column, {
643
+ key: head.key
644
+ }, head.name);
645
+ }), ___EmotionJSX(TBody, {
646
+ items: []
647
+ }, function () {
648
+ return ___EmotionJSX(Row, null, ___EmotionJSX(Cell, null), ___EmotionJSX(Cell, null), ___EmotionJSX(Cell, null));
649
+ })));
650
+ expect(screen.getByRole('alert')).toBeInTheDocument();
651
+ expect(screen.queryByText('Custom')).not.toBeInTheDocument();
652
+ expect(screen.queryByText('No items exist')).not.toBeInTheDocument();
653
+ });
654
+ });
559
655
  describe('Resizable columns', function () {
560
656
  var resizableHeaders = [{
561
657
  key: 'name',
@@ -857,6 +953,401 @@ describe('Resizable columns', function () {
857
953
  });
858
954
  });
859
955
  });
956
+ describe('onRowAction behavior', function () {
957
+ test('clicking a cell fires onRowAction with the correct row key', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {
958
+ var onRowAction, rows, firstBodyRowCells;
959
+ return _regeneratorRuntime().wrap(function _callee12$(_context14) {
960
+ while (1) switch (_context14.prev = _context14.next) {
961
+ case 0:
962
+ onRowAction = jest.fn();
963
+ getComponent({
964
+ onRowAction: onRowAction
965
+ });
966
+ rows = screen.getAllByRole('row');
967
+ firstBodyRowCells = rows[1].querySelectorAll('td');
968
+ _context14.next = 6;
969
+ return userEvent.click(firstBodyRowCells[0]);
970
+ case 6:
971
+ expect(onRowAction).toHaveBeenCalledTimes(1);
972
+ expect(onRowAction).toHaveBeenCalledWith('1');
973
+ case 8:
974
+ case "end":
975
+ return _context14.stop();
976
+ }
977
+ }, _callee12);
978
+ })));
979
+ test('rows receive has-actions class when onRowAction is provided', function () {
980
+ var _context15;
981
+ var onRowAction = jest.fn();
982
+ getComponent({
983
+ onRowAction: onRowAction
984
+ });
985
+ var rows = screen.getAllByRole('row');
986
+
987
+ // All body rows (skip the header row at index 0) should have the has-actions class
988
+ _forEachInstanceProperty(_context15 = _sliceInstanceProperty(rows).call(rows, 1)).call(_context15, function (row) {
989
+ expect(row).toHaveClass('has-actions');
990
+ });
991
+ });
992
+ test('rows do not receive has-actions class when onRowAction is absent', function () {
993
+ var _context16;
994
+ getComponent();
995
+ var rows = screen.getAllByRole('row');
996
+ _forEachInstanceProperty(_context16 = _sliceInstanceProperty(rows).call(rows, 1)).call(_context16, function (row) {
997
+ expect(row).not.toHaveClass('has-actions');
998
+ });
999
+ });
1000
+ test('pressing Enter on a focused row fires onRowAction when selectionMode is none', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee13() {
1001
+ var onRowAction, rows;
1002
+ return _regeneratorRuntime().wrap(function _callee13$(_context17) {
1003
+ while (1) switch (_context17.prev = _context17.next) {
1004
+ case 0:
1005
+ onRowAction = jest.fn();
1006
+ getComponent({
1007
+ selectionMode: 'none',
1008
+ onRowAction: onRowAction
1009
+ });
1010
+ rows = screen.getAllByRole('row');
1011
+ _context17.next = 5;
1012
+ return userEvent.tab();
1013
+ case 5:
1014
+ expect(rows[1]).toHaveFocus();
1015
+
1016
+ // React Aria's usePress fires the action on keyUp (press completion),
1017
+ // so both keyDown and keyUp must be fired.
1018
+ fireEvent.keyDown(rows[1], {
1019
+ key: 'Enter'
1020
+ });
1021
+ fireEvent.keyUp(rows[1], {
1022
+ key: 'Enter'
1023
+ });
1024
+ expect(onRowAction).toHaveBeenCalledTimes(1);
1025
+ expect(onRowAction).toHaveBeenCalledWith('1');
1026
+ case 10:
1027
+ case "end":
1028
+ return _context17.stop();
1029
+ }
1030
+ }, _callee13);
1031
+ })));
1032
+ test('clicking an action row applies is-focused class to that row', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee14() {
1033
+ var onRowAction, rows, firstBodyRowCells, secondBodyRowCells;
1034
+ return _regeneratorRuntime().wrap(function _callee14$(_context18) {
1035
+ while (1) switch (_context18.prev = _context18.next) {
1036
+ case 0:
1037
+ onRowAction = jest.fn();
1038
+ getComponent({
1039
+ onRowAction: onRowAction
1040
+ });
1041
+ rows = screen.getAllByRole('row'); // Click a cell in the first body row (rows[0] is the header row)
1042
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1043
+ _context18.next = 6;
1044
+ return userEvent.click(firstBodyRowCells[0]);
1045
+ case 6:
1046
+ // First body row should have is-focused; all other body rows should not
1047
+ expect(rows[1]).toHaveClass('is-focused');
1048
+ expect(rows[2]).not.toHaveClass('is-focused');
1049
+ expect(rows[3]).not.toHaveClass('is-focused');
1050
+ expect(rows[4]).not.toHaveClass('is-focused');
1051
+
1052
+ // Click a cell in the second body row — highlight should move
1053
+ secondBodyRowCells = rows[2].querySelectorAll('td');
1054
+ _context18.next = 13;
1055
+ return userEvent.click(secondBodyRowCells[0]);
1056
+ case 13:
1057
+ expect(rows[2]).toHaveClass('is-focused');
1058
+ expect(rows[1]).not.toHaveClass('is-focused');
1059
+ case 15:
1060
+ case "end":
1061
+ return _context18.stop();
1062
+ }
1063
+ }, _callee14);
1064
+ })));
1065
+ test('no row has is-focused before any click with onRowAction', function () {
1066
+ var _context19;
1067
+ var onRowAction = jest.fn();
1068
+ getComponent({
1069
+ onRowAction: onRowAction
1070
+ });
1071
+ var rows = screen.getAllByRole('row');
1072
+
1073
+ // At mount time, no body row should have is-focused from active-row state
1074
+ _forEachInstanceProperty(_context19 = _sliceInstanceProperty(rows).call(rows, 1)).call(_context19, function (row) {
1075
+ expect(row).not.toHaveClass('is-focused');
1076
+ });
1077
+ });
1078
+ test('clicking a row without onRowAction does not apply is-focused', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee15() {
1079
+ var rows, firstBodyRowCells;
1080
+ return _regeneratorRuntime().wrap(function _callee15$(_context20) {
1081
+ while (1) switch (_context20.prev = _context20.next) {
1082
+ case 0:
1083
+ getComponent();
1084
+ rows = screen.getAllByRole('row');
1085
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1086
+ _context20.next = 5;
1087
+ return userEvent.click(firstBodyRowCells[0]);
1088
+ case 5:
1089
+ // Without onRowAction the active-row path is not triggered
1090
+ expect(rows[1]).not.toHaveClass('is-focused');
1091
+ case 6:
1092
+ case "end":
1093
+ return _context20.stop();
1094
+ }
1095
+ }, _callee15);
1096
+ })));
1097
+ test('keyboard-focused row receives is-focused when onRowAction is present (AC4)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {
1098
+ var onRowAction, rows;
1099
+ return _regeneratorRuntime().wrap(function _callee16$(_context21) {
1100
+ while (1) switch (_context21.prev = _context21.next) {
1101
+ case 0:
1102
+ onRowAction = jest.fn();
1103
+ getComponent({
1104
+ selectionMode: 'none',
1105
+ onRowAction: onRowAction
1106
+ });
1107
+ rows = screen.getAllByRole('row'); // Tab into the table so the first body row has keyboard focus
1108
+ _context21.next = 5;
1109
+ return userEvent.tab();
1110
+ case 5:
1111
+ expect(rows[1]).toHaveFocus();
1112
+
1113
+ // The row must have is-focused from keyboard focus (isFocusVisible path unchanged)
1114
+ expect(rows[1]).toHaveClass('is-focused');
1115
+ case 7:
1116
+ case "end":
1117
+ return _context21.stop();
1118
+ }
1119
+ }, _callee16);
1120
+ })));
1121
+ test('is-focused class appears only once when keyboard-focused row is also the active row (AC5)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee17() {
1122
+ var _context22;
1123
+ var onRowAction, rows, firstBodyRowCells, isFocusedCount;
1124
+ return _regeneratorRuntime().wrap(function _callee17$(_context23) {
1125
+ while (1) switch (_context23.prev = _context23.next) {
1126
+ case 0:
1127
+ onRowAction = jest.fn();
1128
+ getComponent({
1129
+ selectionMode: 'none',
1130
+ onRowAction: onRowAction
1131
+ });
1132
+ rows = screen.getAllByRole('row'); // Click the first body row to set activeRowKey
1133
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1134
+ _context23.next = 6;
1135
+ return userEvent.click(firstBodyRowCells[0]);
1136
+ case 6:
1137
+ expect(rows[1]).toHaveClass('is-focused');
1138
+
1139
+ // Count occurrences of the class — must be exactly 1
1140
+ isFocusedCount = _filterInstanceProperty(_context22 = rows[1].className.split(/\s+/)).call(_context22, function (cls) {
1141
+ return cls === 'is-focused';
1142
+ }).length;
1143
+ expect(isFocusedCount).toBe(1);
1144
+ case 9:
1145
+ case "end":
1146
+ return _context23.stop();
1147
+ }
1148
+ }, _callee17);
1149
+ })));
1150
+ test('clicking a row focuses the row <tr> so arrow keys work via React Aria', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {
1151
+ var onRowAction, rows, firstBodyRowCells;
1152
+ return _regeneratorRuntime().wrap(function _callee18$(_context24) {
1153
+ while (1) switch (_context24.prev = _context24.next) {
1154
+ case 0:
1155
+ onRowAction = jest.fn();
1156
+ getComponent({
1157
+ onRowAction: onRowAction
1158
+ });
1159
+ rows = screen.getAllByRole('row'); // Click a cell in the first body row
1160
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1161
+ _context24.next = 6;
1162
+ return userEvent.click(firstBodyRowCells[0]);
1163
+ case 6:
1164
+ // The <tr> for the clicked row should now have DOM focus
1165
+ expect(rows[1]).toHaveFocus();
1166
+
1167
+ // Arrow keys should then navigate via React Aria
1168
+ fireEvent.keyDown(rows[1], {
1169
+ key: 'ArrowDown'
1170
+ });
1171
+ fireEvent.keyUp(rows[1], {
1172
+ key: 'ArrowDown'
1173
+ });
1174
+ expect(rows[2]).toHaveFocus();
1175
+ case 10:
1176
+ case "end":
1177
+ return _context24.stop();
1178
+ }
1179
+ }, _callee18);
1180
+ })));
1181
+ test('is-focused (active border) clears when focus leaves the table', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {
1182
+ var onRowAction, rows, firstBodyRowCells;
1183
+ return _regeneratorRuntime().wrap(function _callee19$(_context25) {
1184
+ while (1) switch (_context25.prev = _context25.next) {
1185
+ case 0:
1186
+ onRowAction = jest.fn();
1187
+ getComponent({
1188
+ onRowAction: onRowAction
1189
+ });
1190
+ rows = screen.getAllByRole('row'); // Click a cell in the first body row to set activeRowKey
1191
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1192
+ _context25.next = 6;
1193
+ return userEvent.click(firstBodyRowCells[0]);
1194
+ case 6:
1195
+ expect(rows[1]).toHaveClass('is-focused');
1196
+
1197
+ // Flush the setTimeout(0) that resets actionJustFired so the blur handler
1198
+ // can proceed normally for genuine focus-out events.
1199
+ actHooks(function () {
1200
+ jest.runAllTimers();
1201
+ });
1202
+
1203
+ // Use focusOut (which bubbles) to reach the onBlur handler on the scroll
1204
+ // container, simulating focus leaving the table entirely.
1205
+ fireEvent.focusOut(rows[1], {
1206
+ relatedTarget: null
1207
+ });
1208
+
1209
+ // is-focused should be cleared
1210
+ expect(rows[1]).not.toHaveClass('is-focused');
1211
+ case 10:
1212
+ case "end":
1213
+ return _context25.stop();
1214
+ }
1215
+ }, _callee19);
1216
+ })));
1217
+ test('clicking an already-active row toggles activeRowKey off (clears is-focused)', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee20() {
1218
+ var onRowAction, rows, firstBodyRowCells;
1219
+ return _regeneratorRuntime().wrap(function _callee20$(_context26) {
1220
+ while (1) switch (_context26.prev = _context26.next) {
1221
+ case 0:
1222
+ onRowAction = jest.fn();
1223
+ getComponent({
1224
+ onRowAction: onRowAction
1225
+ });
1226
+ rows = screen.getAllByRole('row');
1227
+ firstBodyRowCells = rows[1].querySelectorAll('td'); // First click sets the row as active
1228
+ _context26.next = 6;
1229
+ return userEvent.click(firstBodyRowCells[0]);
1230
+ case 6:
1231
+ expect(rows[1]).toHaveClass('is-focused');
1232
+
1233
+ // Second click on the same row should toggle it off
1234
+ _context26.next = 9;
1235
+ return userEvent.click(firstBodyRowCells[0]);
1236
+ case 9:
1237
+ expect(rows[1]).not.toHaveClass('is-focused');
1238
+ case 10:
1239
+ case "end":
1240
+ return _context26.stop();
1241
+ }
1242
+ }, _callee20);
1243
+ })));
1244
+ test('active-row highlight does not clear when focus moves to an overlay panel', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee21() {
1245
+ var onRowAction, rows, firstBodyRowCells, panelButton;
1246
+ return _regeneratorRuntime().wrap(function _callee21$(_context27) {
1247
+ while (1) switch (_context27.prev = _context27.next) {
1248
+ case 0:
1249
+ onRowAction = jest.fn();
1250
+ getComponent({
1251
+ onRowAction: onRowAction
1252
+ });
1253
+ rows = screen.getAllByRole('row'); // Click the first body row — sets activeRowKey and fires onRowAction
1254
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1255
+ _context27.next = 6;
1256
+ return userEvent.click(firstBodyRowCells[0]);
1257
+ case 6:
1258
+ expect(rows[1]).toHaveClass('is-focused');
1259
+
1260
+ // Simulate OverlayPanel FocusScope stealing focus to an element outside the table.
1261
+ // The actionJustFired guard (set synchronously in wrappedOnRowAction) should
1262
+ // absorb this blur and keep the active-row highlight intact.
1263
+ panelButton = document.createElement('button');
1264
+ document.body.appendChild(panelButton);
1265
+ fireEvent.focusOut(rows[1], {
1266
+ relatedTarget: panelButton
1267
+ });
1268
+
1269
+ // Highlight must survive the focus-steal
1270
+ expect(rows[1]).toHaveClass('is-focused');
1271
+ document.body.removeChild(panelButton);
1272
+ case 12:
1273
+ case "end":
1274
+ return _context27.stop();
1275
+ }
1276
+ }, _callee21);
1277
+ })));
1278
+ test('Enter key on a focused action row applies is-focused to that row', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee22() {
1279
+ var onRowAction, rows;
1280
+ return _regeneratorRuntime().wrap(function _callee22$(_context28) {
1281
+ while (1) switch (_context28.prev = _context28.next) {
1282
+ case 0:
1283
+ onRowAction = jest.fn();
1284
+ getComponent({
1285
+ selectionMode: 'none',
1286
+ onRowAction: onRowAction
1287
+ });
1288
+ rows = screen.getAllByRole('row'); // Tab to put keyboard focus on the first body row
1289
+ _context28.next = 5;
1290
+ return userEvent.tab();
1291
+ case 5:
1292
+ expect(rows[1]).toHaveFocus();
1293
+
1294
+ // Press Enter to trigger onRowAction via keyboard
1295
+ fireEvent.keyDown(rows[1], {
1296
+ key: 'Enter'
1297
+ });
1298
+ fireEvent.keyUp(rows[1], {
1299
+ key: 'Enter'
1300
+ });
1301
+ expect(onRowAction).toHaveBeenCalledWith('1');
1302
+
1303
+ // The row should carry is-focused (active-row state set from keyboard action)
1304
+ expect(rows[1]).toHaveClass('is-focused');
1305
+ case 10:
1306
+ case "end":
1307
+ return _context28.stop();
1308
+ }
1309
+ }, _callee22);
1310
+ })));
1311
+ test('active-row highlight clears when arrow keys move focus to another row', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee23() {
1312
+ var onRowAction, rows, firstBodyRowCells;
1313
+ return _regeneratorRuntime().wrap(function _callee23$(_context29) {
1314
+ while (1) switch (_context29.prev = _context29.next) {
1315
+ case 0:
1316
+ onRowAction = jest.fn();
1317
+ getComponent({
1318
+ onRowAction: onRowAction
1319
+ });
1320
+ rows = screen.getAllByRole('row'); // Click row 1 to set it as active (simulates opening a panel)
1321
+ firstBodyRowCells = rows[1].querySelectorAll('td');
1322
+ _context29.next = 6;
1323
+ return userEvent.click(firstBodyRowCells[0]);
1324
+ case 6:
1325
+ // Flush the setTimeout(0) guard so subsequent focus events are not swallowed
1326
+ actHooks(function () {
1327
+ jest.runAllTimers();
1328
+ });
1329
+ expect(rows[1]).toHaveClass('is-focused');
1330
+
1331
+ // Simulate the panel closing by returning focus to the row
1332
+ fireEvent.focus(rows[1]);
1333
+
1334
+ // Arrow Down moves focus to row 2 — row 1 should lose is-focused
1335
+ fireEvent.keyDown(rows[1], {
1336
+ key: 'ArrowDown'
1337
+ });
1338
+ fireEvent.keyUp(rows[1], {
1339
+ key: 'ArrowDown'
1340
+ });
1341
+ fireEvent.focus(rows[2]);
1342
+ expect(rows[1]).not.toHaveClass('is-focused');
1343
+ expect(rows[2]).toHaveFocus();
1344
+ case 14:
1345
+ case "end":
1346
+ return _context29.stop();
1347
+ }
1348
+ }, _callee23);
1349
+ })));
1350
+ });
860
1351
  describe('Sortable Table with useAsyncList', function () {
861
1352
  var dataTestId = 'sortableTable';
862
1353
  var defaultTableProps = {
@@ -869,18 +1360,18 @@ describe('Sortable Table with useAsyncList', function () {
869
1360
  return _load.apply(this, arguments);
870
1361
  }
871
1362
  function _load() {
872
- _load = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee20() {
873
- return _regeneratorRuntime().wrap(function _callee20$(_context24) {
874
- while (1) switch (_context24.prev = _context24.next) {
1363
+ _load = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee32() {
1364
+ return _regeneratorRuntime().wrap(function _callee32$(_context40) {
1365
+ while (1) switch (_context40.prev = _context40.next) {
875
1366
  case 0:
876
- return _context24.abrupt("return", {
1367
+ return _context40.abrupt("return", {
877
1368
  items: objects
878
1369
  });
879
1370
  case 1:
880
1371
  case "end":
881
- return _context24.stop();
1372
+ return _context40.stop();
882
1373
  }
883
- }, _callee20);
1374
+ }, _callee32);
884
1375
  }));
885
1376
  return _load.apply(this, arguments);
886
1377
  }
@@ -888,13 +1379,13 @@ describe('Sortable Table with useAsyncList', function () {
888
1379
  return _sort.apply(this, arguments);
889
1380
  }
890
1381
  function _sort() {
891
- _sort = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee21(list) {
892
- var _context25;
893
- return _regeneratorRuntime().wrap(function _callee21$(_context26) {
894
- while (1) switch (_context26.prev = _context26.next) {
1382
+ _sort = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee33(list) {
1383
+ var _context41;
1384
+ return _regeneratorRuntime().wrap(function _callee33$(_context42) {
1385
+ while (1) switch (_context42.prev = _context42.next) {
895
1386
  case 0:
896
1387
  // eslint-disable-next-line no-param-reassign
897
- list.items = _sortInstanceProperty(_context25 = list.items).call(_context25, function (a, b) {
1388
+ list.items = _sortInstanceProperty(_context41 = list.items).call(_context41, function (a, b) {
898
1389
  var first = a[list.sortDescriptor.column];
899
1390
  var second = b[list.sortDescriptor.column];
900
1391
  var cmp = (_parseInt(first) || first) < (_parseInt(second) || second) // eslint-disable-line
@@ -904,17 +1395,17 @@ describe('Sortable Table with useAsyncList', function () {
904
1395
  }
905
1396
  return cmp;
906
1397
  });
907
- return _context26.abrupt("return", list);
1398
+ return _context42.abrupt("return", list);
908
1399
  case 2:
909
1400
  case "end":
910
- return _context26.stop();
1401
+ return _context42.stop();
911
1402
  }
912
- }, _callee21);
1403
+ }, _callee33);
913
1404
  }));
914
1405
  return _sort.apply(this, arguments);
915
1406
  }
916
- var sortableDataTable = function sortableDataTable(_ref12) {
917
- var result = _ref12.result;
1407
+ var sortableDataTable = function sortableDataTable(_ref24) {
1408
+ var result = _ref24.result;
918
1409
  return render(___EmotionJSX(TableBase, _extends({}, defaultTableProps, {
919
1410
  sortDescriptor: result.current.sortDescriptor
920
1411
  }), ___EmotionJSX(THead, {
@@ -931,10 +1422,10 @@ describe('Sortable Table with useAsyncList', function () {
931
1422
  });
932
1423
  })));
933
1424
  };
934
- test('sort by country column A => Z', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee15() {
1425
+ test('sort by country column A => Z', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee27() {
935
1426
  var _renderHook, result, sortableTable, rowgroups, thead, headerCells, tRows;
936
- return _regeneratorRuntime().wrap(function _callee15$(_context18) {
937
- while (1) switch (_context18.prev = _context18.next) {
1427
+ return _regeneratorRuntime().wrap(function _callee27$(_context34) {
1428
+ while (1) switch (_context34.prev = _context34.next) {
938
1429
  case 0:
939
1430
  _renderHook = renderHook(function () {
940
1431
  return useAsyncList({
@@ -946,47 +1437,47 @@ describe('Sortable Table with useAsyncList', function () {
946
1437
  }
947
1438
  });
948
1439
  }), result = _renderHook.result;
949
- _context18.next = 3;
950
- return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {
951
- return _regeneratorRuntime().wrap(function _callee12$(_context14) {
952
- while (1) switch (_context14.prev = _context14.next) {
1440
+ _context34.next = 3;
1441
+ return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee24() {
1442
+ return _regeneratorRuntime().wrap(function _callee24$(_context30) {
1443
+ while (1) switch (_context30.prev = _context30.next) {
953
1444
  case 0:
954
1445
  jest.runOnlyPendingTimers();
955
1446
  case 1:
956
1447
  case "end":
957
- return _context14.stop();
1448
+ return _context30.stop();
958
1449
  }
959
- }, _callee12);
1450
+ }, _callee24);
960
1451
  })));
961
1452
  case 3:
962
- _context18.next = 5;
963
- return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee13() {
964
- var _context15;
965
- return _regeneratorRuntime().wrap(function _callee13$(_context16) {
966
- while (1) switch (_context16.prev = _context16.next) {
1453
+ _context34.next = 5;
1454
+ return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee25() {
1455
+ var _context31;
1456
+ return _regeneratorRuntime().wrap(function _callee25$(_context32) {
1457
+ while (1) switch (_context32.prev = _context32.next) {
967
1458
  case 0:
968
- _sortInstanceProperty(_context15 = result.current).call(_context15, {
1459
+ _sortInstanceProperty(_context31 = result.current).call(_context31, {
969
1460
  column: 'country',
970
1461
  direction: 'ascending'
971
1462
  });
972
1463
  case 1:
973
1464
  case "end":
974
- return _context16.stop();
1465
+ return _context32.stop();
975
1466
  }
976
- }, _callee13);
1467
+ }, _callee25);
977
1468
  })));
978
1469
  case 5:
979
- _context18.next = 7;
980
- return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee14() {
981
- return _regeneratorRuntime().wrap(function _callee14$(_context17) {
982
- while (1) switch (_context17.prev = _context17.next) {
1470
+ _context34.next = 7;
1471
+ return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee26() {
1472
+ return _regeneratorRuntime().wrap(function _callee26$(_context33) {
1473
+ while (1) switch (_context33.prev = _context33.next) {
983
1474
  case 0:
984
1475
  jest.runOnlyPendingTimers();
985
1476
  case 1:
986
1477
  case "end":
987
- return _context17.stop();
1478
+ return _context33.stop();
988
1479
  }
989
- }, _callee14);
1480
+ }, _callee26);
990
1481
  })));
991
1482
  case 7:
992
1483
  sortableDataTable({
@@ -1014,14 +1505,14 @@ describe('Sortable Table with useAsyncList', function () {
1014
1505
  expect(tRows[3]).toHaveTextContent('USA');
1015
1506
  case 28:
1016
1507
  case "end":
1017
- return _context18.stop();
1508
+ return _context34.stop();
1018
1509
  }
1019
- }, _callee15);
1510
+ }, _callee27);
1020
1511
  })));
1021
- test('sort by country column Z => A', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {
1512
+ test('sort by country column Z => A', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee31() {
1022
1513
  var _renderHook2, result, sortableTable, rowgroups, tRows;
1023
- return _regeneratorRuntime().wrap(function _callee19$(_context23) {
1024
- while (1) switch (_context23.prev = _context23.next) {
1514
+ return _regeneratorRuntime().wrap(function _callee31$(_context39) {
1515
+ while (1) switch (_context39.prev = _context39.next) {
1025
1516
  case 0:
1026
1517
  _renderHook2 = renderHook(function () {
1027
1518
  return useAsyncList({
@@ -1033,47 +1524,47 @@ describe('Sortable Table with useAsyncList', function () {
1033
1524
  }
1034
1525
  });
1035
1526
  }), result = _renderHook2.result;
1036
- _context23.next = 3;
1037
- return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee16() {
1038
- return _regeneratorRuntime().wrap(function _callee16$(_context19) {
1039
- while (1) switch (_context19.prev = _context19.next) {
1527
+ _context39.next = 3;
1528
+ return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee28() {
1529
+ return _regeneratorRuntime().wrap(function _callee28$(_context35) {
1530
+ while (1) switch (_context35.prev = _context35.next) {
1040
1531
  case 0:
1041
1532
  jest.runOnlyPendingTimers();
1042
1533
  case 1:
1043
1534
  case "end":
1044
- return _context19.stop();
1535
+ return _context35.stop();
1045
1536
  }
1046
- }, _callee16);
1537
+ }, _callee28);
1047
1538
  })));
1048
1539
  case 3:
1049
- _context23.next = 5;
1050
- return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee17() {
1051
- var _context20;
1052
- return _regeneratorRuntime().wrap(function _callee17$(_context21) {
1053
- while (1) switch (_context21.prev = _context21.next) {
1540
+ _context39.next = 5;
1541
+ return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee29() {
1542
+ var _context36;
1543
+ return _regeneratorRuntime().wrap(function _callee29$(_context37) {
1544
+ while (1) switch (_context37.prev = _context37.next) {
1054
1545
  case 0:
1055
- _sortInstanceProperty(_context20 = result.current).call(_context20, {
1546
+ _sortInstanceProperty(_context36 = result.current).call(_context36, {
1056
1547
  column: 'country',
1057
1548
  direction: 'descending'
1058
1549
  });
1059
1550
  case 1:
1060
1551
  case "end":
1061
- return _context21.stop();
1552
+ return _context37.stop();
1062
1553
  }
1063
- }, _callee17);
1554
+ }, _callee29);
1064
1555
  })));
1065
1556
  case 5:
1066
- _context23.next = 7;
1067
- return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {
1068
- return _regeneratorRuntime().wrap(function _callee18$(_context22) {
1069
- while (1) switch (_context22.prev = _context22.next) {
1557
+ _context39.next = 7;
1558
+ return actHooks(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee30() {
1559
+ return _regeneratorRuntime().wrap(function _callee30$(_context38) {
1560
+ while (1) switch (_context38.prev = _context38.next) {
1070
1561
  case 0:
1071
1562
  jest.runOnlyPendingTimers();
1072
1563
  case 1:
1073
1564
  case "end":
1074
- return _context22.stop();
1565
+ return _context38.stop();
1075
1566
  }
1076
- }, _callee18);
1567
+ }, _callee30);
1077
1568
  })));
1078
1569
  case 7:
1079
1570
  sortableDataTable({
@@ -1097,8 +1588,8 @@ describe('Sortable Table with useAsyncList', function () {
1097
1588
  expect(tRows[3]).toHaveTextContent('Canada');
1098
1589
  case 24:
1099
1590
  case "end":
1100
- return _context23.stop();
1591
+ return _context39.stop();
1101
1592
  }
1102
- }, _callee19);
1593
+ }, _callee31);
1103
1594
  })));
1104
1595
  });