spiderly 19.11.9 → 19.12.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/agent/docs/angular-customization/index.md +55 -13
- package/agent/docs/angular-customization/references/helper-functions.generated.md +1 -0
- package/agent/docs/e2e-testing/index.md +10 -15
- package/agent/skills/add-entity/SKILL.md +12 -1
- package/fesm2022/spiderly.mjs +1900 -402
- package/fesm2022/spiderly.mjs.map +1 -1
- package/lib/components/spiderly-data-table/spiderly-data-table.component.d.ts +369 -142
- package/lib/directives/spiderly-filter-template.directive.d.ts +34 -0
- package/lib/directives/spiderly-overflow-title.directive.d.ts +33 -0
- package/lib/entities/filter-rule.d.ts +5 -7
- package/lib/filters/allowed-operators.d.ts +23 -0
- package/lib/filters/filter-store.d.ts +255 -0
- package/lib/filters/spiderly-filter-bar.component.d.ts +132 -0
- package/lib/services/helper-functions.d.ts +8 -0
- package/package.json +1 -1
- package/public-api.d.ts +5 -0
- package/styles/components/spiderly-data-table/spiderly-data-table.component.scss +150 -18
- package/styles/filters/spiderly-filter-bar.component.scss +163 -0
- package/styles/styles/layout/_mixins.scss +13 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { AfterViewInit, ErrorHandler, EventEmitter, OnChanges, OnDestroy, OnInit, QueryList, TemplateRef } from '@angular/core';
|
|
2
2
|
import { ActivatedRoute, Router } from '@angular/router';
|
|
3
3
|
import { TranslocoService } from '@jsverse/transloco';
|
|
4
|
-
import {
|
|
4
|
+
import { SortMeta } from 'primeng/api';
|
|
5
5
|
import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog';
|
|
6
|
-
import { Table,
|
|
6
|
+
import { Table, TableLazyLoadEvent } from 'primeng/table';
|
|
7
7
|
import { Observable } from 'rxjs';
|
|
8
8
|
import { CellTemplateContext, SpiderlyCellTemplateDirective } from '../../directives/spiderly-cell-template.directive';
|
|
9
9
|
import { Filter } from '../../entities/filter';
|
|
10
10
|
import { LazyLoadSelectedIdsResult } from '../../entities/lazy-load-selected-ids-result';
|
|
11
11
|
import { PaginatedResult } from '../../entities/paginated-result';
|
|
12
12
|
import { PrimengOption } from '../../entities/primeng-option';
|
|
13
|
-
import {
|
|
13
|
+
import { FilterSource, SortKeyLabel } from '../../filters/filter-store';
|
|
14
|
+
import { SpiderlyFilterTemplateDirective } from '../../directives/spiderly-filter-template.directive';
|
|
14
15
|
import { ConfigServiceBase } from '../../services/config.service.base';
|
|
15
16
|
import { SpiderlyMessageService } from '../../services/spiderly-message.service';
|
|
16
17
|
import { SpiderlyFormControl } from '../spiderly-form-control/spiderly-form-control';
|
|
@@ -26,6 +27,52 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
26
27
|
private locale;
|
|
27
28
|
private readonly destroy$;
|
|
28
29
|
table: Table;
|
|
30
|
+
private readonly injector;
|
|
31
|
+
private readonly zone;
|
|
32
|
+
/**
|
|
33
|
+
* The selection column's declared share. Under the fixed layout this is a RATIO, not a width.
|
|
34
|
+
*
|
|
35
|
+
* 4rem, down from 6: the original reserved room for a five-digit select-all counter sitting at
|
|
36
|
+
* body text size beside the box, which is the widest thing it can ever hold and not what it
|
|
37
|
+
* holds on any ordinary screen. The counter is a smaller step now (see the SCSS), so the same
|
|
38
|
+
* five digits fit in two thirds of the space.
|
|
39
|
+
*/
|
|
40
|
+
protected readonly selectionColumnWidth = "4rem";
|
|
41
|
+
/**
|
|
42
|
+
* The selection column's MEASURED width, which is what the frozen identity column offsets
|
|
43
|
+
* itself by. Declaring `6rem` on both looked like the one-telling answer and is wrong: widths
|
|
44
|
+
* are shares, so that column renders at whatever proportion of the table it gets — 148px for a
|
|
45
|
+
* declared 6rem in one spec — and the identity column would sit 52px inside it, overlapping the
|
|
46
|
+
* checkboxes the moment anyone scrolled. The spec caught it; nothing about the page would have.
|
|
47
|
+
*/
|
|
48
|
+
protected frozenOffsetPx: number;
|
|
49
|
+
private selectionWidthObserver?;
|
|
50
|
+
/** Aborts an in-flight column resize's document listeners, from `onUp` or from teardown. */
|
|
51
|
+
private resizeAbort;
|
|
52
|
+
/**
|
|
53
|
+
* Whether this column is pinned against the left edge. Only the FIRST column, and only when it
|
|
54
|
+
* is `lockVisible`: a sticky column in the middle of the grid pins the wrong thing and leaves a
|
|
55
|
+
* hole where it used to be. Once the grid scrolls sideways a row otherwise loses its identity
|
|
56
|
+
* — "Intesa, plaćeno, 12.400" with no idea whose order it is — and NN/g's Data Tables is
|
|
57
|
+
* explicit that the leftmost header column must lock in place. `lockVisible` already names
|
|
58
|
+
* exactly that column in every table, so this needs no new API (CLAUDE.md -> decision 8).
|
|
59
|
+
*/
|
|
60
|
+
isColumnFrozen(col: Column): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* The rightmost pinned cell, which carries the seam's shadow. It is the identity column when
|
|
63
|
+
* there is one and the checkbox column otherwise — a fact only this side knows, which is why
|
|
64
|
+
* the SCSS asking for it as `:last-of-type` drew nothing at all.
|
|
65
|
+
*/
|
|
66
|
+
isLastFrozenColumn(col: Column): boolean;
|
|
67
|
+
get isSelectionColumnLastFrozen(): boolean;
|
|
68
|
+
/** A frozen column starts after the checkbox column, when there is one. */
|
|
69
|
+
frozenColumnOffset(): string;
|
|
70
|
+
/**
|
|
71
|
+
* Tracks the selection column's rendered width. A ResizeObserver rather than a one-off read:
|
|
72
|
+
* every column drag and every window resize re-splits the shares, so the offset moves without
|
|
73
|
+
* anything about the selection column itself changing.
|
|
74
|
+
*/
|
|
75
|
+
private observeSelectionWidth;
|
|
29
76
|
/**
|
|
30
77
|
* Custom toolbar content projected via `<ng-template spiderlyDataTableActions>`.
|
|
31
78
|
* Rendered in the caption action area ahead of the built-in buttons.
|
|
@@ -43,6 +90,28 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
43
90
|
/** Paginator page-size choices; merge rules and persistence: CLAUDE.md → "Rows-per-page". */
|
|
44
91
|
rowsPerPageOptions: number[];
|
|
45
92
|
cols: Column[];
|
|
93
|
+
/**
|
|
94
|
+
* The consumer's filter store — the table's WHOLE filter surface, rendered as the chip bar. A
|
|
95
|
+
* table given none has no filtering at all (`Column.filterType` is only the value's shape; the
|
|
96
|
+
* legacy header-filter fallback was deleted — CLAUDE.md -> "Operator-owned view").
|
|
97
|
+
*
|
|
98
|
+
* READ ONCE, in ngOnInit — a store assigned later is silently ignored: the requery effect
|
|
99
|
+
* stays subscribed to the first store's `applied()`, and `resolvedStateKey` (which
|
|
100
|
+
* `additionalFilterIdLong` feeds) is never re-derived either. A consumer that must swap
|
|
101
|
+
* stores at runtime destroys and recreates the table around the swap — PACMS
|
|
102
|
+
* `integration-matching-products` nulls its view model for exactly this. Teaching
|
|
103
|
+
* ngOnChanges to re-arm both is the open upstream fix.
|
|
104
|
+
*/
|
|
105
|
+
filters?: FilterSource;
|
|
106
|
+
/** Saved questions for this table, rendered as tabs above the bar. */
|
|
107
|
+
views?: TableView[];
|
|
108
|
+
/**
|
|
109
|
+
* The view currently selected. Seeded from the first view in `ngOnInit`, never left null on a
|
|
110
|
+
* table that has views: `viewScope` keys the layout off it, so an unseeded table writes its
|
|
111
|
+
* width and order to the SAME key an unmigrated table uses — orphaned the moment the operator
|
|
112
|
+
* clicks the first tab — and no tab reads as selected until they do.
|
|
113
|
+
*/
|
|
114
|
+
activeViewId: string | null;
|
|
46
115
|
/** Whether the paginator is shown. Pass only when `hasLazyLoad === false`. Defaults to `true`. */
|
|
47
116
|
showPaginator: boolean;
|
|
48
117
|
/** Whether the table is wrapped in a card container. Defaults to `false`. */
|
|
@@ -86,9 +155,6 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
86
155
|
onIsAllSelectedChange: EventEmitter<AllClickEvent>;
|
|
87
156
|
selectedLazyLoadObservableMethod: (tableFilter: Filter) => Observable<LazyLoadSelectedIdsResult>;
|
|
88
157
|
additionalFilterIdLong: number;
|
|
89
|
-
matchModeDateOptions: SelectItem[];
|
|
90
|
-
matchModeNumberOptions: SelectItem[];
|
|
91
|
-
matchModeTextOptions: SelectItem[];
|
|
92
158
|
/** Whether the "Add" button is shown. Defaults to `true`. */
|
|
93
159
|
showAddButton: boolean;
|
|
94
160
|
/** Whether the "Export to Excel" button is shown. Defaults to `true`. */
|
|
@@ -171,12 +237,6 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
171
237
|
* default later flows through to every user who never touched that column.
|
|
172
238
|
*/
|
|
173
239
|
private columnVisibilityOverrides;
|
|
174
|
-
/**
|
|
175
|
-
* Columns revealed by the load-time reconciliation. Kept apart from
|
|
176
|
-
* `columnVisibilityOverrides` so persisting a later unrelated toggle can't promote a
|
|
177
|
-
* transient safety reveal into a durable choice.
|
|
178
|
-
*/
|
|
179
|
-
private revealedByConstraint;
|
|
180
240
|
/** A data column shows values for a `field`; anything else (the actions column) always renders. */
|
|
181
241
|
private static isDataColumn;
|
|
182
242
|
/**
|
|
@@ -185,8 +245,46 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
185
245
|
* are a transient working set — different natural lifetimes.
|
|
186
246
|
*/
|
|
187
247
|
private get columnsStateKey();
|
|
188
|
-
/** Actions columns always render; data columns follow
|
|
248
|
+
/** Actions columns always render; data columns follow the override, then declared default. */
|
|
189
249
|
isColumnVisible(col: Column): boolean;
|
|
250
|
+
/**
|
|
251
|
+
* `cols` in the operator's order. A field the stored order has never seen — a column added in a
|
|
252
|
+
* later release — sorts to the END rather than displacing a layout someone built by hand
|
|
253
|
+
* (CLAUDE.md -> "Operator-owned view", decision 7); the sort is stable, so those keep their
|
|
254
|
+
* declared order among themselves. Actions columns carry no field and are always last, which is
|
|
255
|
+
* where every consumer already declares them.
|
|
256
|
+
*/
|
|
257
|
+
private orderedCols;
|
|
258
|
+
/**
|
|
259
|
+
* Whether this column can move one place in `direction` (-1 left, 1 right). A locked column is
|
|
260
|
+
* the row's anchor — and, once the left edge freezes, the thing a horizontal scroll keeps in
|
|
261
|
+
* view — so it does not move and nothing moves in front of it.
|
|
262
|
+
*/
|
|
263
|
+
canMoveColumn(col: Column, direction: -1 | 1): boolean;
|
|
264
|
+
moveMenuColumn(direction: -1 | 1): void;
|
|
265
|
+
/** The move itself, shared by the menu and the drag — two entry points, one rule. */
|
|
266
|
+
private placeColumn;
|
|
267
|
+
private dataColumnsInOrder;
|
|
268
|
+
/**
|
|
269
|
+
* Header drag, ours rather than PrimeNG's `pReorderableColumn`, for two reasons: its
|
|
270
|
+
* `onMouseDown` arms the th for anything that is not an INPUT, a TEXTAREA or its OWN resizer —
|
|
271
|
+
* so our menu chevron and our resize grip would each start a column drag, and reaching for a
|
|
272
|
+
* width would silently reorder the grid — and its `onColumnDrop` reorders blind, with no notion
|
|
273
|
+
* of a locked column (CLAUDE.md -> decision 6).
|
|
274
|
+
*
|
|
275
|
+
* A shortcut for neighbours, never the mechanism: HTML5 dnd has no edge auto-scroll, so a column
|
|
276
|
+
* scrolled off the right is unreachable this way, and there is no keyboard path at all. The menu
|
|
277
|
+
* carries both.
|
|
278
|
+
*
|
|
279
|
+
* This half is the arming rule; the drop rule is `canDropOn` below.
|
|
280
|
+
*/
|
|
281
|
+
onHeaderMouseDown(event: MouseEvent): void;
|
|
282
|
+
onHeaderDragStart(col: Column, event: DragEvent): void;
|
|
283
|
+
onHeaderDragOver(col: Column, event: DragEvent): void;
|
|
284
|
+
onHeaderDrop(col: Column, event: DragEvent): void;
|
|
285
|
+
/** Nothing lands on, or in front of, the locked column. Enforced here as well as in the menu:
|
|
286
|
+
* a drop is a separate entry point, and the rule is about the grid rather than about a button. */
|
|
287
|
+
private canDropOn;
|
|
190
288
|
private refreshVisibleCols;
|
|
191
289
|
/**
|
|
192
290
|
* Locked columns can't be toggled; the last visible data column can't be hidden — the
|
|
@@ -194,46 +292,56 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
194
292
|
*/
|
|
195
293
|
canToggleColumn(col: Column): boolean;
|
|
196
294
|
toggleColumn(col: Column, visible: boolean): void;
|
|
197
|
-
/** Restores every column to its declared default and forgets the stored override. */
|
|
198
|
-
resetColumnVisibility(): void;
|
|
199
295
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* The one home of the filter-state key rule (sort meta is keyed by `field` instead).
|
|
209
|
-
* Instance rather than static so the template's `[field]` binding can share it.
|
|
296
|
+
* Restores every column to its declared default and forgets the stored overrides — visibility,
|
|
297
|
+
* wrap, order and width alike. It undid visibility only until the header menu shipped three
|
|
298
|
+
* more gestures beside it, and a layout with no way back is worse than one with no knobs.
|
|
299
|
+
*
|
|
300
|
+
* Hiding — here or from the menu — never touches filters or sort: the chip bar names every
|
|
301
|
+
* applied filter and the sort chip names the sort, hidden column or not (decision 2b). The
|
|
302
|
+
* legacy "hidden contributes nothing" apparatus died with the header-filter path.
|
|
210
303
|
*/
|
|
211
|
-
|
|
304
|
+
resetColumnLayout(): void;
|
|
212
305
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
* `_filter()` for the auto-applying types, so `table.filters` holds PENDING edits too.
|
|
217
|
-
* Reading it for the header icon marked a column filtered the moment the operator typed
|
|
218
|
-
* a character, before Apply — claiming the grid was narrowed when it was not.
|
|
306
|
+
* Per-column wrap, by `field`. A SEPARATE key from the visibility overrides on purpose: folding
|
|
307
|
+
* both into one object would invalidate every layout already in an operator's localStorage, and
|
|
308
|
+
* this is the key the width and order overrides will join (decision 5).
|
|
219
309
|
*/
|
|
220
|
-
private
|
|
310
|
+
private columnWrap;
|
|
311
|
+
/** Data-column fields in the operator's order. Empty means "as declared". */
|
|
312
|
+
private columnOrder;
|
|
221
313
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
314
|
+
* Per-column width overrides, as SHARES in the same unit `getColWidth` emits — never pixels.
|
|
315
|
+
* Under the fixed layout the browser splits surplus in proportion to these, so a pixel would
|
|
316
|
+
* pin the column and stop it answering the window: the operator on a 1280 laptop and the one
|
|
317
|
+
* on a 2560 monitor would get the same frozen column (decision 4).
|
|
225
318
|
*/
|
|
226
|
-
|
|
227
|
-
/** Whether the column carries a constraint at all, applied or still being typed. */
|
|
228
|
-
private columnHasConstraint;
|
|
319
|
+
private columnWidths;
|
|
229
320
|
/**
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
|
|
236
|
-
|
|
321
|
+
* Layout keys carry the ACTIVE VIEW, which is what makes a view more than a saved filter: a
|
|
322
|
+
* picking view and a payments view want different COLUMNS, not just different rows. Global
|
|
323
|
+
* layout would re-create the original complaint one level up — the operator still re-picking
|
|
324
|
+
* columns every time the job changes.
|
|
325
|
+
*
|
|
326
|
+
* A table with no views has no segment, so the twenty-six tables that have not migrated keep
|
|
327
|
+
* reading exactly the keys they already wrote.
|
|
328
|
+
*/
|
|
329
|
+
private get viewScope();
|
|
330
|
+
/**
|
|
331
|
+
* Where the applied filters live. Follows `stateStorage` rather than the layout's always-local
|
|
332
|
+
* rule, because that is where they lived before the bar took them off the header: PrimeNG's
|
|
333
|
+
* stateful table persisted them for free, and nothing replaced it — a refresh dropped every
|
|
334
|
+
* filter (Filip, on /tags). A filter is a question you are in the middle of asking, not a
|
|
335
|
+
* durable preference like a column's width.
|
|
336
|
+
*/
|
|
337
|
+
private get filtersStateKey();
|
|
338
|
+
private get filterStorage();
|
|
339
|
+
private persistAppliedFilters;
|
|
340
|
+
private restoreAppliedFilters;
|
|
341
|
+
private get layoutStateKey();
|
|
342
|
+
/** One key for the whole layout — wrap now, widths next (decision 5). */
|
|
343
|
+
private persistColumnLayout;
|
|
344
|
+
private restoreColumnLayout;
|
|
237
345
|
private persistColumnVisibility;
|
|
238
346
|
private restoreColumnVisibility;
|
|
239
347
|
/**
|
|
@@ -242,16 +350,9 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
242
350
|
*/
|
|
243
351
|
private persistedTableState;
|
|
244
352
|
/**
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
* In-memory only — once the constraint is gone, the user's stored choice reapplies.
|
|
249
|
-
*/
|
|
250
|
-
private reconcileVisibilityWithPersistedConstraints;
|
|
251
|
-
/**
|
|
252
|
-
* The declared default as PrimeNG sort meta, or null when none is declared — or when its
|
|
253
|
-
* column is hidden ("hidden contributes nothing"): the table then falls back to the
|
|
254
|
-
* backend's implicit Id DESC, exactly as if no default were declared.
|
|
353
|
+
* The declared default as PrimeNG sort meta, or null when none is declared. Applies even
|
|
354
|
+
* while its column is hidden: the sort chip names the ordering whether or not the column
|
|
355
|
+
* is on screen (decision 2b).
|
|
255
356
|
*/
|
|
256
357
|
private defaultMultiSortMeta;
|
|
257
358
|
private persistedMultiSortMeta;
|
|
@@ -265,20 +366,6 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
265
366
|
* declares no column for.
|
|
266
367
|
*/
|
|
267
368
|
private keepSortableMeta;
|
|
268
|
-
/**
|
|
269
|
-
* The filter twin of `keepSortableMeta` — persisted state outlives the rule that produced
|
|
270
|
-
* it, here a match mode stored before the column declared `matchModes`. It has to REWRITE
|
|
271
|
-
* storage rather than filter a value on the way past: `ColumnFilter.ngOnInit` skips
|
|
272
|
-
* `initFieldFilterConstraint()` whenever the field already carries a constraint, so our
|
|
273
|
-
* `[matchMode]` never applies to a restored one. Left alone, the column keeps filtering by
|
|
274
|
-
* a mode it no longer offers while its match-mode `<p-select>` renders blank (the stored
|
|
275
|
-
* value is not among the options). Runs before PrimeNG's `restoreState()`, which reads this
|
|
276
|
-
* same key on the first `[value]` change.
|
|
277
|
-
*
|
|
278
|
-
* Deliberately narrow: it touches only constraints whose mode the declaring column no
|
|
279
|
-
* longer offers, so every other byte of the persisted blob survives.
|
|
280
|
-
*/
|
|
281
|
-
private reconcilePersistedMatchModes;
|
|
282
369
|
private applyDefaultSortIfUnsorted;
|
|
283
370
|
onPageChange(container: HTMLElement): void;
|
|
284
371
|
/**
|
|
@@ -300,8 +387,6 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
300
387
|
*/
|
|
301
388
|
private reconcileSelectionForLoadedPage;
|
|
302
389
|
clientLoad(): void;
|
|
303
|
-
private clientFilterCount;
|
|
304
|
-
filter(event: TableFilterEvent): void;
|
|
305
390
|
private loadFormArrayItems;
|
|
306
391
|
/**
|
|
307
392
|
* Single source for whether a column header offers click-to-sort (drives both
|
|
@@ -311,6 +396,148 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
311
396
|
* sort fields are rejected with a 400, a clickable header here would be a guaranteed error toast.
|
|
312
397
|
*/
|
|
313
398
|
isColumnSortable(col: Column): boolean;
|
|
399
|
+
/** The column the header menu is currently open for, and its header cell. */
|
|
400
|
+
menuColumn: Column | null;
|
|
401
|
+
private menuHeaderCell;
|
|
402
|
+
private draggedColumn;
|
|
403
|
+
/** False while a gesture that began on the menu chevron or the resize grip is in flight. */
|
|
404
|
+
private headerDragArmed;
|
|
405
|
+
/**
|
|
406
|
+
* A ViewChild rather than a template reference passed in from the header. The popover lives in
|
|
407
|
+
* the CAPTION template and the button that opens it in the HEADER one, and a reference variable
|
|
408
|
+
* does not cross an ng-template boundary — it arrived as undefined, and the click did nothing
|
|
409
|
+
* at all.
|
|
410
|
+
*/
|
|
411
|
+
private readonly columnMenu;
|
|
412
|
+
private readonly filterBar;
|
|
413
|
+
/**
|
|
414
|
+
* Consumer-projected filter controls, forwarded to the bar. Collected here rather than by the
|
|
415
|
+
* bar itself because the bar is OURS: a consumer's template is projected at the table, and
|
|
416
|
+
* content queries only see what was projected into the component that declares them.
|
|
417
|
+
*/
|
|
418
|
+
filterTemplates: QueryList<SpiderlyFilterTemplateDirective>;
|
|
419
|
+
private readonly selectionHeader;
|
|
420
|
+
openColumnMenu(col: Column, event: Event): void;
|
|
421
|
+
/**
|
|
422
|
+
* Switches to a view. Clears first, always: a view is a STATE rather than an addition, and two
|
|
423
|
+
* of them composed produce a question nobody asked. The clear runs through the store directly
|
|
424
|
+
* rather than through `clear(table)`, which would also wipe the sort and the persisted state a
|
|
425
|
+
* view is entitled to keep.
|
|
426
|
+
*/
|
|
427
|
+
selectView(view: TableView): void;
|
|
428
|
+
/**
|
|
429
|
+
* The filter this column stands for. Defaults to the column's own `field`, because a store id
|
|
430
|
+
* IS a backend property name — `toFilterPayload` emits it straight into `Filter.filters`. So
|
|
431
|
+
* `filterId` is an escape hatch for the rare mismatch, not something every column restates:
|
|
432
|
+
* all eight of the first migrated table's declarations were the field name written a second
|
|
433
|
+
* time.
|
|
434
|
+
*/
|
|
435
|
+
private filterIdFor;
|
|
436
|
+
/**
|
|
437
|
+
* Asks the STORE, not the column. Checking only that an id was declared let a typo through to
|
|
438
|
+
* `store.get(id)`, which reads `definitions[id].label` — so a mistyped id threw on click rather
|
|
439
|
+
* than greying the item out. With 195 declarations to migrate, that is the failure mode worth
|
|
440
|
+
* closing here rather than in each consumer.
|
|
441
|
+
*/
|
|
442
|
+
canFilterColumn(col: Column): boolean;
|
|
443
|
+
/**
|
|
444
|
+
* Opens the bar's editor for this column's filter. The bar took the filter off the header and
|
|
445
|
+
* the header is still where an operator reaches for it, which is twenty-seven tables' worth of
|
|
446
|
+
* habit; this is the shortcut back rather than a second filter surface — it drives the same
|
|
447
|
+
* editor, on the same bar, that `+ Filter` opens.
|
|
448
|
+
*/
|
|
449
|
+
filterMenuColumn(): void;
|
|
450
|
+
/**
|
|
451
|
+
* Sorts by this column in the NAMED direction. Clicking a header cycles asc, desc and off,
|
|
452
|
+
* which is fine for one column and a guess for a direction someone wants now — you click, look,
|
|
453
|
+
* and click again if it went the other way. This is also the only sort path that works from a
|
|
454
|
+
* keyboard.
|
|
455
|
+
*
|
|
456
|
+
* A column the generated paginator has no sort case for answers every load with a 400, so the
|
|
457
|
+
* items are disabled by the same predicate that keeps its header from being clickable.
|
|
458
|
+
*/
|
|
459
|
+
sortMenuColumn(order: 1 | -1): void;
|
|
460
|
+
/**
|
|
461
|
+
* Sizes the column to the widest thing in it. The cheaper escape from a cramped column: no
|
|
462
|
+
* drag, no aim. Unlike a drag it does NOT trade with the neighbour — a minimum that grew is
|
|
463
|
+
* exactly the case decision 4 lets push the table past its container and start scrolling.
|
|
464
|
+
*
|
|
465
|
+
* Measures the CELL CONTENT, not the cell: the clamp lives on the inner span, so a `td` reports
|
|
466
|
+
* a scrollWidth that fits while the text inside it does not.
|
|
467
|
+
*/
|
|
468
|
+
fitMenuColumn(): void;
|
|
469
|
+
/**
|
|
470
|
+
* The share that actually yields `needed` pixels — not `needed` scaled by the column's current
|
|
471
|
+
* px-per-share, which is the obvious answer and the wrong one. Shares are a PROPORTION of
|
|
472
|
+
* whatever width the table has, so growing this column's share also shrinks the realized width
|
|
473
|
+
* of every other column, and the naive figure lands short. The spec caught it as a cell that
|
|
474
|
+
* was still clipped after being told to fit.
|
|
475
|
+
*
|
|
476
|
+
* While the columns fit, the table keeps the container's width and the proportion has to solve
|
|
477
|
+
* needed / tableWidth = newShare / (otherShares + newShare)
|
|
478
|
+
* with `otherShares` recovered from what this column currently renders at. Once `needed` is the
|
|
479
|
+
* whole container the proportional regime has no answer: the table is about to overrun its
|
|
480
|
+
* container and scroll (decision 4), and there a share IS its own length, so the pixels convert
|
|
481
|
+
* straight through the root font size.
|
|
482
|
+
*/
|
|
483
|
+
private shareThatFits;
|
|
484
|
+
hideMenuColumn(): void;
|
|
485
|
+
/**
|
|
486
|
+
* Whether this column's cells give up the one-line clamp. The DEFAULT stays clamped
|
|
487
|
+
* (CLAUDE.md -> "Operator-owned view", decision 9); what changes is that the operator picks
|
|
488
|
+
* which column pays the row height, not whoever wrote `cols`.
|
|
489
|
+
*
|
|
490
|
+
* Lands on the td as `.cell-wrap`, whose inherited `--spiderly-cell-*` properties are how the
|
|
491
|
+
* toggle crosses into a projected `spiderlyCellTemplate` too — the contract's one telling is
|
|
492
|
+
* on that SCSS rule; a consumer clamp that hard-codes its values opts out.
|
|
493
|
+
*/
|
|
494
|
+
isColumnWrapped(col: Column): boolean;
|
|
495
|
+
get isMenuColumnWrapped(): boolean;
|
|
496
|
+
toggleWrapForMenuColumn(): void;
|
|
497
|
+
/** Exposed for the template: actions columns carry no field and get no menu. */
|
|
498
|
+
isDataColumn(col: Column): boolean;
|
|
499
|
+
/**
|
|
500
|
+
* What the grid is ordered by, resolved to COLUMN NAMES for the bar. Read off PrimeNG's live
|
|
501
|
+
* meta rather than mirrored into a field, so it cannot fall out of step with the sort the table
|
|
502
|
+
* is actually applying. A field with no column left (hidden, or removed in a later release)
|
|
503
|
+
* falls back to its own name rather than vanishing from the list.
|
|
504
|
+
*/
|
|
505
|
+
/**
|
|
506
|
+
* What the grid is ordered by, resolved to COLUMN NAMES for the bar.
|
|
507
|
+
*
|
|
508
|
+
* A field refreshed per fetch, not a getter: it is bound to the bar's `sort`, which is a SIGNAL
|
|
509
|
+
* input, so a freshly mapped array failed `Object.is` on every change-detection pass and marked
|
|
510
|
+
* the bar's consumers dirty forever — for a value that changes once per request. Same reason
|
|
511
|
+
* `tableStyle` is a field.
|
|
512
|
+
*/
|
|
513
|
+
sortKeys: SortKeyLabel[];
|
|
514
|
+
/**
|
|
515
|
+
* Read off the last REQUEST's sort, not `table._multiSortMeta`. On a first load with a declared
|
|
516
|
+
* default that field is still null: `applyDefaultSortIfUnsorted` writes the default onto the
|
|
517
|
+
* lazy-load event, and PrimeNG fills its own meta only once someone clicks a header. Reading the
|
|
518
|
+
* table there showed no sort on exactly the tables that always have one. A field with no column
|
|
519
|
+
* left falls back to its own name rather than vanishing.
|
|
520
|
+
*/
|
|
521
|
+
private refreshSortKeys;
|
|
522
|
+
/** This column's share, override first, then its declared width, then the per-type default. */
|
|
523
|
+
columnShare(col: Column): number;
|
|
524
|
+
/**
|
|
525
|
+
* A declared width expressed in SHARE units. rem IS the share unit and px converts; any other
|
|
526
|
+
* unit falls back to the per-type default rather than being read as a bare number.
|
|
527
|
+
*
|
|
528
|
+
* `parseFloat` alone shipped here first, so `width: '150px'` resolved to share 150 against
|
|
529
|
+
* neighbours at 12 — one column eating the grid on the first drag or fit. Every declared width
|
|
530
|
+
* in the consumer happens to be rem today, which is exactly why nothing would have caught it.
|
|
531
|
+
*/
|
|
532
|
+
private shareOfDeclaredWidth;
|
|
533
|
+
private defaultShare;
|
|
534
|
+
/**
|
|
535
|
+
* Trades share between the column being dragged and the one on its right, so the table keeps
|
|
536
|
+
* its total: widening a column never starts a horizontal scroll by itself, which only happens
|
|
537
|
+
* once the SUM of the minimums stops fitting. The px delta is converted through the column's
|
|
538
|
+
* own rendered width, which is the only place the share-to-pixel scale is actually known.
|
|
539
|
+
*/
|
|
540
|
+
startColumnResize(col: Column, event: MouseEvent, th: HTMLElement): void;
|
|
314
541
|
/**
|
|
315
542
|
* The column's declared {@link Column.width}, or the default for its filter type.
|
|
316
543
|
*
|
|
@@ -320,51 +547,6 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
320
547
|
* per-type defaults say — a boolean holds "Da"/"Ne", a text column holds a name.
|
|
321
548
|
*/
|
|
322
549
|
getColWidth(col: Column): string;
|
|
323
|
-
/**
|
|
324
|
-
* Memo for the resolution below. Two jobs: the narrowing maps to a NEW array and a
|
|
325
|
-
* template binding must not hand PrimeNG a fresh reference every CD pass, and both
|
|
326
|
-
* halves (offered list, default mode) must come from ONE computation so they cannot
|
|
327
|
-
* disagree. Keyed on the declared array's identity, so reassigning `col.matchModes`
|
|
328
|
-
* recomputes — note PrimeNG itself reads `matchModeOptions` only in its own `ngOnInit`,
|
|
329
|
-
* so a post-init change still never reaches the rendered dropdown.
|
|
330
|
-
*/
|
|
331
|
-
private matchModeResolutions;
|
|
332
|
-
getColMatchModeOptions(col: Column): SelectItem[] | null;
|
|
333
|
-
getColMatchMode(col: Column): any;
|
|
334
|
-
private resolveMatchModes;
|
|
335
|
-
/**
|
|
336
|
-
* Applies `Column.matchModes`, and refuses to half-apply it. Both ways a declaration can
|
|
337
|
-
* be wrong are consumer mistakes that PrimeNG would otherwise turn into a broken filter
|
|
338
|
-
* rather than an error: it reads `matchModeOptions || <type defaults>`, so handing it
|
|
339
|
-
* `[]` renders an EMPTY dropdown (an empty array is truthy) while the default mode still
|
|
340
|
-
* seeds the constraint, and handing it `null` silently restores PrimeNG's own list. So an
|
|
341
|
-
* unusable narrowing falls back to the full list and says so, instead of shipping a
|
|
342
|
-
* dropdown the user cannot pick from.
|
|
343
|
-
*/
|
|
344
|
-
private computeMatchModes;
|
|
345
|
-
private matchModeOptionsForType;
|
|
346
|
-
private defaultMatchModeForType;
|
|
347
|
-
isDropOrMulti(filterType: string): boolean;
|
|
348
|
-
/**
|
|
349
|
-
* Whether the filter type applies on every value change, which hides the menu's Apply
|
|
350
|
-
* button — an Apply there would promise a pending state that cannot exist. Boolean
|
|
351
|
-
* auto-applies through PrimeNG's own `onModelChange`; date and dropdown/multiselect
|
|
352
|
-
* through the filter templates THIS component projects, which call `filterCallback`
|
|
353
|
-
* directly (PrimeNG's built-in element, and with it its `onModelChange`, is only
|
|
354
|
-
* rendered when no template is projected — so the date path is ours, not PrimeNG's).
|
|
355
|
-
* With showApplyButton off, PrimeNG also auto-applies match-mode, operator and
|
|
356
|
-
* constraint-removal changes, so the whole menu stays consistent. Typed input
|
|
357
|
-
* (text/numeric) is deliberately NOT here — it commits on Enter/Apply, since applying
|
|
358
|
-
* per keystroke would fire a lazy load per key. Listing the auto types (not the typed
|
|
359
|
-
* ones) is the safe polarity: an unlisted future type keeps its Apply button rather
|
|
360
|
-
* than silently losing its commit.
|
|
361
|
-
*
|
|
362
|
-
* Known gap this does not close, and it predates the flag: the projected date template
|
|
363
|
-
* binds `[ngModel]` one-way and commits on `(onSelect)`, which the datepicker raises for
|
|
364
|
-
* a calendar pick but not for `onUserInput` — so a date TYPED into the field never
|
|
365
|
-
* reaches the constraint at all, with or without an Apply button.
|
|
366
|
-
*/
|
|
367
|
-
filterAppliesOnChange(filterType: string): boolean;
|
|
368
550
|
navigateToDetails(rowId: number): void;
|
|
369
551
|
/**
|
|
370
552
|
* Handle row click event. Arbitration between "this click navigates the row" and "this click
|
|
@@ -384,6 +566,19 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
384
566
|
ngOnDestroy(): void;
|
|
385
567
|
get showSelectAllCheckbox(): boolean;
|
|
386
568
|
private resetSelection;
|
|
569
|
+
/**
|
|
570
|
+
* A COMMITTED filter re-queries; a draft does not. Re-fetching per keystroke would be the same
|
|
571
|
+
* lie the chip bar exists to prevent, only paid for in requests rather than in credibility.
|
|
572
|
+
*
|
|
573
|
+
* Back to page one first, and off FRESH metadata rather than `reload()`: that one replays the
|
|
574
|
+
* cached lazy-load event, whose `first` was copied when the event was built, so a filter applied
|
|
575
|
+
* from page 3 would keep asking the server to skip 50 rows a narrower result set does not have.
|
|
576
|
+
* The grid comes back empty for a value that is definitely in it.
|
|
577
|
+
*
|
|
578
|
+
* The first run is PrimeNG's: it fires the initial lazy load itself, and re-querying here would
|
|
579
|
+
* make every table load twice.
|
|
580
|
+
*/
|
|
581
|
+
private requeryOnAppliedFilters;
|
|
387
582
|
reload(): void;
|
|
388
583
|
showActions(): boolean;
|
|
389
584
|
getStyleForBodyColumn(col: Column<any>): string;
|
|
@@ -394,6 +589,11 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
394
589
|
colTrackByFn(index: any, item: any): any;
|
|
395
590
|
actionTrackByFn(index: any, item: Action): string;
|
|
396
591
|
exportListToExcel(): void;
|
|
592
|
+
/**
|
|
593
|
+
* Clears everything that narrows the grid. With a store supplied it has to reach BOTH — the
|
|
594
|
+
* store holds the constraints and PrimeNG holds the persisted state and sort — or the bar goes
|
|
595
|
+
* empty while a reload brings the old filters back.
|
|
596
|
+
*/
|
|
397
597
|
clear(table: Table): void;
|
|
398
598
|
setFakeIsAllSelected(): void;
|
|
399
599
|
selectAll(checked: boolean): void;
|
|
@@ -426,7 +626,7 @@ export declare class SpiderlyDataTableComponent implements OnInit, OnChanges, Af
|
|
|
426
626
|
rowUnselect(id: number): void;
|
|
427
627
|
getFormArrayControlByIndex(formControlName: string, index: number): SpiderlyFormControl;
|
|
428
628
|
static ɵfac: i0.ɵɵFactoryDeclaration<SpiderlyDataTableComponent, never>;
|
|
429
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SpiderlyDataTableComponent, "spiderly-data-table", never, { "tableTitle": { "alias": "tableTitle"; "required": false; }; "tableIcon": { "alias": "tableIcon"; "required": false; }; "items": { "alias": "items"; "required": false; }; "rows": { "alias": "rows"; "required": false; }; "rowsPerPageOptions": { "alias": "rowsPerPageOptions"; "required": false; }; "cols": { "alias": "cols"; "required": false; }; "showPaginator": { "alias": "showPaginator"; "required": false; }; "showCardWrapper": { "alias": "showCardWrapper"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "idField": { "alias": "idField"; "required": false; }; "getPaginatedListObservableMethod": { "alias": "getPaginatedListObservableMethod"; "required": false; }; "exportListToExcelObservableMethod": { "alias": "exportListToExcelObservableMethod"; "required": false; }; "deleteItemFromTableObservableMethod": { "alias": "deleteItemFromTableObservableMethod"; "required": false; }; "deleteListFromTableObservableMethod": { "alias": "deleteListFromTableObservableMethod"; "required": false; }; "newlySelectedItems": { "alias": "newlySelectedItems"; "required": false; }; "unselectedItems": { "alias": "unselectedItems"; "required": false; }; "selectionMode": { "alias": "selectionMode"; "required": false; }; "selectedLazyLoadObservableMethod": { "alias": "selectedLazyLoadObservableMethod"; "required": false; }; "additionalFilterIdLong": { "alias": "additionalFilterIdLong"; "required": false; }; "showAddButton": { "alias": "showAddButton"; "required": false; }; "showExportToExcelButton": { "alias": "showExportToExcelButton"; "required": false; }; "showReloadTableButton": { "alias": "showReloadTableButton"; "required": false; }; "getFormArrayItems": { "alias": "getFormArrayItems"; "required": false; }; "hasLazyLoad": { "alias": "hasLazyLoad"; "required": false; }; "stateKey": { "alias": "stateKey"; "required": false; }; "stateStorage": { "alias": "stateStorage"; "required": false; }; "defaultSortField": { "alias": "defaultSortField"; "required": false; }; "defaultSortOrder": { "alias": "defaultSortOrder"; "required": false; }; "getAlreadySelectedItemIds": { "alias": "getAlreadySelectedItemIds"; "required": false; }; "getAlreadySelectedItems": { "alias": "getAlreadySelectedItems"; "required": false; }; "getFormControl": { "alias": "getFormControl"; "required": false; }; "additionalIndexes": { "alias": "additionalIndexes"; "required": false; }; "navigateOnRowClick": { "alias": "navigateOnRowClick"; "required": false; }; "rowNavigationPath": { "alias": "rowNavigationPath"; "required": false; }; }, { "onTotalRecordsChange": "onTotalRecordsChange"; "onLazyLoad": "onLazyLoad"; "onIsAllSelectedChange": "onIsAllSelectedChange"; "onRowSelect": "onRowSelect"; "onRowUnselect": "onRowUnselect"; }, ["actionsTemplate", "cellTemplates"], never, true, never>;
|
|
629
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SpiderlyDataTableComponent, "spiderly-data-table", never, { "tableTitle": { "alias": "tableTitle"; "required": false; }; "tableIcon": { "alias": "tableIcon"; "required": false; }; "items": { "alias": "items"; "required": false; }; "rows": { "alias": "rows"; "required": false; }; "rowsPerPageOptions": { "alias": "rowsPerPageOptions"; "required": false; }; "cols": { "alias": "cols"; "required": false; }; "filters": { "alias": "filters"; "required": false; }; "views": { "alias": "views"; "required": false; }; "showPaginator": { "alias": "showPaginator"; "required": false; }; "showCardWrapper": { "alias": "showCardWrapper"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "idField": { "alias": "idField"; "required": false; }; "getPaginatedListObservableMethod": { "alias": "getPaginatedListObservableMethod"; "required": false; }; "exportListToExcelObservableMethod": { "alias": "exportListToExcelObservableMethod"; "required": false; }; "deleteItemFromTableObservableMethod": { "alias": "deleteItemFromTableObservableMethod"; "required": false; }; "deleteListFromTableObservableMethod": { "alias": "deleteListFromTableObservableMethod"; "required": false; }; "newlySelectedItems": { "alias": "newlySelectedItems"; "required": false; }; "unselectedItems": { "alias": "unselectedItems"; "required": false; }; "selectionMode": { "alias": "selectionMode"; "required": false; }; "selectedLazyLoadObservableMethod": { "alias": "selectedLazyLoadObservableMethod"; "required": false; }; "additionalFilterIdLong": { "alias": "additionalFilterIdLong"; "required": false; }; "showAddButton": { "alias": "showAddButton"; "required": false; }; "showExportToExcelButton": { "alias": "showExportToExcelButton"; "required": false; }; "showReloadTableButton": { "alias": "showReloadTableButton"; "required": false; }; "getFormArrayItems": { "alias": "getFormArrayItems"; "required": false; }; "hasLazyLoad": { "alias": "hasLazyLoad"; "required": false; }; "stateKey": { "alias": "stateKey"; "required": false; }; "stateStorage": { "alias": "stateStorage"; "required": false; }; "defaultSortField": { "alias": "defaultSortField"; "required": false; }; "defaultSortOrder": { "alias": "defaultSortOrder"; "required": false; }; "getAlreadySelectedItemIds": { "alias": "getAlreadySelectedItemIds"; "required": false; }; "getAlreadySelectedItems": { "alias": "getAlreadySelectedItems"; "required": false; }; "getFormControl": { "alias": "getFormControl"; "required": false; }; "additionalIndexes": { "alias": "additionalIndexes"; "required": false; }; "navigateOnRowClick": { "alias": "navigateOnRowClick"; "required": false; }; "rowNavigationPath": { "alias": "rowNavigationPath"; "required": false; }; }, { "onTotalRecordsChange": "onTotalRecordsChange"; "onLazyLoad": "onLazyLoad"; "onIsAllSelectedChange": "onIsAllSelectedChange"; "onRowSelect": "onRowSelect"; "onRowUnselect": "onRowUnselect"; }, ["actionsTemplate", "cellTemplates", "filterTemplates"], never, true, never>;
|
|
430
630
|
}
|
|
431
631
|
export declare class Action {
|
|
432
632
|
name?: string;
|
|
@@ -452,29 +652,60 @@ export declare class Action {
|
|
|
452
652
|
onClick?: (event: ActionClickEvent) => void;
|
|
453
653
|
});
|
|
454
654
|
}
|
|
655
|
+
/**
|
|
656
|
+
* A saved question. The bar lets an operator BUILD one; a view is the one they ask every morning,
|
|
657
|
+
* asked in a click — and without them the whole column-and-filter rework is a pile of knobs
|
|
658
|
+
* someone re-sets daily (CLAUDE.md -> "Operator-owned view", decision 10).
|
|
659
|
+
*
|
|
660
|
+
* Declared in consumer code, not stored per user: with a handful of operators and a handful of
|
|
661
|
+
* fixed daily jobs, shared built-in views cover the work, while personal saved views would drift
|
|
662
|
+
* into five variants of the same question. Personal LAYOUT choices still persist on top, per view.
|
|
663
|
+
*/
|
|
664
|
+
export interface TableView<TFilters = any> {
|
|
665
|
+
id: string;
|
|
666
|
+
label: string;
|
|
667
|
+
/**
|
|
668
|
+
* Sets the filters this view asks for. Receives the table's own store, so a consumer writes it
|
|
669
|
+
* with the store's typing. Called on a CLEARED store: a view is a state, not an addition.
|
|
670
|
+
*/
|
|
671
|
+
apply?: (filters: TFilters) => void;
|
|
672
|
+
/**
|
|
673
|
+
* A view whose `apply` is a function of NOW — "Danas primljene", "this week". Selecting it
|
|
674
|
+
* always re-runs `apply` instead of restoring what an earlier visit stored: under the normal
|
|
675
|
+
* stored-wins rule a relative-date view clicked yesterday would restore yesterday's date under
|
|
676
|
+
* a tab claiming "today". Layout (columns, widths, wrap) still persists per view as usual —
|
|
677
|
+
* transience is about the QUESTION, not the furniture.
|
|
678
|
+
*/
|
|
679
|
+
transient?: boolean;
|
|
680
|
+
}
|
|
455
681
|
export declare class Column<T = any> {
|
|
456
682
|
name?: string;
|
|
457
683
|
field?: string & keyof T;
|
|
458
|
-
|
|
684
|
+
/**
|
|
685
|
+
* The column's VALUE SHAPE: it sizes the column (`getColWidth`), picks the cell rendering
|
|
686
|
+
* (`getRowData`, the blob branch) and the numeric right-align. The name is a fossil of the
|
|
687
|
+
* header-filter era — filtering lives in the store handed to `[filters]` — kept because
|
|
688
|
+
* renaming it would be a 195-declaration migration for zero behavior.
|
|
689
|
+
*/
|
|
459
690
|
filterType?: 'text' | 'date' | 'multiselect' | 'boolean' | 'numeric' | 'blob';
|
|
460
|
-
filterPlaceholder?: string;
|
|
461
|
-
showMatchModes?: boolean;
|
|
462
691
|
/**
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
* match can never hit: `matchModes: [MatchModeCodes.GreaterThan, MatchModeCodes.LessThan]`.
|
|
692
|
+
* The id of the filter in the table's store that this column stands for, which is what the
|
|
693
|
+
* header menu's `Filter…` opens. A LINK, not a declaration: the filter exists in the store
|
|
694
|
+
* whether or not any column names it, and a column needs this only to offer the shortcut.
|
|
467
695
|
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
*
|
|
696
|
+
* Untyped against the store on purpose — a `Column<T>` knows its row type and nothing about
|
|
697
|
+
* which store it will be rendered beside, so the compile-time key check lives where the store
|
|
698
|
+
* is declared (`createFilterStore`), not here.
|
|
699
|
+
*/
|
|
700
|
+
filterId?: string;
|
|
701
|
+
/**
|
|
702
|
+
* @deprecated Dead since the header-filter deletion: NOTHING reads it. It survives on the type
|
|
703
|
+
* only so details-table cols emitted by an OLDER Spiderly.SourceGenerators (which wrote
|
|
704
|
+
* `showMatchModes: true`) still compile against this library during a mixed-version window —
|
|
705
|
+
* a consumer on published NuGet generators plus an npm-linked library build. Delete it once
|
|
706
|
+
* every consumer regenerates with a generator from this release or later.
|
|
475
707
|
*/
|
|
476
|
-
|
|
477
|
-
showAddButton?: boolean;
|
|
708
|
+
showMatchModes?: boolean;
|
|
478
709
|
dropdownOrMultiselectValues?: PrimengOption[];
|
|
479
710
|
actions?: Action[];
|
|
480
711
|
editable?: boolean;
|
|
@@ -493,9 +724,8 @@ export declare class Column<T = any> {
|
|
|
493
724
|
*/
|
|
494
725
|
lockVisible?: boolean;
|
|
495
726
|
/**
|
|
496
|
-
* CSS length fixing this column's width (e.g. `'8rem'`). Overrides the per-
|
|
497
|
-
* which is
|
|
498
|
-
* for a column of short values.
|
|
727
|
+
* CSS length fixing this column's width (e.g. `'8rem'`). Overrides the per-type default,
|
|
728
|
+
* which is generous for a column of short values.
|
|
499
729
|
*
|
|
500
730
|
* Declare a width on the columns that must stay NARROW and leave the flexible one undeclared:
|
|
501
731
|
* the table distributes its surplus in proportion to the declared widths, so a column carrying
|
|
@@ -512,15 +742,12 @@ export declare class Column<T = any> {
|
|
|
512
742
|
* Not applied to editable cells — those belong to their inline input.
|
|
513
743
|
*/
|
|
514
744
|
onCellClick?: (event: CellClickEvent) => void;
|
|
515
|
-
constructor({ name, field,
|
|
745
|
+
constructor({ name, field, filterType, filterId, showMatchModes, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, visible, lockVisible, width, onCellClick, }?: {
|
|
516
746
|
name?: string;
|
|
517
747
|
field?: string & keyof T;
|
|
518
|
-
filterField?: string & keyof T;
|
|
519
748
|
filterType?: 'text' | 'date' | 'multiselect' | 'boolean' | 'numeric' | 'blob';
|
|
520
|
-
|
|
749
|
+
filterId?: string;
|
|
521
750
|
showMatchModes?: boolean;
|
|
522
|
-
matchModes?: MatchModeCodes[];
|
|
523
|
-
showAddButton?: boolean;
|
|
524
751
|
dropdownOrMultiselectValues?: PrimengOption[];
|
|
525
752
|
actions?: Action[];
|
|
526
753
|
editable?: boolean;
|