react-lookup-select 1.0.5 → 1.1.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.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import React3 from "react";
3
3
 
4
4
  // src/internal/state.ts
5
- import { useState, useCallback, useMemo, useEffect } from "react";
5
+ import { useState, useCallback, useRef, useEffect } from "react";
6
6
 
7
7
  // src/internal/core.ts
8
8
  function createSelectionState() {
@@ -174,12 +174,16 @@ function useLookupSelectState(props) {
174
174
  },
175
175
  [open, onOpenChange]
176
176
  );
177
- const selectionManager = useMemo(() => {
178
- return new SelectionManager(mode, mapper);
179
- }, [mode, mapper]);
180
- const queryManager = useMemo(() => {
181
- return new QueryManager({ pageSize });
182
- }, [pageSize]);
177
+ const selectionManagerRef = useRef(null);
178
+ if (!selectionManagerRef.current) {
179
+ selectionManagerRef.current = new SelectionManager(mode, mapper);
180
+ }
181
+ const selectionManager = selectionManagerRef.current;
182
+ const queryManagerRef = useRef(null);
183
+ if (!queryManagerRef.current) {
184
+ queryManagerRef.current = new QueryManager({ pageSize });
185
+ }
186
+ const queryManager = queryManagerRef.current;
183
187
  const [currentSelections, setCurrentSelections] = useState([]);
184
188
  const [backupSelections, setBackupSelections] = useState([]);
185
189
  const resolveValueToRows = useCallback(
@@ -197,6 +201,10 @@ function useLookupSelectState(props) {
197
201
  );
198
202
  if (matchingRow) {
199
203
  resolvedRows.push(matchingRow);
204
+ } else if (typeof console !== "undefined") {
205
+ console.warn(
206
+ `[react-lookup-select] Could not resolve value with id "${searchId}" from data. Ensure the value matches an item in the data array.`
207
+ );
200
208
  }
201
209
  }
202
210
  }
@@ -218,7 +226,7 @@ function useLookupSelectState(props) {
218
226
  }, [value, defaultValue, data, resolveValueToRows, selectionManager]);
219
227
  const toggleRowSelection = useCallback(
220
228
  (row) => {
221
- const newState = selectionManager.toggleRow(row);
229
+ selectionManager.toggleRow(row);
222
230
  const selectedRows = selectionManager.getSelectedRows();
223
231
  setCurrentSelections(selectedRows);
224
232
  if (!modalOpen) {
@@ -242,8 +250,6 @@ function useLookupSelectState(props) {
242
250
  );
243
251
  const updateQuery = useCallback(
244
252
  (updates) => {
245
- const currentState = queryManager.getState();
246
- const newState = { ...currentState, ...updates };
247
253
  if (updates.search !== void 0) {
248
254
  queryManager.updateSearch(updates.search);
249
255
  }
@@ -320,21 +326,12 @@ function useLookupSelectState(props) {
320
326
  import { useEffect as useEffect2, useCallback as useCallback2 } from "react";
321
327
  function useKeyboardNavigation({
322
328
  isModalOpen,
323
- onClose,
324
- onConfirm,
325
- onRowSelect,
326
- currentData,
327
- selectedRows,
328
- mode
329
+ onConfirm
329
330
  }) {
330
331
  const handleKeyDown = useCallback2(
331
332
  (event) => {
332
333
  if (!isModalOpen) return;
333
334
  switch (event.key) {
334
- case "Escape":
335
- event.preventDefault();
336
- onClose();
337
- break;
338
335
  case "Enter":
339
336
  if (event.ctrlKey || event.metaKey) {
340
337
  event.preventDefault();
@@ -342,13 +339,62 @@ function useKeyboardNavigation({
342
339
  }
343
340
  break;
344
341
  case "ArrowDown":
345
- case "ArrowUp":
342
+ case "ArrowUp": {
343
+ const grid = document.querySelector(
344
+ ".lookup-select__grid tbody, .lookup-select__virtual-grid-body"
345
+ );
346
+ if (!grid) break;
347
+ const rows = grid.querySelectorAll(
348
+ 'tr[tabindex="0"], tr[role="row"]'
349
+ );
350
+ if (rows.length === 0) break;
351
+ const currentIndex = Array.from(rows).findIndex(
352
+ (row) => row === document.activeElement
353
+ );
354
+ let nextIndex;
355
+ if (event.key === "ArrowDown") {
356
+ nextIndex = currentIndex < 0 ? 0 : Math.min(currentIndex + 1, rows.length - 1);
357
+ } else {
358
+ nextIndex = currentIndex < 0 ? rows.length - 1 : Math.max(currentIndex - 1, 0);
359
+ }
360
+ event.preventDefault();
361
+ rows[nextIndex]?.focus();
362
+ break;
363
+ }
364
+ case "Home": {
365
+ const gridHome = document.querySelector(
366
+ ".lookup-select__grid tbody, .lookup-select__virtual-grid-body"
367
+ );
368
+ if (!gridHome) break;
369
+ const firstRow = gridHome.querySelector(
370
+ 'tr[tabindex="0"], tr[role="row"]'
371
+ );
372
+ if (firstRow) {
373
+ event.preventDefault();
374
+ firstRow.focus();
375
+ }
346
376
  break;
377
+ }
378
+ case "End": {
379
+ const gridEnd = document.querySelector(
380
+ ".lookup-select__grid tbody, .lookup-select__virtual-grid-body"
381
+ );
382
+ if (!gridEnd) break;
383
+ const allRows = gridEnd.querySelectorAll(
384
+ 'tr[tabindex="0"], tr[role="row"]'
385
+ );
386
+ const lastRow = allRows[allRows.length - 1];
387
+ if (lastRow) {
388
+ event.preventDefault();
389
+ lastRow.focus();
390
+ }
391
+ break;
392
+ }
347
393
  default:
348
394
  break;
349
395
  }
350
396
  },
351
- [isModalOpen, onClose, onConfirm]
397
+ [isModalOpen, onConfirm]
352
398
  );
353
399
  useEffect2(() => {
354
400
  if (isModalOpen) {
@@ -362,36 +408,7 @@ function useKeyboardNavigation({
362
408
  handleKeyDown
363
409
  };
364
410
  }
365
- function useFocusManagement(isOpen) {
366
- useEffect2(() => {
367
- if (!isOpen) return;
368
- const modal = document.querySelector('[role="dialog"]');
369
- if (!modal) return;
370
- const focusableElements = modal.querySelectorAll(
371
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
372
- );
373
- const firstFocusable = focusableElements[0];
374
- const lastFocusable = focusableElements[focusableElements.length - 1];
375
- firstFocusable?.focus();
376
- const handleTabKey = (e) => {
377
- if (e.key !== "Tab") return;
378
- if (e.shiftKey) {
379
- if (document.activeElement === firstFocusable) {
380
- e.preventDefault();
381
- lastFocusable?.focus();
382
- }
383
- } else {
384
- if (document.activeElement === lastFocusable) {
385
- e.preventDefault();
386
- firstFocusable?.focus();
387
- }
388
- }
389
- };
390
- document.addEventListener("keydown", handleTabKey);
391
- return () => {
392
- document.removeEventListener("keydown", handleTabKey);
393
- };
394
- }, [isOpen]);
411
+ function useFocusManagement(_isOpen) {
395
412
  }
396
413
  function useScreenReaderAnnouncements() {
397
414
  const announce = useCallback2(
@@ -530,7 +547,7 @@ function Trigger({
530
547
  }
531
548
 
532
549
  // src/components/Modal.tsx
533
- import { useEffect as useEffect3, useRef } from "react";
550
+ import { useEffect as useEffect3, useRef as useRef2 } from "react";
534
551
  import { createPortal } from "react-dom";
535
552
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
536
553
  function Modal({
@@ -545,16 +562,23 @@ function Modal({
545
562
  ariaDescribedBy,
546
563
  closeButtonLabel = "Close modal"
547
564
  }) {
548
- const modalRef = useRef(null);
549
- const previousFocusRef = useRef(null);
565
+ const modalRef = useRef2(null);
566
+ const previousFocusRef = useRef2(null);
550
567
  useEffect3(() => {
551
568
  if (!isOpen) return;
552
569
  previousFocusRef.current = document.activeElement;
553
- const focusableElements = modalRef.current?.querySelectorAll(
554
- 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
570
+ const autoFocusElement = modalRef.current?.querySelector(
571
+ "[data-autofocus]"
555
572
  );
556
- if (focusableElements && focusableElements.length > 0) {
557
- focusableElements[0].focus();
573
+ if (autoFocusElement) {
574
+ autoFocusElement.focus();
575
+ } else {
576
+ const focusableElements = modalRef.current?.querySelectorAll(
577
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
578
+ );
579
+ if (focusableElements && focusableElements.length > 0) {
580
+ focusableElements[0].focus();
581
+ }
558
582
  }
559
583
  const handleEscape = (e) => {
560
584
  if (e.key === "Escape") {
@@ -563,12 +587,12 @@ function Modal({
563
587
  };
564
588
  const handleTab = (e) => {
565
589
  if (e.key !== "Tab") return;
566
- const focusableElements2 = modalRef.current?.querySelectorAll(
590
+ const focusableElements = modalRef.current?.querySelectorAll(
567
591
  'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
568
592
  );
569
- if (!focusableElements2 || focusableElements2.length === 0) return;
570
- const firstElement = focusableElements2[0];
571
- const lastElement = focusableElements2[focusableElements2.length - 1];
593
+ if (!focusableElements || focusableElements.length === 0) return;
594
+ const firstElement = focusableElements[0];
595
+ const lastElement = focusableElements[focusableElements.length - 1];
572
596
  if (e.shiftKey) {
573
597
  if (document.activeElement === firstElement) {
574
598
  lastElement.focus();
@@ -659,23 +683,17 @@ function SearchInput({
659
683
  placeholder = "Search...",
660
684
  className
661
685
  }) {
662
- const inputRef = useRef(null);
663
- useEffect3(() => {
664
- if (inputRef.current) {
665
- inputRef.current.focus();
666
- }
667
- }, []);
668
686
  return /* @__PURE__ */ jsxs2("div", { className: `lookup-select__search ${className || ""}`, children: [
669
687
  /* @__PURE__ */ jsx2(
670
688
  "input",
671
689
  {
672
- ref: inputRef,
673
690
  type: "text",
674
691
  value,
675
692
  onChange: (e) => onChange(e.target.value),
676
693
  placeholder,
677
694
  className: "lookup-select__search-input",
678
- "aria-label": "Search records"
695
+ "aria-label": "Search records",
696
+ "data-autofocus": true
679
697
  }
680
698
  ),
681
699
  /* @__PURE__ */ jsx2("div", { className: "lookup-select__search-icon", children: /* @__PURE__ */ jsx2("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: "M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z" }) }) })
@@ -732,6 +750,7 @@ function Grid({
732
750
  loading = false,
733
751
  error,
734
752
  emptyText = "No records found",
753
+ onRetry,
735
754
  className,
736
755
  style
737
756
  }) {
@@ -752,13 +771,33 @@ function Grid({
752
771
  return currentSort.sortDir === "asc" ? "\u2191" : "\u2193";
753
772
  };
754
773
  if (loading) {
755
- return /* @__PURE__ */ jsx3("div", { className: "lookup-select__grid-state", children: /* @__PURE__ */ jsx3("div", { className: "lookup-select__loading", children: /* @__PURE__ */ jsx3("p", { children: "Loading..." }) }) });
774
+ return /* @__PURE__ */ jsx3("div", { className: `lookup-select__grid ${className || ""}`, style, children: /* @__PURE__ */ jsxs3("table", { className: "lookup-select__table", children: [
775
+ /* @__PURE__ */ jsx3("thead", { children: /* @__PURE__ */ jsxs3("tr", { children: [
776
+ mode === "multiple" && /* @__PURE__ */ jsx3("th", { className: "lookup-select__header-cell lookup-select__header-cell--checkbox" }),
777
+ columns.map((column) => /* @__PURE__ */ jsx3("th", { className: "lookup-select__header-cell", children: column.title }, String(column.key)))
778
+ ] }) }),
779
+ /* @__PURE__ */ jsx3("tbody", { children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsxs3("tr", { className: "lookup-select__grid-row lookup-select__grid-row--skeleton", children: [
780
+ mode === "multiple" && /* @__PURE__ */ jsx3("td", { className: "lookup-select__cell" }),
781
+ columns.map((col, j) => /* @__PURE__ */ jsx3("td", { className: "lookup-select__cell", children: /* @__PURE__ */ jsx3("div", { className: "lookup-select__skeleton-line" }) }, j))
782
+ ] }, i)) })
783
+ ] }) });
756
784
  }
757
785
  if (error) {
758
- return /* @__PURE__ */ jsx3("div", { className: "lookup-select__grid-state", children: /* @__PURE__ */ jsx3("div", { className: "lookup-select__error", children: /* @__PURE__ */ jsxs3("p", { children: [
759
- "Error: ",
760
- error
761
- ] }) }) });
786
+ return /* @__PURE__ */ jsx3("div", { className: "lookup-select__grid-state", children: /* @__PURE__ */ jsxs3("div", { className: "lookup-select__error", children: [
787
+ /* @__PURE__ */ jsxs3("p", { children: [
788
+ "Error: ",
789
+ error
790
+ ] }),
791
+ onRetry && /* @__PURE__ */ jsx3(
792
+ "button",
793
+ {
794
+ type: "button",
795
+ className: "lookup-select__button lookup-select__button--secondary",
796
+ onClick: onRetry,
797
+ children: "Retry"
798
+ }
799
+ )
800
+ ] }) });
762
801
  }
763
802
  if (data.length === 0) {
764
803
  return /* @__PURE__ */ jsx3("div", { className: "lookup-select__grid-state", children: /* @__PURE__ */ jsx3("div", { className: "lookup-select__empty", children: /* @__PURE__ */ jsx3("p", { children: emptyText }) }) });
@@ -830,7 +869,7 @@ function Grid({
830
869
  "aria-label": "Select all"
831
870
  }
832
871
  ) }) }),
833
- columns.map((column, index) => /* @__PURE__ */ jsx3(
872
+ columns.map((column) => /* @__PURE__ */ jsx3(
834
873
  "th",
835
874
  {
836
875
  className: "lookup-select__table-header",
@@ -886,7 +925,7 @@ function Grid({
886
925
  "aria-label": `Select ${mapper.getText(row)}`
887
926
  }
888
927
  ) }) }),
889
- columns.map((column, columnIndex) => {
928
+ columns.map((column) => {
890
929
  const cellKey = `${rowId}-${typeof column.key === "string" ? column.key : String(column.key)}`;
891
930
  let cellContent;
892
931
  if (column.render) {
@@ -948,13 +987,16 @@ function VirtualGrid(props) {
948
987
  return () => resizeObserver.disconnect();
949
988
  }
950
989
  }, []);
990
+ const selectableCount = React2.useMemo(() => {
991
+ return selectableRow ? data.filter(selectableRow).length : data.length;
992
+ }, [data, selectableRow]);
951
993
  React2.useEffect(() => {
952
994
  if (headerCheckboxRef.current) {
953
995
  const hasSelected = selectedRows.length > 0;
954
- const hasUnselected = selectedRows.length < data.length;
996
+ const hasUnselected = selectedRows.length < selectableCount;
955
997
  headerCheckboxRef.current.indeterminate = hasSelected && hasUnselected;
956
998
  }
957
- }, [selectedRows.length, data.length]);
999
+ }, [selectedRows.length, selectableCount]);
958
1000
  const itemCount = data.length;
959
1001
  const { rowHeight, overscan } = virtualization;
960
1002
  const startIndex = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
@@ -1029,7 +1071,7 @@ function VirtualGrid(props) {
1029
1071
  ref: headerCheckboxRef,
1030
1072
  type: "checkbox",
1031
1073
  className: "lookup-select__checkbox",
1032
- checked: selectedRows.length === data.length && data.length > 0,
1074
+ checked: selectedRows.length === selectableCount && selectableCount > 0,
1033
1075
  onChange: (e) => {
1034
1076
  if (e.target.checked) {
1035
1077
  data.forEach((row) => {
@@ -1112,9 +1154,11 @@ function VirtualRowComponent({
1112
1154
  item,
1113
1155
  columns,
1114
1156
  mode,
1157
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1115
1158
  mapper,
1116
1159
  isSelected,
1117
1160
  isSelectable,
1161
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1118
1162
  onToggle,
1119
1163
  onCheckboxChange,
1120
1164
  onClick
@@ -1156,13 +1200,14 @@ var VirtualRow = React2.memo(
1156
1200
  );
1157
1201
 
1158
1202
  // src/components/Pagination.tsx
1159
- import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1203
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1160
1204
  function Pagination({
1161
1205
  currentPage,
1162
1206
  totalCount,
1163
1207
  pageSize,
1164
1208
  onPageChange,
1165
- className
1209
+ className,
1210
+ i18n
1166
1211
  }) {
1167
1212
  const totalPages = Math.ceil(totalCount / pageSize);
1168
1213
  if (totalPages <= 1) {
@@ -1192,14 +1237,7 @@ function Pagination({
1192
1237
  const startRecord = (currentPage - 1) * pageSize + 1;
1193
1238
  const endRecord = Math.min(currentPage * pageSize, totalCount);
1194
1239
  return /* @__PURE__ */ jsxs5("div", { className: `lookup-select__pagination ${className || ""}`, children: [
1195
- /* @__PURE__ */ jsx5("div", { className: "lookup-select__pagination-info", children: totalCount > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
1196
- startRecord,
1197
- "-",
1198
- endRecord,
1199
- " / ",
1200
- totalCount,
1201
- " records"
1202
- ] }) : "0 records" }),
1240
+ /* @__PURE__ */ jsx5("div", { className: "lookup-select__pagination-info", children: totalCount > 0 ? i18n?.recordsInfo ? i18n.recordsInfo(startRecord, endRecord, totalCount) : `${startRecord}-${endRecord} / ${totalCount} records` : "0 records" }),
1203
1241
  /* @__PURE__ */ jsxs5("div", { className: "lookup-select__pagination-controls", children: [
1204
1242
  /* @__PURE__ */ jsx5(
1205
1243
  "button",
@@ -1208,7 +1246,7 @@ function Pagination({
1208
1246
  className: "lookup-select__pagination-button",
1209
1247
  disabled: currentPage === 1,
1210
1248
  onClick: () => onPageChange(currentPage - 1),
1211
- "aria-label": "Previous page",
1249
+ "aria-label": i18n?.previousPage || "Previous page",
1212
1250
  children: "\u2039"
1213
1251
  }
1214
1252
  ),
@@ -1233,7 +1271,7 @@ function Pagination({
1233
1271
  ${currentPage === pageNum ? "lookup-select__pagination-button--active" : ""}
1234
1272
  `,
1235
1273
  onClick: () => onPageChange(pageNum),
1236
- "aria-label": `Sayfa ${pageNum}`,
1274
+ "aria-label": i18n?.pageLabel ? i18n.pageLabel(pageNum) : `Page ${pageNum}`,
1237
1275
  "aria-current": currentPage === pageNum ? "page" : void 0,
1238
1276
  children: pageNum
1239
1277
  },
@@ -1247,7 +1285,7 @@ function Pagination({
1247
1285
  className: "lookup-select__pagination-button",
1248
1286
  disabled: currentPage === totalPages,
1249
1287
  onClick: () => onPageChange(currentPage + 1),
1250
- "aria-label": "Next page",
1288
+ "aria-label": i18n?.nextPage || "Next page",
1251
1289
  children: "\u203A"
1252
1290
  }
1253
1291
  )
@@ -1256,7 +1294,7 @@ function Pagination({
1256
1294
  }
1257
1295
 
1258
1296
  // src/components/LookupSelect.tsx
1259
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1297
+ import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1260
1298
  function LookupSelect(props) {
1261
1299
  const {
1262
1300
  columns,
@@ -1270,7 +1308,6 @@ function LookupSelect(props) {
1270
1308
  renderTrigger,
1271
1309
  renderModal,
1272
1310
  renderGrid,
1273
- renderHeader,
1274
1311
  renderFooter,
1275
1312
  renderSearch,
1276
1313
  renderPagination,
@@ -1290,7 +1327,6 @@ function LookupSelect(props) {
1290
1327
  const {
1291
1328
  modalOpen,
1292
1329
  openModal,
1293
- closeModal,
1294
1330
  currentSelections,
1295
1331
  toggleRowSelection,
1296
1332
  clearSelections,
@@ -1335,11 +1371,10 @@ function LookupSelect(props) {
1335
1371
  virtualRowHeight,
1336
1372
  pageSize
1337
1373
  ]);
1338
- const { announce } = useScreenReaderAnnouncements();
1374
+ useScreenReaderAnnouncements();
1339
1375
  useFocusManagement(modalOpen);
1340
1376
  useKeyboardNavigation({
1341
1377
  isModalOpen: modalOpen,
1342
- onClose: closeModal,
1343
1378
  onConfirm: confirmSelection,
1344
1379
  currentData: [],
1345
1380
  selectedRows: currentSelections,
@@ -1351,13 +1386,34 @@ function LookupSelect(props) {
1351
1386
  const [serverData, setServerData] = React3.useState([]);
1352
1387
  const [totalCount, setTotalCount] = React3.useState(0);
1353
1388
  const [currentPage, setCurrentPage] = React3.useState(1);
1389
+ const [sortState, setSortState] = React3.useState({});
1390
+ const [debouncedSearch, setDebouncedSearch] = React3.useState("");
1391
+ const debounceTimerRef = React3.useRef(null);
1354
1392
  const handleSearchChange = React3.useCallback(
1355
1393
  (value) => {
1356
1394
  setSearchValue(value);
1357
- updateQuery({ search: value, page: 1 });
1395
+ if (dataSource) {
1396
+ if (debounceTimerRef.current) {
1397
+ clearTimeout(debounceTimerRef.current);
1398
+ }
1399
+ debounceTimerRef.current = setTimeout(() => {
1400
+ setDebouncedSearch(value);
1401
+ setCurrentPage(1);
1402
+ updateQuery({ search: value, page: 1 });
1403
+ }, 300);
1404
+ } else {
1405
+ updateQuery({ search: value, page: 1 });
1406
+ }
1358
1407
  },
1359
- [updateQuery]
1408
+ [updateQuery, dataSource]
1360
1409
  );
1410
+ React3.useEffect(() => {
1411
+ return () => {
1412
+ if (debounceTimerRef.current) {
1413
+ clearTimeout(debounceTimerRef.current);
1414
+ }
1415
+ };
1416
+ }, []);
1361
1417
  const filteredData = React3.useMemo(() => {
1362
1418
  if (!searchValue || dataSource) {
1363
1419
  return data;
@@ -1375,13 +1431,14 @@ function LookupSelect(props) {
1375
1431
  setLoading(true);
1376
1432
  setError(void 0);
1377
1433
  try {
1378
- const query = getCurrentQuery();
1379
- const result = await dataSource({
1380
- ...query,
1381
- search: searchValue,
1434
+ const query = {
1435
+ search: debouncedSearch,
1382
1436
  page: currentPage,
1383
- pageSize: optimizedPageSize
1384
- });
1437
+ pageSize: optimizedPageSize,
1438
+ sortBy: sortState.sortBy,
1439
+ sortDir: sortState.sortDir
1440
+ };
1441
+ const result = await dataSource(query);
1385
1442
  setServerData(result.rows);
1386
1443
  setTotalCount(result.total);
1387
1444
  setLoading(false);
@@ -1393,10 +1450,10 @@ function LookupSelect(props) {
1393
1450
  }
1394
1451
  }, [
1395
1452
  dataSource,
1396
- getCurrentQuery,
1397
- searchValue,
1453
+ debouncedSearch,
1398
1454
  currentPage,
1399
- optimizedPageSize
1455
+ optimizedPageSize,
1456
+ sortState
1400
1457
  ]);
1401
1458
  React3.useEffect(() => {
1402
1459
  if (dataSource && modalOpen) {
@@ -1412,8 +1469,9 @@ function LookupSelect(props) {
1412
1469
  );
1413
1470
  const handleSortChange = React3.useCallback(
1414
1471
  (sortBy, sortDir) => {
1415
- updateQuery({ sortBy, sortDir, page: 1 });
1472
+ setSortState({ sortBy, sortDir });
1416
1473
  setCurrentPage(1);
1474
+ updateQuery({ sortBy, sortDir, page: 1 });
1417
1475
  },
1418
1476
  [updateQuery]
1419
1477
  );
@@ -1450,11 +1508,12 @@ function LookupSelect(props) {
1450
1508
  loading,
1451
1509
  error,
1452
1510
  emptyText: texts.emptyText,
1511
+ onRetry: dataSource ? loadServerData : void 0,
1453
1512
  className: classNames?.grid,
1454
1513
  style: styles?.grid,
1455
1514
  currentSort: dataSource ? {
1456
- sortBy: getCurrentQuery().sortBy || "",
1457
- sortDir: getCurrentQuery().sortDir || "asc"
1515
+ sortBy: sortState.sortBy || "",
1516
+ sortDir: sortState.sortDir || "asc"
1458
1517
  } : void 0,
1459
1518
  onSort: dataSource ? handleSortChange : void 0
1460
1519
  };
@@ -1489,7 +1548,7 @@ function LookupSelect(props) {
1489
1548
  virtualizationConfig
1490
1549
  ]);
1491
1550
  const renderModalContent = () => {
1492
- const defaultContent = /* @__PURE__ */ jsxs6(Fragment2, { children: [
1551
+ const defaultContent = /* @__PURE__ */ jsxs6(Fragment, { children: [
1493
1552
  renderSearch ? renderSearch({
1494
1553
  value: searchValue,
1495
1554
  onChange: handleSearchChange,
@@ -1511,12 +1570,14 @@ function LookupSelect(props) {
1511
1570
  selectedIds: currentSelections.map(mapper.getId),
1512
1571
  onRowSelect: toggleRowSelection,
1513
1572
  onSelectAll: mode === "multiple" ? () => {
1514
- const allIds = currentData.map(mapper.getId);
1515
- const selectedIds = currentSelections.map(mapper.getId);
1516
- if (allIds.length === selectedIds.length) {
1573
+ const selectableData = selectableRow ? currentData.filter(selectableRow) : currentData;
1574
+ const allSelected = selectableData.every(
1575
+ (row) => isRowSelected(row)
1576
+ );
1577
+ if (allSelected) {
1517
1578
  clearSelections();
1518
1579
  } else {
1519
- currentData.forEach((row) => {
1580
+ selectableData.forEach((row) => {
1520
1581
  if (!isRowSelected(row)) {
1521
1582
  toggleRowSelection(row);
1522
1583
  }
@@ -1531,8 +1592,8 @@ function LookupSelect(props) {
1531
1592
  virtualization: shouldUseVirtualization ? virtualizationConfig : void 0,
1532
1593
  selectableRow,
1533
1594
  onSortChange: handleSortChange,
1534
- sortBy: getCurrentQuery().sortBy,
1535
- sortDir: getCurrentQuery().sortDir
1595
+ sortBy: sortState.sortBy,
1596
+ sortDir: sortState.sortDir
1536
1597
  }) : renderGridComponent(),
1537
1598
  dataSource && !renderPagination && /* @__PURE__ */ jsx6(
1538
1599
  Pagination,
@@ -1540,7 +1601,12 @@ function LookupSelect(props) {
1540
1601
  currentPage,
1541
1602
  totalCount,
1542
1603
  pageSize: optimizedPageSize,
1543
- onPageChange: handlePageChange
1604
+ onPageChange: handlePageChange,
1605
+ i18n: {
1606
+ previousPage: i18n?.previousPage,
1607
+ nextPage: i18n?.nextPage,
1608
+ pageLabel: i18n?.paginationInfo ? (pageNum) => i18n.paginationInfo(pageNum, Math.ceil(totalCount / optimizedPageSize)) : void 0
1609
+ }
1544
1610
  }
1545
1611
  ),
1546
1612
  dataSource && renderPagination && renderPagination({
@@ -1548,7 +1614,7 @@ function LookupSelect(props) {
1548
1614
  totalPages: Math.ceil(totalCount / optimizedPageSize),
1549
1615
  onPageChange: handlePageChange,
1550
1616
  pageSize: optimizedPageSize,
1551
- onPageSizeChange: (newSize) => {
1617
+ onPageSizeChange: (_newSize) => {
1552
1618
  },
1553
1619
  totalCount,
1554
1620
  loading