@ngrdt/tabs 0.0.1

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.
@@ -0,0 +1,440 @@
1
+ import {
2
+ AfterContentInit,
3
+ ContentChildren,
4
+ Directive,
5
+ inject,
6
+ Input,
7
+ OnDestroy,
8
+ OnInit,
9
+ QueryList,
10
+ } from '@angular/core';
11
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
12
+ import {
13
+ canTransition$,
14
+ RDT_GUARDED_COMPONENT,
15
+ RdtContainerDirective,
16
+ } from '@ngrdt/core';
17
+ import { RdtShortcut, RdtShortcutService } from '@ngrdt/shortcuts';
18
+ import { firstValueFrom, Subscription, takeWhile } from 'rxjs';
19
+ import { RdtTabContainerComponent } from '../components/tab-container/rdt-tab-container.component';
20
+ import { RdtTabComponent } from '../components/tab/rdt-tab.component';
21
+ import { AutoRdtTabsShortcutStrategy } from '../strategies/auto-rdt-tabs-shortcut-strategy';
22
+ import { RdtTabsShortcutStrategy } from '../strategies/rdt-tabs-shortcut-strategy';
23
+
24
+ @Directive({
25
+ selector: '[rdtTabController]',
26
+ providers: [
27
+ {
28
+ provide: RDT_GUARDED_COMPONENT,
29
+ useExisting: RdtTabControllerDirective,
30
+ },
31
+ ],
32
+ })
33
+ export class RdtTabControllerDirective
34
+ extends RdtContainerDirective
35
+ implements OnInit, AfterContentInit, OnDestroy
36
+ {
37
+ private shortcutService = inject(RdtShortcutService);
38
+ private shortcutSub = new Subscription();
39
+
40
+ // String value lets you use the directive without param.
41
+ @Input()
42
+ set rdtTabController(value: RdtTabsShortcutStrategy | string | null) {
43
+ if (value && typeof value !== 'string') {
44
+ this._strategy = value;
45
+ this.updateShortcuts();
46
+ }
47
+ }
48
+
49
+ protected get tabContainers() {
50
+ return this.getChildrenRecursive().filter(
51
+ (ch) => ch instanceof RdtTabContainerComponent
52
+ ) as unknown as RdtTabContainerComponent[];
53
+ }
54
+ protected get tabs() {
55
+ return this.getChildrenRecursive().filter(
56
+ (ch) => ch instanceof RdtTabComponent
57
+ ) as unknown as RdtTabComponent[];
58
+ }
59
+
60
+ @ContentChildren(RdtTabControllerDirective, { descendants: true })
61
+ protected childControllers!: QueryList<RdtTabControllerDirective>;
62
+
63
+ get strategy() {
64
+ return this._strategy;
65
+ }
66
+ private _strategy: RdtTabsShortcutStrategy =
67
+ new AutoRdtTabsShortcutStrategy();
68
+
69
+ private _lastActiveTabContainer: {
70
+ timestamp: number | null;
71
+ container: RdtTabContainerComponent;
72
+ } | null = null;
73
+
74
+ private _contentWasInit = false;
75
+
76
+ get disabled() {
77
+ return this._disabled;
78
+ }
79
+ private _disabled = false;
80
+
81
+ get shortcuts() {
82
+ return this._shortcuts;
83
+ }
84
+ set shortcuts(value: RdtShortcut[]) {
85
+ const oldSet = new Set<string>(this._shortcuts.map((s) => s.hotkeysValue));
86
+ this._shortcuts = value;
87
+
88
+ if (
89
+ oldSet.size !== value.length ||
90
+ value.some((s) => !oldSet.has(s.hotkeysValue))
91
+ ) {
92
+ this.bindAll();
93
+ }
94
+ }
95
+ private _shortcuts: RdtShortcut[] = [];
96
+
97
+ get activeContainer() {
98
+ return this._lastActiveTabContainer?.container;
99
+ }
100
+
101
+ override ngOnInit() {
102
+ super.ngOnInit();
103
+ this.updateShortcuts();
104
+ }
105
+
106
+ ngAfterContentInit() {
107
+ this.setDefaultActive();
108
+ this.disableSelfWhenChildCtrlExists();
109
+ this._contentWasInit = true;
110
+ if (this.tabs.length > 0) {
111
+ this.onTabChanges();
112
+ }
113
+ if (this.tabContainers.length > 0) {
114
+ this.onTabContainerChanges();
115
+ }
116
+ }
117
+
118
+ override ngOnDestroy(): void {
119
+ super.ngOnDestroy();
120
+ this.unbindAll();
121
+ this._shortcuts.length = 0;
122
+ }
123
+
124
+ getTabContainerIndex(cont: RdtTabContainerComponent): number {
125
+ const level = this.getSameLevelContainers(cont);
126
+ return level.indexOf(cont);
127
+ }
128
+
129
+ /**
130
+ * Activates first parent container of current container
131
+ * that is not disabled and has any non disabled tabs.
132
+ */
133
+ goLevelUp(): boolean {
134
+ let cont = this.activeContainer;
135
+ while (cont) {
136
+ cont = cont.parentTab?.tabContainer;
137
+ if (cont && !cont.disabled && cont.hasNonDisabledTabs) {
138
+ this.activateTabContainer(cont);
139
+ return true;
140
+ }
141
+ }
142
+ return false;
143
+ }
144
+
145
+ /**
146
+ * Activates first container under current tab which
147
+ * is not disabled and has any non disabled tabs.
148
+ */
149
+ goLevelDown(): boolean {
150
+ const cont = this.activeContainer;
151
+ if (!cont || cont.disabled) {
152
+ return false;
153
+ }
154
+ let tab = cont.tabsList.find((t) => t.stateId === cont.value);
155
+ if (!tab || tab.disabled) {
156
+ tab = cont.tabsList.find((t) => !t.disabled);
157
+ }
158
+ if (!tab) {
159
+ return false;
160
+ }
161
+ const targetCont = tab.childContainers.find(
162
+ (c) => !c.disabled && c.hasNonDisabledTabs
163
+ );
164
+ if (targetCont) {
165
+ this.activateTabContainer(targetCont);
166
+ return true;
167
+ }
168
+ return false;
169
+ }
170
+
171
+ /**
172
+ * Activates next container on current level
173
+ * (under parent container of currently active container).
174
+ * Is cyclic.
175
+ */
176
+ goToNextContainer(): boolean {
177
+ return this.goToAdjacentContainer(1);
178
+ }
179
+
180
+ /**
181
+ * Activates previous container on current level
182
+ * (under parent container of currently active container).
183
+ * Is cyclic.
184
+ */
185
+ goToPrevContainer(): boolean {
186
+ return this.goToAdjacentContainer(-1);
187
+ }
188
+
189
+ /**
190
+ * Activates tab within active container at the index of argument.
191
+ */
192
+ goToTabWithIndex(index: number): boolean {
193
+ const cont = this.activeContainer;
194
+ if (!cont) {
195
+ return false;
196
+ }
197
+ const tab = cont.tabsList.get(index);
198
+ if (!tab) {
199
+ return false;
200
+ }
201
+ this.activateTab(tab);
202
+ return true;
203
+ }
204
+
205
+ /**
206
+ * Activates next tab within active container. Is cyclic.
207
+ */
208
+ goToNextTab(): boolean {
209
+ return this.goToAdjacentTab(1);
210
+ }
211
+
212
+ /**
213
+ * Activates previous tab within active container. Is cyclic.
214
+ */
215
+ goToPrevTab(): boolean {
216
+ return this.goToAdjacentTab(-1);
217
+ }
218
+
219
+ private goToAdjacentContainer(dir: -1 | 1) {
220
+ const cont = this.activeContainer;
221
+ if (!cont) {
222
+ return false;
223
+ }
224
+
225
+ const level = this.getSameLevelContainers(cont);
226
+ if (!level) {
227
+ return false;
228
+ }
229
+
230
+ const currentIndex = level.indexOf(cont);
231
+ if (currentIndex < 0) {
232
+ throw new Error('Current container is not within its own level?');
233
+ }
234
+ for (
235
+ let i = (currentIndex + dir + level.length) % level.length;
236
+ i !== currentIndex;
237
+ i = (i + dir + level.length) % level.length
238
+ ) {
239
+ const next = level[i];
240
+ if (!next.disabled && next.hasNonDisabledTabs) {
241
+ this.activateTabContainer(next);
242
+ return true;
243
+ }
244
+ }
245
+ return false;
246
+ }
247
+
248
+ private goToAdjacentTab(dir: -1 | 1) {
249
+ const cont = this.activeContainer;
250
+ if (!cont) {
251
+ return false;
252
+ }
253
+
254
+ const tabs = cont.tabsList.toArray();
255
+ const currentIndex = tabs.findIndex((tab) => tab.stateId === cont.value);
256
+ if (currentIndex < 0) {
257
+ throw new Error('Current tab is not found in its container?!');
258
+ }
259
+
260
+ for (
261
+ let i = (currentIndex + dir + tabs.length) % tabs.length;
262
+ i !== currentIndex;
263
+ i = (i + dir + tabs.length) % tabs.length
264
+ ) {
265
+ const next = tabs[i];
266
+ if (!next.disabled) {
267
+ this.activateTab(next);
268
+ return true;
269
+ }
270
+ }
271
+ return false;
272
+ }
273
+
274
+ private getSameLevelContainers(cont: RdtTabContainerComponent) {
275
+ if (cont.parentTab) {
276
+ return cont.parentTab.childContainers;
277
+ } else {
278
+ return this.tabContainers.filter((cont) => cont.isTopLevel);
279
+ }
280
+ }
281
+
282
+ getTabByValue(value: string) {
283
+ for (const container of this.tabContainers) {
284
+ const tab = container.tabsList.find((ch) => ch.stateId === value);
285
+ if (tab) {
286
+ return tab;
287
+ }
288
+ }
289
+ return null;
290
+ }
291
+
292
+ activateTabContainer(tabs: RdtTabContainerComponent, scrollIntoView = true) {
293
+ if (this._lastActiveTabContainer) {
294
+ this._lastActiveTabContainer.container.active = false;
295
+ }
296
+
297
+ tabs.active = true;
298
+ if (scrollIntoView) {
299
+ tabs.scrollIntoView();
300
+ }
301
+
302
+ this._lastActiveTabContainer = {
303
+ container: tabs,
304
+ timestamp: null,
305
+ };
306
+ }
307
+
308
+ activateTabContainerFromClick(
309
+ tabs: RdtTabContainerComponent,
310
+ timestamp: number
311
+ ) {
312
+ if (this._lastActiveTabContainer) {
313
+ if (
314
+ this._lastActiveTabContainer.timestamp !== null &&
315
+ this._lastActiveTabContainer.timestamp >= timestamp
316
+ ) {
317
+ return;
318
+ }
319
+
320
+ this._lastActiveTabContainer.container.active = false;
321
+ }
322
+
323
+ tabs.active = true;
324
+
325
+ this._lastActiveTabContainer = {
326
+ container: tabs,
327
+ timestamp,
328
+ };
329
+ }
330
+
331
+ async activateTab(tab: RdtTabComponent) {
332
+ if (!this.canActivateTab(tab)) {
333
+ console.warn('Trying to activate disabled tab.');
334
+ return;
335
+ }
336
+
337
+ const formsCheck = await this.canActivateTabForms(tab);
338
+ if (!formsCheck) {
339
+ console.warn(
340
+ 'Trying to activate tab while current tab has unsaved forms'
341
+ );
342
+ return;
343
+ }
344
+
345
+ let current: RdtTabComponent | null = tab;
346
+
347
+ do {
348
+ const container: RdtTabContainerComponent = current!.tabContainer;
349
+ container.value = current!.stateId;
350
+ current = container.parentTab;
351
+ } while (current !== null);
352
+ }
353
+
354
+ canActivateTab(tab: RdtTabComponent) {
355
+ let current: RdtTabComponent | null = tab;
356
+
357
+ do {
358
+ const container: RdtTabContainerComponent = current.tabContainer;
359
+ if (current.disabled || container.disabled) {
360
+ return false;
361
+ }
362
+ current = container.parentTab;
363
+ } while (current !== null);
364
+
365
+ return true;
366
+ }
367
+
368
+ async canActivateTabForms(tab: RdtTabComponent) {
369
+ const container = tab.tabContainer;
370
+ return firstValueFrom(
371
+ canTransition$(container.activeTab?.contDir, tab?.contDir)
372
+ );
373
+ }
374
+
375
+ onTabChanges() {
376
+ this.updateShortcuts();
377
+ }
378
+
379
+ onTabContainerChanges() {
380
+ this.setDefaultActiveWhenAvailable();
381
+ }
382
+
383
+ private disableSelfWhenChildCtrlExists() {
384
+ this.childControllers.changes
385
+ .pipe(takeUntilDestroyed(this.destroyRef))
386
+ .subscribe((val: QueryList<RdtTabControllerDirective>) => {
387
+ this._disabled = val.length > 0;
388
+
389
+ if (this._disabled) {
390
+ this.unbindAll();
391
+ } else {
392
+ this.bindAll();
393
+ }
394
+ });
395
+ }
396
+
397
+ private setDefaultActive() {
398
+ if (this.tabContainers) {
399
+ const defaultCont = this.tabContainers.find(this.canContainerBeDefault);
400
+ if (defaultCont) {
401
+ this.activateTabContainer(defaultCont, false);
402
+ }
403
+ }
404
+ }
405
+
406
+ private setDefaultActiveWhenAvailable() {
407
+ const active = this.activeContainer;
408
+ if (active && this.tabContainers.some((cont) => cont === active)) {
409
+ return;
410
+ }
411
+ const newDefault = this.tabContainers.find(this.canContainerBeDefault);
412
+ if (newDefault) {
413
+ this.activateTabContainer(newDefault, false);
414
+ }
415
+ }
416
+
417
+ private canContainerBeDefault(c: RdtTabContainerComponent) {
418
+ return c.isTopLevel && !c.disabled && c.hasNonDisabledTabs;
419
+ }
420
+
421
+ private updateShortcuts() {
422
+ this.shortcuts = this._strategy.updateShortcuts(this);
423
+ }
424
+
425
+ private bindAll() {
426
+ this.shortcutSub.unsubscribe();
427
+ if (!this._disabled) {
428
+ this.shortcutSub = this.shortcutService
429
+ .listen(this._shortcuts)
430
+ .pipe(takeWhile(() => !this._disabled))
431
+ .subscribe((event) => {
432
+ this._strategy.onShortcut(event.shortcut, this);
433
+ });
434
+ }
435
+ }
436
+
437
+ private unbindAll() {
438
+ this.shortcutSub.unsubscribe();
439
+ }
440
+ }
@@ -0,0 +1,12 @@
1
+ export interface RdtTabContainerState {
2
+ id: any;
3
+ value: any;
4
+ tabStates: RdtTabState[];
5
+ }
6
+
7
+ export interface RdtTabState {
8
+ id: any;
9
+ containerStates: RdtTabContainerState[];
10
+ }
11
+
12
+ export enum RdtTabMode {}
@@ -0,0 +1,24 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { TooltipModule } from 'primeng/tooltip';
4
+ import { RdtTabContainerComponent } from './components/tab-container/rdt-tab-container.component';
5
+ import { RdtTabComponent } from './components/tab/rdt-tab.component';
6
+ import { RdtDestroyInactiveDirective } from './directives/rdt-destroy-inactive.directive';
7
+ import { RdtTabControllerDirective } from './directives/rdt-tab-controller.directive';
8
+
9
+ @NgModule({
10
+ declarations: [
11
+ RdtTabComponent,
12
+ RdtTabContainerComponent,
13
+ RdtTabControllerDirective,
14
+ RdtDestroyInactiveDirective,
15
+ ],
16
+ exports: [
17
+ RdtTabComponent,
18
+ RdtTabContainerComponent,
19
+ RdtTabControllerDirective,
20
+ RdtDestroyInactiveDirective,
21
+ ],
22
+ imports: [CommonModule, TooltipModule],
23
+ })
24
+ export class RdtTabsModule {}
@@ -0,0 +1,81 @@
1
+ import { RdtShortcut } from '@ngrdt/shortcuts';
2
+ import { RdtTabControllerDirective } from '../directives/rdt-tab-controller.directive';
3
+ import { RdtTabsShortcutStrategy } from './rdt-tabs-shortcut-strategy';
4
+
5
+ const TAB_BASE = 'alt';
6
+ const TAB_KEY_SETS = [
7
+ ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
8
+ ['+', 'ě', 'š', 'č', 'ř', 'ž', 'ý', 'á', 'í', 'é'],
9
+ ];
10
+ const NEXT_CONTAINER = RdtShortcut.create('alt', 's');
11
+ const PREV_CONTAINER = RdtShortcut.create('alt', 'w');
12
+ const LEVEL_UP = RdtShortcut.create('ctrl', 'alt', 'up');
13
+ const LEVEL_DOWN = RdtShortcut.create('ctrl', 'alt', 'down');
14
+ const NEXT_TAB = RdtShortcut.create('ctrl', 'alt', 'right');
15
+ const PREV_TAB = RdtShortcut.create('ctrl', 'alt', 'left');
16
+
17
+ interface RdtShortcutActions {
18
+ [key: string]: (ctrl: RdtTabControllerDirective) => boolean;
19
+ }
20
+
21
+ export class AutoRdtTabsShortcutStrategy extends RdtTabsShortcutStrategy {
22
+ override updateShortcuts(): RdtShortcut[] {
23
+ return AutoRdtTabsShortcutStrategy.shortcuts;
24
+ }
25
+
26
+ override onShortcut(
27
+ shortcut: RdtShortcut,
28
+ ctrl: RdtTabControllerDirective
29
+ ): void {
30
+ const key = shortcut.lastKey;
31
+ if (!key) {
32
+ throw new Error('Key should not be undefined!');
33
+ }
34
+ const action = AutoRdtTabsShortcutStrategy.actions[key];
35
+ if (!action) {
36
+ throw new Error(`Unknown action for key ${key}`);
37
+ }
38
+ action(ctrl);
39
+ }
40
+
41
+ private static generateActions() {
42
+ const actions: RdtShortcutActions = {
43
+ [LEVEL_UP.lastKey]: (ctrl) => ctrl.goLevelUp(),
44
+ [LEVEL_DOWN.lastKey]: (ctrl) => ctrl.goLevelDown(),
45
+ [NEXT_CONTAINER.lastKey]: (ctrl) => ctrl.goToNextContainer(),
46
+ [PREV_CONTAINER.lastKey]: (ctrl) => ctrl.goToPrevContainer(),
47
+ [NEXT_TAB.lastKey]: (ctrl) => ctrl.goToNextTab(),
48
+ [PREV_TAB.lastKey]: (ctrl) => ctrl.goToPrevTab(),
49
+ };
50
+
51
+ TAB_KEY_SETS.forEach((set) => {
52
+ set.forEach((char, i) => {
53
+ actions[char] = (ctrl) => ctrl.goToTabWithIndex(i);
54
+ });
55
+ });
56
+ return actions;
57
+ }
58
+
59
+ private static generateShortcuts() {
60
+ const shortcuts: RdtShortcut[] = [
61
+ LEVEL_UP,
62
+ LEVEL_DOWN,
63
+ NEXT_CONTAINER,
64
+ PREV_CONTAINER,
65
+ NEXT_TAB,
66
+ PREV_TAB,
67
+ ];
68
+
69
+ TAB_KEY_SETS.forEach((set) => {
70
+ set.forEach((tabKey) => {
71
+ shortcuts.push(RdtShortcut.create(TAB_BASE, tabKey));
72
+ });
73
+ });
74
+
75
+ return shortcuts;
76
+ }
77
+
78
+ private static shortcuts: RdtShortcut[] =
79
+ AutoRdtTabsShortcutStrategy.generateShortcuts();
80
+ private static actions = AutoRdtTabsShortcutStrategy.generateActions();
81
+ }
@@ -0,0 +1,20 @@
1
+ import { RdtShortcut } from '@ngrdt/shortcuts';
2
+ import { RdtTabControllerDirective } from '../directives/rdt-tab-controller.directive';
3
+
4
+ export abstract class RdtTabsShortcutStrategy {
5
+ /**
6
+ * Gets called onInit and whenever tabs are added/removed from Controller.
7
+ * @param ctrl Controller using this strategy.
8
+ * @returns List of shortcuts to register.
9
+ */
10
+ abstract updateShortcuts(ctrl: RdtTabControllerDirective): RdtShortcut[];
11
+ /**
12
+ * Gets called whenever hotkeys detects one of the registered shortcuts.
13
+ * @param shortcut Registered shortcut.
14
+ * @param ctrl Controller using this strategy.
15
+ */
16
+ abstract onShortcut(
17
+ shortcut: RdtShortcut,
18
+ ctrl: RdtTabControllerDirective
19
+ ): void;
20
+ }
@@ -0,0 +1,30 @@
1
+ import { RdtShortcut } from '@ngrdt/shortcuts';
2
+ import { RdtTabControllerDirective } from '../directives/rdt-tab-controller.directive';
3
+ import { RdtTabsShortcutStrategy } from './rdt-tabs-shortcut-strategy';
4
+
5
+ export interface StaticRdtTabsConfig {
6
+ shortcuts: Map<RdtShortcut, string>;
7
+ }
8
+
9
+ export class StaticRdtTabsShortcutStrategy implements RdtTabsShortcutStrategy {
10
+ constructor(private config: StaticRdtTabsConfig) {}
11
+
12
+ updateShortcuts(): RdtShortcut[] {
13
+ return Array.from(this.config.shortcuts.keys());
14
+ }
15
+
16
+ onShortcut(shortcut: RdtShortcut, ctrl: RdtTabControllerDirective): void {
17
+ const value = this.config.shortcuts.get(shortcut)!;
18
+ const tab = ctrl.getTabByValue(value);
19
+ if (tab) {
20
+ ctrl.activateTab(tab);
21
+ ctrl.activateTabContainer(tab.tabContainer);
22
+ } else {
23
+ console.warn(
24
+ `Registered shortcut has been detected,
25
+ but there is no tab with appropriate value.
26
+ Shortcut: ${shortcut}, value: ${value}`
27
+ );
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,8 @@
1
+ // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment
2
+ globalThis.ngJest = {
3
+ testEnvironmentOptions: {
4
+ errorOnUnknownElements: true,
5
+ errorOnUnknownProperties: true,
6
+ },
7
+ };
8
+ import 'jest-preset-angular/setup-jest';
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "forceConsistentCasingInFileNames": true,
5
+ "strict": true,
6
+ "noImplicitOverride": true,
7
+ "noPropertyAccessFromIndexSignature": true,
8
+ "noImplicitReturns": true,
9
+ "noFallthroughCasesInSwitch": true
10
+ },
11
+ "files": [],
12
+ "include": [],
13
+ "references": [
14
+ {
15
+ "path": "./tsconfig.lib.json"
16
+ },
17
+ {
18
+ "path": "./tsconfig.spec.json"
19
+ }
20
+ ],
21
+ "extends": "../../tsconfig.base.json",
22
+ "angularCompilerOptions": {
23
+ "enableI18nLegacyMessageIdFormat": false,
24
+ "strictInjectionParameters": true,
25
+ "strictInputAccessModifiers": true,
26
+ "strictTemplates": true
27
+ }
28
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "inlineSources": true,
8
+ "types": []
9
+ },
10
+ "exclude": [
11
+ "src/**/*.spec.ts",
12
+ "src/test-setup.ts",
13
+ "jest.config.ts",
14
+ "src/**/*.test.ts"
15
+ ],
16
+ "include": ["src/**/*.ts"]
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.lib.json",
3
+ "compilerOptions": {
4
+ "declarationMap": false
5
+ },
6
+ "angularCompilerOptions": {
7
+ "compilationMode": "partial"
8
+ }
9
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "../../dist/out-tsc",
5
+ "module": "commonjs",
6
+ "target": "es2016",
7
+ "types": ["jest", "node"]
8
+ },
9
+ "files": ["src/test-setup.ts"],
10
+ "include": [
11
+ "jest.config.ts",
12
+ "src/**/*.test.ts",
13
+ "src/**/*.spec.ts",
14
+ "src/**/*.d.ts"
15
+ ]
16
+ }