@bsol-oss/react-datatable5 7.5.1 → 7.6.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/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # React Datatable
2
2
 
3
+ The datetable package is built on top of `@tanstack/react-table` and `chakra-ui` to create a robust datatable. This hook simplifies to initialize the state management for controlling the datatable, and it offers several predefined tables and controls in to enhance data visualization.
4
+
3
5
  ## Installation
4
6
 
5
7
  ```bash
@@ -10,11 +12,11 @@ npm install @tanstack/react-table @chakra-ui/react @emotion/react @bsol-oss/reac
10
12
 
11
13
  ### Hook
12
14
 
13
- The `DataTable` and `DataTableServer` utilize hook to add props.
15
+ The `DataTable` and `DataTableServer` utilize hook to add props.
14
16
 
15
17
  ```tsx
16
18
  const datatable = useDataTable();
17
- const datatableServer = useDataTableServer({url: "<some-url>"});
19
+ const datatableServer = useDataTableServer({ url: "<some-url>" });
18
20
  ```
19
21
 
20
22
  ### DataTable
@@ -43,10 +45,7 @@ const datatableServer = useDataTableServer({url: "<some-url>"});
43
45
  ### DataTableServer
44
46
 
45
47
  ```tsx
46
- <DataTableServer
47
- columns={columns}
48
- {...datatable}
49
- >
48
+ <DataTableServer columns={columns} {...datatable}>
50
49
  <Flex>
51
50
  <TablePagination />
52
51
  <EditViewButton />
@@ -76,7 +75,7 @@ const datatableServer = useDataTableServer({url: "<some-url>"});
76
75
  Example Url generated by the DataTableServer
77
76
 
78
77
  ```
79
- GET http://localhost:8333/api/v1/gpt/chat/history/all?pagination={"offset":0,"rows":10}&sorting={}&where={}&searching=hello
78
+ GET http://localhost:8081/api/g/core_people?offset=0&limit=10&sorting[0][id]=id&sorting[0][desc]=false&where[0][id]=last_name&where[0][value]=nicenice&searching=good
80
79
  ```
81
80
 
82
81
  ### DefaultTable
@@ -112,6 +111,16 @@ GET http://localhost:8333/api/v1/gpt/chat/history/all?pagination={"offset":0,"ro
112
111
  </DataTable>
113
112
  ```
114
113
 
114
+ ### DataDisplay
115
+
116
+ ```tsx
117
+ <DataTable columns={columns} data={data} {...datatable}>
118
+ <DataDisplay />
119
+ </DataTable>
120
+ ```
121
+
122
+ For more details of props and examples, please review the stories in storybook platform.
123
+
115
124
  ## Development
116
125
 
117
126
  ```
package/dist/index.d.ts CHANGED
@@ -117,7 +117,7 @@ declare module "@tanstack/react-table" {
117
117
  itemRank: RankingInfo;
118
118
  }
119
119
  }
120
- interface DataTableProps<TData> {
120
+ interface DataTableProps<TData = unknown> {
121
121
  children?: ReactNode | ReactNode[];
122
122
  data: TData[];
123
123
  columns: ColumnDef<TData, unknown>[];
@@ -366,7 +366,7 @@ interface TextCellProps {
366
366
  }
367
367
  declare const TextCell: ({ label, containerProps, textProps, children, }: TextCellProps) => react_jsx_runtime.JSX.Element;
368
368
 
369
- interface DataTableContext<TData> {
369
+ interface DataTableContext<TData = unknown> {
370
370
  table: Table$1<TData>;
371
371
  globalFilter: string;
372
372
  setGlobalFilter: OnChangeFn<string>;
package/dist/index.js CHANGED
@@ -570,7 +570,7 @@ const PaginationItems = (props) => {
570
570
  return page.type === "ellipsis" ? (jsxRuntime.jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsxRuntime.jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
571
571
  }) }));
572
572
  };
573
- React__namespace.forwardRef(function PaginationPageText(props, ref) {
573
+ const PaginationPageText = React__namespace.forwardRef(function PaginationPageText(props, ref) {
574
574
  const { format = "compact", ...rest } = props;
575
575
  const { page, totalPages, pageRange, count } = react.usePaginationContext();
576
576
  const content = React__namespace.useMemo(() => {
@@ -833,7 +833,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
833
833
  onColumnVisibilityChange: setColumnVisibility,
834
834
  });
835
835
  return (jsxRuntime.jsx(DataTableContext.Provider, { value: {
836
- table: { ...table },
836
+ table: table,
837
837
  globalFilter: globalFilter,
838
838
  setGlobalFilter: setGlobalFilter,
839
839
  type: "client",
@@ -1660,7 +1660,7 @@ const useSchemaContext = () => {
1660
1660
  };
1661
1661
  };
1662
1662
 
1663
- const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, }) => {
1663
+ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
1664
1664
  if (serverUrl === undefined || serverUrl.length == 0) {
1665
1665
  throw new Error("The serverUrl is missing");
1666
1666
  }
@@ -1678,6 +1678,7 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
1678
1678
  searching,
1679
1679
  where,
1680
1680
  limit,
1681
+ offset
1681
1682
  },
1682
1683
  };
1683
1684
  try {
@@ -1700,22 +1701,24 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1700
1701
  if (schema.properties == undefined) {
1701
1702
  throw new Error("schema properties when using DatePicker");
1702
1703
  }
1703
- const { total, showing, close, typeToSearch, showMore } = displayText;
1704
+ const { total, showing, typeToSearch } = displayText;
1704
1705
  const { gridColumn, gridRow, title, renderDisplay } = schema.properties[column];
1705
1706
  const [searchText, setSearchText] = React.useState();
1706
1707
  const [limit, setLimit] = React.useState(10);
1707
1708
  const [openSearchResult, setOpenSearchResult] = React.useState();
1709
+ const [page, setPage] = React.useState(0);
1708
1710
  const [idMap, setIdMap] = React.useState({});
1709
1711
  const ref = React.useRef(null);
1710
1712
  const selectedIds = watch(column) ?? [];
1711
1713
  const query = reactQuery.useQuery({
1712
- queryKey: [`idpicker`, searchText, in_table, limit],
1714
+ queryKey: [`idpicker`, { searchText, in_table, limit, page }],
1713
1715
  queryFn: async () => {
1714
1716
  const data = await getTableData({
1715
1717
  serverUrl,
1716
1718
  searching: searchText ?? "",
1717
1719
  in_table: in_table,
1718
1720
  limit: limit,
1721
+ offset: page * 10,
1719
1722
  });
1720
1723
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
1721
1724
  return [
@@ -1731,15 +1734,15 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1731
1734
  return data;
1732
1735
  },
1733
1736
  enabled: (searchText ?? "")?.length > 0,
1734
- staleTime: 10000,
1737
+ staleTime: 300000,
1735
1738
  });
1736
1739
  reactQuery.useQuery({
1737
- queryKey: [`idpicker`, ...selectedIds],
1740
+ queryKey: [`idpicker`, { selectedIds }],
1738
1741
  queryFn: async () => {
1739
1742
  const data = await getTableData({
1740
1743
  serverUrl,
1741
1744
  in_table: in_table,
1742
- limit: limit,
1745
+ limit: 1,
1743
1746
  where: [{ id: column_ref, value: watchId }],
1744
1747
  });
1745
1748
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
@@ -1756,7 +1759,7 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1756
1759
  return data;
1757
1760
  },
1758
1761
  enabled: (selectedIds ?? []).length > 0,
1759
- staleTime: 10000,
1762
+ staleTime: 300000,
1760
1763
  });
1761
1764
  const { isLoading, isFetching, data, isPending, isError } = query;
1762
1765
  const dataList = React.useMemo(() => data?.data ?? [], [data]);
@@ -1764,6 +1767,7 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1764
1767
  const isDirty = (searchText?.length ?? 0) > 0;
1765
1768
  const onSearchChange = async (event) => {
1766
1769
  setSearchText(event.target.value);
1770
+ setPage(0);
1767
1771
  setLimit(10);
1768
1772
  };
1769
1773
  const watchId = watch(column);
@@ -1793,40 +1797,30 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1793
1797
  setOpenSearchResult(true);
1794
1798
  }, children: "Add" })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
1795
1799
  setOpenSearchResult(true);
1796
- }, children: getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(react.Input, { placeholder: typeToSearch, onChange: (event) => {
1800
+ }, children: getPickedValue() })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: typeToSearch ?? "Type To Search", onChange: (event) => {
1797
1801
  onSearchChange(event);
1798
1802
  setOpenSearchResult(true);
1799
- }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), isError && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isError" }), jsxRuntime.jsx(react.Text, { children: `${total ?? "Total"} ${count}, ${showing ?? "Showing"} ${limit}` }), jsxRuntime.jsx(Button, { onClick: async () => {
1800
- setOpenSearchResult(false);
1801
- }, children: close ?? "Close" }), jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children:
1802
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1803
- dataList.map((item) => {
1804
- const selected = isMultiple
1805
- ? watchIds.some((id) => item[column_ref] === id)
1806
- : watchId === item[column_ref];
1807
- return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
1808
- if (!isMultiple) {
1809
- setOpenSearchResult(false);
1810
- setValue(column, item[column_ref]);
1811
- return;
1812
- }
1813
- const newSet = new Set([
1814
- ...(watchIds ?? []),
1815
- item[column_ref],
1816
- ]);
1817
- setValue(column, [...newSet]);
1818
- }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
1819
- ? renderDisplay(item)
1820
- : item[display_column] }, item[column_ref]));
1821
- }) }), isDirty && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [dataList.length <= 0 && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "Empty Search Result" }), " "] })), count > dataList.length && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsx(Button, { onClick: async () => {
1822
- setLimit((limit) => limit + 10);
1823
- await getTableData({
1824
- serverUrl,
1825
- searching: searchText ?? "",
1826
- in_table: in_table,
1827
- limit: limit + 10,
1828
- });
1829
- }, children: showMore ?? "Show More" }) }))] })] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
1803
+ }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), (searchText?.length ?? 0) > 0 && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isFetching && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isFetching" }), isLoading && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isLoading" }), isPending && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isPending" }), isError && jsxRuntime.jsx(jsxRuntime.Fragment, { children: "isError" }), jsxRuntime.jsx(react.Text, { justifySelf: "center", children: `${total ?? "Total"} ${count}, ${showing ?? "Showing"} ${limit}` }), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children:
1804
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1805
+ dataList.map((item) => {
1806
+ const selected = isMultiple
1807
+ ? watchIds.some((id) => item[column_ref] === id)
1808
+ : watchId === item[column_ref];
1809
+ return (jsxRuntime.jsx(react.Box, { cursor: "pointer", onClick: () => {
1810
+ if (!isMultiple) {
1811
+ setOpenSearchResult(false);
1812
+ setValue(column, item[column_ref]);
1813
+ return;
1814
+ }
1815
+ const newSet = new Set([
1816
+ ...(watchIds ?? []),
1817
+ item[column_ref],
1818
+ ]);
1819
+ setValue(column, [...newSet]);
1820
+ }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
1821
+ ? renderDisplay(item)
1822
+ : item[display_column] }, item[column_ref]));
1823
+ }) }), isDirty && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [dataList.length <= 0 && jsxRuntime.jsx(react.Text, { children: "Empty Search Result" }), " "] }))] }), jsxRuntime.jsx(PaginationRoot, { justifySelf: "center", count: query?.data?.count ?? 0, pageSize: 10, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxRuntime.jsxs(react.HStack, { gap: "4", children: [jsxRuntime.jsx(PaginationPrevTrigger, {}), jsxRuntime.jsx(PaginationPageText, {}), jsxRuntime.jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
1830
1824
  };
1831
1825
 
1832
1826
  const ToggleTip = React__namespace.forwardRef(function ToggleTip(props, ref) {
@@ -2259,10 +2253,20 @@ const FilePicker = ({ column }) => {
2259
2253
  }) }), errors[`${column}`] && (jsxRuntime.jsx(react.Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
2260
2254
  };
2261
2255
 
2256
+ function filterArray(array, searchTerm) {
2257
+ // Convert the search term to lower case for case-insensitive comparison
2258
+ const lowerCaseSearchTerm = searchTerm.toLowerCase();
2259
+ // Use the filter method to return an array of matching items
2260
+ return array.filter((item) => {
2261
+ // Convert each item to a string and check if it includes the search term
2262
+ return item.toString().toLowerCase().includes(lowerCaseSearchTerm);
2263
+ });
2264
+ }
2265
+
2262
2266
  const EnumPicker = ({ column, isMultiple = false }) => {
2263
2267
  const { watch, formState: { errors }, setValue, } = reactHookForm.useFormContext();
2264
2268
  const { schema, displayText } = useSchemaContext();
2265
- const { fieldRequired } = displayText;
2269
+ const { fieldRequired, total, showing, typeToSearch } = displayText;
2266
2270
  const { required } = schema;
2267
2271
  const isRequired = required?.some((columnId) => columnId === column);
2268
2272
  if (schema.properties == undefined) {
@@ -2297,12 +2301,10 @@ const EnumPicker = ({ column, isMultiple = false }) => {
2297
2301
  setOpenSearchResult(true);
2298
2302
  }, children: "Add" })] })), !isMultiple && (jsxRuntime.jsx(Button, { variant: "outline", onClick: () => {
2299
2303
  setOpenSearchResult(true);
2300
- }, children: watchEnum })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { children: [jsxRuntime.jsx(react.Input, { placeholder: "Type to search", onChange: (event) => {
2304
+ }, children: watchEnum })), jsxRuntime.jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsxRuntime.jsx(PopoverTrigger, {}), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsxRuntime.jsx(react.Input, { placeholder: typeToSearch ?? "Type to search", onChange: (event) => {
2301
2305
  onSearchChange(event);
2302
2306
  setOpenSearchResult(true);
2303
- }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsxRuntime.jsx(react.Text, { children: `Search Result: ${count}, Showing ${limit}` }), jsxRuntime.jsx(Button, { onClick: async () => {
2304
- setOpenSearchResult(false);
2305
- }, children: "close" }), jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children: dataList.map((item) => {
2307
+ }, autoComplete: "off", ref: ref }), jsxRuntime.jsx(PopoverTitle, {}), jsxRuntime.jsx(react.Text, { children: `${total ?? "Total"}: ${count}, ${showing ?? "Showing"} ${limit}` }), jsxRuntime.jsxs(react.Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsxRuntime.jsx(react.Flex, { flexFlow: "column wrap", children: filterArray(dataList, searchText ?? "").map((item) => {
2306
2308
  const selected = isMultiple
2307
2309
  ? watchEnums.some((enumValue) => item === enumValue)
2308
2310
  : watchEnum == item;
package/dist/index.mjs CHANGED
@@ -550,7 +550,7 @@ const PaginationItems = (props) => {
550
550
  return page.type === "ellipsis" ? (jsx(PaginationEllipsis, { index: index, ...props }, index)) : (jsx(PaginationItem, { type: "page", value: page.value, ...props }, index));
551
551
  }) }));
552
552
  };
553
- React.forwardRef(function PaginationPageText(props, ref) {
553
+ const PaginationPageText = React.forwardRef(function PaginationPageText(props, ref) {
554
554
  const { format = "compact", ...rest } = props;
555
555
  const { page, totalPages, pageRange, count } = usePaginationContext();
556
556
  const content = React.useMemo(() => {
@@ -813,7 +813,7 @@ function DataTable({ columns, data, enableRowSelection = true, enableMultiRowSel
813
813
  onColumnVisibilityChange: setColumnVisibility,
814
814
  });
815
815
  return (jsx(DataTableContext.Provider, { value: {
816
- table: { ...table },
816
+ table: table,
817
817
  globalFilter: globalFilter,
818
818
  setGlobalFilter: setGlobalFilter,
819
819
  type: "client",
@@ -1640,7 +1640,7 @@ const useSchemaContext = () => {
1640
1640
  };
1641
1641
  };
1642
1642
 
1643
- const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, }) => {
1643
+ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], limit = 10, offset = 0, }) => {
1644
1644
  if (serverUrl === undefined || serverUrl.length == 0) {
1645
1645
  throw new Error("The serverUrl is missing");
1646
1646
  }
@@ -1658,6 +1658,7 @@ const getTableData = async ({ serverUrl, in_table, searching = "", where = [], l
1658
1658
  searching,
1659
1659
  where,
1660
1660
  limit,
1661
+ offset
1661
1662
  },
1662
1663
  };
1663
1664
  try {
@@ -1680,22 +1681,24 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1680
1681
  if (schema.properties == undefined) {
1681
1682
  throw new Error("schema properties when using DatePicker");
1682
1683
  }
1683
- const { total, showing, close, typeToSearch, showMore } = displayText;
1684
+ const { total, showing, typeToSearch } = displayText;
1684
1685
  const { gridColumn, gridRow, title, renderDisplay } = schema.properties[column];
1685
1686
  const [searchText, setSearchText] = useState();
1686
1687
  const [limit, setLimit] = useState(10);
1687
1688
  const [openSearchResult, setOpenSearchResult] = useState();
1689
+ const [page, setPage] = useState(0);
1688
1690
  const [idMap, setIdMap] = useState({});
1689
1691
  const ref = useRef(null);
1690
1692
  const selectedIds = watch(column) ?? [];
1691
1693
  const query = useQuery({
1692
- queryKey: [`idpicker`, searchText, in_table, limit],
1694
+ queryKey: [`idpicker`, { searchText, in_table, limit, page }],
1693
1695
  queryFn: async () => {
1694
1696
  const data = await getTableData({
1695
1697
  serverUrl,
1696
1698
  searching: searchText ?? "",
1697
1699
  in_table: in_table,
1698
1700
  limit: limit,
1701
+ offset: page * 10,
1699
1702
  });
1700
1703
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
1701
1704
  return [
@@ -1711,15 +1714,15 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1711
1714
  return data;
1712
1715
  },
1713
1716
  enabled: (searchText ?? "")?.length > 0,
1714
- staleTime: 10000,
1717
+ staleTime: 300000,
1715
1718
  });
1716
1719
  useQuery({
1717
- queryKey: [`idpicker`, ...selectedIds],
1720
+ queryKey: [`idpicker`, { selectedIds }],
1718
1721
  queryFn: async () => {
1719
1722
  const data = await getTableData({
1720
1723
  serverUrl,
1721
1724
  in_table: in_table,
1722
- limit: limit,
1725
+ limit: 1,
1723
1726
  where: [{ id: column_ref, value: watchId }],
1724
1727
  });
1725
1728
  const newMap = Object.fromEntries((data ?? { data: [] }).data.map((item) => {
@@ -1736,7 +1739,7 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1736
1739
  return data;
1737
1740
  },
1738
1741
  enabled: (selectedIds ?? []).length > 0,
1739
- staleTime: 10000,
1742
+ staleTime: 300000,
1740
1743
  });
1741
1744
  const { isLoading, isFetching, data, isPending, isError } = query;
1742
1745
  const dataList = useMemo(() => data?.data ?? [], [data]);
@@ -1744,6 +1747,7 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1744
1747
  const isDirty = (searchText?.length ?? 0) > 0;
1745
1748
  const onSearchChange = async (event) => {
1746
1749
  setSearchText(event.target.value);
1750
+ setPage(0);
1747
1751
  setLimit(10);
1748
1752
  };
1749
1753
  const watchId = watch(column);
@@ -1773,40 +1777,30 @@ const IdPicker = ({ column, in_table, column_ref, display_column, isMultiple = f
1773
1777
  setOpenSearchResult(true);
1774
1778
  }, children: "Add" })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
1775
1779
  setOpenSearchResult(true);
1776
- }, children: getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(Input, { placeholder: typeToSearch, onChange: (event) => {
1780
+ }, children: getPickedValue() })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start", strategy: "fixed" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: typeToSearch ?? "Type To Search", onChange: (event) => {
1777
1781
  onSearchChange(event);
1778
1782
  setOpenSearchResult(true);
1779
- }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), isError && jsx(Fragment, { children: "isError" }), jsx(Text, { children: `${total ?? "Total"} ${count}, ${showing ?? "Showing"} ${limit}` }), jsx(Button, { onClick: async () => {
1780
- setOpenSearchResult(false);
1781
- }, children: close ?? "Close" }), jsx(Flex, { flexFlow: "column wrap", children:
1782
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1783
- dataList.map((item) => {
1784
- const selected = isMultiple
1785
- ? watchIds.some((id) => item[column_ref] === id)
1786
- : watchId === item[column_ref];
1787
- return (jsx(Box, { cursor: "pointer", onClick: () => {
1788
- if (!isMultiple) {
1789
- setOpenSearchResult(false);
1790
- setValue(column, item[column_ref]);
1791
- return;
1792
- }
1793
- const newSet = new Set([
1794
- ...(watchIds ?? []),
1795
- item[column_ref],
1796
- ]);
1797
- setValue(column, [...newSet]);
1798
- }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
1799
- ? renderDisplay(item)
1800
- : item[display_column] }, item[column_ref]));
1801
- }) }), isDirty && (jsxs(Fragment, { children: [dataList.length <= 0 && jsx(Fragment, { children: "Empty Search Result" }), " "] })), count > dataList.length && (jsx(Fragment, { children: jsx(Button, { onClick: async () => {
1802
- setLimit((limit) => limit + 10);
1803
- await getTableData({
1804
- serverUrl,
1805
- searching: searchText ?? "",
1806
- in_table: in_table,
1807
- limit: limit + 10,
1808
- });
1809
- }, children: showMore ?? "Show More" }) }))] })] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
1783
+ }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), (searchText?.length ?? 0) > 0 && (jsxs(Fragment, { children: [isFetching && jsx(Fragment, { children: "isFetching" }), isLoading && jsx(Fragment, { children: "isLoading" }), isPending && jsx(Fragment, { children: "isPending" }), isError && jsx(Fragment, { children: "isError" }), jsx(Text, { justifySelf: "center", children: `${total ?? "Total"} ${count}, ${showing ?? "Showing"} ${limit}` }), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Flex, { flexFlow: "column wrap", children:
1784
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1785
+ dataList.map((item) => {
1786
+ const selected = isMultiple
1787
+ ? watchIds.some((id) => item[column_ref] === id)
1788
+ : watchId === item[column_ref];
1789
+ return (jsx(Box, { cursor: "pointer", onClick: () => {
1790
+ if (!isMultiple) {
1791
+ setOpenSearchResult(false);
1792
+ setValue(column, item[column_ref]);
1793
+ return;
1794
+ }
1795
+ const newSet = new Set([
1796
+ ...(watchIds ?? []),
1797
+ item[column_ref],
1798
+ ]);
1799
+ setValue(column, [...newSet]);
1800
+ }, opacity: 0.7, _hover: { opacity: 1 }, ...(selected ? { color: "gray.400/50" } : {}), children: !!renderDisplay === true
1801
+ ? renderDisplay(item)
1802
+ : item[display_column] }, item[column_ref]));
1803
+ }) }), isDirty && (jsxs(Fragment, { children: [dataList.length <= 0 && jsx(Text, { children: "Empty Search Result" }), " "] }))] }), jsx(PaginationRoot, { justifySelf: "center", count: query?.data?.count ?? 0, pageSize: 10, defaultPage: 1, page: page + 1, onPageChange: (e) => setPage(e.page - 1), children: jsxs(HStack, { gap: "4", children: [jsx(PaginationPrevTrigger, {}), jsx(PaginationPageText, {}), jsx(PaginationNextTrigger, {})] }) })] }))] }) })] }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
1810
1804
  };
1811
1805
 
1812
1806
  const ToggleTip = React.forwardRef(function ToggleTip(props, ref) {
@@ -2239,10 +2233,20 @@ const FilePicker = ({ column }) => {
2239
2233
  }) }), errors[`${column}`] && (jsx(Text, { color: "red.400", children: fieldRequired ?? "The field is requried" }))] }));
2240
2234
  };
2241
2235
 
2236
+ function filterArray(array, searchTerm) {
2237
+ // Convert the search term to lower case for case-insensitive comparison
2238
+ const lowerCaseSearchTerm = searchTerm.toLowerCase();
2239
+ // Use the filter method to return an array of matching items
2240
+ return array.filter((item) => {
2241
+ // Convert each item to a string and check if it includes the search term
2242
+ return item.toString().toLowerCase().includes(lowerCaseSearchTerm);
2243
+ });
2244
+ }
2245
+
2242
2246
  const EnumPicker = ({ column, isMultiple = false }) => {
2243
2247
  const { watch, formState: { errors }, setValue, } = useFormContext();
2244
2248
  const { schema, displayText } = useSchemaContext();
2245
- const { fieldRequired } = displayText;
2249
+ const { fieldRequired, total, showing, typeToSearch } = displayText;
2246
2250
  const { required } = schema;
2247
2251
  const isRequired = required?.some((columnId) => columnId === column);
2248
2252
  if (schema.properties == undefined) {
@@ -2277,12 +2281,10 @@ const EnumPicker = ({ column, isMultiple = false }) => {
2277
2281
  setOpenSearchResult(true);
2278
2282
  }, children: "Add" })] })), !isMultiple && (jsx(Button, { variant: "outline", onClick: () => {
2279
2283
  setOpenSearchResult(true);
2280
- }, children: watchEnum })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { children: [jsx(Input, { placeholder: "Type to search", onChange: (event) => {
2284
+ }, children: watchEnum })), jsxs(PopoverRoot, { open: openSearchResult, onOpenChange: (e) => setOpenSearchResult(e.open), closeOnInteractOutside: true, initialFocusEl: () => ref.current, positioning: { placement: "bottom-start" }, children: [jsx(PopoverTrigger, {}), jsx(PopoverContent, { children: jsxs(PopoverBody, { display: "grid", gap: 1, children: [jsx(Input, { placeholder: typeToSearch ?? "Type to search", onChange: (event) => {
2281
2285
  onSearchChange(event);
2282
2286
  setOpenSearchResult(true);
2283
- }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Text, { children: `Search Result: ${count}, Showing ${limit}` }), jsx(Button, { onClick: async () => {
2284
- setOpenSearchResult(false);
2285
- }, children: "close" }), jsx(Flex, { flexFlow: "column wrap", children: dataList.map((item) => {
2287
+ }, autoComplete: "off", ref: ref }), jsx(PopoverTitle, {}), jsx(Text, { children: `${total ?? "Total"}: ${count}, ${showing ?? "Showing"} ${limit}` }), jsxs(Grid, { gridTemplateColumns: "repeat(auto-fit, minmax(15rem, 1fr))", overflow: "auto", maxHeight: "50vh", children: [jsx(Flex, { flexFlow: "column wrap", children: filterArray(dataList, searchText ?? "").map((item) => {
2286
2288
  const selected = isMultiple
2287
2289
  ? watchEnums.some((enumValue) => item === enumValue)
2288
2290
  : watchEnum == item;
@@ -10,7 +10,7 @@ declare module "@tanstack/react-table" {
10
10
  itemRank: RankingInfo;
11
11
  }
12
12
  }
13
- export interface DataTableProps<TData> {
13
+ export interface DataTableProps<TData = unknown> {
14
14
  children?: ReactNode | ReactNode[];
15
15
  data: TData[];
16
16
  columns: ColumnDef<TData, unknown>[];
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { OnChangeFn, Table } from "@tanstack/react-table";
3
- export interface DataTableContext<TData> {
3
+ export interface DataTableContext<TData = unknown> {
4
4
  table: Table<TData>;
5
5
  globalFilter: string;
6
6
  setGlobalFilter: OnChangeFn<string>;
@@ -0,0 +1 @@
1
+ export declare function filterArray(array: string[], searchTerm: string): string[];
@@ -2,6 +2,7 @@ export interface GetTableDataConfig {
2
2
  serverUrl: string;
3
3
  in_table: string;
4
4
  limit?: number;
5
+ offset?: number;
5
6
  where?: {
6
7
  id: string;
7
8
  value: string[];
@@ -12,4 +13,4 @@ export interface GetTableResponse {
12
13
  data?: object[];
13
14
  count: number;
14
15
  }
15
- export declare const getTableData: ({ serverUrl, in_table, searching, where, limit, }: GetTableDataConfig) => Promise<any>;
16
+ export declare const getTableData: ({ serverUrl, in_table, searching, where, limit, offset, }: GetTableDataConfig) => Promise<any>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsol-oss/react-datatable5",
3
- "version": "7.5.1",
3
+ "version": "7.6.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",