ng-hub-ui-board 19.3.6 → 19.3.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.
package/.npmignore CHANGED
@@ -1,2 +1 @@
1
- # Nested package.json's are only needed for development.
2
- **/package.json
1
+ node_modules
package/CHANGELOG.md ADDED
@@ -0,0 +1,76 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [19.3.8] - 2026-01-16
9
+
10
+ ### Fixed
11
+
12
+ - Ensured correct publication of compiled artifacts by refining the release process.
13
+ - Reverted `exports` configuration to maintain consistency with other libraries.
14
+
15
+ ## [19.3.7] - 2026-01-16
16
+
17
+ ### Fixed
18
+
19
+ - Removed incorrect `!src/**/*` exclusion from `package.json` that was preventing CSS files from being included in the published package.
20
+
21
+ ## [19.3.6] - 2026-01-16
22
+
23
+ ### Fixed
24
+
25
+ - Added `styles` export configuration in package.json to properly expose SCSS files.
26
+
27
+ ## [19.3.5] - 2026-01-15
28
+
29
+ ### Changed
30
+
31
+ - Complete refactoring of board styling to use CSS variables for enhanced customization.
32
+ - Documented all available CSS variables in README.
33
+ - Added `StylingBoardExampleComponent` to showcase custom styling capabilities.
34
+
35
+ ## [19.3.4] - 2026-01-15
36
+
37
+ ### Changed
38
+
39
+ - Complete refactoring of board styling to use CSS variables for enhanced customization.
40
+ - Documented all available CSS variables in README.
41
+ - Added `StylingBoardExampleComponent` to showcase custom styling capabilities.
42
+
43
+ ## [19.3.3] - 2026-01-15
44
+
45
+ ### Changed
46
+
47
+ - Complete refactoring of board styling to use CSS variables for enhanced customization.
48
+ - Documented all available CSS variables in README.
49
+ - Added `StylingBoardExampleComponent` to showcase custom styling capabilities.
50
+
51
+ ## [19.3.2] - 2025-01-15
52
+
53
+ ### Changed
54
+
55
+ - Improved `reachedEnd` event documentation in README with correct usage examples showing `event.data` as the complete `BoardColumn` object
56
+ - Updated `reachedEnd` event example to include proper container with fixed height requirement for scroll detection
57
+ - Enhanced license section in README with detailed explanation of CC BY 4.0 permissions, requirements, and attribution example
58
+
59
+ ### Fixed
60
+
61
+ - Corrected misleading `reachedEnd` event documentation that incorrectly showed direct access to `event.data.title` instead of extracting the column first
62
+
63
+ ## [19.3.1] - 2024-10-05
64
+
65
+ ### Added
66
+
67
+ - Comprehensive JSDoc coverage across public models, directives, pipes, and the `HubBoardComponent` for improved API discoverability.
68
+ - New unit test ensuring the `reachedEnd` event is not emitted when column data is unavailable.
69
+
70
+ ### Changed
71
+
72
+ - Refined infinite-scroll detection tolerance to ensure `reachedEnd` fires reliably at the bottom of each column.
73
+ - Hardened the document example logic to avoid duplicate lazy-load requests while columns are already loading.
74
+ - Typed the `invertColor` pipe output and improved error handling for invalid HEX values.
75
+
76
+ [19.3.1]: https://github.com/carlos-morcillo/ng-hub-ui-board/compare/19.3.0...19.3.1
@@ -0,0 +1,23 @@
1
+ # Functionalities of Board Library
2
+
3
+ This table details the functionalities of the `ng-hub-ui-board` library and indicates which ones are covered by interactive examples.
4
+
5
+ ## Kanban Board (`hub-ui-board`)
6
+
7
+ | Category | Functionality | Example Covered |
8
+ | :--- | :--- | :---: |
9
+ | **Basic Usage** | Board Display (Columns & Cards) | ✅ |
10
+ | | Responsive Layout | ✅ |
11
+ | **Interactions** | Card Drag & Drop (Same Column) | ✅ |
12
+ | | Card Drag & Drop (Cross Column) | ✅ |
13
+ | | Column Reordering | ✅ |
14
+ | | Card Click Handling | ✅ |
15
+ | | Infinite Scroll (Column Reach End) | ✅ |
16
+ | **Templates** | Custom Card Template (`*cardTpt`) | ✅ |
17
+ | | Custom Column Header Template (`*columnHeaderTpt`) | ✅ |
18
+ | | Custom Column Footer Template (`*columnFooterTpt`) | ✅ |
19
+ | **Configuration** | Disable Column Sorting | ✅ |
20
+ | | Custom Scroll Detection Padding | ✅ |
21
+
22
+ ---
23
+ *Note: ✅ indicates an active interactive example is available in the documentation.*
package/karma.conf.js ADDED
@@ -0,0 +1,44 @@
1
+ // Karma configuration file, see link for more information
2
+ // https://karma-runner.github.io/1.0/config/configuration-file.html
3
+
4
+ module.exports = function (config) {
5
+ config.set({
6
+ basePath: '',
7
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
8
+ plugins: [
9
+ require('karma-jasmine'),
10
+ require('karma-chrome-launcher'),
11
+ require('karma-jasmine-html-reporter'),
12
+ require('karma-coverage'),
13
+ require('@angular-devkit/build-angular/plugins/karma')
14
+ ],
15
+ client: {
16
+ jasmine: {
17
+ // you can add configuration options for Jasmine here
18
+ // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19
+ // for example, you can disable the random execution with `random: false`
20
+ // or set a specific seed with `seed: 4321`
21
+ },
22
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
23
+ },
24
+ jasmineHtmlReporter: {
25
+ suppressAll: true // removes the duplicated traces
26
+ },
27
+ coverageReporter: {
28
+ dir: require('path').join(__dirname, '../../coverage/board'),
29
+ subdir: '.',
30
+ reporters: [
31
+ { type: 'html' },
32
+ { type: 'text-summary' }
33
+ ]
34
+ },
35
+ reporters: ['progress', 'kjhtml'],
36
+ port: 9876,
37
+ colors: true,
38
+ logLevel: config.LOG_INFO,
39
+ autoWatch: true,
40
+ browsers: ['Chrome'],
41
+ singleRun: false,
42
+ restartOnFileChange: true
43
+ });
44
+ };
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/board",
4
+ "lib": {
5
+ "entryFile": "src/public-api.ts",
6
+ "styleIncludePaths": ["src/lib/styles"]
7
+ },
8
+ "assets": ["src/lib/styles"]
9
+ }
package/package.json CHANGED
@@ -1,105 +1,101 @@
1
1
  {
2
- "name": "ng-hub-ui-board",
3
- "version": "19.3.6",
4
- "description": "An Angular-based Kanban board component with Trello-like drag-and-drop, customizable columns, and straightforward event handling.",
5
- "main": "bundles/ng-hub-ui-board.umd.js",
6
- "module": "fesm2022/ng-hub-ui-board.mjs",
7
- "typings": "index.d.ts",
8
- "exports": {
9
- "./package.json": {
10
- "default": "./package.json"
11
- },
12
- ".": {
13
- "types": "./index.d.ts",
14
- "default": "./fesm2022/ng-hub-ui-board.mjs"
15
- },
16
- "./styles/*": {
17
- "sass": "./src/lib/styles/*",
18
- "default": "./src/lib/styles/*"
19
- }
20
- },
21
- "peerDependencies": {
22
- "@angular/common": ">=18.0.0",
23
- "@angular/core": ">=18.0.0",
24
- "@angular/cdk": ">=18.0.0"
25
- },
26
- "dependencies": {
27
- "tslib": "^2.3.0"
28
- },
29
- "sideEffects": false,
30
- "files": [
31
- "**/*",
32
- "!**/*.spec.ts",
33
- "!**/*.spec.js",
34
- "!**/*.test.ts",
35
- "!**/*.test.js",
36
- "!src/**/*"
37
- ],
38
- "keywords": [
39
- "angular",
40
- "kanban",
41
- "board",
42
- "trello",
43
- "drag-drop",
44
- "dnd",
45
- "columns",
46
- "cards",
47
- "tasks",
48
- "todo",
49
- "productivity",
50
- "collaboration",
51
- "organization",
52
- "project-management",
53
- "workflow",
54
- "agile",
55
- "scrum",
56
- "component",
57
- "reusable",
58
- "open-source",
59
- "typescript",
60
- "standalone",
61
- "cdk",
62
- "ui-library",
63
- "ng-hub-ui"
64
- ],
65
- "author": {
66
- "name": "Carlos Morcillo Fernández",
67
- "email": "carlos.morcillo@me.com",
68
- "url": "https://www.carlosmorcillo.com"
69
- },
70
- "maintainers": [
71
- {
72
- "name": "Carlos Morcillo Fernández",
73
- "email": "carlos.morcillo@me.com",
74
- "url": "https://www.carlosmorcillo.com"
75
- }
76
- ],
77
- "homepage": "https://github.com/carlos-morcillo/ng-hub-ui-board#readme",
78
- "repository": {
79
- "type": "git",
80
- "url": "git+https://github.com/carlos-morcillo/ng-hub-ui-board.git"
81
- },
82
- "bugs": {
83
- "url": "https://github.com/carlos-morcillo/ng-hub-ui-board/issues",
84
- "email": "carlos.morcillo@me.com"
85
- },
86
- "funding": {
87
- "type": "buymeacoffee",
88
- "url": "https://buymeacoffee.com/carlosmorcillo"
89
- },
90
- "license": "CC-BY-4.0",
91
- "engines": {
92
- "node": ">=18.13.0",
93
- "npm": ">=9.0.0"
94
- },
95
- "publishConfig": {
96
- "access": "public",
97
- "registry": "https://registry.npmjs.org/"
98
- },
99
- "ng-add": {
100
- "save": "dependencies"
101
- },
102
- "contributors": [
103
- "Carlos Morcillo Fernández <carlos.morcillo@me.com>"
104
- ]
105
- }
2
+ "name": "ng-hub-ui-board",
3
+ "version": "19.3.8",
4
+ "description": "An Angular-based Kanban board component with Trello-like drag-and-drop, customizable columns, and straightforward event handling.",
5
+ "main": "bundles/ng-hub-ui-board.umd.js",
6
+ "module": "fesm2022/ng-hub-ui-board.mjs",
7
+ "typings": "index.d.ts",
8
+ "peerDependencies": {
9
+ "@angular/common": ">=18.0.0",
10
+ "@angular/core": ">=18.0.0",
11
+ "@angular/cdk": ">=18.0.0"
12
+ },
13
+ "dependencies": {
14
+ "tslib": "^2.3.0"
15
+ },
16
+ "sideEffects": false,
17
+ "scripts": {
18
+ "build": "ng build board",
19
+ "build:prod": "ng build board --configuration production",
20
+ "test": "ng test board",
21
+ "test:watch": "ng test board --watch",
22
+ "test:coverage": "ng test board --code-coverage",
23
+ "lint": "ng lint board",
24
+ "pack": "npm pack",
25
+ "publish:npm": "npm publish"
26
+ },
27
+ "files": [
28
+ "**/*",
29
+ "!**/*.spec.ts",
30
+ "!**/*.spec.js",
31
+ "!**/*.test.ts",
32
+ "!**/*.test.js"
33
+ ],
34
+ "keywords": [
35
+ "angular",
36
+ "kanban",
37
+ "board",
38
+ "trello",
39
+ "drag-drop",
40
+ "dnd",
41
+ "columns",
42
+ "cards",
43
+ "tasks",
44
+ "todo",
45
+ "productivity",
46
+ "collaboration",
47
+ "organization",
48
+ "project-management",
49
+ "workflow",
50
+ "agile",
51
+ "scrum",
52
+ "component",
53
+ "reusable",
54
+ "open-source",
55
+ "typescript",
56
+ "standalone",
57
+ "cdk",
58
+ "ui-library",
59
+ "ng-hub-ui"
60
+ ],
61
+ "author": {
62
+ "name": "Carlos Morcillo Fernández",
63
+ "email": "carlos.morcillo@me.com",
64
+ "url": "https://www.carlosmorcillo.com"
65
+ },
66
+ "maintainers": [
67
+ {
68
+ "name": "Carlos Morcillo Fernández",
69
+ "email": "carlos.morcillo@me.com",
70
+ "url": "https://www.carlosmorcillo.com"
71
+ }
72
+ ],
73
+ "homepage": "https://github.com/carlos-morcillo/ng-hub-ui-board#readme",
74
+ "repository": {
75
+ "type": "git",
76
+ "url": "git+https://github.com/carlos-morcillo/ng-hub-ui-board.git"
77
+ },
78
+ "bugs": {
79
+ "url": "https://github.com/carlos-morcillo/ng-hub-ui-board/issues",
80
+ "email": "carlos.morcillo@me.com"
81
+ },
82
+ "funding": {
83
+ "type": "buymeacoffee",
84
+ "url": "https://buymeacoffee.com/carlosmorcillo"
85
+ },
86
+ "license": "CC-BY-4.0",
87
+ "engines": {
88
+ "node": ">=18.13.0",
89
+ "npm": ">=9.0.0"
90
+ },
91
+ "publishConfig": {
92
+ "access": "public",
93
+ "registry": "https://registry.npmjs.org/"
94
+ },
95
+ "ng-add": {
96
+ "save": "dependencies"
97
+ },
98
+ "contributors": [
99
+ "Carlos Morcillo Fernández <carlos.morcillo@me.com>"
100
+ ]
101
+ }
@@ -0,0 +1,51 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { HubBoardComponent } from './components/board/board.component';
3
+ import { BoardColumnFooterDirective } from './directives/board-column-footer.directive';
4
+ import { BoardColumnHeaderDirective } from './directives/board-column-header.directive';
5
+ import { CardTemplateDirective } from './directives/card-template.directive';
6
+
7
+ /**
8
+ * Angular module that provides board functionality with drag-and-drop support.
9
+ *
10
+ * This module includes all the necessary components and directives for creating
11
+ * Kanban-style boards with customizable columns, cards, and templates.
12
+ *
13
+ * @deprecated Use standalone components instead. Import individual components and directives directly.
14
+ * @publicApi
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // Legacy module approach (not recommended)
19
+ * import { BoardModule } from 'ng-hub-ui-board';
20
+ *
21
+ * @NgModule({
22
+ * imports: [BoardModule]
23
+ * })
24
+ * export class AppModule {}
25
+ *
26
+ * // Recommended standalone approach
27
+ * import { HubBoardComponent, CardTemplateDirective } from 'ng-hub-ui-board';
28
+ *
29
+ * @Component({
30
+ * standalone: true,
31
+ * imports: [HubBoardComponent, CardTemplateDirective]
32
+ * })
33
+ * export class MyComponent {}
34
+ * ```
35
+ */
36
+ @NgModule({
37
+ declarations: [],
38
+ imports: [
39
+ HubBoardComponent,
40
+ CardTemplateDirective,
41
+ BoardColumnHeaderDirective,
42
+ BoardColumnFooterDirective
43
+ ],
44
+ exports: [
45
+ HubBoardComponent,
46
+ CardTemplateDirective,
47
+ BoardColumnHeaderDirective,
48
+ BoardColumnFooterDirective
49
+ ]
50
+ })
51
+ export class BoardModule {}
@@ -0,0 +1,88 @@
1
+ @if (columns().length) {
2
+ <div
3
+ class="hub-board__drop-list"
4
+ cdkDropList
5
+ cdkDropListOrientation="horizontal"
6
+ [cdkDropListData]="columns()"
7
+ (cdkDropListDropped)="dropColumn($event)"
8
+ [cdkDropListSortingDisabled]="columnSortingDisabled()"
9
+ >
10
+ <div cdkDropListGroup class="hub-board__columns">
11
+ @for (column of columns(); let index = $index; track column) {
12
+ <div class="hub-board__column-container" cdkDrag [cdkDragData]="column" [cdkDragDisabled]="column.disabled">
13
+ <div class="hub-board__column" [ngClass]="column.classlist" [ngStyle]="column.style">
14
+ <div class="hub-board__column-header">
15
+ <ng-container
16
+ [ngTemplateOutlet]="columnHeaderTpt() || defaultColumnHeaderTpt"
17
+ [ngTemplateOutletContext]="{ column: column }"
18
+ >
19
+ </ng-container>
20
+ </div>
21
+ <div
22
+ class="hub-board__column-body"
23
+ cdkDropList
24
+ [cdkDropListData]="column"
25
+ (cdkDropListDropped)="dropCard($event)"
26
+ (scroll)="onScroll(index, $event)"
27
+ [cdkDropListEnterPredicate]="column.predicate ?? defaultEnterPredicateFn"
28
+ [cdkDropListSortingDisabled]="column.cardSortingDisabled"
29
+ >
30
+ @for ( card of column.cards; let index = $index; track card ) {
31
+ <div
32
+ class="hub-board__card"
33
+ [class.hub-board__card--disabled]="card.disabled"
34
+ cdkDrag
35
+ [cdkDragData]="card"
36
+ [cdkDragDisabled]="card.disabled"
37
+ (click)="cardClick(card)"
38
+ (mousedown)="card.disabled && $event.stopPropagation()"
39
+ [ngClass]="card.classlist"
40
+ [ngStyle]="card.style"
41
+ >
42
+ <div class="hub-board__card-body">
43
+ <ng-container
44
+ [ngTemplateOutlet]="cardTpt() || defaultCardTpt"
45
+ [ngTemplateOutletContext]="{
46
+ item: card,
47
+ column
48
+ }"
49
+ >
50
+ </ng-container>
51
+ </div>
52
+ </div>
53
+ }
54
+ </div>
55
+
56
+ @if (columnFooterTpt()) {
57
+ <div class="hub-board__column-footer">
58
+ <ng-container
59
+ [ngTemplateOutlet]="columnFooterTpt() ?? null"
60
+ [ngTemplateOutletContext]="{
61
+ column: column
62
+ }"
63
+ >
64
+ </ng-container>
65
+ </div>
66
+ }
67
+ </div>
68
+ </div>
69
+ }
70
+ </div>
71
+ </div>
72
+ }
73
+
74
+ <ng-template #defaultCardTpt let-item="item">
75
+ <h6 class="hub-board__card-title">{{ item.title }}</h6>
76
+ <p class="hub-board__card-subtitle">{{ item.description }}</p>
77
+ </ng-template>
78
+
79
+ <ng-template #defaultColumnHeaderTpt let-column="column">
80
+ <div class="d-flex flex-column">
81
+ <h5 class="hub-board__column-header-title">
82
+ {{ column.title }}
83
+ </h5>
84
+ <h6 class="hub-board__column-header-subtitle">
85
+ {{ column.description }}
86
+ </h6>
87
+ </div>
88
+ </ng-template>
@@ -0,0 +1,167 @@
1
+ import { CdkDragDrop, DragDropModule, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
2
+ import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
3
+ import { Component, Signal, TemplateRef, computed, contentChild, input, output } from '@angular/core';
4
+ import { BoardColumnFooterDirective } from '../../directives/board-column-footer.directive';
5
+ import { BoardColumnHeaderDirective } from '../../directives/board-column-header.directive';
6
+ import { CardTemplateDirective } from '../../directives/card-template.directive';
7
+ import { Board } from '../../models/board';
8
+ import { BoardCard } from '../../models/board-card';
9
+ import { BoardColumn } from '../../models/board-column';
10
+ import { ReachedEndEvent } from '../../models/reached-end-event';
11
+
12
+ /**
13
+ * Standalone Kanban-style board component that provides column-based drag-and-drop,
14
+ * custom templates and infinite-scroll detection.
15
+ *
16
+ * @publicApi
17
+ */
18
+ @Component({
19
+ selector: 'hub-board, hub-ui-board',
20
+ templateUrl: './board.component.html',
21
+ imports: [NgClass, NgStyle, NgTemplateOutlet, DragDropModule],
22
+ host: {
23
+ class: 'hub-board'
24
+ }
25
+ })
26
+ export class HubBoardComponent {
27
+ /**
28
+ * Reactive input containing the full board definition (columns and cards).
29
+ */
30
+ readonly board = input<Board>();
31
+
32
+ /**
33
+ * Pixel threshold used when determining whether a column has reached scroll end.
34
+ * Allows for fractional scroll values across different browsers.
35
+ */
36
+ private readonly scrollDetectionPadding = 1;
37
+
38
+ /**
39
+ * Derived list of board columns exposed as a signal to the template.
40
+ */
41
+ columns: Signal<Array<BoardColumn>> = computed(() => {
42
+ return this.board()?.columns ?? [];
43
+ });
44
+
45
+ /**
46
+ * When true, column reordering via drag-and-drop is disabled.
47
+ */
48
+ readonly columnSortingDisabled = input<boolean>(false);
49
+
50
+ /**
51
+ * Custom card template supplied via the `cardTpt` structural directive.
52
+ */
53
+ readonly cardTpt = contentChild(CardTemplateDirective, {
54
+ read: TemplateRef<unknown>
55
+ });
56
+
57
+ /**
58
+ * Custom column header template supplied via the `columnHeaderTpt` structural directive.
59
+ */
60
+ readonly columnHeaderTpt = contentChild(BoardColumnHeaderDirective, {
61
+ read: TemplateRef<unknown>
62
+ });
63
+
64
+ /**
65
+ * Custom column footer template supplied via the `columnFooterTpt` structural directive.
66
+ */
67
+ readonly columnFooterTpt = contentChild(BoardColumnFooterDirective, {
68
+ read: TemplateRef<unknown>
69
+ });
70
+
71
+ /**
72
+ * Emits each time a card is clicked within the board.
73
+ */
74
+ readonly onCardClick = output<BoardCard>();
75
+
76
+ /**
77
+ * Emits when a card has been repositioned, either within the same column or into another column.
78
+ */
79
+ readonly onCardMoved = output<CdkDragDrop<BoardColumn, BoardColumn, BoardCard<any>>>();
80
+
81
+ /**
82
+ * Emits when columns are reordered through drag-and-drop.
83
+ */
84
+ readonly onColumnMoved = output<CdkDragDrop<BoardColumn[]>>();
85
+
86
+ /**
87
+ * Emits when a column body is scrolled to its end, enabling infinite-scroll behaviour.
88
+ */
89
+ readonly reachedEnd = output<ReachedEndEvent>();
90
+
91
+ /**
92
+ * Default predicate that allows any card to be dropped into any column.
93
+ *
94
+ * @returns Always `true`, indicating that drop operations are permitted.
95
+ */
96
+ defaultEnterPredicateFn = () => true;
97
+
98
+ /**
99
+ * Emits the clicked card through {@link onCardClick}.
100
+ *
101
+ * @param item - The card that triggered the click event.
102
+ */
103
+ cardClick(item: BoardCard) {
104
+ this.onCardClick.emit(item);
105
+ }
106
+
107
+ /**
108
+ * Updates column order when a drag-and-drop operation completes and emits the resulting event.
109
+ *
110
+ * @param event - Drag-and-drop metadata describing the column movement.
111
+ */
112
+ dropColumn(event: CdkDragDrop<BoardColumn[]>) {
113
+ moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
114
+ this.onColumnMoved.emit(event);
115
+ }
116
+
117
+ /**
118
+ * Applies card reordering or transfer logic depending on the drag-drop target,
119
+ * then emits the corresponding drag event metadata.
120
+ *
121
+ * @param event - Drag-and-drop metadata describing the card movement.
122
+ */
123
+ dropCard(event: CdkDragDrop<BoardColumn, BoardColumn, BoardCard<any>>) {
124
+ if (event.previousContainer === event.container) {
125
+ // Reorder the card within the same column
126
+ moveItemInArray(event.container.data.cards, event.previousIndex, event.currentIndex);
127
+ } else {
128
+ // Transfer the card from one column to another
129
+ transferArrayItem(
130
+ event.previousContainer.data.cards,
131
+ event.container.data.cards,
132
+ event.previousIndex,
133
+ event.currentIndex
134
+ );
135
+ }
136
+ this.onCardMoved.emit(event);
137
+ }
138
+
139
+ /**
140
+ * Emits {@link reachedEnd} once a column body is scrolled to its bottom.
141
+ *
142
+ * @param index - Index of the scrolled column within the board.
143
+ * @param event - Browser scroll event originating from the column body element.
144
+ */
145
+ onScroll(index: number, event: Event) {
146
+ const el = event.target as HTMLElement | null;
147
+ if (!el) {
148
+ return;
149
+ }
150
+
151
+ const scrolledToBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - this.scrollDetectionPadding;
152
+
153
+ if (!scrolledToBottom) {
154
+ return;
155
+ }
156
+
157
+ const column = this.board()?.columns?.[index];
158
+ if (!column) {
159
+ return;
160
+ }
161
+
162
+ this.reachedEnd.emit({
163
+ index,
164
+ data: column
165
+ });
166
+ }
167
+ }