antd-crud-table 0.7.0 → 0.8.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.
@@ -1 +1 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./CrudTable-DRN70sET.cjs");require("./exportData.cjs"),exports.default=e.t;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./CrudTable-BfVtTGYV.cjs");require("./exportData.cjs"),exports.default=e.t;
@@ -66,6 +66,16 @@ export interface CrudTableConfig<T extends object, K extends keyof T> {
66
66
  enableColumnSettings?: boolean;
67
67
  /** Show the export entries in the toolbar menu. Defaults to true. */
68
68
  enableExport?: boolean;
69
+ /**
70
+ * Show the import entry in the toolbar menu. Defaults to false.
71
+ *
72
+ * Import creates records through the data source's `create` (or `createMany`
73
+ * when available), so it is only meaningful for a writable source. Opt-in,
74
+ * mirroring how a consumer decides whether the table accepts bulk input.
75
+ */
76
+ enableImport?: boolean;
77
+ /** Max simultaneous single-row creates during import. Defaults to 5. */
78
+ importConcurrency?: number;
69
79
  /**
70
80
  * Whether export covers the whole filtered result set or just the rows on
71
81
  * screen. Defaults to `'all'`, falling back to `'page'` when the data source
package/dist/CrudTable.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as e } from "./CrudTable-Btf58zof.js";
1
+ import { t as e } from "./CrudTable-jy8Db0uQ.js";
2
2
  import "./exportData.js";
3
3
  export { e as default };
@@ -1 +1 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./en_US-D3Kl6g3n.cjs");let t=require("react"),n=require("react/jsx-runtime");var r=(0,t.lazy)(()=>Promise.resolve().then(()=>require("./CrudTable.cjs"))),i=i=>(0,n.jsx)(t.Suspense,{fallback:(0,n.jsx)(`div`,{style:{textAlign:`center`,padding:`2rem`},children:i.locale?.loading??e.t.loading}),children:(0,n.jsx)(r,{...i})});exports.default=i;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./en_US-Q8nDeJhg.cjs");let t=require("react"),n=require("react/jsx-runtime");var r=(0,t.lazy)(()=>Promise.resolve().then(()=>require("./CrudTable.cjs"))),i=i=>(0,n.jsx)(t.Suspense,{fallback:(0,n.jsx)(`div`,{style:{textAlign:`center`,padding:`2rem`},children:i.locale?.loading??e.t.loading}),children:(0,n.jsx)(r,{...i})});exports.default=i;
@@ -1,4 +1,4 @@
1
- import { t as e } from "./en_US-DGCMDOdX.js";
1
+ import { t as e } from "./en_US-DghHhwRq.js";
2
2
  import { Suspense as t, lazy as n } from "react";
3
3
  import { jsx as r } from "react/jsx-runtime";
4
4
  //#region lib/CrudTableLazy.tsx
@@ -21,17 +21,62 @@ export interface RestParamNames {
21
21
  /** Parameter carrying the sort direction. Defaults to `sortOrder`. */
22
22
  sortOrder: string;
23
23
  }
24
+ /**
25
+ * An HTTP verb.
26
+ *
27
+ * The common ones are listed so they autocomplete, but any string is accepted:
28
+ * a closed union cannot describe every API, and being unable to send the verb
29
+ * a server expects is not a constraint worth enforcing.
30
+ */
31
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | (string & Record<never, never>);
24
32
  /** HTTP verbs used per mutating operation. */
25
33
  export interface RestMethods {
26
34
  /** Verb for creating a record. Defaults to `POST`. */
27
- create: 'POST' | 'PUT';
35
+ create: HttpMethod;
28
36
  /** Verb for updating a record. Defaults to `PUT`. */
29
- update: 'PUT' | 'PATCH' | 'POST';
37
+ update: HttpMethod;
30
38
  /** Verb for deleting a record. Defaults to `DELETE`. */
31
- remove: 'DELETE' | 'POST';
39
+ remove: HttpMethod;
40
+ }
41
+ /** Which operation a request belongs to. */
42
+ export type RestOperation = 'list' | 'create' | 'update' | 'remove';
43
+ /** Query-string values a caller can attach to a request. */
44
+ export type RestQueryValue = string | number | boolean;
45
+ /**
46
+ * What a request is for, handed to every call-time hook.
47
+ *
48
+ * Carrying the operation and its subject is what lets one hook serve all four
49
+ * - an `Idempotency-Key` on create, an `If-Match` built from the id on update,
50
+ * a fresh token on everything.
51
+ */
52
+ export interface RestRequestContext<T, K extends keyof T> {
53
+ operation: RestOperation;
54
+ /** Present for `update` and `remove`. */
55
+ id?: T[K];
56
+ /** Present for `create` and `update`. */
57
+ draft?: CrudDraft<T>;
58
+ /** Present for `list`. */
59
+ query?: CrudQuery<T>;
60
+ }
61
+ /**
62
+ * Per-request adjustments, resolved at call time.
63
+ *
64
+ * Returned from {@link RestDataSourceOptions.configureRequest}, which may be
65
+ * async - so a token can be awaited from a refresh call rather than captured
66
+ * when the source was constructed.
67
+ */
68
+ export interface RestRequestOverrides {
69
+ /** Merged over the static headers. */
70
+ headers?: Record<string, string>;
71
+ /** Replaces the verb this operation would otherwise use. */
72
+ method?: HttpMethod;
73
+ /** Merged over the static query parameters. */
74
+ query?: Record<string, RestQueryValue>;
75
+ /** Passed through to `fetch` - `credentials`, `mode`, `cache`, `signal`, ... */
76
+ init?: Omit<RequestInit, 'method' | 'body' | 'headers'>;
32
77
  }
33
78
  /** Everything needed to point a {@link RestDataSource} at an API. */
34
- export interface RestDataSourceOptions<T> {
79
+ export interface RestDataSourceOptions<T, K extends keyof T = keyof T> {
35
80
  /** Prefixed to every request path, exactly once. */
36
81
  baseUrl?: string;
37
82
  /** Overrides for the per-operation paths. */
@@ -42,10 +87,35 @@ export interface RestDataSourceOptions<T> {
42
87
  methods?: Partial<RestMethods>;
43
88
  /** Sent with every request, merged over the default content type. */
44
89
  headers?: Readonly<Record<string, string>>;
90
+ /** Appended to every request's query string, merged with generated parameters. */
91
+ query?: Readonly<Record<string, RestQueryValue>>;
92
+ /**
93
+ * Passed through to `fetch` on every request.
94
+ *
95
+ * This is where `credentials: 'include'` for cookie auth lives, along with
96
+ * `mode`, `cache`, `redirect` and a long-lived `signal`.
97
+ */
98
+ init?: Omit<RequestInit, 'method' | 'body' | 'headers'>;
99
+ /**
100
+ * Adjusts a request as it is made.
101
+ *
102
+ * Runs per call and may be async, so it covers what static options cannot:
103
+ * a rotating or awaited token, a header only one operation sends, a verb
104
+ * chosen from the payload. Its result is merged over the static options.
105
+ */
106
+ configureRequest?: (context: RestRequestContext<T, K>) => RestRequestOverrides | Promise<RestRequestOverrides>;
45
107
  /** Maps a draft onto the request body. Defaults to sending the draft as-is. */
46
- serializeRequest?: (draft: CrudDraft<T>) => unknown;
108
+ serializeRequest?: (draft: CrudDraft<T>, context: RestRequestContext<T, K>) => unknown;
47
109
  /** Maps a list response onto a page. Required when the API wraps its payload. */
48
110
  parseResponse?: (payload: unknown) => CrudPage<T>;
111
+ /**
112
+ * Maps a create or update response onto the stored record.
113
+ *
114
+ * The inbound counterpart to `serializeRequest`. Without it a write response
115
+ * is taken as the record itself, so an API that answers `{ data: { ... } }`
116
+ * hands back the envelope.
117
+ */
118
+ parseRecord?: (payload: unknown, context: RestRequestContext<T, K>) => T;
49
119
  /** Injected for testing; defaults to the global `fetch`. */
50
120
  fetchImpl?: typeof fetch;
51
121
  }
@@ -80,12 +150,20 @@ export declare class RestDataSource<T extends object, K extends keyof T> impleme
80
150
  protected readonly methods: RestMethods;
81
151
  /** Headers sent with every request. */
82
152
  protected readonly headers: Readonly<Record<string, string>>;
153
+ /** Appended to every request's query string. */
154
+ protected readonly query: Readonly<Record<string, RestQueryValue>>;
155
+ /** Passed through to `fetch` on every request. */
156
+ protected readonly init: Omit<RequestInit, 'method' | 'body' | 'headers'>;
157
+ /** Resolves per-request adjustments at call time. */
158
+ protected readonly configureRequest?: (context: RestRequestContext<T, K>) => RestRequestOverrides | Promise<RestRequestOverrides>;
83
159
  /** Maps a draft onto the request body. */
84
- protected readonly serializeRequest: (draft: CrudDraft<T>) => unknown;
160
+ protected readonly serializeRequest: (draft: CrudDraft<T>, context: RestRequestContext<T, K>) => unknown;
85
161
  /** Maps a list payload onto a page, when the API wraps its results. */
86
162
  protected readonly parseResponse?: (payload: unknown) => CrudPage<T>;
163
+ /** Maps a create or update response onto the stored record. */
164
+ protected readonly parseRecord?: (payload: unknown, context: RestRequestContext<T, K>) => T;
87
165
  private readonly fetchImpl;
88
- constructor(options?: RestDataSourceOptions<T>);
166
+ constructor(options?: RestDataSourceOptions<T, K>);
89
167
  /**
90
168
  * Encode sort instructions as query parameters.
91
169
  *
@@ -94,6 +172,15 @@ export declare class RestDataSource<T extends object, K extends keyof T> impleme
94
172
  * server may not share. Override to support one.
95
173
  */
96
174
  protected serializeSort(sort: readonly CrudSort<T>[] | undefined, params: URLSearchParams): void;
175
+ /**
176
+ * Encode filters as query parameters.
177
+ *
178
+ * Each filter is sent under its own field name, which suits an API that
179
+ * filters per column. An API with a single search parameter - `?q=` is the
180
+ * common shape - wants them combined instead, so this is a seam rather than
181
+ * inline, matching {@link serializeSort}.
182
+ */
183
+ protected serializeFilters(filters: CrudQuery<T>['filters'], params: URLSearchParams): void;
97
184
  /** Build the list URL, including pagination, sort and filters. */
98
185
  protected buildListUrl(query: CrudQuery<T>): string;
99
186
  /** Path addressing a single record. Override for `?id=` style APIs. */
@@ -112,7 +199,9 @@ export declare class RestDataSource<T extends object, K extends keyof T> impleme
112
199
  * building a full URL earlier and prefixing again is how it ended up
113
200
  * duplicated for relative bases.
114
201
  */
115
- protected request(path: string, init?: RequestInit): Promise<unknown>;
202
+ protected request(path: string, context: RestRequestContext<T, K>, init?: RequestInit): Promise<unknown>;
203
+ /** Interpret a create or update response. */
204
+ protected toRecord(payload: unknown, context: RestRequestContext<T, K>): T;
116
205
  list(query: CrudQuery<T>): Promise<CrudPage<T>>;
117
206
  create(draft: CrudDraft<T>): Promise<T>;
118
207
  update(id: T[K], draft: CrudDraft<T>): Promise<T>;
@@ -6,6 +6,6 @@ export { StaticDataSource } from './StaticDataSource';
6
6
  export { LocalStorageDataSource } from './LocalStorageDataSource';
7
7
  export type { Timestamped } from './LocalStorageDataSource';
8
8
  export { RestDataSource, RestError } from './RestDataSource';
9
- export type { RestDataSourceOptions, RestEndpoints, RestMethods, RestParamNames, } from './RestDataSource';
9
+ export type { HttpMethod, RestDataSourceOptions, RestEndpoints, RestMethods, RestOperation, RestParamNames, RestQueryValue, RestRequestContext, RestRequestOverrides, } from './RestDataSource';
10
10
  export { CustomDataSource, UnsupportedOperationError } from './CustomDataSource';
11
11
  export type { CrudOperations } from './CustomDataSource';
@@ -71,6 +71,14 @@ export interface CrudDataSource<T, K extends keyof T> {
71
71
  list(query: CrudQuery<T>): Promise<CrudPage<T>>;
72
72
  /** Persist a new record and return it as stored, identity included. */
73
73
  create(draft: CrudDraft<T>): Promise<T>;
74
+ /**
75
+ * Persist many new records in one call, returning them as stored.
76
+ *
77
+ * Exists so bulk import can avoid firing one request per row against sources
78
+ * that can create server-side in a batch. Optional: callers must fall back to
79
+ * repeated `create` (with bounded concurrency) when a source does not offer it.
80
+ */
81
+ createMany?(drafts: readonly CrudDraft<T>[]): Promise<readonly T[]>;
74
82
  /** Merge `draft` into the record at `id` and return the stored result. */
75
83
  update(id: T[K], draft: CrudDraft<T>): Promise<T>;
76
84
  /** Delete the record at `id`. */
@@ -23,6 +23,25 @@ var e = {
23
23
  exportPage: (e) => `Export page as ${e}`,
24
24
  nothingToExport: "Nothing to export",
25
25
  exportFailed: (e) => `Export failed: ${e}`,
26
+ importMenu: "Import",
27
+ importTitle: "Import data",
28
+ importSelectFile: "Choose a file to import",
29
+ importAcceptHint: (e) => `Accepted formats: ${e}`,
30
+ importMapColumns: "Map columns",
31
+ importIgnoreColumn: "— Ignore —",
32
+ importPreview: "Preview",
33
+ importRowLabel: "Row",
34
+ importStatusLabel: "Status",
35
+ importRowValid: "Valid",
36
+ importSummary: (e, t) => `${e} valid, ${t} to skip`,
37
+ importPreviewTruncated: (e, t) => `Showing first ${e} of ${t} rows`,
38
+ importRun: "Import",
39
+ importBack: "Back",
40
+ importNothingValid: "No valid rows to import",
41
+ importSuccess: (e) => `Imported ${e} rows`,
42
+ importPartial: (e, t, n) => `Imported ${e} of ${t}. ${n} failed.`,
43
+ importParseFailed: (e) => `Could not read file: ${e}`,
44
+ importUnsupportedFormat: (e) => `Unsupported file format: ${e}`,
26
45
  createSuccess: "Created successfully",
27
46
  updateSuccess: "Updated successfully",
28
47
  deleteSuccess: "Deleted successfully",
@@ -0,0 +1 @@
1
+ var e={actions:`Actions`,edit:`Edit`,delete:`Delete`,create:`New`,refresh:`Refresh`,createTitle:`Create Item`,editTitle:`Edit Item`,ok:`OK`,cancel:`Cancel`,requiredField:e=>`${e} is required`,confirmDeleteTitle:`Are you sure?`,confirmDeleteContent:`This action cannot be undone.`,confirmDeleteOk:`Yes, Delete`,confirmBulkDeleteTitle:e=>`Delete ${e} items?`,confirmBulkDeleteOk:`Yes, Delete All`,deleteSelected:e=>`Delete Selected (${e})`,selectItemsToDelete:`Please select items to delete`,bulkDeleteSuccess:e=>`Deleted ${e} items`,bulkDeletePartial:(e,t,n)=>`Deleted ${e} of ${t}. ${n} failed.`,exportAll:e=>`Export all as ${e}`,exportPage:e=>`Export page as ${e}`,nothingToExport:`Nothing to export`,exportFailed:e=>`Export failed: ${e}`,importMenu:`Import`,importTitle:`Import data`,importSelectFile:`Choose a file to import`,importAcceptHint:e=>`Accepted formats: ${e}`,importMapColumns:`Map columns`,importIgnoreColumn:`— Ignore —`,importPreview:`Preview`,importRowLabel:`Row`,importStatusLabel:`Status`,importRowValid:`Valid`,importSummary:(e,t)=>`${e} valid, ${t} to skip`,importPreviewTruncated:(e,t)=>`Showing first ${e} of ${t} rows`,importRun:`Import`,importBack:`Back`,importNothingValid:`No valid rows to import`,importSuccess:e=>`Imported ${e} rows`,importPartial:(e,t,n)=>`Imported ${e} of ${t}. ${n} failed.`,importParseFailed:e=>`Could not read file: ${e}`,importUnsupportedFormat:e=>`Unsupported file format: ${e}`,createSuccess:`Created successfully`,updateSuccess:`Updated successfully`,deleteSuccess:`Deleted successfully`,loading:`Loading CRUD table…`,yes:`Yes`,no:`No`,empty:`-`,selectPlaceholder:e=>`Select ${e.toLowerCase()}`,tagsPlaceholder:`Type and press enter`,invalidEmail:`Please enter a valid email`,invalidUrl:`Please enter a valid URL`,invalidImageUrl:`Please enter a valid image URL`,invalidJson:`Please enter valid JSON`};Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return e}});
@@ -19,6 +19,18 @@ export interface FieldTypeDefinition {
19
19
  toFormValue?: (value: unknown) => unknown;
20
20
  /** Convert the submitted form value back into the record shape. */
21
21
  fromFormValue?: (value: unknown) => unknown;
22
+ /**
23
+ * Convert a raw string cell from an imported file into the record shape.
24
+ *
25
+ * Import values arrive as text (a CSV field, a spreadsheet cell), which is a
26
+ * different starting point from {@link fromFormValue} (whose input is the
27
+ * form control's own value - a dayjs, a boolean, an object). A type that
28
+ * needs no conversion omits this and the raw string is stored as-is; types
29
+ * whose record shape is not a string (numbers, dates, arrays, JSON) provide
30
+ * one. `enum` is resolved by the importer instead, since it needs the
31
+ * column's `enumOptions` to accept either the stored key or the exported label.
32
+ */
33
+ fromImportValue?: (value: string) => unknown;
22
34
  /** Validation rules implied by the type itself (merged before user rules). */
23
35
  rules?: (col: FieldColumn, locale: CrudTableLocale) => FormRule[];
24
36
  /** Form.Item valuePropName override (e.g. 'checked' for Switch). */
@@ -71,7 +71,7 @@ export interface StaticStrategy<T, K extends keyof T> extends UseCrudTableOption
71
71
  /** Serves records from a REST API. */
72
72
  export interface RestStrategy<T, K extends keyof T> extends UseCrudTableOptionsBase<T, K> {
73
73
  /** Endpoints, parameter names, verbs and payload mapping. */
74
- api: RestDataSourceOptions<T>;
74
+ api: RestDataSourceOptions<T, K>;
75
75
  }
76
76
  /** Serves records persisted to `localStorage`. */
77
77
  export interface LocalStorageStrategy<T, K extends keyof T> extends UseCrudTableOptionsBase<T, K> {
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./CrudTable-DRN70sET.cjs"),t=require("./useCrudTable-40jpmCkr.cjs"),n=require("./en_US-D3Kl6g3n.cjs"),r=require("./exportData.cjs"),i=require("./CrudTableLazy.cjs"),a=require("./useLocalStorageCrud.cjs");exports.CrudTable=e.t,exports.default=e.t,exports.CrudTableLazy=i.default,exports.CustomDataSource=t.r,exports.InMemoryDataSource=t.l,exports.LocalStorageDataSource=t.s,exports.RestDataSource=t.a,exports.RestError=t.o,exports.StaticDataSource=t.c,exports.UnsupportedOperationError=t.i,exports.defaultFieldLocale=e.r,exports.defaultIdGenerator=t.m,exports.enUS=n.t,exports.exportAllData=r.exportAllData,exports.exportData=r.exportData,exports.exportToCSV=r.exportToCSV,exports.exportToExcel=r.exportToExcel,exports.exportToJSON=r.exportToJSON,exports.fieldRegistry=e.i,exports.filterRecords=t.u,exports.getFieldDefinition=e.a,exports.paginateRecords=t.d,exports.queryRecords=t.f,exports.randomUuid=t.h,exports.sortRecords=t.p,exports.toError=t.t,exports.useCrudTable=t.n,exports.useLocalStorageCrud=a.useLocalStorageCrud,exports.useResolvedLocale=e.n;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./CrudTable-BfVtTGYV.cjs"),t=require("./useCrudTable-Ex2Imgll.cjs"),n=require("./en_US-Q8nDeJhg.cjs"),r=require("./exportData.cjs"),i=require("./CrudTableLazy.cjs"),a=require("./useLocalStorageCrud.cjs");let o=require("to-spreadsheet");var s=e=>e.replace(/&#x([0-9a-fA-F]+);/g,(e,t)=>String.fromCodePoint(parseInt(t,16))).replace(/&#(\d+);/g,(e,t)=>String.fromCodePoint(parseInt(t,10))).replace(/&lt;/g,`<`).replace(/&gt;/g,`>`).replace(/&quot;/g,`"`).replace(/&apos;/g,`'`).replace(/&amp;/g,`&`),c=(e,t)=>{let n=e.match(RegExp(`\\b${t.replace(`:`,`\\:`)}\\s*=\\s*"([^"]*)"|\\b${t.replace(`:`,`\\:`)}\\s*=\\s*'([^']*)'`));if(n)return s(n[1]===void 0?n[2]:n[1])},l=e=>{let t=e.match(/<Table\b[^>]*>([\s\S]*?)<\/Table>/i);if(!t)return[];let n=t[1],r=[],i=0,a=/<Row\b([^>]*)>([\s\S]*?)<\/Row>|<Row\b([^>]*)\/>/gi,o;for(;(o=a.exec(n))!==null;){let e=o[1]??o[3]??``,t=o[2]??``,n=c(e,`ss:Index`);n&&(i=Number(n)-1);let a=[],l=0,u=/<Cell\b([^>]*)>([\s\S]*?)<\/Cell>|<Cell\b([^>]*)\/>/gi,d;for(;(d=u.exec(t))!==null;){let e=d[1]??d[3]??``,t=d[2]??``,n=c(e,`ss:Index`);n&&(l=Number(n)-1);let r=t.match(/<Data\b[^>]*>([\s\S]*?)<\/Data>/i),i=r?s(r[1]):``;a[l]=i,l++}for(let e=0;e<a.length;e++)a[e]===void 0&&(a[e]=``);r[i]=a,i++}let l=r.reduce((e,t)=>Math.max(e,t?t.length:0),0);for(let e=0;e<r.length;e++){r[e]||(r[e]=[]);for(let t=0;t<l;t++)r[e][t]===void 0&&(r[e][t]=``)}return r},u=t=>e.m(l(typeof t==`string`?t:e.a(t)));e.f(`xls`,u);var d=e=>e==null?``:e instanceof Date?e.toISOString():String(e),f=async t=>{let n=(await(0,o.readExcel)(t)).sheets[0];if(!n)return{headers:[],rows:[]};let r=n.rows.map(e=>e.map(d));return e.m(r)};e.f(`xlsx`,f),exports.CrudImportModal=e.n,exports.CrudTable=e.t,exports.default=e.t,exports.CrudTableLazy=i.default,exports.CustomDataSource=t.r,exports.InMemoryDataSource=t.l,exports.LocalStorageDataSource=t.s,exports.RestDataSource=t.a,exports.RestError=t.o,exports.StaticDataSource=t.c,exports.UnsupportedOperationError=t.i,exports.autoMapColumns=e.r,exports.coerceValue=e.i,exports.defaultFieldLocale=e.g,exports.defaultIdGenerator=t.m,exports.detectFormat=e.o,exports.enUS=n.t,exports.evaluateRules=e.s,exports.exportAllData=r.exportAllData,exports.exportData=r.exportData,exports.exportToCSV=r.exportToCSV,exports.exportToExcel=r.exportToExcel,exports.exportToJSON=r.exportToJSON,exports.fieldRegistry=e._,exports.fileParsers=e.c,exports.filterRecords=t.u,exports.getFieldDefinition=e.v,exports.paginateRecords=t.d,exports.parseCsv=e.l,exports.parseSpreadsheetML=l,exports.parseSpreadsheetMLTable=u,exports.parseTable=e.u,exports.parseXlsx=f,exports.prepareRows=e.d,exports.queryRecords=t.f,exports.randomUuid=t.h,exports.registerFileParser=e.f,exports.runImport=e.p,exports.sortRecords=t.p,exports.toError=t.t,exports.useCrudTable=t.n,exports.useLocalStorageCrud=a.useLocalStorageCrud,exports.useResolvedLocale=e.h;
package/dist/index.d.ts CHANGED
@@ -7,7 +7,7 @@ export { useLocalStorageCrud } from './hooks/useLocalStorageCrud';
7
7
  export type { CrudOperationName, CrudTableActions, CrudTableState, UseCrudTableOptions, StaticStrategy, RestStrategy, LocalStorageStrategy, OperationsStrategy, DataSourceStrategy, } from './hooks/useCrudTable';
8
8
  export type { UseLocalStorageCrudOptions } from './hooks/useLocalStorageCrud';
9
9
  export { CustomDataSource, InMemoryDataSource, LocalStorageDataSource, RestDataSource, RestError, StaticDataSource, UnsupportedOperationError, defaultIdGenerator, filterRecords, paginateRecords, queryRecords, randomUuid, sortRecords, } from './core';
10
- export type { CrudDataSource, CrudDraft, CrudFilters, CrudFilterValue, CrudOperations, CrudPage, CrudQuery, CrudSort, IdGenerator, RestDataSourceOptions, RestEndpoints, RestMethods, RestParamNames, SortDirection, Timestamped, } from './core';
10
+ export type { CrudDataSource, CrudDraft, CrudFilters, CrudFilterValue, CrudOperations, CrudPage, CrudQuery, CrudSort, IdGenerator, HttpMethod, RestDataSourceOptions, RestEndpoints, RestMethods, RestOperation, RestParamNames, RestQueryValue, RestRequestContext, RestRequestOverrides, SortDirection, Timestamped, } from './core';
11
11
  export { enUS, useResolvedLocale } from './locale';
12
12
  export type { CrudTableLocale, PartialCrudTableLocale, ResolvedLocale } from './locale';
13
13
  export { fieldRegistry, getFieldDefinition, defaultFieldLocale } from './fields/registry';
@@ -15,3 +15,9 @@ export type { FieldType, FieldTypeDefinition } from './fields/registry';
15
15
  export type { EnumOption, FieldColumn } from './fields/types';
16
16
  export { exportData, exportToCSV, exportToJSON, exportToExcel, exportAllData, } from './utils/exportData';
17
17
  export type { ColumnOption, ExportFormat, ExportOptions } from './utils/exportData';
18
+ export { parseCsv, parseTable, detectFormat, autoMapColumns, coerceValue, evaluateRules, prepareRows, runImport, registerFileParser, fileParsers, } from './utils/importData';
19
+ export type { ImportFormat, ImportColumn, ParsedTable, ColumnMapping, PreparedRow, ImportResult, ImportRowOutcome, ImportSink, RunImportOptions, FileParser, } from './utils/importData';
20
+ export { default as CrudImportModal } from './CrudImportModal';
21
+ export type { CrudImportModalProps } from './CrudImportModal';
22
+ export { parseSpreadsheetML, parseSpreadsheetMLTable } from './utils/importSpreadsheetML';
23
+ export { parseXlsx } from './utils/importXlsx';
package/dist/index.js CHANGED
@@ -1,7 +1,50 @@
1
- import { a as e, i as t, n, r, t as i } from "./CrudTable-Btf58zof.js";
2
- import { a, c as o, d as s, f as c, h as l, i as u, l as d, m as f, n as p, o as m, p as h, r as g, s as _, t as v, u as y } from "./useCrudTable-DxjnXVlQ.js";
3
- import { t as b } from "./en_US-DGCMDOdX.js";
4
- import { exportAllData as x, exportData as S, exportToCSV as C, exportToExcel as w, exportToJSON as T } from "./exportData.js";
5
- import E from "./CrudTableLazy.js";
6
- import { useLocalStorageCrud as D } from "./useLocalStorageCrud.js";
7
- export { i as CrudTable, i as default, E as CrudTableLazy, g as CustomDataSource, d as InMemoryDataSource, _ as LocalStorageDataSource, a as RestDataSource, m as RestError, o as StaticDataSource, u as UnsupportedOperationError, r as defaultFieldLocale, f as defaultIdGenerator, b as enUS, x as exportAllData, S as exportData, C as exportToCSV, w as exportToExcel, T as exportToJSON, t as fieldRegistry, y as filterRecords, e as getFieldDefinition, s as paginateRecords, c as queryRecords, l as randomUuid, h as sortRecords, v as toError, p as useCrudTable, D as useLocalStorageCrud, n as useResolvedLocale };
1
+ import { _ as e, a as t, c as n, d as r, f as i, g as a, h as o, i as s, l as c, m as l, n as u, o as d, p as f, r as p, s as m, t as h, u as g, v as _ } from "./CrudTable-jy8Db0uQ.js";
2
+ import { a as v, c as y, d as b, f as x, h as S, i as C, l as w, m as T, n as E, o as D, p as O, r as k, s as A, t as j, u as M } from "./useCrudTable-BVXxakfl.js";
3
+ import { t as N } from "./en_US-DghHhwRq.js";
4
+ import { exportAllData as P, exportData as F, exportToCSV as I, exportToExcel as L, exportToJSON as R } from "./exportData.js";
5
+ import z from "./CrudTableLazy.js";
6
+ import { useLocalStorageCrud as B } from "./useLocalStorageCrud.js";
7
+ import { readExcel as V } from "to-spreadsheet";
8
+ //#region lib/utils/importSpreadsheetML.ts
9
+ var H = (e) => e.replace(/&#x([0-9a-fA-F]+);/g, (e, t) => String.fromCodePoint(parseInt(t, 16))).replace(/&#(\d+);/g, (e, t) => String.fromCodePoint(parseInt(t, 10))).replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, "\"").replace(/&apos;/g, "'").replace(/&amp;/g, "&"), U = (e, t) => {
10
+ let n = e.match(RegExp(`\\b${t.replace(":", "\\:")}\\s*=\\s*"([^"]*)"|\\b${t.replace(":", "\\:")}\\s*=\\s*'([^']*)'`));
11
+ if (n) return H(n[1] === void 0 ? n[2] : n[1]);
12
+ }, W = (e) => {
13
+ let t = e.match(/<Table\b[^>]*>([\s\S]*?)<\/Table>/i);
14
+ if (!t) return [];
15
+ let n = t[1], r = [], i = 0, a = /<Row\b([^>]*)>([\s\S]*?)<\/Row>|<Row\b([^>]*)\/>/gi, o;
16
+ for (; (o = a.exec(n)) !== null;) {
17
+ let e = o[1] ?? o[3] ?? "", t = o[2] ?? "", n = U(e, "ss:Index");
18
+ n && (i = Number(n) - 1);
19
+ let a = [], s = 0, c = /<Cell\b([^>]*)>([\s\S]*?)<\/Cell>|<Cell\b([^>]*)\/>/gi, l;
20
+ for (; (l = c.exec(t)) !== null;) {
21
+ let e = l[1] ?? l[3] ?? "", t = l[2] ?? "", n = U(e, "ss:Index");
22
+ n && (s = Number(n) - 1);
23
+ let r = t.match(/<Data\b[^>]*>([\s\S]*?)<\/Data>/i), i = r ? H(r[1]) : "";
24
+ a[s] = i, s++;
25
+ }
26
+ for (let e = 0; e < a.length; e++) a[e] === void 0 && (a[e] = "");
27
+ r[i] = a, i++;
28
+ }
29
+ let s = r.reduce((e, t) => Math.max(e, t ? t.length : 0), 0);
30
+ for (let e = 0; e < r.length; e++) {
31
+ r[e] || (r[e] = []);
32
+ for (let t = 0; t < s; t++) r[e][t] === void 0 && (r[e][t] = "");
33
+ }
34
+ return r;
35
+ }, G = (e) => l(W(typeof e == "string" ? e : t(e)));
36
+ i("xls", G);
37
+ //#endregion
38
+ //#region lib/utils/importXlsx.ts
39
+ var K = (e) => e == null ? "" : e instanceof Date ? e.toISOString() : String(e), q = async (e) => {
40
+ let t = (await V(e)).sheets[0];
41
+ if (!t) return {
42
+ headers: [],
43
+ rows: []
44
+ };
45
+ let n = t.rows.map((e) => e.map(K));
46
+ return l(n);
47
+ };
48
+ i("xlsx", q);
49
+ //#endregion
50
+ export { u as CrudImportModal, h as CrudTable, h as default, z as CrudTableLazy, k as CustomDataSource, w as InMemoryDataSource, A as LocalStorageDataSource, v as RestDataSource, D as RestError, y as StaticDataSource, C as UnsupportedOperationError, p as autoMapColumns, s as coerceValue, a as defaultFieldLocale, T as defaultIdGenerator, d as detectFormat, N as enUS, m as evaluateRules, P as exportAllData, F as exportData, I as exportToCSV, L as exportToExcel, R as exportToJSON, e as fieldRegistry, n as fileParsers, M as filterRecords, _ as getFieldDefinition, b as paginateRecords, c as parseCsv, W as parseSpreadsheetML, G as parseSpreadsheetMLTable, g as parseTable, q as parseXlsx, r as prepareRows, x as queryRecords, S as randomUuid, i as registerFileParser, f as runImport, O as sortRecords, j as toError, E as useCrudTable, B as useLocalStorageCrud, o as useResolvedLocale };
@@ -58,6 +58,44 @@ export interface CrudTableLocale {
58
58
  nothingToExport: string;
59
59
  /** Error shown when gathering or writing the export failed. */
60
60
  exportFailed: (message: string) => string;
61
+ /** Menu entry that opens the import dialog. */
62
+ importMenu: string;
63
+ /** Import dialog title. */
64
+ importTitle: string;
65
+ /** Prompt to choose a file to import. */
66
+ importSelectFile: string;
67
+ /** Hint listing the accepted file formats (e.g. "CSV"). */
68
+ importAcceptHint: (formats: string) => string;
69
+ /** Heading of the header-to-column mapping step. */
70
+ importMapColumns: string;
71
+ /** The "do not import this column" option in the mapping selects. */
72
+ importIgnoreColumn: string;
73
+ /** Heading of the parsed-row preview. */
74
+ importPreview: string;
75
+ /** Column header for the row-number column in the preview. */
76
+ importRowLabel: string;
77
+ /** Column header for the per-row status column in the preview. */
78
+ importStatusLabel: string;
79
+ /** Status text for a row that passed validation. */
80
+ importRowValid: string;
81
+ /** Summary of how many rows are valid / invalid before importing. */
82
+ importSummary: (valid: number, invalid: number) => string;
83
+ /** Note shown when the preview is truncated to the first `shown` of `total`. */
84
+ importPreviewTruncated: (shown: number, total: number) => string;
85
+ /** Label of the button that performs the import. */
86
+ importRun: string;
87
+ /** Label of the button that returns to file selection. */
88
+ importBack: string;
89
+ /** Warning shown when no rows are valid to import. */
90
+ importNothingValid: string;
91
+ /** Confirmation that every row was imported. */
92
+ importSuccess: (count: number) => string;
93
+ /** Report of a partial import: created of total, with a failure count. */
94
+ importPartial: (created: number, total: number, failed: number) => string;
95
+ /** Error shown when reading or parsing the file failed. */
96
+ importParseFailed: (message: string) => string;
97
+ /** Error shown when the chosen file's format is not supported. */
98
+ importUnsupportedFormat: (name: string) => string;
61
99
  /** Confirmation that a record was created. */
62
100
  createSuccess: string;
63
101
  /** Confirmation that a record was updated. */