@simple-table/angular 4.2.2 → 4.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { reflectComponentType, createComponent, EventEmitter, inject, ElementRef, ApplicationRef, EnvironmentInjector, Output, Input, Component, makeEnvironmentProviders } from '@angular/core';
2
+ import { reflectComponentType, createComponent, inject, TemplateRef, Input, Directive, ElementRef, EventEmitter, ApplicationRef, EnvironmentInjector, Injector, NgZone, ContentChildren, Output, ChangeDetectionStrategy, Component, NgModule, makeEnvironmentProviders } from '@angular/core';
3
3
  import { collectHeaderAccessors, asRows, SimpleTableVanilla, headersStructurallyEqual, rowsShallowUnchanged } from 'simple-table-core';
4
4
  export { PIVOT_ACCESSOR_PREFIX, PIVOT_BLANK_LABEL, PIVOT_IS_TOTAL_KEY, asRows, buildPivotAccessor, buildPivotRowTotalAccessor, pivotRows } from 'simple-table-core';
5
5
 
6
- const ST_RENDERER_GENERATION = Symbol.for("simple-table.rendererGeneration");
6
+ const ST_RENDERER_GENERATION$1 = Symbol.for("simple-table.rendererGeneration");
7
7
  /** Declared `@Input` / `input()` names for a component type (template + prop). */
8
8
  function declaredInputNames(component) {
9
9
  const mirror = reflectComponentType(component);
@@ -36,16 +36,17 @@ function applyComponentProps(componentRef, props) {
36
36
  }
37
37
  componentRef.changeDetectorRef.detectChanges();
38
38
  }
39
- function mountAngularComponent(component, props, appRef, injector, registry, host) {
39
+ function mountAngularComponent(component, props, options, host) {
40
40
  const el = host ?? document.createElement("div");
41
41
  const componentRef = createComponent(component, {
42
- environmentInjector: injector,
42
+ environmentInjector: options.envInjector,
43
+ elementInjector: options.elementInjector,
43
44
  hostElement: el,
44
45
  });
45
46
  applyComponentProps(componentRef, props);
46
- appRef.attachView(componentRef.hostView);
47
- registry?.register(el, () => {
48
- appRef.detachView(componentRef.hostView);
47
+ options.appRef.attachView(componentRef.hostView);
48
+ options.registry?.register(el, () => {
49
+ options.appRef.detachView(componentRef.hostView);
49
50
  componentRef.destroy();
50
51
  });
51
52
  return { host: el, componentRef };
@@ -63,14 +64,20 @@ function mountAngularComponent(component, props, appRef, injector, registry, hos
63
64
  * Pass an optional {@link MountRegistry} so core's `onRendererHostDiscard` can
64
65
  * destroy the ComponentRef (including any CDK Overlay / floating UI) when the
65
66
  * host is discarded. The table adapter always supplies a registry; the public
66
- * helper used for one-shot static slots (e.g. `tableEmptyStateRenderer`) may omit it.
67
- *
68
- * These are injected automatically when the consumer uses
69
- * `provideSimpleTable()` in their application providers.
67
+ * helper used for one-shot static slots may omit it. Pass `elementInjector` so
68
+ * dynamically created components see providers on ancestors of `<simple-table>`.
69
+ * `ApplicationRef` and `EnvironmentInjector` come from Angular's injector;
70
+ * `provideSimpleTable()` is optional.
70
71
  */
71
- function wrapAngularRenderer(component, appRef, injector, registry) {
72
+ function wrapAngularRenderer(component, appRef, injector, registry, elementInjector) {
73
+ const options = {
74
+ appRef,
75
+ envInjector: injector,
76
+ registry,
77
+ elementInjector,
78
+ };
72
79
  return (props) => {
73
- return mountAngularComponent(component, props, appRef, injector, registry).host;
80
+ return mountAngularComponent(component, props, options).host;
74
81
  };
75
82
  }
76
83
  /**
@@ -79,15 +86,16 @@ function wrapAngularRenderer(component, appRef, injector, registry) {
79
86
  * and wiping local state. Mirrors Vue's {@link wrapVueHeaderRenderer} /
80
87
  * React's wrapReactHeaderRenderer.
81
88
  */
82
- function wrapAngularHeaderRenderer(component, appRef, injector, registry) {
89
+ function wrapAngularHeaderRenderer(component, options) {
90
+ const registry = options.registry;
83
91
  let host = null;
84
92
  let componentRef = null;
85
93
  return (props) => {
86
- if (host && componentRef && registry.isRegistered(host)) {
94
+ if (host && componentRef && registry?.isRegistered(host)) {
87
95
  applyComponentProps(componentRef, props);
88
96
  return host;
89
97
  }
90
- const mounted = mountAngularComponent(component, props, appRef, injector, registry);
98
+ const mounted = mountAngularComponent(component, props, options);
91
99
  host = mounted.host;
92
100
  componentRef = mounted.componentRef;
93
101
  return host;
@@ -100,14 +108,18 @@ function wrapAngularHeaderRenderer(component, appRef, injector, registry) {
100
108
  * For `kind: "header"`, also reuses a single mount host so sort/filter
101
109
  * refreshes preserve Angular component state.
102
110
  */
103
- function wrapCachedAngularRenderer(component, appRef, injector, registry, accessor, kind) {
111
+ function wrapCachedAngularRenderer(component, options, accessor, kind) {
112
+ const registry = options.registry;
113
+ if (!registry) {
114
+ throw new Error("wrapCachedAngularRenderer requires a MountRegistry");
115
+ }
104
116
  const cache = kind === "cell" ? registry.cellRendererCache : registry.headerRendererCache;
105
117
  const existing = cache.get(accessor);
106
118
  if (existing) {
107
119
  if (kind === "cell" && existing.component !== component) {
108
120
  existing.component = component;
109
- const current = existing.wrapped[ST_RENDERER_GENERATION];
110
- existing.wrapped[ST_RENDERER_GENERATION] =
121
+ const current = existing.wrapped[ST_RENDERER_GENERATION$1];
122
+ existing.wrapped[ST_RENDERER_GENERATION$1] =
111
123
  (typeof current === "number" ? current : 0) + 1;
112
124
  }
113
125
  else {
@@ -127,7 +139,7 @@ function wrapCachedAngularRenderer(component, appRef, injector, registry, access
127
139
  applyComponentProps(componentRef, props);
128
140
  return host;
129
141
  }
130
- const mounted = mountAngularComponent(slot.component, props, appRef, injector, registry);
142
+ const mounted = mountAngularComponent(slot.component, props, options);
131
143
  host = mounted.host;
132
144
  componentRef = mounted.componentRef;
133
145
  return host;
@@ -137,10 +149,10 @@ function wrapCachedAngularRenderer(component, appRef, injector, registry, access
137
149
  return wrapped;
138
150
  }
139
151
  const wrapped = (props) => {
140
- return mountAngularComponent(slot.component, props, appRef, injector, registry).host;
152
+ return mountAngularComponent(slot.component, props, options).host;
141
153
  };
142
154
  slot.wrapped = wrapped;
143
- wrapped[ST_RENDERER_GENERATION] = 0;
155
+ wrapped[ST_RENDERER_GENERATION$1] = 0;
144
156
  cache.set(accessor, slot);
145
157
  return wrapped;
146
158
  }
@@ -148,21 +160,155 @@ function wrapCachedAngularRenderer(component, appRef, injector, registry, access
148
160
  * Column-editor row renderer: one host per `accessor` so popout list rebuilds
149
161
  * update in place instead of remounting Angular state (mirrors Vue/React).
150
162
  */
151
- function wrapAngularColumnEditorRowRenderer(component, appRef, injector, registry) {
163
+ function wrapAngularColumnEditorRowRenderer(component, options) {
164
+ const registry = options.registry;
152
165
  const mounts = new Map();
153
166
  return (props) => {
154
167
  const key = String(props.accessor);
155
168
  const existing = mounts.get(key);
156
- if (existing && registry.isRegistered(existing.host)) {
169
+ if (existing && registry?.isRegistered(existing.host)) {
157
170
  applyComponentProps(existing.componentRef, props);
158
171
  return existing.host;
159
172
  }
160
- const mounted = mountAngularComponent(component, props, appRef, injector, registry);
173
+ const mounted = mountAngularComponent(component, props, options);
161
174
  mounts.set(key, mounted);
162
175
  return mounted.host;
163
176
  };
164
177
  }
165
178
 
179
+ const ST_RENDERER_GENERATION = Symbol.for("simple-table.rendererGeneration");
180
+ function applyTemplateContext(view, next) {
181
+ const ctx = view.context;
182
+ for (const key of Object.keys(ctx)) {
183
+ if (!(key in next)) {
184
+ delete ctx[key];
185
+ }
186
+ }
187
+ Object.assign(ctx, next);
188
+ view.detectChanges();
189
+ }
190
+ function mountEmbeddedView(template, context, options) {
191
+ const host = document.createElement("div");
192
+ const view = (options.elementInjector
193
+ ? template.createEmbeddedView(context, options.elementInjector)
194
+ : template.createEmbeddedView(context));
195
+ view.detectChanges();
196
+ options.appRef.attachView(view);
197
+ for (const node of view.rootNodes) {
198
+ host.appendChild(node);
199
+ }
200
+ options.registry?.register(host, () => {
201
+ options.appRef.detachView(view);
202
+ view.destroy();
203
+ });
204
+ return { host, view };
205
+ }
206
+ /**
207
+ * Turns an `ng-template` into a core renderer: create the view, attach it so
208
+ * clicks and bindings work, and tear it down when the table discards the host.
209
+ */
210
+ function wrapAngularTemplate(template, options, mapContext) {
211
+ return (props) => {
212
+ return mountEmbeddedView(template, mapContext(props), options).host;
213
+ };
214
+ }
215
+ /**
216
+ * Stable wrapper per column accessor so rebuilds do not swap renderer identity.
217
+ * Header views update in place when the same template is still mounted.
218
+ */
219
+ function wrapCachedAngularTemplate(template, options, accessor, kind, mapContext) {
220
+ const registry = options.registry;
221
+ if (!registry) {
222
+ throw new Error("wrapCachedAngularTemplate requires a MountRegistry");
223
+ }
224
+ const cache = kind === "cell" ? registry.cellTemplateCache : registry.headerTemplateCache;
225
+ const existing = cache.get(accessor);
226
+ if (existing) {
227
+ if (kind === "cell" && existing.component !== template) {
228
+ existing.component = template;
229
+ const current = existing.wrapped[ST_RENDERER_GENERATION];
230
+ existing.wrapped[ST_RENDERER_GENERATION] =
231
+ (typeof current === "number" ? current : 0) + 1;
232
+ }
233
+ else {
234
+ existing.component = template;
235
+ }
236
+ return existing.wrapped;
237
+ }
238
+ const slot = {
239
+ component: template,
240
+ wrapped: null,
241
+ };
242
+ if (kind === "header") {
243
+ let host = null;
244
+ let view = null;
245
+ let mountedTemplate = null;
246
+ const wrapped = (props) => {
247
+ const ctx = mapContext(props);
248
+ if (host &&
249
+ view &&
250
+ registry.isRegistered(host) &&
251
+ mountedTemplate === slot.component) {
252
+ applyTemplateContext(view, ctx);
253
+ return host;
254
+ }
255
+ const mounted = mountEmbeddedView(slot.component, ctx, options);
256
+ host = mounted.host;
257
+ view = mounted.view;
258
+ mountedTemplate = slot.component;
259
+ return host;
260
+ };
261
+ slot.wrapped = wrapped;
262
+ cache.set(accessor, slot);
263
+ return wrapped;
264
+ }
265
+ const wrapped = (props) => {
266
+ return mountEmbeddedView(slot.component, mapContext(props), options).host;
267
+ };
268
+ slot.wrapped = wrapped;
269
+ wrapped[ST_RENDERER_GENERATION] = 0;
270
+ cache.set(accessor, slot);
271
+ return wrapped;
272
+ }
273
+ function cellTemplateContext(props) {
274
+ const record = props;
275
+ return {
276
+ $implicit: record.row,
277
+ ...record,
278
+ };
279
+ }
280
+ function headerTemplateContext(props) {
281
+ const record = props;
282
+ return {
283
+ $implicit: record.header,
284
+ ...record,
285
+ };
286
+ }
287
+ function footerTemplateContext(props) {
288
+ const record = props;
289
+ return {
290
+ $implicit: record.currentPage,
291
+ ...record,
292
+ };
293
+ }
294
+ function loadingTemplateContext(props) {
295
+ const record = props;
296
+ return {
297
+ $implicit: record.parentRow,
298
+ ...record,
299
+ };
300
+ }
301
+ function errorTemplateContext(props) {
302
+ const record = props;
303
+ return {
304
+ $implicit: record.error,
305
+ ...record,
306
+ };
307
+ }
308
+ function emptyTemplateContext(_props) {
309
+ return {};
310
+ }
311
+
166
312
  /** Resolve column definitions. */
167
313
  function resolveAngularColumns(config) {
168
314
  const headers = config.columns;
@@ -171,9 +317,46 @@ function resolveAngularColumns(config) {
171
317
  }
172
318
  return headers;
173
319
  }
174
- function buildVanillaConfig(config, registry, appRef, injector) {
320
+ function resolveTableEmptyState(value, wrap, registry) {
321
+ if (value === null) {
322
+ if (registry.tableEmptyStateMount) {
323
+ registry.disposeHost(registry.tableEmptyStateMount.host);
324
+ registry.tableEmptyStateMount = null;
325
+ }
326
+ return null;
327
+ }
328
+ if (value.ɵcmp) {
329
+ return () => {
330
+ const existing = registry.tableEmptyStateMount;
331
+ if (existing &&
332
+ existing.component === value &&
333
+ registry.isRegistered(existing.host)) {
334
+ return existing.host;
335
+ }
336
+ if (existing) {
337
+ registry.disposeHost(existing.host);
338
+ registry.tableEmptyStateMount = null;
339
+ }
340
+ const host = wrap(value)({});
341
+ registry.tableEmptyStateMount = { component: value, host };
342
+ return host;
343
+ };
344
+ }
345
+ if (registry.tableEmptyStateMount) {
346
+ registry.disposeHost(registry.tableEmptyStateMount.host);
347
+ registry.tableEmptyStateMount = null;
348
+ }
349
+ return value;
350
+ }
351
+ function buildVanillaConfig(config, registry, appRef, injector, elementInjector, slots) {
175
352
  const { columns: _columns, rows, footerRenderer, emptyStateRenderer, errorStateRenderer, loadingStateRenderer, tableEmptyStateRenderer, headerDropdown, columnEditorConfig, icons, rowButtons, onColumnOrderChange, onColumnWidthChange, onHeaderEdit, onColumnSelect, enableColumnEditor, enableColumnEditorInitOpen, enablePagination, onTableReady, hoverRowBackground, oddColumnBackground, oddEvenRowBackground, ...rest } = config;
176
- const wrap = (component) => wrapAngularRenderer(component, appRef, injector, registry);
353
+ const mountOptions = {
354
+ appRef,
355
+ envInjector: injector,
356
+ registry,
357
+ elementInjector,
358
+ };
359
+ const wrap = (component) => wrapAngularRenderer(component, appRef, injector, registry, elementInjector);
177
360
  function transformIcons(iconsConfig) {
178
361
  const result = {};
179
362
  for (const [key, value] of Object.entries(iconsConfig)) {
@@ -199,7 +382,7 @@ function buildVanillaConfig(config, registry, appRef, injector) {
199
382
  ...cfgRest,
200
383
  ...(rowRenderer
201
384
  ? {
202
- rowRenderer: wrapAngularColumnEditorRowRenderer(rowRenderer, appRef, injector, registry),
385
+ rowRenderer: wrapAngularColumnEditorRowRenderer(rowRenderer, mountOptions),
203
386
  }
204
387
  : {}),
205
388
  ...(customRenderer ? { customRenderer: wrap(customRenderer) } : {}),
@@ -209,17 +392,25 @@ function buildVanillaConfig(config, registry, appRef, injector) {
209
392
  const { cellRenderer, headerRenderer, children, nestedTable, ...headerRest } = header;
210
393
  const accessor = String(header.accessor);
211
394
  const transformed = { ...headerRest };
212
- if (cellRenderer) {
395
+ const cellTemplate = slots?.cellTemplates?.get(accessor);
396
+ if (cellTemplate) {
397
+ transformed.cellRenderer = wrapCachedAngularTemplate(cellTemplate, mountOptions, accessor, "cell", cellTemplateContext);
398
+ }
399
+ else if (cellRenderer) {
213
400
  if (cellRenderer.ɵcmp) {
214
- transformed.cellRenderer = wrapCachedAngularRenderer(cellRenderer, appRef, injector, registry, accessor, "cell");
401
+ transformed.cellRenderer = wrapCachedAngularRenderer(cellRenderer, mountOptions, accessor, "cell");
215
402
  }
216
403
  else {
217
404
  transformed.cellRenderer = cellRenderer;
218
405
  }
219
406
  }
220
- if (headerRenderer) {
407
+ const headerTemplate = slots?.headerTemplates?.get(accessor);
408
+ if (headerTemplate) {
409
+ transformed.headerRenderer = wrapCachedAngularTemplate(headerTemplate, mountOptions, accessor, "header", headerTemplateContext);
410
+ }
411
+ else if (headerRenderer) {
221
412
  if (headerRenderer.ɵcmp) {
222
- transformed.headerRenderer = wrapCachedAngularRenderer(headerRenderer, appRef, injector, registry, accessor, "header");
413
+ transformed.headerRenderer = wrapCachedAngularRenderer(headerRenderer, mountOptions, accessor, "header");
223
414
  }
224
415
  else {
225
416
  transformed.headerRenderer = headerRenderer;
@@ -229,7 +420,7 @@ function buildVanillaConfig(config, registry, appRef, injector) {
229
420
  transformed.children = children.map(transformHeader);
230
421
  if (nestedTable) {
231
422
  const nestedFull = { ...nestedTable, rows: [] };
232
- transformed.nestedTable = buildVanillaConfig(nestedFull, registry, appRef, injector);
423
+ transformed.nestedTable = buildVanillaConfig(nestedFull, registry, appRef, injector, elementInjector);
233
424
  }
234
425
  return transformed;
235
426
  }
@@ -266,7 +457,10 @@ function buildVanillaConfig(config, registry, appRef, injector) {
266
457
  if (onColumnSelect) {
267
458
  vanillaConfig.onColumnSelect = (header) => onColumnSelect(header);
268
459
  }
269
- if (footerRenderer !== undefined) {
460
+ if (slots?.footerTemplate) {
461
+ vanillaConfig.footerRenderer = wrapAngularTemplate(slots.footerTemplate, mountOptions, footerTemplateContext);
462
+ }
463
+ else if (footerRenderer !== undefined) {
270
464
  if (footerRenderer.ɵcmp) {
271
465
  vanillaConfig.footerRenderer = wrap(footerRenderer);
272
466
  }
@@ -282,7 +476,10 @@ function buildVanillaConfig(config, registry, appRef, injector) {
282
476
  vanillaConfig.emptyStateRenderer = emptyStateRenderer;
283
477
  }
284
478
  }
285
- if (errorStateRenderer !== undefined) {
479
+ if (slots?.errorTemplate) {
480
+ vanillaConfig.errorStateRenderer = wrapAngularTemplate(slots.errorTemplate, mountOptions, errorTemplateContext);
481
+ }
482
+ else if (errorStateRenderer !== undefined) {
286
483
  if (errorStateRenderer.ɵcmp) {
287
484
  vanillaConfig.errorStateRenderer = wrap(errorStateRenderer);
288
485
  }
@@ -290,7 +487,10 @@ function buildVanillaConfig(config, registry, appRef, injector) {
290
487
  vanillaConfig.errorStateRenderer = errorStateRenderer;
291
488
  }
292
489
  }
293
- if (loadingStateRenderer !== undefined) {
490
+ if (slots?.loadingTemplate) {
491
+ vanillaConfig.loadingStateRenderer = wrapAngularTemplate(slots.loadingTemplate, mountOptions, loadingTemplateContext);
492
+ }
493
+ else if (loadingStateRenderer !== undefined) {
294
494
  if (loadingStateRenderer.ɵcmp) {
295
495
  vanillaConfig.loadingStateRenderer = wrap(loadingStateRenderer);
296
496
  }
@@ -298,8 +498,12 @@ function buildVanillaConfig(config, registry, appRef, injector) {
298
498
  vanillaConfig.loadingStateRenderer = loadingStateRenderer;
299
499
  }
300
500
  }
301
- if (tableEmptyStateRenderer !== undefined) {
302
- vanillaConfig.tableEmptyStateRenderer = tableEmptyStateRenderer;
501
+ if (slots?.emptyTemplate) {
502
+ const renderEmpty = wrapAngularTemplate(slots.emptyTemplate, mountOptions, emptyTemplateContext);
503
+ vanillaConfig.tableEmptyStateRenderer = () => renderEmpty({});
504
+ }
505
+ else if (tableEmptyStateRenderer !== undefined) {
506
+ vanillaConfig.tableEmptyStateRenderer = resolveTableEmptyState(tableEmptyStateRenderer, wrap, registry);
303
507
  }
304
508
  if (headerDropdown !== undefined) {
305
509
  vanillaConfig.headerDropdown = wrap(headerDropdown);
@@ -327,6 +531,10 @@ class MountRegistry {
327
531
  this.nextId = 0;
328
532
  this.cellRendererCache = new Map();
329
533
  this.headerRendererCache = new Map();
534
+ this.cellTemplateCache = new Map();
535
+ this.headerTemplateCache = new Map();
536
+ /** One-shot `tableEmptyStateRenderer` component mount, reused across config rebuilds. */
537
+ this.tableEmptyStateMount = null;
330
538
  this.disposeHost = (host) => {
331
539
  if (typeof host.getAttribute !== "function")
332
540
  return;
@@ -364,19 +572,25 @@ class MountRegistry {
364
572
  clear() {
365
573
  this.cellRendererCache.clear();
366
574
  this.headerRendererCache.clear();
575
+ this.cellTemplateCache.clear();
576
+ this.headerTemplateCache.clear();
577
+ this.tableEmptyStateMount = null;
367
578
  for (const dispose of this.entries.values()) {
368
579
  dispose();
369
580
  }
370
581
  this.entries.clear();
371
582
  }
372
583
  pruneRendererCaches(liveAccessors) {
373
- for (const key of this.cellRendererCache.keys()) {
374
- if (!liveAccessors.has(key))
375
- this.cellRendererCache.delete(key);
376
- }
377
- for (const key of this.headerRendererCache.keys()) {
378
- if (!liveAccessors.has(key))
379
- this.headerRendererCache.delete(key);
584
+ for (const cache of [
585
+ this.cellRendererCache,
586
+ this.headerRendererCache,
587
+ this.cellTemplateCache,
588
+ this.headerTemplateCache,
589
+ ]) {
590
+ for (const key of cache.keys()) {
591
+ if (!liveAccessors.has(key))
592
+ cache.delete(key);
593
+ }
380
594
  }
381
595
  }
382
596
  get size() {
@@ -384,6 +598,150 @@ class MountRegistry {
384
598
  }
385
599
  }
386
600
 
601
+ /**
602
+ * Page-template cell for a column, matched by `accessor`.
603
+ * Context: `$implicit` is `row`; also `value`, `formattedValue`, and the rest of
604
+ * the core cell renderer props.
605
+ */
606
+ class StCellDirective {
607
+ constructor() {
608
+ this.templateRef = inject(TemplateRef);
609
+ }
610
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StCellDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
611
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StCellDirective, isStandalone: true, selector: "ng-template[stCell]", inputs: { stCell: "stCell" }, ngImport: i0 }); }
612
+ }
613
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StCellDirective, decorators: [{
614
+ type: Directive,
615
+ args: [{
616
+ selector: "ng-template[stCell]",
617
+ standalone: true,
618
+ }]
619
+ }], propDecorators: { stCell: [{
620
+ type: Input,
621
+ args: [{ required: true }]
622
+ }] } });
623
+ /**
624
+ * Page-template header for a column, matched by `accessor`.
625
+ * Context: `$implicit` is `header`; also `components` (sort/filter icons).
626
+ */
627
+ class StHeaderDirective {
628
+ constructor() {
629
+ this.templateRef = inject(TemplateRef);
630
+ }
631
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StHeaderDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
632
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StHeaderDirective, isStandalone: true, selector: "ng-template[stHeader]", inputs: { stHeader: "stHeader" }, ngImport: i0 }); }
633
+ }
634
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StHeaderDirective, decorators: [{
635
+ type: Directive,
636
+ args: [{
637
+ selector: "ng-template[stHeader]",
638
+ standalone: true,
639
+ }]
640
+ }], propDecorators: { stHeader: [{
641
+ type: Input,
642
+ args: [{ required: true }]
643
+ }] } });
644
+ /** Whole-table empty UI. Shown when there are no rows. */
645
+ class StEmptyDirective {
646
+ constructor() {
647
+ this.templateRef = inject(TemplateRef);
648
+ }
649
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StEmptyDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
650
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StEmptyDirective, isStandalone: true, selector: "ng-template[stEmpty]", ngImport: i0 }); }
651
+ }
652
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StEmptyDirective, decorators: [{
653
+ type: Directive,
654
+ args: [{
655
+ selector: "ng-template[stEmpty]",
656
+ standalone: true,
657
+ }]
658
+ }] });
659
+ /** Pagination / custom footer. Context matches core footer renderer props. */
660
+ class StFooterDirective {
661
+ constructor() {
662
+ this.templateRef = inject(TemplateRef);
663
+ }
664
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StFooterDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
665
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StFooterDirective, isStandalone: true, selector: "ng-template[stFooter]", ngImport: i0 }); }
666
+ }
667
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StFooterDirective, decorators: [{
668
+ type: Directive,
669
+ args: [{
670
+ selector: "ng-template[stFooter]",
671
+ standalone: true,
672
+ }]
673
+ }] });
674
+ /** Nested-group loading row (not the table-level skeleton `isLoading` flag). */
675
+ class StLoadingDirective {
676
+ constructor() {
677
+ this.templateRef = inject(TemplateRef);
678
+ }
679
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StLoadingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
680
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StLoadingDirective, isStandalone: true, selector: "ng-template[stLoading]", ngImport: i0 }); }
681
+ }
682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StLoadingDirective, decorators: [{
683
+ type: Directive,
684
+ args: [{
685
+ selector: "ng-template[stLoading]",
686
+ standalone: true,
687
+ }]
688
+ }] });
689
+ /** Nested-group error row. */
690
+ class StErrorDirective {
691
+ constructor() {
692
+ this.templateRef = inject(TemplateRef);
693
+ }
694
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StErrorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
695
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StErrorDirective, isStandalone: true, selector: "ng-template[stError]", ngImport: i0 }); }
696
+ }
697
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StErrorDirective, decorators: [{
698
+ type: Directive,
699
+ args: [{
700
+ selector: "ng-template[stError]",
701
+ standalone: true,
702
+ }]
703
+ }] });
704
+ /**
705
+ * Opt-in: put a core-built DOM node (sort icon, filter icon, …) into the host.
706
+ * Clones the node so the table can still own the original.
707
+ */
708
+ class StDomSlotDirective {
709
+ constructor() {
710
+ this.host = inject(ElementRef);
711
+ }
712
+ ngOnChanges() {
713
+ this.sync();
714
+ }
715
+ ngOnDestroy() {
716
+ this.host.nativeElement.replaceChildren();
717
+ }
718
+ sync() {
719
+ const el = this.host.nativeElement;
720
+ el.replaceChildren();
721
+ const slot = this.stDomSlot;
722
+ if (slot == null)
723
+ return;
724
+ if (typeof slot === "string") {
725
+ el.textContent = slot;
726
+ return;
727
+ }
728
+ if (slot instanceof Node) {
729
+ el.appendChild(slot.cloneNode(true));
730
+ }
731
+ }
732
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StDomSlotDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
733
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.27", type: StDomSlotDirective, isStandalone: true, selector: "[stDomSlot]", inputs: { stDomSlot: "stDomSlot" }, usesOnChanges: true, ngImport: i0 }); }
734
+ }
735
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: StDomSlotDirective, decorators: [{
736
+ type: Directive,
737
+ args: [{
738
+ selector: "[stDomSlot]",
739
+ standalone: true,
740
+ }]
741
+ }], propDecorators: { stDomSlot: [{
742
+ type: Input
743
+ }] } });
744
+
387
745
  /**
388
746
  * SimpleTable — Angular adapter for simple-table-core.
389
747
  *
@@ -393,18 +751,44 @@ class MountRegistry {
393
751
  * Prefer typed `rows` / `columns` (`AngularColumnDef<MyRow>`). For a typed
394
752
  * imperative handle, use `@ViewChild(SimpleTableComponent) table!: SimpleTableComponent<MyRow>`
395
753
  * or listen to `(tableReady)`.
754
+ *
755
+ * Page templates (`stCell`, `stEmpty`, …) and `(sortChange)`-style outputs are
756
+ * the native Angular API. Import `SimpleTableImports` on the page. `class` on
757
+ * this host styles the wrapper; `[className]` styles the inner grid root.
396
758
  */
397
759
  class SimpleTableComponent {
398
760
  constructor() {
399
761
  /** Emits the TableAPI once the table has mounted. */
400
762
  this.tableReady = new EventEmitter();
763
+ this.cellClick = new EventEmitter();
764
+ this.cellEdit = new EventEmitter();
765
+ this.sortChange = new EventEmitter();
766
+ this.filterChange = new EventEmitter();
767
+ this.rowSelectionChange = new EventEmitter();
768
+ this.rowGroupExpand = new EventEmitter();
769
+ this.columnOrderChange = new EventEmitter();
770
+ this.columnVisibilityChange = new EventEmitter();
771
+ this.columnWidthChange = new EventEmitter();
772
+ this.pageChange = new EventEmitter();
773
+ this.loadMore = new EventEmitter();
774
+ this.headerEdit = new EventEmitter();
775
+ this.columnSelect = new EventEmitter();
776
+ this.pivotChange = new EventEmitter();
401
777
  this.instance = null;
402
778
  this.registry = new MountRegistry();
779
+ this.syncedSlotsKey = "";
403
780
  this.wasLoading = false;
404
781
  this.didInitialAutoSize = false;
782
+ this.slotUnsub = [];
405
783
  this.hostEl = inject((ElementRef));
406
784
  this.appRef = inject(ApplicationRef);
407
785
  this.envInjector = inject(EnvironmentInjector);
786
+ this.elementInjector = inject(Injector);
787
+ this.ngZone = inject(NgZone);
788
+ }
789
+ // Run table event callbacks in Angular's zone so the page template updates.
790
+ inZone(work) {
791
+ return this.ngZone.run(work);
408
792
  }
409
793
  maybeRefitAutoSizeColumns(leftLoading) {
410
794
  if (!this.instance)
@@ -420,29 +804,71 @@ class SimpleTableComponent {
420
804
  this.instance.refitAutoSizeColumns?.();
421
805
  }
422
806
  }
423
- ngOnInit() {
807
+ collectSlots() {
808
+ const cellTemplates = new Map();
809
+ for (const slot of this.cellSlots ?? []) {
810
+ cellTemplates.set(slot.stCell, slot.templateRef);
811
+ }
812
+ const headerTemplates = new Map();
813
+ for (const slot of this.headerSlots ?? []) {
814
+ headerTemplates.set(slot.stHeader, slot.templateRef);
815
+ }
816
+ return {
817
+ cellTemplates,
818
+ headerTemplates,
819
+ emptyTemplate: this.emptySlots?.last?.templateRef,
820
+ footerTemplate: this.footerSlots?.last?.templateRef,
821
+ loadingTemplate: this.loadingSlots?.last?.templateRef,
822
+ errorTemplate: this.errorSlots?.last?.templateRef,
823
+ };
824
+ }
825
+ slotsFingerprint(slots) {
826
+ const cells = [...(slots.cellTemplates?.keys() ?? [])].sort().join(",");
827
+ const headers = [...(slots.headerTemplates?.keys() ?? [])].sort().join(",");
828
+ return [
829
+ `c:${cells}`,
830
+ `h:${headers}`,
831
+ `e:${slots.emptyTemplate ? 1 : 0}`,
832
+ `f:${slots.footerTemplate ? 1 : 0}`,
833
+ `l:${slots.loadingTemplate ? 1 : 0}`,
834
+ `r:${slots.errorTemplate ? 1 : 0}`,
835
+ ].join("|");
836
+ }
837
+ buildConfig() {
838
+ const props = this.getProps();
839
+ const slots = this.collectSlots();
840
+ return {
841
+ props,
842
+ slots,
843
+ slotsKey: this.slotsFingerprint(slots),
844
+ fullConfig: buildVanillaConfig(props, this.registry, this.appRef, this.envInjector, this.elementInjector, slots),
845
+ };
846
+ }
847
+ mountTable() {
424
848
  const container = this.hostEl.nativeElement.querySelector("div");
425
849
  if (!container)
426
850
  return;
427
- const props = this.getProps();
428
- this.instance = new SimpleTableVanilla(container, buildVanillaConfig(props, this.registry, this.appRef, this.envInjector));
851
+ const { props, slotsKey, fullConfig } = this.buildConfig();
852
+ this.instance = new SimpleTableVanilla(container, fullConfig);
429
853
  this.instance.mount();
430
854
  this.syncedDefaultHeaders = resolveAngularColumns(props);
431
855
  this.syncedRows = props.rows;
856
+ this.syncedSlotsKey = slotsKey;
432
857
  this.wasLoading = Boolean(props.isLoading);
433
858
  this.maybeRefitAutoSizeColumns(false);
434
859
  this.tableReady.emit(this.instance.getAPI());
435
860
  }
436
- ngOnChanges() {
861
+ applyConfig() {
437
862
  if (!this.instance)
438
863
  return;
439
- const props = this.getProps();
440
- const fullConfig = buildVanillaConfig(props, this.registry, this.appRef, this.envInjector);
864
+ const { props, slotsKey, fullConfig } = this.buildConfig();
441
865
  const patch = { ...fullConfig };
442
866
  const resolvedColumns = resolveAngularColumns(props);
443
867
  const headersUnchanged = headersStructurallyEqual(this.syncedDefaultHeaders, resolvedColumns);
444
868
  this.syncedDefaultHeaders = resolvedColumns;
445
- if (headersUnchanged) {
869
+ const slotsChanged = slotsKey !== this.syncedSlotsKey;
870
+ this.syncedSlotsKey = slotsKey;
871
+ if (headersUnchanged && !slotsChanged) {
446
872
  delete patch.columns;
447
873
  }
448
874
  const rowsUnchanged = rowsShallowUnchanged(this.syncedRows, props.rows, props.getRowId);
@@ -456,7 +882,27 @@ class SimpleTableComponent {
456
882
  this.instance.update(patch);
457
883
  this.maybeRefitAutoSizeColumns(leftLoading);
458
884
  }
885
+ ngAfterContentInit() {
886
+ this.mountTable();
887
+ const lists = [
888
+ this.cellSlots,
889
+ this.headerSlots,
890
+ this.emptySlots,
891
+ this.footerSlots,
892
+ this.loadingSlots,
893
+ this.errorSlots,
894
+ ];
895
+ for (const list of lists) {
896
+ this.slotUnsub.push(list.changes.subscribe(() => this.applyConfig()));
897
+ }
898
+ }
899
+ ngOnChanges() {
900
+ this.applyConfig();
901
+ }
459
902
  ngOnDestroy() {
903
+ for (const sub of this.slotUnsub)
904
+ sub.unsubscribe();
905
+ this.slotUnsub = [];
460
906
  this.instance?.destroy();
461
907
  this.instance = null;
462
908
  this.syncedDefaultHeaders = undefined;
@@ -487,38 +933,26 @@ class SimpleTableComponent {
487
933
  props.headerDropdown = this.headerDropdown;
488
934
  if (this.columnEditorConfig !== undefined)
489
935
  props.columnEditorConfig = this.columnEditorConfig;
490
- if (this.onCellClick !== undefined)
491
- props.onCellClick = this.onCellClick;
492
- if (this.onCellEdit !== undefined)
493
- props.onCellEdit = this.onCellEdit;
494
- if (this.onSortChange !== undefined)
495
- props.onSortChange = this.onSortChange;
496
- if (this.onFilterChange !== undefined)
497
- props.onFilterChange = this.onFilterChange;
498
- if (this.onRowSelectionChange !== undefined)
499
- props.onRowSelectionChange = this.onRowSelectionChange;
500
- if (this.onRowGroupExpand !== undefined)
501
- props.onRowGroupExpand = this.onRowGroupExpand;
502
- if (this.onColumnOrderChange !== undefined)
503
- props.onColumnOrderChange = this.onColumnOrderChange;
504
- if (this.onColumnVisibilityChange !== undefined)
505
- props.onColumnVisibilityChange = this.onColumnVisibilityChange;
506
- if (this.onColumnWidthChange !== undefined)
507
- props.onColumnWidthChange = this.onColumnWidthChange;
508
- if (this.onPageChange !== undefined)
509
- props.onPageChange = this.onPageChange;
510
- if (this.onLoadMore !== undefined)
511
- props.onLoadMore = this.onLoadMore;
936
+ if (this.onNextPage !== undefined)
937
+ props.onNextPage = this.onNextPage;
512
938
  if (this.onTableReady !== undefined)
513
939
  props.onTableReady = this.onTableReady;
514
940
  if (this.rowGrouping !== undefined)
515
941
  props.rowGrouping = this.rowGrouping;
942
+ if (this.canExpandRowGroup !== undefined)
943
+ props.canExpandRowGroup = this.canExpandRowGroup;
944
+ if (this.enableStickyParents !== undefined)
945
+ props.enableStickyParents = this.enableStickyParents;
516
946
  if (this.pivot !== undefined)
517
947
  props.pivot = this.pivot;
518
- if (this.onPivotChange !== undefined)
519
- props.onPivotChange = this.onPivotChange;
520
948
  if (this.enableRowSelection !== undefined)
521
949
  props.enableRowSelection = this.enableRowSelection;
950
+ if (this.rowSelectionMode !== undefined)
951
+ props.rowSelectionMode = this.rowSelectionMode;
952
+ if (this.selectRowOnClick !== undefined)
953
+ props.selectRowOnClick = this.selectRowOnClick;
954
+ if (this.showRowSelectionColumn !== undefined)
955
+ props.showRowSelectionColumn = this.showRowSelectionColumn;
522
956
  if (this.theme !== undefined)
523
957
  props.theme = this.theme;
524
958
  if (this.quickFilter !== undefined)
@@ -527,6 +961,8 @@ class SimpleTableComponent {
527
961
  props.isLoading = this.isLoading;
528
962
  if (this.getRowId !== undefined)
529
963
  props.getRowId = this.getRowId;
964
+ if (this.getRowClass !== undefined)
965
+ props.getRowClass = this.getRowClass;
530
966
  if (this.enablePagination !== undefined)
531
967
  props.enablePagination = this.enablePagination;
532
968
  if (this.rowsPerPage !== undefined)
@@ -559,8 +995,6 @@ class SimpleTableComponent {
559
995
  props.selectableColumns = this.selectableColumns;
560
996
  if (this.enableHeaderEditing !== undefined)
561
997
  props.enableHeaderEditing = this.enableHeaderEditing;
562
- if (this.onHeaderEdit !== undefined)
563
- props.onHeaderEdit = this.onHeaderEdit;
564
998
  if (this.customTheme !== undefined)
565
999
  props.customTheme = this.customTheme;
566
1000
  if (this.icons !== undefined)
@@ -575,8 +1009,18 @@ class SimpleTableComponent {
575
1009
  props.rowButtons = this.rowButtons;
576
1010
  if (this.hideFooter !== undefined)
577
1011
  props.hideFooter = this.hideFooter;
1012
+ if (this.hideHeader !== undefined)
1013
+ props.hideHeader = this.hideHeader;
1014
+ if (this.footerRenderKey !== undefined)
1015
+ props.footerRenderKey = this.footerRenderKey;
578
1016
  if (this.footerPosition !== undefined)
579
1017
  props.footerPosition = this.footerPosition;
1018
+ if (this.className !== undefined)
1019
+ props.className = this.className;
1020
+ if (this.copyHeadersToClipboard !== undefined)
1021
+ props.copyHeadersToClipboard = this.copyHeadersToClipboard;
1022
+ if (this.includeHeadersInCSVExport !== undefined)
1023
+ props.includeHeadersInCSVExport = this.includeHeadersInCSVExport;
580
1024
  if (this.initialSortColumn !== undefined)
581
1025
  props.initialSortColumn = this.initialSortColumn;
582
1026
  if (this.initialSortDirection !== undefined)
@@ -587,28 +1031,138 @@ class SimpleTableComponent {
587
1031
  props.autoExpandColumns = this.autoExpandColumns;
588
1032
  if (this.animations !== undefined)
589
1033
  props.animations = this.animations;
1034
+ if (this.cellUpdateFlash !== undefined)
1035
+ props.cellUpdateFlash = this.cellUpdateFlash;
590
1036
  if (this.enableVirtualization !== undefined)
591
1037
  props.enableVirtualization = this.enableVirtualization;
592
1038
  if (this.hoverRowBackground !== undefined)
593
1039
  props.hoverRowBackground = this.hoverRowBackground;
594
- if (this.hoverRowBackground !== undefined)
595
- props.hoverRowBackground = this.hoverRowBackground;
596
- if (this.oddColumnBackground !== undefined)
597
- props.oddColumnBackground = this.oddColumnBackground;
598
1040
  if (this.oddColumnBackground !== undefined)
599
1041
  props.oddColumnBackground = this.oddColumnBackground;
600
1042
  if (this.oddEvenRowBackground !== undefined)
601
1043
  props.oddEvenRowBackground = this.oddEvenRowBackground;
602
- if (this.oddEvenRowBackground !== undefined)
603
- props.oddEvenRowBackground = this.oddEvenRowBackground;
1044
+ if (this.onCellClick || this.cellClick.observed) {
1045
+ props.onCellClick = (event) => {
1046
+ this.inZone(() => {
1047
+ this.onCellClick?.(event);
1048
+ this.cellClick.emit(event);
1049
+ });
1050
+ };
1051
+ }
1052
+ if (this.onCellEdit || this.cellEdit.observed) {
1053
+ props.onCellEdit = (event) => {
1054
+ this.inZone(() => {
1055
+ this.onCellEdit?.(event);
1056
+ this.cellEdit.emit(event);
1057
+ });
1058
+ };
1059
+ }
1060
+ if (this.onSortChange || this.sortChange.observed) {
1061
+ props.onSortChange = (sort) => {
1062
+ this.inZone(() => {
1063
+ this.onSortChange?.(sort);
1064
+ this.sortChange.emit(sort);
1065
+ });
1066
+ };
1067
+ }
1068
+ if (this.onFilterChange || this.filterChange.observed) {
1069
+ props.onFilterChange = (filters) => {
1070
+ this.inZone(() => {
1071
+ this.onFilterChange?.(filters);
1072
+ this.filterChange.emit(filters);
1073
+ });
1074
+ };
1075
+ }
1076
+ if (this.onRowSelectionChange || this.rowSelectionChange.observed) {
1077
+ props.onRowSelectionChange = (event) => {
1078
+ this.inZone(() => {
1079
+ this.onRowSelectionChange?.(event);
1080
+ this.rowSelectionChange.emit(event);
1081
+ });
1082
+ };
1083
+ }
1084
+ if (this.onRowGroupExpand || this.rowGroupExpand.observed) {
1085
+ props.onRowGroupExpand = (event) => {
1086
+ return this.inZone(() => {
1087
+ const result = this.onRowGroupExpand?.(event);
1088
+ this.rowGroupExpand.emit(event);
1089
+ return result;
1090
+ });
1091
+ };
1092
+ }
1093
+ if (this.onColumnOrderChange || this.columnOrderChange.observed) {
1094
+ props.onColumnOrderChange = (headers) => {
1095
+ this.inZone(() => {
1096
+ this.onColumnOrderChange?.(headers);
1097
+ this.columnOrderChange.emit(headers);
1098
+ });
1099
+ };
1100
+ }
1101
+ if (this.onColumnVisibilityChange || this.columnVisibilityChange.observed) {
1102
+ props.onColumnVisibilityChange = (state) => {
1103
+ this.inZone(() => {
1104
+ this.onColumnVisibilityChange?.(state);
1105
+ this.columnVisibilityChange.emit(state);
1106
+ });
1107
+ };
1108
+ }
1109
+ if (this.onColumnWidthChange || this.columnWidthChange.observed) {
1110
+ props.onColumnWidthChange = (headers) => {
1111
+ this.inZone(() => {
1112
+ this.onColumnWidthChange?.(headers);
1113
+ this.columnWidthChange.emit(headers);
1114
+ });
1115
+ };
1116
+ }
1117
+ if (this.onPageChange || this.pageChange.observed) {
1118
+ props.onPageChange = (page) => {
1119
+ return this.inZone(() => {
1120
+ const result = this.onPageChange?.(page);
1121
+ this.pageChange.emit(page);
1122
+ return result;
1123
+ });
1124
+ };
1125
+ }
1126
+ if (this.onLoadMore || this.loadMore.observed) {
1127
+ props.onLoadMore = () => {
1128
+ this.inZone(() => {
1129
+ this.onLoadMore?.();
1130
+ this.loadMore.emit();
1131
+ });
1132
+ };
1133
+ }
1134
+ if (this.onHeaderEdit || this.headerEdit.observed) {
1135
+ props.onHeaderEdit = (header, newLabel) => {
1136
+ this.inZone(() => {
1137
+ this.onHeaderEdit?.(header, newLabel);
1138
+ this.headerEdit.emit({ header, newLabel });
1139
+ });
1140
+ };
1141
+ }
1142
+ if (this.onColumnSelect || this.columnSelect.observed) {
1143
+ props.onColumnSelect = (header) => {
1144
+ this.inZone(() => {
1145
+ this.onColumnSelect?.(header);
1146
+ this.columnSelect.emit(header);
1147
+ });
1148
+ };
1149
+ }
1150
+ if (this.onPivotChange || this.pivotChange.observed) {
1151
+ props.onPivotChange = (pivot) => {
1152
+ this.inZone(() => {
1153
+ this.onPivotChange?.(pivot);
1154
+ this.pivotChange.emit(pivot);
1155
+ });
1156
+ };
1157
+ }
604
1158
  return props;
605
1159
  }
606
1160
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: SimpleTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
607
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.27", type: SimpleTableComponent, isStandalone: true, selector: "simple-table", inputs: { rows: "rows", columns: "columns", footerRenderer: "footerRenderer", loadingStateRenderer: "loadingStateRenderer", errorStateRenderer: "errorStateRenderer", emptyStateRenderer: "emptyStateRenderer", tableEmptyStateRenderer: "tableEmptyStateRenderer", headerDropdown: "headerDropdown", columnEditorConfig: "columnEditorConfig", onCellClick: "onCellClick", onCellEdit: "onCellEdit", onSortChange: "onSortChange", onFilterChange: "onFilterChange", onRowSelectionChange: "onRowSelectionChange", onRowGroupExpand: "onRowGroupExpand", onColumnOrderChange: "onColumnOrderChange", onColumnVisibilityChange: "onColumnVisibilityChange", onColumnWidthChange: "onColumnWidthChange", onPageChange: "onPageChange", onLoadMore: "onLoadMore", onTableReady: "onTableReady", rowGrouping: "rowGrouping", pivot: "pivot", onPivotChange: "onPivotChange", enableRowSelection: "enableRowSelection", theme: "theme", quickFilter: "quickFilter", isLoading: "isLoading", getRowId: "getRowId", enablePagination: "enablePagination", rowsPerPage: "rowsPerPage", serverSidePagination: "serverSidePagination", totalRowCount: "totalRowCount", height: "height", maxHeight: "maxHeight", scrollParent: "scrollParent", infiniteScrollThreshold: "infiniteScrollThreshold", columnResizing: "columnResizing", columnReordering: "columnReordering", enableColumnEditor: "enableColumnEditor", enableColumnEditorInitOpen: "enableColumnEditorInitOpen", enablePivotPanel: "enablePivotPanel", selectableCells: "selectableCells", selectableColumns: "selectableColumns", enableHeaderEditing: "enableHeaderEditing", onHeaderEdit: "onHeaderEdit", customTheme: "customTheme", icons: "icons", externalFilterHandling: "externalFilterHandling", externalSortHandling: "externalSortHandling", columnBorders: "columnBorders", rowButtons: "rowButtons", hideFooter: "hideFooter", footerPosition: "footerPosition", initialSortColumn: "initialSortColumn", initialSortDirection: "initialSortDirection", expandAll: "expandAll", autoExpandColumns: "autoExpandColumns", animations: "animations", enableVirtualization: "enableVirtualization", hoverRowBackground: "hoverRowBackground", oddColumnBackground: "oddColumnBackground", oddEvenRowBackground: "oddEvenRowBackground" }, outputs: { tableReady: "tableReady" }, usesOnChanges: true, ngImport: i0, template: `<div #host></div>`, isInline: true, styles: [":host{display:block}\n"] }); }
1161
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.27", type: SimpleTableComponent, isStandalone: true, selector: "simple-table", inputs: { rows: "rows", columns: "columns", footerRenderer: "footerRenderer", loadingStateRenderer: "loadingStateRenderer", errorStateRenderer: "errorStateRenderer", emptyStateRenderer: "emptyStateRenderer", tableEmptyStateRenderer: "tableEmptyStateRenderer", headerDropdown: "headerDropdown", columnEditorConfig: "columnEditorConfig", onCellClick: "onCellClick", onCellEdit: "onCellEdit", onSortChange: "onSortChange", onFilterChange: "onFilterChange", onRowSelectionChange: "onRowSelectionChange", onRowGroupExpand: "onRowGroupExpand", onColumnOrderChange: "onColumnOrderChange", onColumnVisibilityChange: "onColumnVisibilityChange", onColumnWidthChange: "onColumnWidthChange", onPageChange: "onPageChange", onNextPage: "onNextPage", onLoadMore: "onLoadMore", onTableReady: "onTableReady", rowGrouping: "rowGrouping", canExpandRowGroup: "canExpandRowGroup", enableStickyParents: "enableStickyParents", pivot: "pivot", onPivotChange: "onPivotChange", enableRowSelection: "enableRowSelection", rowSelectionMode: "rowSelectionMode", selectRowOnClick: "selectRowOnClick", showRowSelectionColumn: "showRowSelectionColumn", theme: "theme", quickFilter: "quickFilter", isLoading: "isLoading", getRowId: "getRowId", getRowClass: "getRowClass", enablePagination: "enablePagination", rowsPerPage: "rowsPerPage", serverSidePagination: "serverSidePagination", totalRowCount: "totalRowCount", height: "height", maxHeight: "maxHeight", scrollParent: "scrollParent", infiniteScrollThreshold: "infiniteScrollThreshold", columnResizing: "columnResizing", columnReordering: "columnReordering", enableColumnEditor: "enableColumnEditor", enableColumnEditorInitOpen: "enableColumnEditorInitOpen", enablePivotPanel: "enablePivotPanel", selectableCells: "selectableCells", selectableColumns: "selectableColumns", enableHeaderEditing: "enableHeaderEditing", onHeaderEdit: "onHeaderEdit", onColumnSelect: "onColumnSelect", customTheme: "customTheme", icons: "icons", externalFilterHandling: "externalFilterHandling", externalSortHandling: "externalSortHandling", columnBorders: "columnBorders", rowButtons: "rowButtons", hideFooter: "hideFooter", hideHeader: "hideHeader", footerRenderKey: "footerRenderKey", footerPosition: "footerPosition", className: "className", copyHeadersToClipboard: "copyHeadersToClipboard", includeHeadersInCSVExport: "includeHeadersInCSVExport", initialSortColumn: "initialSortColumn", initialSortDirection: "initialSortDirection", expandAll: "expandAll", autoExpandColumns: "autoExpandColumns", animations: "animations", cellUpdateFlash: "cellUpdateFlash", enableVirtualization: "enableVirtualization", hoverRowBackground: "hoverRowBackground", oddColumnBackground: "oddColumnBackground", oddEvenRowBackground: "oddEvenRowBackground" }, outputs: { tableReady: "tableReady", cellClick: "cellClick", cellEdit: "cellEdit", sortChange: "sortChange", filterChange: "filterChange", rowSelectionChange: "rowSelectionChange", rowGroupExpand: "rowGroupExpand", columnOrderChange: "columnOrderChange", columnVisibilityChange: "columnVisibilityChange", columnWidthChange: "columnWidthChange", pageChange: "pageChange", loadMore: "loadMore", headerEdit: "headerEdit", columnSelect: "columnSelect", pivotChange: "pivotChange" }, queries: [{ propertyName: "cellSlots", predicate: StCellDirective }, { propertyName: "headerSlots", predicate: StHeaderDirective }, { propertyName: "emptySlots", predicate: StEmptyDirective }, { propertyName: "footerSlots", predicate: StFooterDirective }, { propertyName: "loadingSlots", predicate: StLoadingDirective }, { propertyName: "errorSlots", predicate: StErrorDirective }], usesOnChanges: true, ngImport: i0, template: `<div #host></div><ng-content />`, isInline: true, styles: [":host{display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
608
1162
  }
609
1163
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: SimpleTableComponent, decorators: [{
610
1164
  type: Component,
611
- args: [{ selector: "simple-table", standalone: true, template: `<div #host></div>`, styles: [":host{display:block}\n"] }]
1165
+ args: [{ selector: "simple-table", standalone: true, template: `<div #host></div><ng-content />`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}\n"] }]
612
1166
  }], propDecorators: { rows: [{
613
1167
  type: Input,
614
1168
  args: [{ required: true }]
@@ -648,18 +1202,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
648
1202
  type: Input
649
1203
  }], onPageChange: [{
650
1204
  type: Input
1205
+ }], onNextPage: [{
1206
+ type: Input
651
1207
  }], onLoadMore: [{
652
1208
  type: Input
653
1209
  }], onTableReady: [{
654
1210
  type: Input
655
1211
  }], rowGrouping: [{
656
1212
  type: Input
1213
+ }], canExpandRowGroup: [{
1214
+ type: Input
1215
+ }], enableStickyParents: [{
1216
+ type: Input
657
1217
  }], pivot: [{
658
1218
  type: Input
659
1219
  }], onPivotChange: [{
660
1220
  type: Input
661
1221
  }], enableRowSelection: [{
662
1222
  type: Input
1223
+ }], rowSelectionMode: [{
1224
+ type: Input
1225
+ }], selectRowOnClick: [{
1226
+ type: Input
1227
+ }], showRowSelectionColumn: [{
1228
+ type: Input
663
1229
  }], theme: [{
664
1230
  type: Input
665
1231
  }], quickFilter: [{
@@ -668,6 +1234,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
668
1234
  type: Input
669
1235
  }], getRowId: [{
670
1236
  type: Input
1237
+ }], getRowClass: [{
1238
+ type: Input
671
1239
  }], enablePagination: [{
672
1240
  type: Input
673
1241
  }], rowsPerPage: [{
@@ -702,6 +1270,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
702
1270
  type: Input
703
1271
  }], onHeaderEdit: [{
704
1272
  type: Input
1273
+ }], onColumnSelect: [{
1274
+ type: Input
705
1275
  }], customTheme: [{
706
1276
  type: Input
707
1277
  }], icons: [{
@@ -716,8 +1286,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
716
1286
  type: Input
717
1287
  }], hideFooter: [{
718
1288
  type: Input
1289
+ }], hideHeader: [{
1290
+ type: Input
1291
+ }], footerRenderKey: [{
1292
+ type: Input
719
1293
  }], footerPosition: [{
720
1294
  type: Input
1295
+ }], className: [{
1296
+ type: Input
1297
+ }], copyHeadersToClipboard: [{
1298
+ type: Input
1299
+ }], includeHeadersInCSVExport: [{
1300
+ type: Input
721
1301
  }], initialSortColumn: [{
722
1302
  type: Input
723
1303
  }], initialSortDirection: [{
@@ -728,6 +1308,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
728
1308
  type: Input
729
1309
  }], animations: [{
730
1310
  type: Input
1311
+ }], cellUpdateFlash: [{
1312
+ type: Input
731
1313
  }], enableVirtualization: [{
732
1314
  type: Input
733
1315
  }], hoverRowBackground: [{
@@ -738,36 +1320,116 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
738
1320
  type: Input
739
1321
  }], tableReady: [{
740
1322
  type: Output
1323
+ }], cellClick: [{
1324
+ type: Output
1325
+ }], cellEdit: [{
1326
+ type: Output
1327
+ }], sortChange: [{
1328
+ type: Output
1329
+ }], filterChange: [{
1330
+ type: Output
1331
+ }], rowSelectionChange: [{
1332
+ type: Output
1333
+ }], rowGroupExpand: [{
1334
+ type: Output
1335
+ }], columnOrderChange: [{
1336
+ type: Output
1337
+ }], columnVisibilityChange: [{
1338
+ type: Output
1339
+ }], columnWidthChange: [{
1340
+ type: Output
1341
+ }], pageChange: [{
1342
+ type: Output
1343
+ }], loadMore: [{
1344
+ type: Output
1345
+ }], headerEdit: [{
1346
+ type: Output
1347
+ }], columnSelect: [{
1348
+ type: Output
1349
+ }], pivotChange: [{
1350
+ type: Output
1351
+ }], cellSlots: [{
1352
+ type: ContentChildren,
1353
+ args: [StCellDirective]
1354
+ }], headerSlots: [{
1355
+ type: ContentChildren,
1356
+ args: [StHeaderDirective]
1357
+ }], emptySlots: [{
1358
+ type: ContentChildren,
1359
+ args: [StEmptyDirective]
1360
+ }], footerSlots: [{
1361
+ type: ContentChildren,
1362
+ args: [StFooterDirective]
1363
+ }], loadingSlots: [{
1364
+ type: ContentChildren,
1365
+ args: [StLoadingDirective]
1366
+ }], errorSlots: [{
1367
+ type: ContentChildren,
1368
+ args: [StErrorDirective]
741
1369
  }] } });
742
1370
 
1371
+ const ST_STANDALONE = [
1372
+ SimpleTableComponent,
1373
+ StCellDirective,
1374
+ StHeaderDirective,
1375
+ StEmptyDirective,
1376
+ StFooterDirective,
1377
+ StLoadingDirective,
1378
+ StErrorDirective,
1379
+ StDomSlotDirective,
1380
+ ];
1381
+ /**
1382
+ * One import for a page that uses `<simple-table>` plus `stCell` / `stEmpty` /
1383
+ * `(sortChange)` and the other template directives.
1384
+ *
1385
+ * ```ts
1386
+ * @Component({
1387
+ * standalone: true,
1388
+ * imports: [SimpleTableImports],
1389
+ * })
1390
+ * ```
1391
+ */
1392
+ class SimpleTableImports {
1393
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: SimpleTableImports, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1394
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.27", ngImport: i0, type: SimpleTableImports, imports: [SimpleTableComponent,
1395
+ StCellDirective,
1396
+ StHeaderDirective,
1397
+ StEmptyDirective,
1398
+ StFooterDirective,
1399
+ StLoadingDirective,
1400
+ StErrorDirective,
1401
+ StDomSlotDirective], exports: [SimpleTableComponent,
1402
+ StCellDirective,
1403
+ StHeaderDirective,
1404
+ StEmptyDirective,
1405
+ StFooterDirective,
1406
+ StLoadingDirective,
1407
+ StErrorDirective,
1408
+ StDomSlotDirective] }); }
1409
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: SimpleTableImports }); }
1410
+ }
1411
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: SimpleTableImports, decorators: [{
1412
+ type: NgModule,
1413
+ args: [{
1414
+ imports: [...ST_STANDALONE],
1415
+ exports: [...ST_STANDALONE],
1416
+ }]
1417
+ }] });
1418
+
743
1419
  /**
744
- * Call this in your application's `providers` array (or `bootstrapApplication`
745
- * providers) to register the dependencies that simple-table-angular's renderer
746
- * bridge needs — specifically `ApplicationRef` and `EnvironmentInjector`.
1420
+ * Optional. Angular already provides `ApplicationRef` and `EnvironmentInjector`.
1421
+ * The table does not require this in `bootstrapApplication` / `providers`.
747
1422
  *
748
- * These are already provided by Angular's platform by default, so in practice
749
- * this function is a no-op placeholder that serves as a clear signal to
750
- * consumers that the adapter has been correctly wired up. If future versions
751
- * need custom providers they will be added here without breaking the call site.
1423
+ * Kept so existing apps that call it keep compiling. Future versions may add
1424
+ * real providers here without changing the call site.
752
1425
  *
753
1426
  * @example
754
- * // main.ts
755
1427
  * bootstrapApplication(AppComponent, {
756
1428
  * providers: [provideSimpleTable()],
757
1429
  * });
758
- *
759
- * @example
760
- * // app.module.ts
761
- * @NgModule({ providers: [provideSimpleTable()] })
762
- * export class AppModule {}
763
1430
  */
764
1431
  function provideSimpleTable() {
765
- return makeEnvironmentProviders([
766
- // ApplicationRef and EnvironmentInjector are part of Angular's core platform
767
- // and are available without any additional registration.
768
- // This factory is intentionally empty — it exists for API symmetry with
769
- // other Angular ecosystem libraries and to allow non-breaking additions later.
770
- ]);
1432
+ return makeEnvironmentProviders([]);
771
1433
  }
772
1434
 
773
1435
  // Component
@@ -776,5 +1438,5 @@ function provideSimpleTable() {
776
1438
  * Generated bundle index. Do not edit.
777
1439
  */
778
1440
 
779
- export { SimpleTableComponent, provideSimpleTable, wrapAngularRenderer };
1441
+ export { SimpleTableComponent, SimpleTableImports, StCellDirective, StDomSlotDirective, StEmptyDirective, StErrorDirective, StFooterDirective, StHeaderDirective, StLoadingDirective, provideSimpleTable, wrapAngularRenderer };
780
1442
  //# sourceMappingURL=simple-table-angular.mjs.map