ag-grid-url-sync 0.4.1 → 0.5.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 +143 -50
- package/dist/core/ag-grid-url-sync.d.ts +19 -5
- package/dist/core/ag-grid-url-sync.js +28 -17
- package/dist/core/ag-grid-url-sync.js.map +1 -1
- package/dist/core/grid-integration.d.ts +27 -1
- package/dist/core/grid-integration.js +161 -129
- package/dist/core/grid-integration.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/individual-params.d.ts +26 -0
- package/dist/core/individual-params.js +236 -0
- package/dist/core/individual-params.js.map +1 -0
- package/dist/core/issue-columns.d.ts +2 -0
- package/dist/core/issue-columns.js +11 -0
- package/dist/core/issue-columns.js.map +1 -0
- package/dist/core/issues.d.ts +34 -0
- package/dist/core/issues.js +58 -0
- package/dist/core/issues.js.map +1 -0
- package/dist/core/operators.d.ts +189 -0
- package/dist/core/operators.js +60 -0
- package/dist/core/operators.js.map +1 -0
- package/dist/core/options.d.ts +21 -0
- package/dist/core/options.js +21 -0
- package/dist/core/options.js.map +1 -0
- package/dist/core/schemas.d.ts +51 -0
- package/dist/core/schemas.js +59 -0
- package/dist/core/schemas.js.map +1 -0
- package/dist/core/serialization/formats.d.ts +8 -9
- package/dist/core/serialization/formats.js +70 -47
- package/dist/core/serialization/formats.js.map +1 -1
- package/dist/core/serialization/grouped.d.ts +13 -11
- package/dist/core/serialization/grouped.js +24 -17
- package/dist/core/serialization/grouped.js.map +1 -1
- package/dist/core/to-error.d.ts +5 -0
- package/dist/core/to-error.js +4 -0
- package/dist/core/to-error.js.map +1 -0
- package/dist/core/types.d.ts +172 -33
- package/dist/core/types.js +35 -108
- package/dist/core/types.js.map +1 -1
- package/dist/core/url-generator.d.ts +10 -7
- package/dist/core/url-generator.js +29 -121
- package/dist/core/url-generator.js.map +1 -1
- package/dist/core/url-parser.d.ts +19 -7
- package/dist/core/url-parser.js +31 -239
- package/dist/core/url-parser.js.map +1 -1
- package/dist/core/validation.d.ts +21 -14
- package/dist/core/validation.js +58 -54
- package/dist/core/validation.js.map +1 -1
- package/dist/core/view-storage.js +21 -19
- package/dist/core/view-storage.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react/types.d.ts +36 -11
- package/dist/react/use-ag-grid-url-sync.js +151 -97
- package/dist/react/use-ag-grid-url-sync.js.map +1 -1
- package/package.json +35 -16
package/dist/core/validation.js
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
format: 'querystring',
|
|
8
|
-
onParseError: () => { }
|
|
9
|
-
};
|
|
10
|
-
export function validateFilterValue(value, config, operation) {
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
import { InvalidFilterError, InvalidDateError } from './types.js';
|
|
3
|
+
import { ColumnFilterSchema } from './schemas.js';
|
|
4
|
+
import { resolveOptions } from './options.js';
|
|
5
|
+
export { DEFAULT_CONFIG } from './options.js';
|
|
6
|
+
export function validateFilterValue(value, config = {}, operation) {
|
|
11
7
|
if (operation === 'blank' || operation === 'notBlank') {
|
|
12
8
|
return '';
|
|
13
9
|
}
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
const { maxValueLength } = resolveOptions(config);
|
|
11
|
+
if (value.length > maxValueLength) {
|
|
12
|
+
throw new InvalidFilterError(`Filter value exceeds maximum length of ${maxValueLength} characters`, undefined, { code: 'VALUE_TOO_LONG' });
|
|
16
13
|
}
|
|
17
14
|
return value;
|
|
18
15
|
}
|
|
@@ -20,9 +17,6 @@ export function validateNumberFilter(value) {
|
|
|
20
17
|
if (!Number.isFinite(value)) {
|
|
21
18
|
return { valid: false, error: 'Filter value must be a finite number' };
|
|
22
19
|
}
|
|
23
|
-
if (Math.abs(value) > Number.MAX_SAFE_INTEGER) {
|
|
24
|
-
return { valid: false, error: 'Number value exceeds safe integer range' };
|
|
25
|
-
}
|
|
26
20
|
return { valid: true };
|
|
27
21
|
}
|
|
28
22
|
export function validateNumberRange(min, max) {
|
|
@@ -40,24 +34,58 @@ export function validateNumberRange(min, max) {
|
|
|
40
34
|
}
|
|
41
35
|
return { valid: true };
|
|
42
36
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
37
|
+
const NUMBER_FORMAT = /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;
|
|
38
|
+
const EXPONENT_SPACE = /(?<=[\d.][eE]) (?=\d+$)/;
|
|
39
|
+
const MAX_PRECISION = 100;
|
|
40
|
+
function significantDigits(text) {
|
|
41
|
+
const [mantissa = '', exponent = '0'] = text.replace(/^[+-]/, '').split(/e/i);
|
|
42
|
+
const [whole = '', fraction = ''] = mantissa.split('.');
|
|
43
|
+
const allDigits = whole + fraction;
|
|
44
|
+
const leadingZeros = allDigits.length - allDigits.replace(/^0+/, '').length;
|
|
45
|
+
const digits = allDigits.slice(leadingZeros).replace(/0+$/, '');
|
|
46
|
+
if (digits === '')
|
|
47
|
+
return '';
|
|
48
|
+
const point = whole.length - leadingZeros + Number(exponent);
|
|
49
|
+
return `${digits}e${point}`;
|
|
50
|
+
}
|
|
51
|
+
function keepsDigits(text, number) {
|
|
52
|
+
const key = significantDigits(text);
|
|
53
|
+
const precision = Math.max(1, key.indexOf('e'));
|
|
54
|
+
const magnitude = Math.abs(number);
|
|
55
|
+
return (key === significantDigits(String(magnitude)) ||
|
|
56
|
+
key === significantDigits(magnitude.toPrecision(precision)));
|
|
57
|
+
}
|
|
58
|
+
const NUMBER_ISSUE = { code: 'INVALID_NUMBER' };
|
|
59
|
+
export function readNumber(value) {
|
|
60
|
+
const text = value?.trim() ?? '';
|
|
61
|
+
if (!text) {
|
|
62
|
+
return new InvalidFilterError('Number filter value cannot be empty', undefined, NUMBER_ISSUE);
|
|
51
63
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
throw new InvalidFilterError(`Invalid number format: ${value}`);
|
|
64
|
+
if (!NUMBER_FORMAT.test(text)) {
|
|
65
|
+
return new InvalidFilterError(`Invalid number format: ${text}`, undefined, NUMBER_ISSUE);
|
|
55
66
|
}
|
|
56
|
-
const
|
|
67
|
+
const number = parseFloat(text);
|
|
68
|
+
const validation = validateNumberFilter(number);
|
|
57
69
|
if (!validation.valid) {
|
|
58
|
-
|
|
70
|
+
return new InvalidFilterError(validation.error || 'Invalid number value', undefined, NUMBER_ISSUE);
|
|
71
|
+
}
|
|
72
|
+
if (significantDigits(text).indexOf('e') > MAX_PRECISION) {
|
|
73
|
+
return new InvalidFilterError(`Number value has more than ${MAX_PRECISION} significant digits: ${text}`, undefined, NUMBER_ISSUE);
|
|
74
|
+
}
|
|
75
|
+
if (!keepsDigits(text, number)) {
|
|
76
|
+
return new InvalidFilterError(`Number value ${text} would be rounded to ${number}`, undefined, NUMBER_ISSUE);
|
|
59
77
|
}
|
|
60
|
-
return
|
|
78
|
+
return number;
|
|
79
|
+
}
|
|
80
|
+
export function parseExactNumber(value) {
|
|
81
|
+
const number = readNumber(value);
|
|
82
|
+
return number instanceof InvalidFilterError ? null : number;
|
|
83
|
+
}
|
|
84
|
+
export function validateAndParseNumber(value) {
|
|
85
|
+
const number = readNumber((value?.trim() ?? '').replace(EXPONENT_SPACE, '+'));
|
|
86
|
+
if (number instanceof InvalidFilterError)
|
|
87
|
+
throw number;
|
|
88
|
+
return number;
|
|
61
89
|
}
|
|
62
90
|
export function validateAndParseDate(value) {
|
|
63
91
|
const trimmedValue = value?.trim();
|
|
@@ -132,30 +160,6 @@ export function validateAndParseDateRange(rangeValue) {
|
|
|
132
160
|
return [startDate, endDate];
|
|
133
161
|
}
|
|
134
162
|
export function isValidColumnFilter(obj) {
|
|
135
|
-
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
const filter = obj;
|
|
139
|
-
if (!filter.filterType ||
|
|
140
|
-
!filter.type ||
|
|
141
|
-
typeof filter.filterType !== 'string' ||
|
|
142
|
-
typeof filter.type !== 'string') {
|
|
143
|
-
return false;
|
|
144
|
-
}
|
|
145
|
-
if (filter.filterType === 'text') {
|
|
146
|
-
return (typeof filter.filter === 'string' &&
|
|
147
|
-
TEXT_FILTER_OPERATIONS.includes(filter.type));
|
|
148
|
-
}
|
|
149
|
-
if (filter.filterType === 'number') {
|
|
150
|
-
return (typeof filter.filter === 'number' &&
|
|
151
|
-
NUMBER_FILTER_OPERATIONS.includes(filter.type) &&
|
|
152
|
-
(filter.filterTo === undefined || typeof filter.filterTo === 'number'));
|
|
153
|
-
}
|
|
154
|
-
if (filter.filterType === 'date') {
|
|
155
|
-
return (typeof filter.filter === 'string' &&
|
|
156
|
-
DATE_FILTER_OPERATIONS.includes(filter.type) &&
|
|
157
|
-
(filter.filterTo === undefined || typeof filter.filterTo === 'string'));
|
|
158
|
-
}
|
|
159
|
-
return false;
|
|
163
|
+
return v.is(ColumnFilterSchema, obj);
|
|
160
164
|
}
|
|
161
165
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
import { GridViewSchema, StoredViewsSchema } from './schemas.js';
|
|
3
|
+
import { URLSyncError } from './types.js';
|
|
4
|
+
import { toError } from './to-error.js';
|
|
1
5
|
const SCHEMA_VERSION = 'v1';
|
|
2
6
|
const keyFor = (storageKey) => `ag-grid-url-sync:views:${SCHEMA_VERSION}:${storageKey}`;
|
|
3
7
|
const empty = () => ({ views: [], activeId: null });
|
|
4
8
|
function isGridView(value) {
|
|
5
|
-
|
|
6
|
-
return false;
|
|
7
|
-
const candidate = value;
|
|
8
|
-
return (typeof candidate.id === 'string' &&
|
|
9
|
-
typeof candidate.name === 'string' &&
|
|
10
|
-
typeof candidate.updatedAt === 'number' &&
|
|
11
|
-
typeof candidate.filterModel === 'object' &&
|
|
12
|
-
candidate.filterModel !== null);
|
|
9
|
+
return v.is(GridViewSchema, value);
|
|
13
10
|
}
|
|
14
11
|
function createId() {
|
|
15
12
|
if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) {
|
|
@@ -32,15 +29,14 @@ export function createViewStore(storageKey) {
|
|
|
32
29
|
if (!raw)
|
|
33
30
|
return empty();
|
|
34
31
|
try {
|
|
35
|
-
const parsed = JSON.parse(raw);
|
|
36
|
-
if (
|
|
32
|
+
const parsed = v.safeParse(StoredViewsSchema, JSON.parse(raw));
|
|
33
|
+
if (!parsed.success)
|
|
37
34
|
return empty();
|
|
38
|
-
const { views, activeId } = parsed;
|
|
39
|
-
const validViews =
|
|
35
|
+
const { views, activeId } = parsed.output;
|
|
36
|
+
const validViews = views.filter(isGridView);
|
|
40
37
|
return {
|
|
41
38
|
views: validViews,
|
|
42
|
-
activeId:
|
|
43
|
-
validViews.some(view => view.id === activeId)
|
|
39
|
+
activeId: activeId !== null && validViews.some(view => view.id === activeId)
|
|
44
40
|
? activeId
|
|
45
41
|
: null
|
|
46
42
|
};
|
|
@@ -51,7 +47,9 @@ export function createViewStore(storageKey) {
|
|
|
51
47
|
};
|
|
52
48
|
const write = (next) => {
|
|
53
49
|
if (typeof window === 'undefined') {
|
|
54
|
-
throw new
|
|
50
|
+
throw new URLSyncError('Browser storage is unavailable.', undefined, {
|
|
51
|
+
code: 'STORAGE_UNAVAILABLE'
|
|
52
|
+
});
|
|
55
53
|
}
|
|
56
54
|
try {
|
|
57
55
|
window.localStorage.setItem(key, JSON.stringify(next));
|
|
@@ -61,9 +59,11 @@ export function createViewStore(storageKey) {
|
|
|
61
59
|
error instanceof DOMException &&
|
|
62
60
|
(error.name === 'QuotaExceededError' ||
|
|
63
61
|
error.name === 'NS_ERROR_DOM_QUOTA_REACHED');
|
|
64
|
-
throw
|
|
65
|
-
? 'Browser storage is full. Delete a saved view and try again.'
|
|
66
|
-
: 'Error writing to storage.',
|
|
62
|
+
throw isQuota
|
|
63
|
+
? new URLSyncError('Browser storage is full. Delete a saved view and try again.', toError(error), { code: 'STORAGE_FULL' })
|
|
64
|
+
: new URLSyncError('Error writing to storage.', toError(error), {
|
|
65
|
+
code: 'STORAGE_WRITE_FAILED'
|
|
66
|
+
});
|
|
67
67
|
}
|
|
68
68
|
};
|
|
69
69
|
return {
|
|
@@ -78,7 +78,9 @@ export function createViewStore(storageKey) {
|
|
|
78
78
|
saveView: (name, filterModel) => {
|
|
79
79
|
const trimmedName = name.trim();
|
|
80
80
|
if (!trimmedName) {
|
|
81
|
-
throw new
|
|
81
|
+
throw new URLSyncError('A view name is required.', undefined, {
|
|
82
|
+
code: 'VIEW_NAME_REQUIRED'
|
|
83
|
+
});
|
|
82
84
|
}
|
|
83
85
|
const current = read();
|
|
84
86
|
const existing = current.views.find(view => view.name === trimmedName);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-storage.js","sourceRoot":"","sources":["../../src/core/view-storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"view-storage.js","sourceRoot":"","sources":["../../src/core/view-storage.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { AGGridUrlSync, createUrlSync } from './core/ag-grid-url-sync.js';
|
|
2
2
|
export * from './core/types.js';
|
|
3
|
-
export { validateFilterValue
|
|
3
|
+
export { validateFilterValue } from './core/validation.js';
|
|
4
|
+
export { DEFAULT_CONFIG } from './core/options.js';
|
|
4
5
|
export { parseUrlFilters, parseFilterParam } from './core/url-parser.js';
|
|
5
6
|
export { serializeFilters, generateUrl } from './core/url-generator.js';
|
|
6
7
|
export { getFilterModel, applyFilterModel } from './core/grid-integration.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { AGGridUrlSync, createUrlSync } from './core/ag-grid-url-sync.js';
|
|
2
2
|
export * from './core/types.js';
|
|
3
|
-
export { validateFilterValue
|
|
3
|
+
export { validateFilterValue } from './core/validation.js';
|
|
4
|
+
export { DEFAULT_CONFIG } from './core/options.js';
|
|
4
5
|
export { parseUrlFilters, parseFilterParam } from './core/url-parser.js';
|
|
5
6
|
export { serializeFilters, generateUrl } from './core/url-generator.js';
|
|
6
7
|
export { getFilterModel, applyFilterModel } from './core/grid-integration.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAEzE,cAAc,iBAAiB,CAAA;AAG/B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAEzE,cAAc,iBAAiB,CAAA;AAG/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAGlD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGxE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGvE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAS7E,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,iCAAiC,CAAA;AAExC,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EACjB,MAAM,iCAAiC,CAAA"}
|
package/dist/react/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AGGridUrlSyncConfig, FilterState, SerializationFormat, SerializationMode } from '../core/types.js';
|
|
1
|
+
import type { AGGridUrlSyncConfig, FilterState, SerializationFormat, SerializationMode, URLSyncError } from '../core/types.js';
|
|
2
2
|
import type { GridView } from '../core/view-storage.js';
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options for the React hook
|
|
@@ -13,7 +13,7 @@ export interface UseAGGridUrlSyncOptions extends AGGridUrlSyncConfig {
|
|
|
13
13
|
*
|
|
14
14
|
* @example 'employee-grid'
|
|
15
15
|
*/
|
|
16
|
-
storageKey?: string;
|
|
16
|
+
storageKey?: string | undefined;
|
|
17
17
|
/**
|
|
18
18
|
* Automatically apply URL filters when the component mounts and grid API becomes ready
|
|
19
19
|
*
|
|
@@ -21,13 +21,14 @@ export interface UseAGGridUrlSyncOptions extends AGGridUrlSyncConfig {
|
|
|
21
21
|
* take precedence: a shared link should show the sender's filters rather than
|
|
22
22
|
* the recipient's stored view.
|
|
23
23
|
*
|
|
24
|
-
* Attempted once per grid. A failed attempt is reported
|
|
25
|
-
* `onParseError
|
|
26
|
-
*
|
|
24
|
+
* Attempted once per grid. A failed attempt is reported one time (a bad
|
|
25
|
+
* filter through `onParseError`, any other failure through `onError`) and is
|
|
26
|
+
* not retried on later renders; pass a new `gridApi`, or call
|
|
27
|
+
* `applyUrlFilters`, to try again.
|
|
27
28
|
*
|
|
28
29
|
* Default: false
|
|
29
30
|
*/
|
|
30
|
-
autoApplyOnMount?: boolean;
|
|
31
|
+
autoApplyOnMount?: boolean | undefined;
|
|
31
32
|
/**
|
|
32
33
|
* Whether the hook should be enabled when the grid API is ready
|
|
33
34
|
*
|
|
@@ -38,12 +39,18 @@ export interface UseAGGridUrlSyncOptions extends AGGridUrlSyncConfig {
|
|
|
38
39
|
*
|
|
39
40
|
* Default: true
|
|
40
41
|
*/
|
|
41
|
-
enabledWhenReady?: boolean;
|
|
42
|
+
enabledWhenReady?: boolean | undefined;
|
|
42
43
|
/**
|
|
43
|
-
* Optional
|
|
44
|
-
*
|
|
44
|
+
* Optional handler for operation failures: an operation called before the
|
|
45
|
+
* grid is ready (`NOT_READY`), a grid API error (`GRID_ERROR`), a saved view
|
|
46
|
+
* that is not found or cannot be stored (`VIEW_*`, `STORAGE_*`). `context`
|
|
47
|
+
* names the operation, for example `'apply-url-filters'`.
|
|
48
|
+
*
|
|
49
|
+
* Each failure reaches one callback only (#220). A filter that is dropped or
|
|
50
|
+
* not valid goes to `onParseError`, not here. The hook never writes to the
|
|
51
|
+
* console, so a failure with no handler is silent.
|
|
45
52
|
*/
|
|
46
|
-
onError?: (error: Error, context: string) => void;
|
|
53
|
+
onError?: ((error: Error, context: string) => void) | undefined;
|
|
47
54
|
}
|
|
48
55
|
/**
|
|
49
56
|
* Return type for the useAGGridUrlSync hook
|
|
@@ -78,9 +85,27 @@ export interface UseAGGridUrlSyncReturn {
|
|
|
78
85
|
*/
|
|
79
86
|
currentUrl: string;
|
|
80
87
|
/**
|
|
81
|
-
* Whether the grid has
|
|
88
|
+
* Whether the grid has filters that the library supports.
|
|
89
|
+
*
|
|
90
|
+
* Comes from the grid's filter state, not from the URL, because the URL also
|
|
91
|
+
* keeps the page's own params. A filter that the URL cannot carry (for
|
|
92
|
+
* example a text value over `maxValueLength`) still counts, so a "clear
|
|
93
|
+
* filters" button stays enabled. The URL leaves that filter out, reports it
|
|
94
|
+
* through `onParseError`, and puts it in `issues`.
|
|
82
95
|
*/
|
|
83
96
|
hasFilters: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* The filters that were dropped (#229): the data issues of the latest URL
|
|
99
|
+
* apply (`applyUrlFilters`, `applyFilters`, auto-apply), and of the latest
|
|
100
|
+
* URL write (each filter change). Each one is a `URLSyncError` with a
|
|
101
|
+
* `code` and, when it is known, a `column`. The apply issues stay until the
|
|
102
|
+
* next apply, `clearFilters` or `loadView`.
|
|
103
|
+
*
|
|
104
|
+
* The array keeps its identity while its content does not change. Operation
|
|
105
|
+
* failures (`NOT_READY`, `GRID_ERROR`, storage) go to `onError` and are not
|
|
106
|
+
* here. With `throwOnError`, the hook throws a picked issue during render.
|
|
107
|
+
*/
|
|
108
|
+
issues: readonly URLSyncError[];
|
|
84
109
|
/**
|
|
85
110
|
* Parse filters from a URL without applying them
|
|
86
111
|
* @param url - URL to parse
|