@tanstack/angular-table 9.0.0-alpha.45 → 9.0.0-alpha.47
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/dist/fesm2022/tanstack-angular-table.mjs +85 -44
- package/dist/fesm2022/tanstack-angular-table.mjs.map +1 -1
- package/dist/types/tanstack-angular-table.d.ts +32 -48
- package/package.json +6 -6
- package/src/flex-render/flexRenderComponentFactory.ts +10 -0
- package/src/flex-render/view.ts +19 -0
- package/src/helpers/createTableHook.ts +24 -11
- package/src/helpers/table.ts +3 -5
- package/src/index.ts +2 -0
- package/src/injectTable.ts +30 -97
- package/src/reactivity.ts +11 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Type, ComponentMirror, OutputEmitterRef, InputSignal, Injector, createComponent, Binding, TemplateRef, InjectionToken, Signal
|
|
3
|
-
import { TableFeatures, RowData, CellData, Cell, Header, CellContext, HeaderContext,
|
|
2
|
+
import { Type, ComponentMirror, OutputEmitterRef, InputSignal, Injector, createComponent, Binding, TemplateRef, InjectionToken, Signal } from '@angular/core';
|
|
3
|
+
import { TableFeatures, RowData, CellData, Cell, Header, CellContext, HeaderContext, Table, TableOptions, Column, Row, IdentifiedColumnDef, AccessorFn, DeepKeys, DeepValue, AccessorFnColumnDef, AccessorKeyColumnDef, ColumnDef, DisplayColumnDef, GroupColumnDef } from '@tanstack/table-core';
|
|
4
4
|
export * from '@tanstack/table-core';
|
|
5
5
|
import { Atom, ReadonlyAtom, Store, ReadonlyStore } from '@tanstack/angular-store';
|
|
6
|
+
export { shallow } from '@tanstack/angular-store';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Simplified directive wrapper of `*flexRender`.
|
|
@@ -361,43 +362,7 @@ declare class FlexRenderDirective<TFeatures extends TableFeatures, TRowData exte
|
|
|
361
362
|
}
|
|
362
363
|
|
|
363
364
|
type SubscribeSource<TValue> = Atom<TValue> | ReadonlyAtom<TValue> | Store<TValue> | ReadonlyStore<TValue>;
|
|
364
|
-
|
|
365
|
-
* Store mode: pass `selector` (required) to project from full table state.
|
|
366
|
-
* Source mode: pass `source` (atom or store); omit `selector` for the whole value
|
|
367
|
-
* (identity), or pass `selector` to project. Split overloads match React `Subscribe`
|
|
368
|
-
* inference.
|
|
369
|
-
*/
|
|
370
|
-
interface AngularTableComputed<TFeatures extends TableFeatures> {
|
|
371
|
-
<TSourceValue>(props: {
|
|
372
|
-
source: SubscribeSource<TSourceValue>;
|
|
373
|
-
selector?: undefined;
|
|
374
|
-
equal?: ValueEqualityFn<TSourceValue>;
|
|
375
|
-
}): Signal<Readonly<TSourceValue>>;
|
|
376
|
-
<TSourceValue, TSubSelected>(props: {
|
|
377
|
-
source: SubscribeSource<TSourceValue>;
|
|
378
|
-
selector: (state: TSourceValue) => TSubSelected;
|
|
379
|
-
equal?: ValueEqualityFn<TSubSelected>;
|
|
380
|
-
}): Signal<Readonly<TSubSelected>>;
|
|
381
|
-
<TSubSelected>(props: {
|
|
382
|
-
selector: (state: TableState<TFeatures>) => TSubSelected;
|
|
383
|
-
equal?: ValueEqualityFn<TSubSelected>;
|
|
384
|
-
}): Signal<Readonly<TSubSelected>>;
|
|
385
|
-
}
|
|
386
|
-
type AngularTable<TFeatures extends TableFeatures, TData extends RowData, TSelected = TableState<TFeatures>> = Table<TFeatures, TData> & {
|
|
387
|
-
/**
|
|
388
|
-
* The selected state from the table store, based on the selector provided.
|
|
389
|
-
*/
|
|
390
|
-
readonly state: Signal<Readonly<TSelected>>;
|
|
391
|
-
/**
|
|
392
|
-
* A signal that returns the entire table instance. Will update on table/options change.
|
|
393
|
-
*/
|
|
394
|
-
readonly value: Signal<AngularTable<TFeatures, TData, TSelected>>;
|
|
395
|
-
/**
|
|
396
|
-
* Creates a computed that subscribe to changes in the table store with a custom selector.
|
|
397
|
-
* Default equality function is "shallow".
|
|
398
|
-
*/
|
|
399
|
-
computed: AngularTableComputed<TFeatures>;
|
|
400
|
-
};
|
|
365
|
+
type AngularTable<TFeatures extends TableFeatures, TData extends RowData> = Table<TFeatures, TData>;
|
|
401
366
|
/**
|
|
402
367
|
* Creates and returns an Angular-reactive table instance.
|
|
403
368
|
*
|
|
@@ -454,7 +419,7 @@ type AngularTable<TFeatures extends TableFeatures, TData extends RowData, TSelec
|
|
|
454
419
|
*
|
|
455
420
|
* @returns An Angular-reactive TanStack Table instance.
|
|
456
421
|
*/
|
|
457
|
-
declare function injectTable<TFeatures extends TableFeatures, TData extends RowData
|
|
422
|
+
declare function injectTable<TFeatures extends TableFeatures, TData extends RowData>(options: () => TableOptions<TFeatures, TData>): AngularTable<TFeatures, TData>;
|
|
458
423
|
|
|
459
424
|
/**
|
|
460
425
|
* DI context shape for a TanStack Table cell.
|
|
@@ -635,15 +600,15 @@ declare const TanStackTableToken: InjectionToken<Signal<any>>;
|
|
|
635
600
|
* }
|
|
636
601
|
* ```
|
|
637
602
|
*/
|
|
638
|
-
declare class TanStackTable<TFeatures extends TableFeatures, TData extends RowData
|
|
603
|
+
declare class TanStackTable<TFeatures extends TableFeatures, TData extends RowData> {
|
|
639
604
|
/**
|
|
640
605
|
* The current TanStack Table instance.
|
|
641
606
|
*
|
|
642
607
|
* Provided as a required signal input so DI consumers always read the latest value.
|
|
643
608
|
*/
|
|
644
|
-
readonly table: i0.InputSignal<AngularTable<TFeatures, TData
|
|
645
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<TanStackTable<any, any
|
|
646
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<TanStackTable<any, any
|
|
609
|
+
readonly table: i0.InputSignal<AngularTable<TFeatures, TData>>;
|
|
610
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TanStackTable<any, any>, never>;
|
|
611
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<TanStackTable<any, any>, "[tanStackTable]", ["table"], { "table": { "alias": "tanStackTable"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
647
612
|
}
|
|
648
613
|
/**
|
|
649
614
|
* Injects the current TanStack Table instance signal.
|
|
@@ -652,7 +617,7 @@ declare class TanStackTable<TFeatures extends TableFeatures, TData extends RowDa
|
|
|
652
617
|
* - there is a nearest `[tanStackTable]` directive in the DI tree, or
|
|
653
618
|
* - the caller is rendered via `*flexRender` with render props containing `table`
|
|
654
619
|
*/
|
|
655
|
-
declare function injectTableContext<TFeatures extends TableFeatures, TData extends RowData
|
|
620
|
+
declare function injectTableContext<TFeatures extends TableFeatures, TData extends RowData>(): Signal<AngularTable<TFeatures, TData>>;
|
|
656
621
|
|
|
657
622
|
type RenderableComponent = Type<any> | (<T extends NonNullable<unknown>>(props: T) => FlexRenderContent<T>);
|
|
658
623
|
/**
|
|
@@ -739,7 +704,7 @@ type AppColumnHelper<TFeatures extends TableFeatures, TData extends RowData, TCe
|
|
|
739
704
|
/**
|
|
740
705
|
* Extended table API returned by useAppTable with all App wrapper components
|
|
741
706
|
*/
|
|
742
|
-
type AppAngularTable<TFeatures extends TableFeatures, TData extends RowData,
|
|
707
|
+
type AppAngularTable<TFeatures extends TableFeatures, TData extends RowData, TTableComponents extends Record<string, RenderableComponent>, TCellComponents extends Record<string, RenderableComponent>, THeaderComponents extends Record<string, RenderableComponent>> = AngularTable<TFeatures, TData> & NoInfer<TTableComponents> & {
|
|
743
708
|
appCell: <TValue>(cell: Cell<TFeatures, TData, TValue>) => Cell<TFeatures, TData, TValue> & NoInfer<TCellComponents>;
|
|
744
709
|
appHeader: <TValue>(header: Header<TFeatures, TData, TValue>) => Header<TFeatures, TData, TValue> & NoInfer<THeaderComponents>;
|
|
745
710
|
appFooter: <TValue>(footer: Header<TFeatures, TData, TValue>) => Header<TFeatures, TData, TValue> & NoInfer<THeaderComponents>;
|
|
@@ -778,8 +743,27 @@ type CreateTableHookResult<TFeatures extends TableFeatures, TTableComponents ext
|
|
|
778
743
|
injectTableCellContext: <TValue extends CellData = CellData, TRowData extends RowData = RowData>() => Signal<Cell<TFeatures, TRowData, TValue>>;
|
|
779
744
|
injectFlexRenderHeaderContext: <TData extends RowData, TValue extends CellData>() => HeaderContext<TFeatures, TData, TValue>;
|
|
780
745
|
injectFlexRenderCellContext: <TData extends RowData, TValue extends CellData>() => CellContext<TFeatures, TData, TValue>;
|
|
781
|
-
injectAppTable: <TData extends RowData
|
|
746
|
+
injectAppTable: <TData extends RowData>(tableOptions: () => Omit<TableOptions<TFeatures, TData>, '_features' | '_rowModels'>) => AppAngularTable<TFeatures, TData, TTableComponents, TCellComponents, THeaderComponents>;
|
|
782
747
|
};
|
|
748
|
+
/**
|
|
749
|
+
* Creates app-scoped Angular table helpers with features, row models, and
|
|
750
|
+
* renderable component maps pre-bound.
|
|
751
|
+
*
|
|
752
|
+
* Use this when an app or design system wants typed `injectAppTable`,
|
|
753
|
+
* pre-bound column helpers, and typed table/cell/header context injection
|
|
754
|
+
* helpers without repeating the same feature and component generics.
|
|
755
|
+
*
|
|
756
|
+
* @example
|
|
757
|
+
* ```ts
|
|
758
|
+
* const { injectAppTable, createAppColumnHelper } = createTableHook({
|
|
759
|
+
* _features,
|
|
760
|
+
* _rowModels: {},
|
|
761
|
+
* tableComponents: {},
|
|
762
|
+
* cellComponents: {},
|
|
763
|
+
* headerComponents: {},
|
|
764
|
+
* })
|
|
765
|
+
* ```
|
|
766
|
+
*/
|
|
783
767
|
declare function createTableHook<TFeatures extends TableFeatures, const TTableComponents extends Record<string, RenderableComponent>, const TCellComponents extends Record<string, RenderableComponent>, const THeaderComponents extends Record<string, RenderableComponent>>({ tableComponents, cellComponents, headerComponents, ...defaultTableOptions }: CreateTableContextOptions<TFeatures, TTableComponents, TCellComponents, THeaderComponents>): CreateTableHookResult<TFeatures, TTableComponents, TCellComponents, THeaderComponents>;
|
|
784
768
|
|
|
785
769
|
/**
|
|
@@ -793,4 +777,4 @@ declare function createTableHook<TFeatures extends TableFeatures, const TTableCo
|
|
|
793
777
|
declare const FlexRender: readonly [typeof FlexRenderDirective, typeof FlexRenderCell];
|
|
794
778
|
|
|
795
779
|
export { FlexRender, FlexRenderCell, FlexRenderComponentInstance, FlexRenderComponentProps, FlexRenderDirective, TanStackTable, TanStackTableCell, TanStackTableCellToken, TanStackTableHeader, TanStackTableHeaderToken, TanStackTableToken, createTableHook, flexRenderComponent, injectFlexRenderContext, injectTable, injectTableCellContext, injectTableContext, injectTableHeaderContext };
|
|
796
|
-
export type { AngularTable,
|
|
780
|
+
export type { AngularTable, AppAngularTable, AppCellContext, AppColumnDefBase, AppColumnDefTemplate, AppColumnHelper, AppDisplayColumnDef, AppGroupColumnDef, AppHeaderContext, CreateTableContextOptions, CreateTableHookResult, FlexRenderComponent, FlexRenderContent, FlexRenderInputContent, RenderableComponent, SubscribeSource, TanStackTableCellContext, TanStackTableHeaderContext };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/angular-table",
|
|
3
|
-
"version": "9.0.0-alpha.
|
|
3
|
+
"version": "9.0.0-alpha.47",
|
|
4
4
|
"description": "Headless UI for building powerful tables & datagrids for Angular.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@tanstack/angular-store": "^0.11.0",
|
|
53
53
|
"tslib": "^2.8.1",
|
|
54
|
-
"@tanstack/table-core": "9.0.0-alpha.
|
|
54
|
+
"@tanstack/table-core": "9.0.0-alpha.47"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@analogjs/vite-plugin-angular": "^2.5.
|
|
58
|
-
"@analogjs/vitest-angular": "^2.5.
|
|
59
|
-
"@angular/core": "^21.2.
|
|
60
|
-
"@angular/platform-browser": "^21.2.
|
|
57
|
+
"@analogjs/vite-plugin-angular": "^2.5.1",
|
|
58
|
+
"@analogjs/vitest-angular": "^2.5.1",
|
|
59
|
+
"@angular/core": "^21.2.12",
|
|
60
|
+
"@angular/platform-browser": "^21.2.12",
|
|
61
61
|
"ng-packagr": "^21.2.3",
|
|
62
62
|
"typescript": "6.0.3"
|
|
63
63
|
},
|
|
@@ -11,6 +11,10 @@ import {
|
|
|
11
11
|
} from '@angular/core'
|
|
12
12
|
import { FlexRenderComponent } from './flexRenderComponent'
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Creates and manages Angular component instances used by flex-rendered table
|
|
16
|
+
* content.
|
|
17
|
+
*/
|
|
14
18
|
@Injectable()
|
|
15
19
|
export class FlexRenderComponentFactory {
|
|
16
20
|
readonly #viewContainerRef: ViewContainerRef
|
|
@@ -46,6 +50,12 @@ export class FlexRenderComponentFactory {
|
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Runtime wrapper around an Angular component rendered by `FlexRenderDirective`.
|
|
55
|
+
*
|
|
56
|
+
* It diffs inputs and outputs across table updates so component renderers can
|
|
57
|
+
* be reused instead of recreated on every cell/header render.
|
|
58
|
+
*/
|
|
49
59
|
export class FlexRenderComponentRef<T> {
|
|
50
60
|
readonly #keyValueDiffersFactory: KeyValueDiffers
|
|
51
61
|
#componentData: FlexRenderComponent<T>
|
package/src/flex-render/view.ts
CHANGED
|
@@ -15,6 +15,13 @@ export type FlexRenderTypedContent =
|
|
|
15
15
|
| { kind: 'templateRef'; content: TemplateRef<unknown> }
|
|
16
16
|
| { kind: 'component'; content: Type<unknown> }
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Normalizes arbitrary Angular flex-render content into the renderer's internal
|
|
20
|
+
* tagged representation.
|
|
21
|
+
*
|
|
22
|
+
* This lets the directive decide whether to reuse, update, or recreate an
|
|
23
|
+
* embedded view or component view.
|
|
24
|
+
*/
|
|
18
25
|
export function mapToFlexRenderTypedContent(
|
|
19
26
|
content: FlexRenderContent<any>,
|
|
20
27
|
): FlexRenderTypedContent {
|
|
@@ -80,6 +87,12 @@ export abstract class FlexRenderView<
|
|
|
80
87
|
abstract unmount(): void
|
|
81
88
|
}
|
|
82
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Tracks an Angular embedded template view rendered by `FlexRenderDirective`.
|
|
92
|
+
*
|
|
93
|
+
* Template views receive updated props through their proxied context and can be
|
|
94
|
+
* reused while the rendered content kind stays compatible.
|
|
95
|
+
*/
|
|
83
96
|
export class FlexRenderTemplateView extends FlexRenderView<
|
|
84
97
|
EmbeddedViewRef<unknown>,
|
|
85
98
|
Extract<FlexRenderTypedContent, { kind: 'primitive' | 'templateRef' }>
|
|
@@ -132,6 +145,12 @@ export class FlexRenderTemplateView extends FlexRenderView<
|
|
|
132
145
|
}
|
|
133
146
|
}
|
|
134
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Tracks an Angular component view rendered by `FlexRenderDirective`.
|
|
150
|
+
*
|
|
151
|
+
* Component views own input/output updates for `flexRenderComponent(...)`
|
|
152
|
+
* results and component classes rendered directly from column definitions.
|
|
153
|
+
*/
|
|
135
154
|
export class FlexRenderComponentView extends FlexRenderView<
|
|
136
155
|
FlexRenderComponentRef<unknown>,
|
|
137
156
|
Extract<FlexRenderTypedContent, { kind: 'component' | 'flexRenderComponent' }>
|
|
@@ -243,11 +243,10 @@ export type AppColumnHelper<
|
|
|
243
243
|
export type AppAngularTable<
|
|
244
244
|
TFeatures extends TableFeatures,
|
|
245
245
|
TData extends RowData,
|
|
246
|
-
TSelected,
|
|
247
246
|
TTableComponents extends Record<string, RenderableComponent>,
|
|
248
247
|
TCellComponents extends Record<string, RenderableComponent>,
|
|
249
248
|
THeaderComponents extends Record<string, RenderableComponent>,
|
|
250
|
-
> = AngularTable<TFeatures, TData
|
|
249
|
+
> = AngularTable<TFeatures, TData> &
|
|
251
250
|
NoInfer<TTableComponents> & {
|
|
252
251
|
appCell: <TValue>(
|
|
253
252
|
cell: Cell<TFeatures, TData, TValue>,
|
|
@@ -333,22 +332,39 @@ export type CreateTableHookResult<
|
|
|
333
332
|
TData extends RowData,
|
|
334
333
|
TValue extends CellData,
|
|
335
334
|
>() => CellContext<TFeatures, TData, TValue>
|
|
336
|
-
injectAppTable: <TData extends RowData
|
|
335
|
+
injectAppTable: <TData extends RowData>(
|
|
337
336
|
tableOptions: () => Omit<
|
|
338
337
|
TableOptions<TFeatures, TData>,
|
|
339
338
|
'_features' | '_rowModels'
|
|
340
339
|
>,
|
|
341
|
-
selector?: (state: TableState<TFeatures>) => TSelected,
|
|
342
340
|
) => AppAngularTable<
|
|
343
341
|
TFeatures,
|
|
344
342
|
TData,
|
|
345
|
-
TSelected,
|
|
346
343
|
TTableComponents,
|
|
347
344
|
TCellComponents,
|
|
348
345
|
THeaderComponents
|
|
349
346
|
>
|
|
350
347
|
}
|
|
351
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Creates app-scoped Angular table helpers with features, row models, and
|
|
351
|
+
* renderable component maps pre-bound.
|
|
352
|
+
*
|
|
353
|
+
* Use this when an app or design system wants typed `injectAppTable`,
|
|
354
|
+
* pre-bound column helpers, and typed table/cell/header context injection
|
|
355
|
+
* helpers without repeating the same feature and component generics.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```ts
|
|
359
|
+
* const { injectAppTable, createAppColumnHelper } = createTableHook({
|
|
360
|
+
* _features,
|
|
361
|
+
* _rowModels: {},
|
|
362
|
+
* tableComponents: {},
|
|
363
|
+
* cellComponents: {},
|
|
364
|
+
* headerComponents: {},
|
|
365
|
+
* })
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
352
368
|
export function createTableHook<
|
|
353
369
|
TFeatures extends TableFeatures,
|
|
354
370
|
const TTableComponents extends Record<string, RenderableComponent>,
|
|
@@ -412,11 +428,9 @@ export function createTableHook<
|
|
|
412
428
|
TableOptions<TFeatures, TData>,
|
|
413
429
|
'_features' | '_rowModels'
|
|
414
430
|
>,
|
|
415
|
-
selector?: (state: TableState<TFeatures>) => TSelected,
|
|
416
431
|
): AppAngularTable<
|
|
417
432
|
TFeatures,
|
|
418
433
|
TData,
|
|
419
|
-
TSelected,
|
|
420
434
|
TTableComponents,
|
|
421
435
|
TCellComponents,
|
|
422
436
|
THeaderComponents
|
|
@@ -445,8 +459,8 @@ export function createTableHook<
|
|
|
445
459
|
},
|
|
446
460
|
}
|
|
447
461
|
|
|
448
|
-
return injectTable<TFeatures, TData
|
|
449
|
-
|
|
462
|
+
return injectTable<TFeatures, TData>(() => {
|
|
463
|
+
return {
|
|
450
464
|
...defaultTableOptions,
|
|
451
465
|
...tableOptions(),
|
|
452
466
|
_features: {
|
|
@@ -454,8 +468,7 @@ export function createTableHook<
|
|
|
454
468
|
appTableFeatures,
|
|
455
469
|
},
|
|
456
470
|
} as TableOptions<TFeatures, TData>
|
|
457
|
-
|
|
458
|
-
}, selector) as AngularTable<any, any>
|
|
471
|
+
}) as AngularTable<any, any>
|
|
459
472
|
}
|
|
460
473
|
|
|
461
474
|
function createAppColumnHelper<TData extends RowData>(): AppColumnHelper<
|
package/src/helpers/table.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Directive, InjectionToken, inject, input } from '@angular/core'
|
|
2
|
-
import { RowData, TableFeatures
|
|
2
|
+
import { RowData, TableFeatures } from '@tanstack/table-core'
|
|
3
3
|
import { AngularTable } from '../injectTable'
|
|
4
4
|
import type { Signal } from '@angular/core'
|
|
5
5
|
|
|
@@ -59,14 +59,13 @@ export const TanStackTableToken = new InjectionToken<
|
|
|
59
59
|
export class TanStackTable<
|
|
60
60
|
TFeatures extends TableFeatures,
|
|
61
61
|
TData extends RowData,
|
|
62
|
-
TSelected extends {} = TableState<TFeatures>,
|
|
63
62
|
> {
|
|
64
63
|
/**
|
|
65
64
|
* The current TanStack Table instance.
|
|
66
65
|
*
|
|
67
66
|
* Provided as a required signal input so DI consumers always read the latest value.
|
|
68
67
|
*/
|
|
69
|
-
readonly table = input.required<AngularTable<TFeatures, TData
|
|
68
|
+
readonly table = input.required<AngularTable<TFeatures, TData>>({
|
|
70
69
|
alias: 'tanStackTable',
|
|
71
70
|
})
|
|
72
71
|
}
|
|
@@ -81,7 +80,6 @@ export class TanStackTable<
|
|
|
81
80
|
export function injectTableContext<
|
|
82
81
|
TFeatures extends TableFeatures,
|
|
83
82
|
TData extends RowData,
|
|
84
|
-
|
|
85
|
-
>(): Signal<AngularTable<TFeatures, TData, TSelected>> {
|
|
83
|
+
>(): Signal<AngularTable<TFeatures, TData>> {
|
|
86
84
|
return inject(TanStackTableToken)
|
|
87
85
|
}
|
package/src/index.ts
CHANGED
|
@@ -22,3 +22,5 @@ export * from './helpers/flexRenderCell'
|
|
|
22
22
|
* @see {@link FlexRenderDirective} and {@link FlexRenderCell} for more details on the directives included in this export.
|
|
23
23
|
*/
|
|
24
24
|
export const FlexRender = [FlexRenderDirective, FlexRenderCell] as const
|
|
25
|
+
|
|
26
|
+
export { shallow } from '@tanstack/angular-store'
|
package/src/injectTable.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Injector,
|
|
3
|
+
NgZone,
|
|
3
4
|
assertInInjectionContext,
|
|
4
|
-
computed,
|
|
5
5
|
effect,
|
|
6
6
|
inject,
|
|
7
7
|
untracked,
|
|
8
8
|
} from '@angular/core'
|
|
9
9
|
import { constructTable } from '@tanstack/table-core'
|
|
10
|
-
import { injectSelector, shallow } from '@tanstack/angular-store'
|
|
11
10
|
import { lazyInit } from './lazySignalInitializer'
|
|
12
11
|
import { angularReactivity } from './reactivity'
|
|
13
12
|
import type {
|
|
@@ -21,9 +20,7 @@ import type {
|
|
|
21
20
|
Table,
|
|
22
21
|
TableFeatures,
|
|
23
22
|
TableOptions,
|
|
24
|
-
TableState,
|
|
25
23
|
} from '@tanstack/table-core'
|
|
26
|
-
import type { Signal, ValueEqualityFn } from '@angular/core'
|
|
27
24
|
|
|
28
25
|
export type SubscribeSource<TValue> =
|
|
29
26
|
| Atom<TValue>
|
|
@@ -31,48 +28,10 @@ export type SubscribeSource<TValue> =
|
|
|
31
28
|
| Store<TValue>
|
|
32
29
|
| ReadonlyStore<TValue>
|
|
33
30
|
|
|
34
|
-
/**
|
|
35
|
-
* Store mode: pass `selector` (required) to project from full table state.
|
|
36
|
-
* Source mode: pass `source` (atom or store); omit `selector` for the whole value
|
|
37
|
-
* (identity), or pass `selector` to project. Split overloads match React `Subscribe`
|
|
38
|
-
* inference.
|
|
39
|
-
*/
|
|
40
|
-
export interface AngularTableComputed<TFeatures extends TableFeatures> {
|
|
41
|
-
<TSourceValue>(props: {
|
|
42
|
-
source: SubscribeSource<TSourceValue>
|
|
43
|
-
selector?: undefined
|
|
44
|
-
equal?: ValueEqualityFn<TSourceValue>
|
|
45
|
-
}): Signal<Readonly<TSourceValue>>
|
|
46
|
-
<TSourceValue, TSubSelected>(props: {
|
|
47
|
-
source: SubscribeSource<TSourceValue>
|
|
48
|
-
selector: (state: TSourceValue) => TSubSelected
|
|
49
|
-
equal?: ValueEqualityFn<TSubSelected>
|
|
50
|
-
}): Signal<Readonly<TSubSelected>>
|
|
51
|
-
<TSubSelected>(props: {
|
|
52
|
-
selector: (state: TableState<TFeatures>) => TSubSelected
|
|
53
|
-
equal?: ValueEqualityFn<TSubSelected>
|
|
54
|
-
}): Signal<Readonly<TSubSelected>>
|
|
55
|
-
}
|
|
56
|
-
|
|
57
31
|
export type AngularTable<
|
|
58
32
|
TFeatures extends TableFeatures,
|
|
59
33
|
TData extends RowData,
|
|
60
|
-
|
|
61
|
-
> = Table<TFeatures, TData> & {
|
|
62
|
-
/**
|
|
63
|
-
* The selected state from the table store, based on the selector provided.
|
|
64
|
-
*/
|
|
65
|
-
readonly state: Signal<Readonly<TSelected>>
|
|
66
|
-
/**
|
|
67
|
-
* A signal that returns the entire table instance. Will update on table/options change.
|
|
68
|
-
*/
|
|
69
|
-
readonly value: Signal<AngularTable<TFeatures, TData, TSelected>>
|
|
70
|
-
/**
|
|
71
|
-
* Creates a computed that subscribe to changes in the table store with a custom selector.
|
|
72
|
-
* Default equality function is "shallow".
|
|
73
|
-
*/
|
|
74
|
-
computed: AngularTableComputed<TFeatures>
|
|
75
|
-
}
|
|
34
|
+
> = Table<TFeatures, TData>
|
|
76
35
|
|
|
77
36
|
/**
|
|
78
37
|
* Creates and returns an Angular-reactive table instance.
|
|
@@ -133,68 +92,42 @@ export type AngularTable<
|
|
|
133
92
|
export function injectTable<
|
|
134
93
|
TFeatures extends TableFeatures,
|
|
135
94
|
TData extends RowData,
|
|
136
|
-
TSelected = TableState<TFeatures>,
|
|
137
95
|
>(
|
|
138
96
|
options: () => TableOptions<TFeatures, TData>,
|
|
139
|
-
|
|
140
|
-
): AngularTable<TFeatures, TData, TSelected> {
|
|
97
|
+
): AngularTable<TFeatures, TData> {
|
|
141
98
|
assertInInjectionContext(injectTable)
|
|
142
99
|
const injector = inject(Injector)
|
|
100
|
+
const ngZone = inject(NgZone)
|
|
143
101
|
|
|
144
|
-
return
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
let isMount = true
|
|
154
|
-
effect(
|
|
155
|
-
() => {
|
|
156
|
-
const newOptions = options()
|
|
157
|
-
if (isMount) {
|
|
158
|
-
isMount = false
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
untracked(() =>
|
|
162
|
-
table.setOptions((previous) => ({
|
|
163
|
-
...previous,
|
|
164
|
-
...newOptions,
|
|
165
|
-
})),
|
|
166
|
-
)
|
|
167
|
-
},
|
|
168
|
-
{ injector, debugName: 'tableOptionsUpdate' },
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
table.computed = function Subscribe(props: {
|
|
172
|
-
source?: SubscribeSource<unknown>
|
|
173
|
-
selector?: (state: unknown) => unknown
|
|
174
|
-
equal?: ValueEqualityFn<unknown>
|
|
175
|
-
}) {
|
|
176
|
-
const source = props.source ?? table.store
|
|
177
|
-
return injectSelector(source, props.selector as never, {
|
|
178
|
-
compare: props.equal ?? shallow,
|
|
179
|
-
injector,
|
|
102
|
+
return ngZone.runOutsideAngular(() =>
|
|
103
|
+
lazyInit(() => {
|
|
104
|
+
const table = constructTable({
|
|
105
|
+
...options(),
|
|
106
|
+
_features: {
|
|
107
|
+
coreReativityFeature: angularReactivity(injector),
|
|
108
|
+
...options()._features,
|
|
109
|
+
},
|
|
180
110
|
})
|
|
181
|
-
} as AngularTableComputed<TFeatures>
|
|
182
|
-
|
|
183
|
-
Object.defineProperty(table, 'state', {
|
|
184
|
-
value: computed(() => selector?.(table.store.get()) ?? table.store.get()),
|
|
185
|
-
})
|
|
186
111
|
|
|
187
|
-
|
|
188
|
-
|
|
112
|
+
let isMount = true
|
|
113
|
+
effect(
|
|
189
114
|
() => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
115
|
+
const newOptions = options()
|
|
116
|
+
if (isMount) {
|
|
117
|
+
isMount = false
|
|
118
|
+
return
|
|
119
|
+
}
|
|
120
|
+
untracked(() =>
|
|
121
|
+
table.setOptions((previous) => ({
|
|
122
|
+
...previous,
|
|
123
|
+
...newOptions,
|
|
124
|
+
})),
|
|
125
|
+
)
|
|
193
126
|
},
|
|
194
|
-
{
|
|
195
|
-
)
|
|
196
|
-
})
|
|
127
|
+
{ injector, debugName: 'tableOptionsUpdate' },
|
|
128
|
+
)
|
|
197
129
|
|
|
198
|
-
|
|
199
|
-
|
|
130
|
+
return table
|
|
131
|
+
}),
|
|
132
|
+
)
|
|
200
133
|
}
|
package/src/reactivity.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, signal, untracked } from '@angular/core'
|
|
1
|
+
import { NgZone, computed, signal, untracked } from '@angular/core'
|
|
2
2
|
import { toObservable } from '@angular/core/rxjs-interop'
|
|
3
3
|
import type { Atom, Observer, ReadonlyAtom } from '@tanstack/angular-store'
|
|
4
4
|
import type {
|
|
@@ -40,9 +40,19 @@ function signalToWritableAtom<T>(
|
|
|
40
40
|
})
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Creates the table-core reactivity bindings used by the Angular adapter.
|
|
45
|
+
*
|
|
46
|
+
* Readonly table atoms are backed by Angular `computed` signals and writable
|
|
47
|
+
* atoms by Angular `signal`. Subscriptions bridge through `toObservable` with
|
|
48
|
+
* the caller's injector so table APIs can be consumed from Angular `computed`
|
|
49
|
+
* and `effect` calls.
|
|
50
|
+
*/
|
|
43
51
|
export function angularReactivity(injector: Injector): TableReactivityBindings {
|
|
52
|
+
const ngZone = injector.get(NgZone)
|
|
44
53
|
return {
|
|
45
54
|
createOptionsStore: true,
|
|
55
|
+
schedule: (fn) => ngZone.runOutsideAngular(() => queueMicrotask(fn)),
|
|
46
56
|
createReadonlyAtom: <T>(fn: () => T, options?: TableAtomOptions<T>) => {
|
|
47
57
|
const signal = computed(() => fn(), {
|
|
48
58
|
equal: options?.compare,
|