spiderly 19.9.3 → 19.9.5

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.
@@ -88,6 +88,12 @@ export declare class SpiderlyDataTableComponent implements OnInit, AfterViewInit
88
88
  /** Direction for `defaultSortField`: 1 ascending (default), -1 descending. */
89
89
  defaultSortOrder: 1 | -1;
90
90
  initialMultiSortMeta: SortMeta[] | null;
91
+ /** Columns currently rendered — `cols` minus the hidden ones. Actions columns always render. */
92
+ visibleCols: Column[];
93
+ /** Cached count of visible data columns, so template bindings don't re-derive it per CD cycle. */
94
+ private visibleDataColsCount;
95
+ /** Data columns offered in the column chooser (actions columns are excluded). */
96
+ chooserCols: Column[];
91
97
  resolvedStateKey: string | null;
92
98
  selectedItemIds: number[];
93
99
  getAlreadySelectedItemIds: (additionalIndexes?: any) => number[];
@@ -113,7 +119,66 @@ export declare class SpiderlyDataTableComponent implements OnInit, AfterViewInit
113
119
  ngAfterViewInit(): void;
114
120
  private setupRemovableSort;
115
121
  ngOnInit(): void;
116
- /** The declared default as PrimeNG sort meta, or null when none is declared. */
122
+ /**
123
+ * User visibility choices (field → visible), holding only fields the user explicitly
124
+ * toggled away from their declared default — so a page changing a column's declared
125
+ * default later flows through to every user who never touched that column.
126
+ */
127
+ private columnVisibilityOverrides;
128
+ /**
129
+ * Columns revealed by the load-time reconciliation. Kept apart from
130
+ * `columnVisibilityOverrides` so persisting a later unrelated toggle can't promote a
131
+ * transient safety reveal into a durable choice.
132
+ */
133
+ private revealedByConstraint;
134
+ /** A data column shows values for a `field`; anything else (the actions column) always renders. */
135
+ private static isDataColumn;
136
+ /**
137
+ * Storage slot for the visibility overrides. Deliberately ALWAYS localStorage, even when
138
+ * `stateStorage` is 'session': the column layout is a durable preference, while filters
139
+ * are a transient working set — different natural lifetimes.
140
+ */
141
+ private get columnsStateKey();
142
+ /** Actions columns always render; data columns follow reveal/override, then declared default. */
143
+ isColumnVisible(col: Column): boolean;
144
+ private refreshVisibleCols;
145
+ /**
146
+ * Locked columns can't be toggled; the last visible data column can't be hidden — the
147
+ * table must never collapse to just an actions column. Revealing is always allowed.
148
+ */
149
+ canToggleColumn(col: Column): boolean;
150
+ toggleColumn(col: Column, visible: boolean): void;
151
+ /** Restores every column to its declared default and forgets the stored override. */
152
+ resetColumnVisibility(): void;
153
+ /**
154
+ * A hidden column contributes nothing to filtering or sorting: the header is the only
155
+ * filter surface, so a kept constraint would restrict the data invisibly. Reloads (once)
156
+ * only when a constraint was actually cleared — plain hides don't need a server round-trip.
157
+ */
158
+ private clearHiddenColumnConstraints;
159
+ /** Whether filter metadata (single or array) carries a real constraint, not just an empty slot. */
160
+ private static isActiveFilterMeta;
161
+ private persistColumnVisibility;
162
+ private restoreColumnVisibility;
163
+ /** Parses a JSON entry from web storage; missing or corrupted entries read as null. */
164
+ private static readStoredJson;
165
+ /**
166
+ * PrimeNG's persisted table state (filters/sort/pagination), read directly from storage
167
+ * because we need it before PrimeNG's restoreState() runs on the first [value] change.
168
+ */
169
+ private persistedTableState;
170
+ /**
171
+ * Guards the "hidden contributes nothing" invariant against state this component didn't
172
+ * write (older blobs, hand-edited storage): a hidden column the persisted table state
173
+ * still filters or sorts by is revealed rather than constraining the data invisibly.
174
+ * In-memory only — once the constraint is gone, the user's stored choice reapplies.
175
+ */
176
+ private reconcileVisibilityWithPersistedConstraints;
177
+ /**
178
+ * The declared default as PrimeNG sort meta, or null when none is declared — or when its
179
+ * column is hidden ("hidden contributes nothing"): the table then falls back to the
180
+ * backend's implicit Id DESC, exactly as if no default were declared.
181
+ */
117
182
  private defaultMultiSortMeta;
118
183
  private persistedMultiSortMeta;
119
184
  private applyDefaultSortIfUnsorted;
@@ -195,6 +260,17 @@ export declare class Column<T = any> {
195
260
  showTime?: boolean;
196
261
  decimalPlaces?: number;
197
262
  sortable?: boolean;
263
+ /**
264
+ * Whether the column is initially rendered. Defaults to `true`. Declare `visible: false` for
265
+ * columns that should be available in the column chooser but hidden until the user reveals them.
266
+ */
267
+ visible?: boolean;
268
+ /**
269
+ * Pins the column: it always renders and shows in the chooser as checked and disabled.
270
+ * Use for the row's identifying column (e.g. a product's title) so the table can never
271
+ * lose its anchor.
272
+ */
273
+ lockVisible?: boolean;
198
274
  /**
199
275
  * Fired when this column's cell is clicked. Receives a {@link CellClickEvent} with the row id,
200
276
  * the column field, the full row, the raw and formatted cell value, the clicked `<td>` element
@@ -205,7 +281,7 @@ export declare class Column<T = any> {
205
281
  * Not applied to editable cells — those belong to their inline input.
206
282
  */
207
283
  onCellClick?: (event: CellClickEvent) => void;
208
- constructor({ name, field, filterField, filterType, filterPlaceholder, showMatchModes, showAddButton, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, onCellClick, }?: {
284
+ constructor({ name, field, filterField, filterType, filterPlaceholder, showMatchModes, showAddButton, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, visible, lockVisible, onCellClick, }?: {
209
285
  name?: string;
210
286
  field?: string & keyof T;
211
287
  filterField?: string & keyof T;
@@ -219,6 +295,8 @@ export declare class Column<T = any> {
219
295
  showTime?: boolean;
220
296
  decimalPlaces?: number;
221
297
  sortable?: boolean;
298
+ visible?: boolean;
299
+ lockVisible?: boolean;
222
300
  onCellClick?: (event: CellClickEvent) => void;
223
301
  });
224
302
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spiderly",
3
- "version": "19.9.3",
3
+ "version": "19.9.5",
4
4
  "author": "Filip Trivan",
5
5
  "license": "MIT",
6
6
  "description": "Spiderly Angular Library to use in combination with Spiderly.",
@@ -43,6 +43,32 @@
43
43
  text-decoration: underline;
44
44
  }
45
45
 
46
+ .column-chooser {
47
+ display: flex;
48
+ flex-direction: column;
49
+ gap: 8px;
50
+ }
51
+ .column-chooser-option {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 8px;
55
+ cursor: pointer;
56
+ }
57
+ .column-chooser-reset {
58
+ margin-top: 4px;
59
+ padding: 0;
60
+ border: none;
61
+ background: none;
62
+ color: var(--p-primary-color);
63
+ cursor: pointer;
64
+ align-self: flex-start;
65
+ font-size: 0.875rem;
66
+
67
+ &:hover {
68
+ text-decoration: underline;
69
+ }
70
+ }
71
+
46
72
  ::ng-deep {
47
73
  .p-datatable-thead {
48
74
  position: unset !important;