@tanstack/angular-table 9.0.0-alpha.6 → 9.0.0-alpha.8

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.
@@ -108,10 +108,10 @@ export class FlexRenderDirective {
108
108
  },
109
109
  };
110
110
  }
111
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: FlexRenderDirective, deps: [{ token: ViewContainerRef }, { token: TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
112
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: FlexRenderDirective, isStandalone: true, selector: "[flexRender]", inputs: { content: ["flexRender", "content"], props: ["flexRenderProps", "props"], injector: ["flexRenderInjector", "injector"] }, ngImport: i0 });
111
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FlexRenderDirective, deps: [{ token: ViewContainerRef }, { token: TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
112
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.5", type: FlexRenderDirective, isStandalone: true, selector: "[flexRender]", inputs: { content: ["flexRender", "content"], props: ["flexRenderProps", "props"], injector: ["flexRenderInjector", "injector"] }, ngImport: i0 });
113
113
  }
114
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: FlexRenderDirective, decorators: [{
114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FlexRenderDirective, decorators: [{
115
115
  type: Directive,
116
116
  args: [{
117
117
  selector: '[flexRender]',
@@ -235,10 +235,10 @@ class FlexRenderDirective {
235
235
  },
236
236
  };
237
237
  }
238
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: FlexRenderDirective, deps: [{ token: ViewContainerRef }, { token: TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
239
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.3", type: FlexRenderDirective, isStandalone: true, selector: "[flexRender]", inputs: { content: ["flexRender", "content"], props: ["flexRenderProps", "props"], injector: ["flexRenderInjector", "injector"] }, ngImport: i0 });
238
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FlexRenderDirective, deps: [{ token: ViewContainerRef }, { token: TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
239
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.0.5", type: FlexRenderDirective, isStandalone: true, selector: "[flexRender]", inputs: { content: ["flexRender", "content"], props: ["flexRenderProps", "props"], injector: ["flexRenderInjector", "injector"] }, ngImport: i0 });
240
240
  }
241
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.3", ngImport: i0, type: FlexRenderDirective, decorators: [{
241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FlexRenderDirective, decorators: [{
242
242
  type: Directive,
243
243
  args: [{
244
244
  selector: '[flexRender]',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/angular-table",
3
- "version": "9.0.0-alpha.6",
3
+ "version": "9.0.0-alpha.8",
4
4
  "description": "Headless UI for building powerful tables & datagrids for Angular.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  ],
44
44
  "dependencies": {
45
45
  "tslib": "^2.6.3",
46
- "@tanstack/table-core": "9.0.0-alpha.6"
46
+ "@tanstack/table-core": "9.0.0-alpha.8"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@analogjs/vite-plugin-angular": "^1.5.0",
@@ -1,95 +0,0 @@
1
- import { describe, test } from 'vitest'
2
- import {
3
- type ColumnDef,
4
- injectTable,
5
- getCoreRowModel,
6
- type Table,
7
- } from '../index'
8
- import { Component, input, isSignal, signal, untracked } from '@angular/core'
9
- import { TestBed } from '@angular/core/testing'
10
- import { setSignalInputs } from './test-utils'
11
-
12
- describe('injectTable', () => {
13
- test('should render with required signal inputs', () => {
14
- @Component({
15
- selector: 'app-fake',
16
- template: ``,
17
- standalone: true,
18
- })
19
- class FakeComponent {
20
- data = input.required<any[]>()
21
-
22
- table = injectTable(() => ({
23
- data: this.data(),
24
- columns: [],
25
- getCoreRowModel: getCoreRowModel(),
26
- }))
27
- }
28
-
29
- const fixture = TestBed.createComponent(FakeComponent)
30
- setSignalInputs(fixture.componentInstance, {
31
- data: [],
32
- })
33
-
34
- fixture.detectChanges()
35
- })
36
-
37
- describe('Proxy table', () => {
38
- type Data = { id: string; title: string }
39
- const data = signal<Data[]>([{ id: '1', title: 'Title' }])
40
- const columns: ColumnDef<Data>[] = [
41
- { id: 'id', header: 'Id', cell: context => context.getValue() },
42
- { id: 'title', header: 'Title', cell: context => context.getValue() },
43
- ]
44
- const table = injectTable(() => ({
45
- data: data(),
46
- columns: columns,
47
- getCoreRowModel: getCoreRowModel(),
48
- getRowId: row => row.id,
49
- }))
50
- const tablePropertyKeys = Object.keys(table())
51
-
52
- test('table must be a signal', () => {
53
- expect(isSignal(table)).toEqual(true)
54
- })
55
-
56
- test('supports "in" operator', () => {
57
- expect('getCoreRowModel' in table).toBe(true)
58
- expect('options' in table).toBe(true)
59
- expect('notFound' in table).toBe(false)
60
- })
61
-
62
- test('supports "Object.keys"', () => {
63
- const keys = Object.keys(table())
64
- expect(Object.keys(table)).toEqual(keys)
65
- })
66
-
67
- test.each(
68
- tablePropertyKeys.map(property => [
69
- property,
70
- testShouldBeComputedProperty(untracked(table), property),
71
- ])
72
- )('property (%s) is computed -> (%s)', (name, expected) => {
73
- const tableProperty = table[name as keyof typeof table]
74
- expect(isSignal(tableProperty)).toEqual(expected)
75
- })
76
- })
77
- })
78
-
79
- const testShouldBeComputedProperty = (
80
- table: Table<any>,
81
- propertyName: string
82
- ) => {
83
- if (propertyName.endsWith('Handler') || propertyName.endsWith('Model')) {
84
- return false
85
- }
86
-
87
- if (propertyName.startsWith('get')) {
88
- // Only properties with no arguments are computed
89
- const fn = table[propertyName as keyof Table<any>]
90
- // Cannot test if is lazy computed since we return the unwrapped value
91
- return fn instanceof Function && fn.length === 0
92
- }
93
-
94
- return false
95
- }
@@ -1,178 +0,0 @@
1
- import { Component, ViewChild, input, type TemplateRef } from '@angular/core'
2
- import { TestBed, type ComponentFixture } from '@angular/core/testing'
3
- import { createColumnHelper } from '@tanstack/table-core'
4
- import { skip } from 'node:test'
5
- import { describe, expect, test } from 'vitest'
6
- import {
7
- FlexRenderComponent,
8
- FlexRenderDirective,
9
- injectFlexRenderContext,
10
- } from '../flex-render'
11
- import { setFixtureSignalInput, setFixtureSignalInputs } from './test-utils'
12
-
13
- interface Data {
14
- id: string
15
- title: string
16
- description: string
17
- status: 'success' | 'failed' | 'pending'
18
- favorite?: boolean
19
- }
20
-
21
- describe('FlexRenderDirective', () => {
22
- const helper = createColumnHelper<Data>()
23
-
24
- test('should render primitives', async () => {
25
- const fixture = TestBed.createComponent(TestRenderComponent)
26
-
27
- // String
28
- setFixtureSignalInputs(fixture, {
29
- content: 'My value',
30
- context: {},
31
- })
32
- expectPrimitiveValueIs(fixture, 'My value')
33
-
34
- // Numbers
35
- setFixtureSignalInputs(fixture, {
36
- content: 0,
37
- context: {},
38
- })
39
- expectPrimitiveValueIs(fixture, '0')
40
-
41
- // Functions that returns primitives
42
- setFixtureSignalInputs(fixture, {
43
- content: () => 'My value 2',
44
- context: {},
45
- })
46
- expectPrimitiveValueIs(fixture, 'My value 2')
47
-
48
- // Null
49
- setFixtureSignalInputs(fixture, {
50
- content: () => null,
51
- context: {},
52
- })
53
- expectPrimitiveValueIs(fixture, '')
54
-
55
- // Undefined
56
- setFixtureSignalInputs(fixture, {
57
- content: () => undefined,
58
- context: {},
59
- })
60
- expectPrimitiveValueIs(fixture, '')
61
- })
62
-
63
- test('should render TemplateRef', () => {
64
- @Component({
65
- template: `
66
- <ng-template #template let-context>{{ context.property }}</ng-template>
67
- `,
68
- standalone: true,
69
- })
70
- class FakeTemplateRefComponent {
71
- @ViewChild('template', { static: true })
72
- templateRef!: TemplateRef<any>
73
- }
74
-
75
- const templateRef = TestBed.createComponent(FakeTemplateRefComponent)
76
- .componentInstance.templateRef
77
-
78
- const fixture = TestBed.createComponent(TestRenderComponent)
79
- setFixtureSignalInputs(fixture, {
80
- content: () => templateRef,
81
- context: {
82
- property: 'Property context value',
83
- },
84
- })
85
-
86
- expect(fixture.nativeElement.textContent).toEqual('Property context value')
87
-
88
- setFixtureSignalInput(fixture, 'context', { property: 'Updated value' })
89
- fixture.detectChanges()
90
-
91
- expect(fixture.nativeElement.textContent).toEqual('Updated value')
92
- })
93
-
94
- test('should render components', () => {
95
- @Component({
96
- template: `{{ context.property }}`,
97
- standalone: true,
98
- })
99
- class FakeComponent {
100
- context = injectFlexRenderContext<{ property: string }>()
101
- }
102
-
103
- const fixture = TestBed.createComponent(TestRenderComponent)
104
- setFixtureSignalInputs(fixture, {
105
- content: () => new FlexRenderComponent(FakeComponent),
106
- context: {
107
- property: 'Context value',
108
- },
109
- })
110
-
111
- expect(fixture.nativeElement.textContent).toEqual('Context value')
112
-
113
- setFixtureSignalInput(fixture, 'context', { property: 'Updated value' })
114
- fixture.detectChanges()
115
-
116
- expect(fixture.nativeElement.textContent).toEqual('Updated value')
117
- })
118
-
119
- // Skip for now, test framework (using ComponentRef.setInput) cannot recognize signal inputs
120
- // as component inputs
121
- skip('should render custom components', () => {
122
- @Component({
123
- template: `{{ row().property }}`,
124
- standalone: true,
125
- })
126
- class FakeComponent {
127
- row = input.required<{ property: string }>()
128
- }
129
-
130
- const fixture = TestBed.createComponent(TestRenderComponent)
131
- setFixtureSignalInputs(fixture, {
132
- content: () => FakeComponent,
133
- context: {
134
- row: {
135
- property: 'Row value',
136
- },
137
- },
138
- })
139
-
140
- expect(fixture.nativeElement.textContent).toEqual('Row value')
141
-
142
- setFixtureSignalInput(fixture, 'context', {
143
- row: { property: 'Updated value' },
144
- })
145
- fixture.detectChanges()
146
-
147
- expect(fixture.nativeElement.textContent).toEqual('Updated value')
148
- })
149
- })
150
-
151
- @Component({
152
- selector: 'app-test-render',
153
- template: `
154
- <ng-container *flexRender="content(); props: context(); let renderValue">
155
- <span [innerHTML]="renderValue"></span>
156
- </ng-container>
157
- `,
158
- standalone: true,
159
- imports: [FlexRenderDirective],
160
- })
161
- class TestRenderComponent {
162
- readonly content = input.required<FlexRenderDirectiveAllowedContent>()
163
-
164
- readonly context = input.required<Record<string, unknown>>()
165
- }
166
-
167
- type FlexRenderDirectiveAllowedContent = FlexRenderDirective<
168
- NonNullable<unknown>
169
- >['content']
170
-
171
- function expectPrimitiveValueIs(
172
- fixture: ComponentFixture<unknown>,
173
- value: unknown
174
- ) {
175
- const span = fixture.nativeElement.querySelector('span')
176
- expect(span).toBeDefined()
177
- expect(span.innerHTML).toEqual(value)
178
- }
@@ -1,124 +0,0 @@
1
- import { describe, expect, test } from 'vitest'
2
- import {
3
- ChangeDetectionStrategy,
4
- Component,
5
- type WritableSignal,
6
- computed,
7
- effect,
8
- input,
9
- signal,
10
- } from '@angular/core'
11
- import { TestBed } from '@angular/core/testing'
12
- import { lazyInit } from '../lazy-signal-initializer'
13
- import { flushQueue, setFixtureSignalInputs } from './test-utils'
14
-
15
- describe('lazyInit', () => {
16
- test('should init lazily in next tick when not accessing manually', async () => {
17
- const mockFn = vi.fn()
18
-
19
- TestBed.runInInjectionContext(() => {
20
- lazyInit(() => {
21
- mockFn()
22
- return {
23
- data: signal(true),
24
- }
25
- })
26
- })
27
-
28
- expect(mockFn).not.toHaveBeenCalled()
29
-
30
- await new Promise(setImmediate)
31
-
32
- expect(mockFn).toHaveBeenCalled()
33
- })
34
-
35
- test('should init eagerly accessing manually', async () => {
36
- const mockFn = vi.fn()
37
-
38
- TestBed.runInInjectionContext(() => {
39
- const lazySignal = lazyInit(() => {
40
- mockFn()
41
- return {
42
- data: signal(true),
43
- }
44
- })
45
-
46
- lazySignal.data()
47
- })
48
-
49
- expect(mockFn).toHaveBeenCalled()
50
- })
51
-
52
- test('should init lazily and only once', async () => {
53
- const initCallFn = vi.fn()
54
- const registerDataValue = vi.fn<[number]>()
55
-
56
- let value!: { data: WritableSignal<number> }
57
- const outerSignal = signal(0)
58
-
59
- TestBed.runInInjectionContext(() => {
60
- value = lazyInit(() => {
61
- initCallFn()
62
-
63
- void outerSignal()
64
-
65
- return { data: signal(0) }
66
- })
67
-
68
- effect(() => registerDataValue(value.data()))
69
- })
70
-
71
- value.data()
72
-
73
- await flushQueue()
74
-
75
- expect(outerSignal).toBeDefined()
76
-
77
- expect(initCallFn).toHaveBeenCalledTimes(1)
78
-
79
- outerSignal.set(1)
80
- await flushQueue()
81
- outerSignal.set(2)
82
- await flushQueue()
83
- value.data.set(4)
84
- await flushQueue()
85
-
86
- expect(initCallFn).toHaveBeenCalledTimes(1)
87
- expect(registerDataValue).toHaveBeenCalledTimes(2)
88
- })
89
-
90
- test('should support required signal input', async () => {
91
- @Component({
92
- standalone: true,
93
- template: `{{ call }} - {{ lazySignal.data() }}`,
94
- changeDetection: ChangeDetectionStrategy.OnPush,
95
- })
96
- class Test {
97
- readonly title = input.required<string>()
98
- call = 0
99
-
100
- lazySignal = lazyInit(() => {
101
- this.call++
102
- return {
103
- data: computed(() => this.title()),
104
- }
105
- })
106
- }
107
-
108
- const fixture = TestBed.createComponent(Test)
109
-
110
- setFixtureSignalInputs(fixture, { title: 'newValue' })
111
- expect(fixture.debugElement.nativeElement.textContent).toBe('0 - newValue')
112
- await flushQueue()
113
-
114
- setFixtureSignalInputs(fixture, { title: 'updatedValue' })
115
- expect(fixture.debugElement.nativeElement.textContent).toBe(
116
- '1 - updatedValue'
117
- )
118
-
119
- setFixtureSignalInputs(fixture, { title: 'newUpdatedValue' })
120
- expect(fixture.debugElement.nativeElement.textContent).toBe(
121
- '1 - newUpdatedValue'
122
- )
123
- })
124
- })
@@ -1,12 +0,0 @@
1
- import '@analogjs/vite-plugin-angular/setup-vitest'
2
-
3
- import {
4
- BrowserDynamicTestingModule,
5
- platformBrowserDynamicTesting,
6
- } from '@angular/platform-browser-dynamic/testing'
7
- import { getTestBed } from '@angular/core/testing'
8
-
9
- getTestBed().initTestEnvironment(
10
- BrowserDynamicTestingModule,
11
- platformBrowserDynamicTesting()
12
- )
@@ -1,62 +0,0 @@
1
- import type { InputSignal } from '@angular/core'
2
- import { SIGNAL, signalSetFn } from '@angular/core/primitives/signals'
3
- import type { ComponentFixture } from '@angular/core/testing'
4
-
5
- type ToSignalInputUpdatableMap<T> = {
6
- [K in keyof T as T[K] extends InputSignal<any>
7
- ? K
8
- : never]: T[K] extends InputSignal<infer Value> ? Value : never
9
- }
10
-
11
- /**
12
- * Set required signal input value to component fixture
13
- * @see https://github.com/angular/angular/issues/54013
14
- */
15
- export function setSignalInputs<T extends NonNullable<unknown>>(
16
- component: T,
17
- inputs: ToSignalInputUpdatableMap<T>
18
- ) {
19
- for (const inputKey in inputs) {
20
- if (componentHasSignalInputProperty(component, inputKey)) {
21
- signalSetFn(component[inputKey][SIGNAL], inputs[inputKey])
22
- }
23
- }
24
- }
25
-
26
- export function setFixtureSignalInputs<T extends NonNullable<unknown>>(
27
- componentFixture: ComponentFixture<T>,
28
- inputs: ToSignalInputUpdatableMap<T>,
29
- options: { detectChanges: boolean } = { detectChanges: true }
30
- ) {
31
- setSignalInputs(componentFixture.componentInstance, inputs)
32
- if (options.detectChanges) {
33
- componentFixture.detectChanges()
34
- }
35
- }
36
-
37
- export function setFixtureSignalInput<
38
- T extends NonNullable<unknown>,
39
- InputMaps extends ToSignalInputUpdatableMap<T>,
40
- InputName extends keyof InputMaps,
41
- >(
42
- componentFixture: ComponentFixture<T>,
43
- inputName: InputName,
44
- value: InputMaps[InputName]
45
- ) {
46
- setSignalInputs(componentFixture.componentInstance, {
47
- [inputName]: value,
48
- } as ToSignalInputUpdatableMap<T>)
49
- }
50
-
51
- function componentHasSignalInputProperty<TProperty extends string>(
52
- component: object,
53
- property: TProperty
54
- ): component is { [key in TProperty]: InputSignal<unknown> } {
55
- return (
56
- component.hasOwnProperty(property) && (component as any)[property][SIGNAL]
57
- )
58
- }
59
-
60
- export async function flushQueue() {
61
- await new Promise(setImmediate)
62
- }