@ethanhann/mantine-dataview 0.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/LICENSE +21 -0
- package/README.md +640 -0
- package/dist/components/DataBulkActions/DataBulkActions.d.ts +9 -0
- package/dist/components/DataBulkActions/index.d.ts +1 -0
- package/dist/components/DataCards/DataCards.d.ts +24 -0
- package/dist/components/DataCards/index.d.ts +1 -0
- package/dist/components/DataPagination/DataPagination.d.ts +13 -0
- package/dist/components/DataPagination/index.d.ts +1 -0
- package/dist/components/DataTable/DataTable.d.ts +13 -0
- package/dist/components/DataTable/index.d.ts +1 -0
- package/dist/components/DataToolbar/DataToolbar.d.ts +16 -0
- package/dist/components/DataToolbar/FacetBuckets.d.ts +6 -0
- package/dist/components/DataToolbar/FilterControl.d.ts +6 -0
- package/dist/components/DataToolbar/FilterControls.d.ts +5 -0
- package/dist/components/DataToolbar/SortControl.d.ts +4 -0
- package/dist/components/DataToolbar/ViewSwitcher.d.ts +5 -0
- package/dist/components/DataToolbar/VisibilityMenu.d.ts +4 -0
- package/dist/components/DataToolbar/index.d.ts +2 -0
- package/dist/components/DataView/DataView.d.ts +36 -0
- package/dist/components/DataView/context.d.ts +13 -0
- package/dist/components/DataView/index.d.ts +2 -0
- package/dist/components/StateMessage.d.ts +12 -0
- package/dist/components/icons.d.ts +14 -0
- package/dist/components/types.d.ts +43 -0
- package/dist/core/cardComposition.d.ts +34 -0
- package/dist/core/exportCsv.d.ts +10 -0
- package/dist/core/formatValue.d.ts +4 -0
- package/dist/core/resolveStatus.d.ts +11 -0
- package/dist/core/useDataView.d.ts +2 -0
- package/dist/core/useDataViewFetcher.d.ts +7 -0
- package/dist/core/useForceCards.d.ts +8 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +1395 -0
- package/dist/index.js.map +1 -0
- package/dist/serializer-CGmBq-Jz.cjs +2 -0
- package/dist/serializer-CGmBq-Jz.cjs.map +1 -0
- package/dist/serializer-u2zq_sU7.js +117 -0
- package/dist/serializer-u2zq_sU7.js.map +1 -0
- package/dist/stories/data.d.ts +14 -0
- package/dist/types/column.d.ts +74 -0
- package/dist/types/facets.d.ts +27 -0
- package/dist/types/options.d.ts +95 -0
- package/dist/types/request.d.ts +18 -0
- package/dist/types/state.d.ts +57 -0
- package/dist/url/index.cjs +2 -0
- package/dist/url/index.cjs.map +1 -0
- package/dist/url/index.d.ts +5 -0
- package/dist/url/index.js +20 -0
- package/dist/url/index.js.map +1 -0
- package/dist/url/serializer.d.ts +33 -0
- package/dist/url/types.d.ts +23 -0
- package/dist/url/useUrlSync.d.ts +23 -0
- package/package.json +90 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { MantineBreakpoint } from '@mantine/core';
|
|
2
|
+
import { Column, Table } from '@tanstack/react-table';
|
|
3
|
+
import { ExportCsvOptions } from '../core/exportCsv';
|
|
4
|
+
import { UrlSerializer, UrlStateAdapter } from '../url/types';
|
|
5
|
+
import { ColumnDataType, ColumnFormatOption, DataColumnDef } from './column';
|
|
6
|
+
import { FacetData } from './facets';
|
|
7
|
+
import { DataViewRequest } from './request';
|
|
8
|
+
import { DataViewState, DataViewStatus, Status, ViewMode } from './state';
|
|
9
|
+
/** Force cards at or below a Mantine breakpoint. Cards are the preferred view on small screens. */
|
|
10
|
+
export interface ResponsiveOptions {
|
|
11
|
+
forceCardsBelow?: MantineBreakpoint;
|
|
12
|
+
lockSwitcherOnMobile?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** URL state sync that is agnostic about the router. */
|
|
15
|
+
export interface UrlSyncOptions {
|
|
16
|
+
adapter: UrlStateAdapter;
|
|
17
|
+
/** Override param names or codecs. */
|
|
18
|
+
serialize?: Partial<UrlSerializer>;
|
|
19
|
+
/** Which slices of state to sync. The default is all of them. */
|
|
20
|
+
include?: Array<keyof DataViewState>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Debounce in milliseconds for request emission on filter and search changes. A single number
|
|
24
|
+
* applies to both. An object sets a separate timing for each field.
|
|
25
|
+
*/
|
|
26
|
+
export type DebounceOptions = number | {
|
|
27
|
+
globalFilter?: number;
|
|
28
|
+
columnFilters?: number;
|
|
29
|
+
};
|
|
30
|
+
export interface UseDataViewOptions<TData> {
|
|
31
|
+
columns: DataColumnDef<TData>[];
|
|
32
|
+
rows: TData[];
|
|
33
|
+
/** Total rows across all pages, for page math. */
|
|
34
|
+
rowCount: number;
|
|
35
|
+
status: Status;
|
|
36
|
+
error?: unknown;
|
|
37
|
+
/**
|
|
38
|
+
* Stable identity. It is required for selection that survives paging. It is wrapped in
|
|
39
|
+
* `NoInfer` so `TData` is pinned by `rows` and `columns`, not by this callback.
|
|
40
|
+
*/
|
|
41
|
+
getRowId: (row: NoInfer<TData>) => string;
|
|
42
|
+
/** Fired whenever view state changes. Turn it into a fetch and feed `rows` back in. */
|
|
43
|
+
onRequestChange?: (request: DataViewRequest) => void;
|
|
44
|
+
initialState?: Partial<DataViewState>;
|
|
45
|
+
state?: Partial<DataViewState>;
|
|
46
|
+
onStateChange?: (state: DataViewState) => void;
|
|
47
|
+
/** Default `'table'`. */
|
|
48
|
+
defaultView?: ViewMode;
|
|
49
|
+
/** Default `[10, 25, 50, 100]`. */
|
|
50
|
+
pageSizeOptions?: number[];
|
|
51
|
+
enableRowSelection?: boolean | ((row: NoInfer<TData>) => boolean);
|
|
52
|
+
enableGlobalFilter?: boolean;
|
|
53
|
+
debounce?: DebounceOptions;
|
|
54
|
+
responsive?: ResponsiveOptions;
|
|
55
|
+
urlSync?: UrlSyncOptions;
|
|
56
|
+
/** Table-level format defaults keyed by data type. Column-level `format` overrides these. */
|
|
57
|
+
formatDefaults?: Partial<Record<ColumnDataType, ColumnFormatOption>>;
|
|
58
|
+
/** Facet aggregation data from the server, keyed by column ID. */
|
|
59
|
+
facets?: Record<string, FacetData>;
|
|
60
|
+
}
|
|
61
|
+
/** Current selection, derived from `rowSelection` keyed by `getRowId`. */
|
|
62
|
+
export interface DataViewSelection<TData> {
|
|
63
|
+
count: number;
|
|
64
|
+
/** Ids of every selected row across all pages. This is the stable basis for bulk actions. */
|
|
65
|
+
ids: string[];
|
|
66
|
+
/** Selected rows present on the current page. The core holds no data for other pages. */
|
|
67
|
+
rows: TData[];
|
|
68
|
+
clear: () => void;
|
|
69
|
+
}
|
|
70
|
+
export interface UseDataViewReturn<TData> {
|
|
71
|
+
/** The underlying v8 instance, offered as an escape hatch. */
|
|
72
|
+
table: Table<TData>;
|
|
73
|
+
/** Current normalized request. */
|
|
74
|
+
request: DataViewRequest;
|
|
75
|
+
state: DataViewState;
|
|
76
|
+
view: ViewMode;
|
|
77
|
+
setView: (v: ViewMode) => void;
|
|
78
|
+
/** True when the responsive rule forces cards. */
|
|
79
|
+
isMobileForced: boolean;
|
|
80
|
+
status: Status;
|
|
81
|
+
error: unknown;
|
|
82
|
+
/** Renderer facing state. One of loading, empty, filtered empty, error, or ready. */
|
|
83
|
+
renderStatus: DataViewStatus;
|
|
84
|
+
/** Emit the current request again. The error state retry uses this. */
|
|
85
|
+
refetch: () => void;
|
|
86
|
+
/** Resolved page size choices for the pager. The default is `[10, 25, 50, 100]`. */
|
|
87
|
+
pageSizeOptions: number[];
|
|
88
|
+
sortableColumns: Column<TData>[];
|
|
89
|
+
filterableColumns: Column<TData>[];
|
|
90
|
+
selection: DataViewSelection<TData>;
|
|
91
|
+
/** Export visible columns and current page rows as a CSV file download. */
|
|
92
|
+
exportCsv: (options?: ExportCsvOptions) => void;
|
|
93
|
+
/** Latest facet data from the server response, keyed by column ID. */
|
|
94
|
+
facets: Record<string, FacetData>;
|
|
95
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FacetData } from './facets';
|
|
2
|
+
import { DataViewFilter, DataViewPagination, DataViewSort } from './state';
|
|
3
|
+
/** Emitted by the core whenever view state changes. The consumer turns it into a fetch. */
|
|
4
|
+
export interface DataViewRequest {
|
|
5
|
+
pagination: DataViewPagination;
|
|
6
|
+
sorting: DataViewSort[];
|
|
7
|
+
/** Filters keyed by column. The `value` shape depends on the filter variant. */
|
|
8
|
+
filters: DataViewFilter[];
|
|
9
|
+
globalFilter: string;
|
|
10
|
+
}
|
|
11
|
+
/** What the consumer feeds back in for the current page. */
|
|
12
|
+
export interface DataViewResponse<TData> {
|
|
13
|
+
rows: TData[];
|
|
14
|
+
/** Total rows across all pages, used for page math. */
|
|
15
|
+
rowCount: number;
|
|
16
|
+
/** Optional facet aggregation data, keyed by column ID. */
|
|
17
|
+
facets?: Record<string, FacetData>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** The two presentations that one core state instance can be projected into. */
|
|
2
|
+
export type ViewMode = "table" | "cards";
|
|
3
|
+
/** Raw fetch lifecycle reported by the consumer. */
|
|
4
|
+
export type Status = "idle" | "loading" | "success" | "error";
|
|
5
|
+
export interface DataViewPagination {
|
|
6
|
+
pageIndex: number;
|
|
7
|
+
pageSize: number;
|
|
8
|
+
}
|
|
9
|
+
export interface DataViewSort {
|
|
10
|
+
id: string;
|
|
11
|
+
desc: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface DataViewFilter {
|
|
14
|
+
/** Column id the filter is keyed by. */
|
|
15
|
+
id: string;
|
|
16
|
+
/** Value shape depends on the column's filter variant. */
|
|
17
|
+
value: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The single source of truth for every feature. All affordances such as table headers, card
|
|
21
|
+
* overlays, and toolbar controls are projections of this object, keyed by column id.
|
|
22
|
+
*/
|
|
23
|
+
/** Columns pinned to the left or right edge of the table. */
|
|
24
|
+
export interface DataViewColumnPinning {
|
|
25
|
+
left?: string[];
|
|
26
|
+
right?: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface DataViewState {
|
|
29
|
+
pagination: DataViewPagination;
|
|
30
|
+
sorting: DataViewSort[];
|
|
31
|
+
columnFilters: DataViewFilter[];
|
|
32
|
+
globalFilter: string;
|
|
33
|
+
/** Keyed by `getRowId`, so selection survives paging and refetches. */
|
|
34
|
+
rowSelection: Record<string, boolean>;
|
|
35
|
+
columnVisibility: Record<string, boolean>;
|
|
36
|
+
columnPinning: DataViewColumnPinning;
|
|
37
|
+
view: ViewMode;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Derived renderer facing status as a discriminated union. Both presentations switch over it
|
|
41
|
+
* exhaustively so the four states stay consistent across views. Those states are loading, empty,
|
|
42
|
+
* filtered empty, and error. There are also idle and the populated `ready` state.
|
|
43
|
+
*/
|
|
44
|
+
export type DataViewStatus = {
|
|
45
|
+
phase: "idle";
|
|
46
|
+
} | {
|
|
47
|
+
phase: "loading";
|
|
48
|
+
} | {
|
|
49
|
+
phase: "ready";
|
|
50
|
+
} | {
|
|
51
|
+
phase: "empty";
|
|
52
|
+
} | {
|
|
53
|
+
phase: "empty-filtered";
|
|
54
|
+
} | {
|
|
55
|
+
phase: "error";
|
|
56
|
+
error: unknown;
|
|
57
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../serializer-CGmBq-Jz.cjs");function t(){return{read(){return Object.fromEntries(new URLSearchParams(window.location.search).entries())},write(e,t){let n=new URLSearchParams(e),r=`${window.location.pathname}?${n.toString()}${window.location.hash}`;t?.replace?window.history.replaceState(null,``,r):window.history.pushState(null,``,r)},subscribe(e){return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)}}}exports.defaultUrlSerializer=e.t,exports.deserializeParams=e.n,exports.resolveInclude=e.r,exports.serializeState=e.i,exports.windowHistoryAdapter=t;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/url/index.ts"],"sourcesContent":["// Subpath entry for @ethanhann/mantine-dataview/url.\n// It exports windowHistoryAdapter and the serializer utilities.\n\nimport type { UrlStateAdapter } from \"./types\";\n\n// Serializer utilities for consumers building custom adapters or param schemes.\nexport {\n\tdefaultUrlSerializer,\n\tdeserializeParams,\n\tresolveInclude,\n\ttype SyncableKey,\n\tserializeState,\n} from \"./serializer\";\nexport type { UrlSerializer, UrlStateAdapter } from \"./types\";\n\n/** Default adapter built on the History API. It has no dependencies. */\nexport function windowHistoryAdapter(): UrlStateAdapter {\n\treturn {\n\t\tread() {\n\t\t\treturn Object.fromEntries(\n\t\t\t\tnew URLSearchParams(window.location.search).entries(),\n\t\t\t);\n\t\t},\n\t\twrite(next, opts) {\n\t\t\tconst params = new URLSearchParams(next);\n\t\t\tconst url = `${window.location.pathname}?${params.toString()}${window.location.hash}`;\n\t\t\tif (opts?.replace) {\n\t\t\t\twindow.history.replaceState(null, \"\", url);\n\t\t\t} else {\n\t\t\t\twindow.history.pushState(null, \"\", url);\n\t\t\t}\n\t\t},\n\t\tsubscribe(onChange) {\n\t\t\twindow.addEventListener(\"popstate\", onChange);\n\t\t\treturn () => window.removeEventListener(\"popstate\", onChange);\n\t\t},\n\t};\n}\n"],"mappings":"iHAgBA,SAAgB,GAAwC,CACvD,MAAO,CACN,MAAO,CACN,OAAO,OAAO,YACb,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,QAAQ,CACrD,CACD,EACA,MAAM,EAAM,EAAM,CACjB,IAAM,EAAS,IAAI,gBAAgB,CAAI,EACjC,EAAM,GAAG,OAAO,SAAS,SAAS,GAAG,EAAO,SAAS,IAAI,OAAO,SAAS,OAC3E,GAAM,QACT,OAAO,QAAQ,aAAa,KAAM,GAAI,CAAG,EAEzC,OAAO,QAAQ,UAAU,KAAM,GAAI,CAAG,CAExC,EACA,UAAU,EAAU,CAEnB,OADA,OAAO,iBAAiB,WAAY,CAAQ,MAC/B,OAAO,oBAAoB,WAAY,CAAQ,CAC7D,CACD,CACD"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { UrlStateAdapter } from './types';
|
|
2
|
+
export { defaultUrlSerializer, deserializeParams, resolveInclude, type SyncableKey, serializeState, } from './serializer';
|
|
3
|
+
export type { UrlSerializer, UrlStateAdapter } from './types';
|
|
4
|
+
/** Default adapter built on the History API. It has no dependencies. */
|
|
5
|
+
export declare function windowHistoryAdapter(): UrlStateAdapter;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "../serializer-u2zq_sU7.js";
|
|
2
|
+
//#region src/url/index.ts
|
|
3
|
+
function i() {
|
|
4
|
+
return {
|
|
5
|
+
read() {
|
|
6
|
+
return Object.fromEntries(new URLSearchParams(window.location.search).entries());
|
|
7
|
+
},
|
|
8
|
+
write(e, t) {
|
|
9
|
+
let n = new URLSearchParams(e), r = `${window.location.pathname}?${n.toString()}${window.location.hash}`;
|
|
10
|
+
t?.replace ? window.history.replaceState(null, "", r) : window.history.pushState(null, "", r);
|
|
11
|
+
},
|
|
12
|
+
subscribe(e) {
|
|
13
|
+
return window.addEventListener("popstate", e), () => window.removeEventListener("popstate", e);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { r as defaultUrlSerializer, t as deserializeParams, n as resolveInclude, e as serializeState, i as windowHistoryAdapter };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/url/index.ts"],"sourcesContent":["// Subpath entry for @ethanhann/mantine-dataview/url.\n// It exports windowHistoryAdapter and the serializer utilities.\n\nimport type { UrlStateAdapter } from \"./types\";\n\n// Serializer utilities for consumers building custom adapters or param schemes.\nexport {\n\tdefaultUrlSerializer,\n\tdeserializeParams,\n\tresolveInclude,\n\ttype SyncableKey,\n\tserializeState,\n} from \"./serializer\";\nexport type { UrlSerializer, UrlStateAdapter } from \"./types\";\n\n/** Default adapter built on the History API. It has no dependencies. */\nexport function windowHistoryAdapter(): UrlStateAdapter {\n\treturn {\n\t\tread() {\n\t\t\treturn Object.fromEntries(\n\t\t\t\tnew URLSearchParams(window.location.search).entries(),\n\t\t\t);\n\t\t},\n\t\twrite(next, opts) {\n\t\t\tconst params = new URLSearchParams(next);\n\t\t\tconst url = `${window.location.pathname}?${params.toString()}${window.location.hash}`;\n\t\t\tif (opts?.replace) {\n\t\t\t\twindow.history.replaceState(null, \"\", url);\n\t\t\t} else {\n\t\t\t\twindow.history.pushState(null, \"\", url);\n\t\t\t}\n\t\t},\n\t\tsubscribe(onChange) {\n\t\t\twindow.addEventListener(\"popstate\", onChange);\n\t\t\treturn () => window.removeEventListener(\"popstate\", onChange);\n\t\t},\n\t};\n}\n"],"mappings":";;AAgBA,SAAgB,IAAwC;CACvD,OAAO;EACN,OAAO;GACN,OAAO,OAAO,YACb,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,QAAQ,CACrD;EACD;EACA,MAAM,GAAM,GAAM;GACjB,IAAM,IAAS,IAAI,gBAAgB,CAAI,GACjC,IAAM,GAAG,OAAO,SAAS,SAAS,GAAG,EAAO,SAAS,IAAI,OAAO,SAAS;GAC/E,AAAI,GAAM,UACT,OAAO,QAAQ,aAAa,MAAM,IAAI,CAAG,IAEzC,OAAO,QAAQ,UAAU,MAAM,IAAI,CAAG;EAExC;EACA,UAAU,GAAU;GAEnB,OADA,OAAO,iBAAiB,YAAY,CAAQ,SAC/B,OAAO,oBAAoB,YAAY,CAAQ;EAC7D;CACD;AACD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ColumnFilterMeta } from '../types/column';
|
|
2
|
+
import { DataViewState } from '../types/state';
|
|
3
|
+
import { UrlSerializer } from './types';
|
|
4
|
+
export type SyncableKey = "pagination" | "sorting" | "columnFilters" | "globalFilter" | "view";
|
|
5
|
+
export declare const SYNCABLE_KEYS: readonly SyncableKey[];
|
|
6
|
+
type FilterMetaLookup = (id: string) => ColumnFilterMeta | undefined;
|
|
7
|
+
/** Default param names and a filter codec for each variant. Every field can be overridden. */
|
|
8
|
+
export declare const defaultUrlSerializer: UrlSerializer;
|
|
9
|
+
/** Resolves the `include` option to the supported, syncable subset. The default is all of them. */
|
|
10
|
+
export declare function resolveInclude(include?: Array<keyof DataViewState>): SyncableKey[];
|
|
11
|
+
export interface SerializeContext {
|
|
12
|
+
serializer: UrlSerializer;
|
|
13
|
+
include: SyncableKey[];
|
|
14
|
+
getFilterMeta?: FilterMetaLookup;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Serializes the included slices to query params. Empty or default values are omitted to keep
|
|
18
|
+
* the URL clean. The page is emitted only past the first page, counting from one. Empty search,
|
|
19
|
+
* sort, and filter values drop out entirely.
|
|
20
|
+
*/
|
|
21
|
+
export declare function serializeState(state: DataViewState, { serializer, include, getFilterMeta }: SerializeContext): Record<string, string>;
|
|
22
|
+
export interface DeserializeContext extends SerializeContext {
|
|
23
|
+
/** Fallback for slices not present in the URL (defaults on hydrate, current on popstate). */
|
|
24
|
+
current: DataViewState;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parses query params into a state patch. The URL is authoritative for every included slice. An
|
|
28
|
+
* absent sort, search, or filter means none, and an absent page means the first page.
|
|
29
|
+
*/
|
|
30
|
+
export declare function deserializeParams(params: Record<string, string>, { serializer, include, getFilterMeta, current }: DeserializeContext): Partial<DataViewState>;
|
|
31
|
+
/** Remove the params this serializer manages (for the included slices), preserving the rest. */
|
|
32
|
+
export declare function stripManagedParams(params: Record<string, string>, serializer: UrlSerializer, include: SyncableKey[]): Record<string, string>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ColumnFilterMeta } from '../types/column';
|
|
2
|
+
export interface UrlStateAdapter {
|
|
3
|
+
/** Current query params as a flat record. */
|
|
4
|
+
read(): Record<string, string>;
|
|
5
|
+
/** Write the next params. The `replace` flag chooses between a new history entry and a push. */
|
|
6
|
+
write(next: Record<string, string>, opts?: {
|
|
7
|
+
replace?: boolean;
|
|
8
|
+
}): void;
|
|
9
|
+
/** Optional. Notifies on external navigation such as back or forward. Returns a cleanup. */
|
|
10
|
+
subscribe?(onChange: () => void): () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface UrlSerializer {
|
|
13
|
+
page: string;
|
|
14
|
+
size: string;
|
|
15
|
+
sort: string;
|
|
16
|
+
search: string;
|
|
17
|
+
view: string;
|
|
18
|
+
/** Prefix for column filters. For example `f.` produces `f.<columnId>=<encoded>`. */
|
|
19
|
+
filterPrefix: string;
|
|
20
|
+
/** The column's filter meta, its variant and options, selects the codec. */
|
|
21
|
+
encodeFilter(columnId: string, value: unknown, meta?: ColumnFilterMeta): string;
|
|
22
|
+
decodeFilter(columnId: string, raw: string, meta?: ColumnFilterMeta): unknown;
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ColumnFilterMeta } from '../types/column';
|
|
2
|
+
import { UrlSyncOptions } from '../types/options';
|
|
3
|
+
import { DataViewState } from '../types/state';
|
|
4
|
+
import { SyncableKey } from './serializer';
|
|
5
|
+
import { UrlSerializer, UrlStateAdapter } from './types';
|
|
6
|
+
type FilterMetaLookup = (id: string) => ColumnFilterMeta | undefined;
|
|
7
|
+
export interface ResolvedUrlConfig {
|
|
8
|
+
adapter: UrlStateAdapter;
|
|
9
|
+
serializer: UrlSerializer;
|
|
10
|
+
include: SyncableKey[];
|
|
11
|
+
}
|
|
12
|
+
/** Merges the consumer's `urlSync` options with defaults, or returns `null` when sync is off. */
|
|
13
|
+
export declare function resolveUrlConfig(urlSync: UrlSyncOptions | undefined): ResolvedUrlConfig | null;
|
|
14
|
+
/** Reads the URL once and produces the initial state patch. It is safe to call during render. */
|
|
15
|
+
export declare function hydrateFromUrl(config: ResolvedUrlConfig | null, current: DataViewState, getFilterMeta: FilterMetaLookup): Partial<DataViewState>;
|
|
16
|
+
interface UseUrlSyncArgs {
|
|
17
|
+
config: ResolvedUrlConfig | null;
|
|
18
|
+
state: DataViewState;
|
|
19
|
+
applyPatch: (patch: Partial<DataViewState>) => void;
|
|
20
|
+
getFilterMeta: FilterMetaLookup;
|
|
21
|
+
}
|
|
22
|
+
export declare function useUrlSync({ config, state, applyPatch, getFilterMeta, }: UseUrlSyncArgs): void;
|
|
23
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ethanhann/mantine-dataview",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A React library that renders server-driven, paginated datasets as a table or card grid, switchable at runtime, built on Mantine v9 and TanStack Table v8",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./url": {
|
|
16
|
+
"types": "./dist/url/index.d.ts",
|
|
17
|
+
"import": "./dist/url/index.js",
|
|
18
|
+
"require": "./dist/url/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": [
|
|
25
|
+
"**/*.css"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"dev": "storybook dev -p 6006",
|
|
29
|
+
"build": "vite build",
|
|
30
|
+
"test": "vitest",
|
|
31
|
+
"test:run": "vitest run",
|
|
32
|
+
"test:coverage": "vitest run --coverage",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"storybook:build": "storybook build",
|
|
35
|
+
"prepublishOnly": "npm run build"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@mantine/core": "^9.0.0",
|
|
39
|
+
"@mantine/dates": "^9.0.0",
|
|
40
|
+
"@mantine/hooks": "^9.0.0",
|
|
41
|
+
"@tanstack/react-table": "^8.0.0",
|
|
42
|
+
"react": "^19.0.0",
|
|
43
|
+
"react-dom": "^19.0.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@axe-core/react": "^4.11.1",
|
|
47
|
+
"@biomejs/biome": "2.4.16",
|
|
48
|
+
"@mantine/code-highlight": "^9.3.0",
|
|
49
|
+
"@mantine/core": "^9.3.0",
|
|
50
|
+
"@mantine/dates": "^9.3.0",
|
|
51
|
+
"@mantine/hooks": "^9.3.0",
|
|
52
|
+
"@storybook/addon-a11y": "^10.3.4",
|
|
53
|
+
"@storybook/react": "^10.3.4",
|
|
54
|
+
"@storybook/react-vite": "^10.3.4",
|
|
55
|
+
"@tabler/icons-react": "^3.41.1",
|
|
56
|
+
"@tanstack/react-table": "^8.21.3",
|
|
57
|
+
"@testing-library/dom": "^10.4.1",
|
|
58
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
59
|
+
"@testing-library/react": "^16.3.2",
|
|
60
|
+
"@testing-library/user-event": "^14.6.1",
|
|
61
|
+
"@types/bun": "^1.3.11",
|
|
62
|
+
"@types/react": "^19.2.14",
|
|
63
|
+
"@types/react-dom": "^19.2.3",
|
|
64
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
65
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
66
|
+
"dayjs": "^1.11.21",
|
|
67
|
+
"highlight.js": "^11.11.1",
|
|
68
|
+
"jsdom": "^29.0.1",
|
|
69
|
+
"postcss": "^8.5.8",
|
|
70
|
+
"postcss-preset-mantine": "^1.18.0",
|
|
71
|
+
"postcss-simple-vars": "^7.0.1",
|
|
72
|
+
"react": "^19.2.4",
|
|
73
|
+
"react-dom": "^19.2.4",
|
|
74
|
+
"storybook": "^10.3.4",
|
|
75
|
+
"typescript": "^6.0.2",
|
|
76
|
+
"unplugin-dts": "^1.0.2",
|
|
77
|
+
"vite": "^8.0.3",
|
|
78
|
+
"vitest": "^4.1.2",
|
|
79
|
+
"vitest-axe": "^0.1.0",
|
|
80
|
+
"vitest-canvas-mock": "^1.1.4"
|
|
81
|
+
},
|
|
82
|
+
"repository": {
|
|
83
|
+
"type": "git",
|
|
84
|
+
"url": "git+https://github.com/ethanhann/mantine-grid.git"
|
|
85
|
+
},
|
|
86
|
+
"publishConfig": {
|
|
87
|
+
"registry": "https://registry.npmjs.org"
|
|
88
|
+
},
|
|
89
|
+
"license": "MIT"
|
|
90
|
+
}
|