antd-crud-table 0.4.0 → 0.7.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 (41) hide show
  1. package/README.md +293 -783
  2. package/dist/CrudTable-Btf58zof.js +610 -0
  3. package/dist/CrudTable-DRN70sET.cjs +1 -0
  4. package/dist/CrudTable.cjs +1 -1
  5. package/dist/CrudTable.d.ts +85 -18
  6. package/dist/CrudTable.js +3 -306
  7. package/dist/CrudTableLazy.cjs +1 -1
  8. package/dist/CrudTableLazy.d.ts +4 -3
  9. package/dist/CrudTableLazy.js +8 -7
  10. package/dist/core/CustomDataSource.d.ts +35 -0
  11. package/dist/core/InMemoryDataSource.d.ts +30 -0
  12. package/dist/core/LocalStorageDataSource.d.ts +30 -0
  13. package/dist/core/RestDataSource.d.ts +120 -0
  14. package/dist/core/StaticDataSource.d.ts +20 -0
  15. package/dist/core/identity.d.ts +28 -0
  16. package/dist/core/inMemoryQuery.d.ts +26 -0
  17. package/dist/core/index.d.ts +11 -0
  18. package/dist/core/types.d.ts +86 -0
  19. package/dist/en_US-D3Kl6g3n.cjs +1 -0
  20. package/dist/en_US-DGCMDOdX.js +41 -0
  21. package/dist/exportData.cjs +13 -13
  22. package/dist/exportData.js +48 -39
  23. package/dist/fields/registry.d.ts +38 -0
  24. package/dist/fields/types.d.ts +29 -0
  25. package/dist/hooks/useCrudTable.d.ts +114 -57
  26. package/dist/hooks/useLocalStorageCrud.d.ts +14 -9
  27. package/dist/index.cjs +1 -0
  28. package/dist/index.d.ts +14 -6
  29. package/dist/index.js +7 -0
  30. package/dist/locale/en_US.d.ts +10 -0
  31. package/dist/locale/index.d.ts +4 -0
  32. package/dist/locale/types.d.ts +89 -0
  33. package/dist/locale/useResolvedLocale.d.ts +35 -0
  34. package/dist/useCrudTable-40jpmCkr.cjs +1 -0
  35. package/dist/useCrudTable-DxjnXVlQ.js +460 -0
  36. package/dist/useCrudTable.cjs +1 -1
  37. package/dist/useCrudTable.js +2 -235
  38. package/dist/useLocalStorageCrud.cjs +1 -1
  39. package/dist/useLocalStorageCrud.js +12 -198
  40. package/dist/utils/exportData.d.ts +37 -12
  41. package/package.json +52 -16
@@ -1 +1 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`./CrudTable.cjs`);let e=require(`antd`),t=require(`react`);var n=(e,t=[])=>{try{let n=localStorage.getItem(e);return n?JSON.parse(n):t}catch{return t}},r=(e,t)=>{try{localStorage.setItem(e,JSON.stringify(t))}catch(e){console.error(`Failed to save to localStorage:`,e)}},i=(e,t,i=[])=>({getList:async t=>{let{current:r=1,pageSize:a=10,sortBy:o,sortOrder:s,...c}=t,l=n(e,i);Object.entries(c).forEach(([e,t])=>{t!=null&&t!==``&&e!==`current`&&e!==`pageSize`&&(l=l.filter(n=>{let r=n[e];return r==null?!1:String(r).toLowerCase().includes(String(t).toLowerCase())}))}),o&&s&&l.sort((e,t)=>{let n=e[o],r=t[o];if(n==null)return 1;if(r==null)return-1;let i=n>r?1:n<r?-1:0;return s===`ascend`?i:-i});let u=(r-1)*a;return{data:l.slice(u,u+a),total:l.length,success:!0}},create:async a=>{let o=n(e,i),s=o.length>0?Math.max(...o.map(e=>Number(e[t])||0),0):0,c={[t]:s+1,...a,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return o.push(c),r(e,o),c},update:async(a,o)=>{let s=n(e,i),c=s.findIndex(e=>e[t]===a);if(c===-1)throw Error(`Item not found`);return s[c]={...s[c],...o,updatedAt:new Date().toISOString()},r(e,s),s[c]},delete:async a=>{r(e,n(e,i).filter(e=>e[t]!==a))}}),a=(n,r,a=[],o)=>{let s=(0,t.useRef)(null),[c,l]=(0,t.useState)({loading:!1,error:null,data:[],total:0,current:1,pageSize:o?.defaultPageSize||10}),u=i(r,n,a),d=(0,t.useCallback)(async()=>{l(e=>({...e,loading:!0,error:null}));try{let e={current:c.current,pageSize:c.pageSize},t=await u.getList(e);l(e=>({...e,data:t.data,total:t.total,loading:!1}))}catch(t){let n=t instanceof Error?t.message:`Failed to fetch data`;l(e=>({...e,loading:!1,error:n})),o?.onError?.(`fetch`,t),e.message.error(n)}},[c.current,c.pageSize,u,o]);return(0,t.useEffect)(()=>{d()},[]),{refresh:d,create:(0,t.useCallback)(async t=>{try{l(e=>({...e,loading:!0}));let n=await u.create(t);return o?.optimisticUpdates?l(e=>({...e,data:[...e.data,n],total:e.total+1,loading:!1})):await d(),o?.onSuccess?.(`create`,n),e.message.success(`Created successfully`),s.current?.reload(),n}catch(t){l(e=>({...e,loading:!1}));let n=t instanceof Error?t.message:`Create failed`;return o?.onError?.(`create`,t),e.message.error(n),null}},[u,o,d]),update:(0,t.useCallback)(async(t,r)=>{try{l(e=>({...e,loading:!0}));let i=await u.update(t,r);return o?.optimisticUpdates?l(e=>({...e,data:e.data.map(e=>e[n]===t?{...e,...i}:e),loading:!1})):await d(),o?.onSuccess?.(`update`,i),e.message.success(`Updated successfully`),s.current?.reload(),i}catch(t){l(e=>({...e,loading:!1}));let n=t instanceof Error?t.message:`Update failed`;return o?.onError?.(`update`,t),e.message.error(n),null}},[u,o,n,d]),delete:(0,t.useCallback)(async t=>{try{return l(e=>({...e,loading:!0})),await u.delete(t),o?.optimisticUpdates?l(e=>({...e,data:e.data.filter(e=>e[n]!==t),total:e.total-1,loading:!1})):await d(),o?.onSuccess?.(`delete`,t),e.message.success(`Deleted successfully`),s.current?.reload(),!0}catch(t){l(e=>({...e,loading:!1}));let n=t instanceof Error?t.message:`Delete failed`;return o?.onError?.(`delete`,t),e.message.error(n),!1}},[u,o,n,d]),setPageSize:(0,t.useCallback)(e=>{l(t=>({...t,pageSize:e,current:1}))},[]),setCurrentPage:(0,t.useCallback)(e=>{l(t=>({...t,current:e}))},[]),state:c,actionRef:s}};exports.default=a,exports.useLocalStorageCrud=a;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./useCrudTable-40jpmCkr.cjs");let t=require("react");var n=(n,r,i=[],a)=>{let o=e.n(n,{...a,storageKey:r,initialData:i}),{refresh:s}=o;return(0,t.useEffect)(()=>{s()},[]),o};exports.useLocalStorageCrud=n;
@@ -1,201 +1,15 @@
1
- import { message as e } from "antd";
2
- import { useCallback as t, useEffect as n, useRef as r, useState as i } from "react";
1
+ import { n as e } from "./useCrudTable-DxjnXVlQ.js";
2
+ import { useEffect as t } from "react";
3
3
  //#region lib/hooks/useLocalStorageCrud.ts
4
- var a = (e, t = []) => {
5
- try {
6
- let n = localStorage.getItem(e);
7
- return n ? JSON.parse(n) : t;
8
- } catch {
9
- return t;
10
- }
11
- }, o = (e, t) => {
12
- try {
13
- localStorage.setItem(e, JSON.stringify(t));
14
- } catch (e) {
15
- console.error("Failed to save to localStorage:", e);
16
- }
17
- }, s = (e, t, n = []) => ({
18
- getList: async (t) => {
19
- let { current: r = 1, pageSize: i = 10, sortBy: o, sortOrder: s, ...c } = t, l = a(e, n);
20
- Object.entries(c).forEach(([e, t]) => {
21
- t != null && t !== "" && e !== "current" && e !== "pageSize" && (l = l.filter((n) => {
22
- let r = n[e];
23
- return r == null ? !1 : String(r).toLowerCase().includes(String(t).toLowerCase());
24
- }));
25
- }), o && s && l.sort((e, t) => {
26
- let n = e[o], r = t[o];
27
- if (n == null) return 1;
28
- if (r == null) return -1;
29
- let i = n > r ? 1 : n < r ? -1 : 0;
30
- return s === "ascend" ? i : -i;
31
- });
32
- let u = (r - 1) * i;
33
- return {
34
- data: l.slice(u, u + i),
35
- total: l.length,
36
- success: !0
37
- };
38
- },
39
- create: async (r) => {
40
- let i = a(e, n), s = i.length > 0 ? Math.max(...i.map((e) => Number(e[t]) || 0), 0) : 0, c = {
41
- [t]: s + 1,
42
- ...r,
43
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
44
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
45
- };
46
- return i.push(c), o(e, i), c;
47
- },
48
- update: async (r, i) => {
49
- let s = a(e, n), c = s.findIndex((e) => e[t] === r);
50
- if (c === -1) throw Error("Item not found");
51
- return s[c] = {
52
- ...s[c],
53
- ...i,
54
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
55
- }, o(e, s), s[c];
56
- },
57
- delete: async (r) => {
58
- o(e, a(e, n).filter((e) => e[t] !== r));
59
- }
60
- }), c = (a, o, c = [], l) => {
61
- let u = r(null), [d, f] = i({
62
- loading: !1,
63
- error: null,
64
- data: [],
65
- total: 0,
66
- current: 1,
67
- pageSize: l?.defaultPageSize || 10
68
- }), p = s(o, a, c), m = t(async () => {
69
- f((e) => ({
70
- ...e,
71
- loading: !0,
72
- error: null
73
- }));
74
- try {
75
- let e = {
76
- current: d.current,
77
- pageSize: d.pageSize
78
- }, t = await p.getList(e);
79
- f((e) => ({
80
- ...e,
81
- data: t.data,
82
- total: t.total,
83
- loading: !1
84
- }));
85
- } catch (t) {
86
- let n = t instanceof Error ? t.message : "Failed to fetch data";
87
- f((e) => ({
88
- ...e,
89
- loading: !1,
90
- error: n
91
- })), l?.onError?.("fetch", t), e.error(n);
92
- }
93
- }, [
94
- d.current,
95
- d.pageSize,
96
- p,
97
- l
98
- ]);
99
- return n(() => {
100
- m();
101
- }, []), {
102
- refresh: m,
103
- create: t(async (t) => {
104
- try {
105
- f((e) => ({
106
- ...e,
107
- loading: !0
108
- }));
109
- let n = await p.create(t);
110
- return l?.optimisticUpdates ? f((e) => ({
111
- ...e,
112
- data: [...e.data, n],
113
- total: e.total + 1,
114
- loading: !1
115
- })) : await m(), l?.onSuccess?.("create", n), e.success("Created successfully"), u.current?.reload(), n;
116
- } catch (t) {
117
- f((e) => ({
118
- ...e,
119
- loading: !1
120
- }));
121
- let n = t instanceof Error ? t.message : "Create failed";
122
- return l?.onError?.("create", t), e.error(n), null;
123
- }
124
- }, [
125
- p,
126
- l,
127
- m
128
- ]),
129
- update: t(async (t, n) => {
130
- try {
131
- f((e) => ({
132
- ...e,
133
- loading: !0
134
- }));
135
- let r = await p.update(t, n);
136
- return l?.optimisticUpdates ? f((e) => ({
137
- ...e,
138
- data: e.data.map((e) => e[a] === t ? {
139
- ...e,
140
- ...r
141
- } : e),
142
- loading: !1
143
- })) : await m(), l?.onSuccess?.("update", r), e.success("Updated successfully"), u.current?.reload(), r;
144
- } catch (t) {
145
- f((e) => ({
146
- ...e,
147
- loading: !1
148
- }));
149
- let n = t instanceof Error ? t.message : "Update failed";
150
- return l?.onError?.("update", t), e.error(n), null;
151
- }
152
- }, [
153
- p,
154
- l,
155
- a,
156
- m
157
- ]),
158
- delete: t(async (t) => {
159
- try {
160
- return f((e) => ({
161
- ...e,
162
- loading: !0
163
- })), await p.delete(t), l?.optimisticUpdates ? f((e) => ({
164
- ...e,
165
- data: e.data.filter((e) => e[a] !== t),
166
- total: e.total - 1,
167
- loading: !1
168
- })) : await m(), l?.onSuccess?.("delete", t), e.success("Deleted successfully"), u.current?.reload(), !0;
169
- } catch (t) {
170
- f((e) => ({
171
- ...e,
172
- loading: !1
173
- }));
174
- let n = t instanceof Error ? t.message : "Delete failed";
175
- return l?.onError?.("delete", t), e.error(n), !1;
176
- }
177
- }, [
178
- p,
179
- l,
180
- a,
181
- m
182
- ]),
183
- setPageSize: t((e) => {
184
- f((t) => ({
185
- ...t,
186
- pageSize: e,
187
- current: 1
188
- }));
189
- }, []),
190
- setCurrentPage: t((e) => {
191
- f((t) => ({
192
- ...t,
193
- current: e
194
- }));
195
- }, []),
196
- state: d,
197
- actionRef: u
198
- };
4
+ var n = (n, r, i = [], a) => {
5
+ let o = e(n, {
6
+ ...a,
7
+ storageKey: r,
8
+ initialData: i
9
+ }), { refresh: s } = o;
10
+ return t(() => {
11
+ s();
12
+ }, []), o;
199
13
  };
200
14
  //#endregion
201
- export { c as default, c as useLocalStorageCrud };
15
+ export { n as useLocalStorageCrud };
@@ -1,17 +1,33 @@
1
- export type ExportFormat = 'csv' | 'json' | 'xlsx';
2
- interface ColumnOption {
1
+ import { EnumOption } from '../fields/types';
2
+ /**
3
+ * Supported export formats.
4
+ *
5
+ * `excel` emits Excel 2003 SpreadsheetML, not OOXML. It was previously named
6
+ * `xlsx`, which promised a format this library does not produce - writing a
7
+ * real .xlsx means owning a ZIP implementation, which is not worth a
8
+ * dependency-free library taking on. See exportToExcel for the tradeoff.
9
+ */
10
+ export type ExportFormat = 'csv' | 'json' | 'excel';
11
+ /** The column information an exporter needs: a header, a key, and how to format. */
12
+ export interface ColumnOption {
13
+ /** Header text. Falls back to `dataIndex`. */
3
14
  title?: string;
15
+ /** The record property this column reads. */
4
16
  dataIndex?: string;
17
+ /** Drives value formatting for booleans, enums and dates. */
5
18
  fieldType?: string;
6
- enumOptions?: Record<string, {
7
- text: string;
8
- color?: string;
9
- }>;
19
+ /** Labels for `enum` columns, so exports carry text rather than raw keys. */
20
+ enumOptions?: Record<string, EnumOption>;
10
21
  }
11
- interface ExportOptions<T> {
22
+ /** One export request. */
23
+ export interface ExportOptions<T> {
24
+ /** Records to write. */
12
25
  data: T[];
26
+ /** Columns to include, in order. */
13
27
  columns: ColumnOption[];
28
+ /** Base filename; the extension is chosen by the format. Defaults to `export`. */
14
29
  filename?: string;
30
+ /** Output format. Defaults to `csv`. */
15
31
  format?: ExportFormat;
16
32
  }
17
33
  /**
@@ -23,15 +39,24 @@ export declare const exportToCSV: <T>(options: ExportOptions<T>) => void;
23
39
  */
24
40
  export declare const exportToJSON: <T>(options: ExportOptions<T>) => void;
25
41
  /**
26
- * Export data to XLSX format (using simple XML format)
42
+ * Export data as an Excel-compatible spreadsheet.
43
+ *
44
+ * Emits Excel 2003 SpreadsheetML - an XML dialect Excel and LibreOffice open
45
+ * natively - written to a `.xls` file, rather than a real OOXML `.xlsx`, which
46
+ * would mean adding a dependency such as exceljs or hand-rolling a ZIP writer.
47
+ *
48
+ * Known consequence: because the content is SpreadsheetML and the extension is
49
+ * `.xls`, Excel 2016 and later show "The file format and extension don't
50
+ * match" on open. The file is intact and opens correctly once confirmed. The
51
+ * format is named `excel` rather than `xlsx` so the API does not claim
52
+ * otherwise.
27
53
  */
28
- export declare const exportToXLSX: <T extends Record<string, any>>(options: ExportOptions<T>) => void;
54
+ export declare const exportToExcel: <T extends object>(options: ExportOptions<T>) => void;
29
55
  /**
30
56
  * Export data with specified format
31
57
  */
32
- export declare const exportData: <T extends Record<string, any>>(options: ExportOptions<T>) => void;
58
+ export declare const exportData: <T extends object>(options: ExportOptions<T>) => void;
33
59
  /**
34
60
  * Export all data (including paginated data)
35
61
  */
36
- export declare const exportAllData: <T extends Record<string, any>>(getAllData: () => Promise<T[]>, columns: ColumnOption[], filename?: string, format?: ExportFormat) => Promise<void>;
37
- export default exportData;
62
+ export declare const exportAllData: <T extends object>(getAllData: () => Promise<T[]>, columns: ColumnOption[], filename?: string, format?: ExportFormat) => Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "antd-crud-table",
3
3
  "private": false,
4
- "version": "0.4.0",
4
+ "version": "0.7.0",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/maifeeulasad/antd-crud-table",
7
7
  "repository": {
@@ -16,38 +16,58 @@
16
16
  "components"
17
17
  ],
18
18
  "license": "MIT",
19
+ "engines": {
20
+ "node": ">=20.19.0"
21
+ },
19
22
  "author": "Maifee Ul Asad<maifeeulasad@gmail.com>",
20
23
  "peerDependencies": {
21
24
  "@ant-design/icons": "^6.0.0",
22
25
  "@ant-design/pro-components": "^2.8.10",
23
26
  "antd": "^6.3.6",
24
- "date-fns": "^4.1.0",
25
27
  "dayjs": "^1.11.13",
26
- "react": "^18.0.0",
27
- "react-dom": "^18.0.0"
28
+ "react": "^18.0.0 || ^19.0.0",
29
+ "react-dom": "^18.0.0 || ^19.0.0"
28
30
  },
29
31
  "devDependencies": {
32
+ "@ant-design/icons": "^6.0.0",
33
+ "@ant-design/pro-components": "^2.8.10",
30
34
  "@eslint/js": "^9.22.0",
35
+ "@storybook/react-vite": "^10.5.10",
36
+ "@testing-library/dom": "^10.4.1",
37
+ "@testing-library/react": "^16.3.2",
38
+ "@testing-library/user-event": "^14.6.6",
31
39
  "@types/node": "^22.15.2",
32
- "@types/react": "^19.0.10",
33
- "@types/react-dom": "^19.0.4",
40
+ "@types/react": "^19.2.18",
41
+ "@types/react-dom": "^19.2.5",
34
42
  "@vitejs/plugin-react-swc": "^3.8.0",
43
+ "@vitest/coverage-v8": "^4.1.11",
44
+ "antd": "^6.3.6",
45
+ "dayjs": "^1.11.13",
35
46
  "eslint": "^9.22.0",
36
47
  "eslint-plugin-react-hooks": "^5.2.0",
37
48
  "eslint-plugin-react-refresh": "^0.4.19",
38
49
  "globals": "^16.0.0",
39
- "react": "^18.0.0",
40
- "react-dom": "^18.0.0",
50
+ "jsdom": "^29.1.1",
51
+ "react": "^19.2.8",
52
+ "react-dom": "^19.2.8",
53
+ "storybook": "^10.5.10",
54
+ "typedoc": "^0.28.20",
41
55
  "typescript": "~5.7.2",
42
56
  "typescript-eslint": "^8.26.1",
43
57
  "vite": "^8.0.8",
44
- "vite-plugin-dts": "^4.5.3"
58
+ "vite-plugin-dts": "^4.5.3",
59
+ "vitest": "^4.1.11"
45
60
  },
46
- "main": "./dist/CrudTable.cjs",
47
- "module": "./dist/CrudTable.js",
48
- "types": "./dist/CrudTable.d.ts",
61
+ "main": "./dist/index.cjs",
62
+ "module": "./dist/index.js",
63
+ "types": "./dist/index.d.ts",
49
64
  "exports": {
50
65
  ".": {
66
+ "types": "./dist/index.d.ts",
67
+ "import": "./dist/index.js",
68
+ "require": "./dist/index.cjs"
69
+ },
70
+ "./CrudTable": {
51
71
  "types": "./dist/CrudTable.d.ts",
52
72
  "import": "./dist/CrudTable.js",
53
73
  "require": "./dist/CrudTable.cjs"
@@ -63,21 +83,37 @@
63
83
  "require": "./dist/useCrudTable.cjs"
64
84
  },
65
85
  "./hooks/useLocalStorageCrud": {
66
- "types": "./dist/hooks/useLocalStorageCrud.d.ts"
86
+ "types": "./dist/hooks/useLocalStorageCrud.d.ts",
87
+ "import": "./dist/useLocalStorageCrud.js",
88
+ "require": "./dist/useLocalStorageCrud.cjs"
67
89
  },
68
90
  "./utils/exportData": {
69
- "types": "./dist/utils/exportData.d.ts"
70
- }
91
+ "types": "./dist/utils/exportData.d.ts",
92
+ "import": "./dist/exportData.js",
93
+ "require": "./dist/exportData.cjs"
94
+ },
95
+ "./styles.css": "./dist/antd-crud-table.css"
71
96
  },
72
97
  "files": [
73
98
  "dist"
74
99
  ],
100
+ "sideEffects": [
101
+ "*.css"
102
+ ],
75
103
  "scripts": {
76
104
  "dev": "vite",
77
- "build:static": "tsc -b && vite build",
105
+ "build:demo": "tsc -b && vite build",
78
106
  "build:lib": "tsc --p ./tsconfig.build.json && vite build --config vite.config.lib.ts",
107
+ "docs:api": "typedoc",
108
+ "build:storybook": "STORYBOOK_BASE=\"${SITE_BASE:-/antd-crud-table/}storybook/\" storybook build -o dist-site/storybook",
109
+ "build:site": "pnpm build:demo && pnpm docs:api && pnpm build:storybook && pnpm inject:analytics",
110
+ "inject:analytics": "node scripts/inject-analytics.ts dist-site",
111
+ "storybook": "storybook dev -p 6006",
79
112
  "lint": "eslint .",
80
113
  "lint:fix": "eslint . --fix",
114
+ "test": "vitest run",
115
+ "test:watch": "vitest",
116
+ "test:coverage": "vitest run --coverage",
81
117
  "preview": "vite preview"
82
118
  }
83
119
  }