ng-hub-ui-board 19.2.0 → 19.3.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.
package/.npmignore ADDED
@@ -0,0 +1,2 @@
1
+ # Nested package.json's are only needed for development.
2
+ **/package.json
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  This component is part of the ng-hub-ui ecosystem, which includes:
8
8
 
9
- - [ng-hub-ui-table](https://www.npmjs.com/package/ng-hub-ui-table)
9
+ - [ng-hub-ui-paginable](https://www.npmjs.com/package/ng-hub-ui-paginable)
10
10
  - [ng-hub-ui-modal](https://www.npmjs.com/package/ng-hub-ui-modal)
11
11
  - [ng-hub-ui-stepper](https://www.npmjs.com/package/ng-hub-ui-stepper)
12
12
  - [ng-hub-ui-breadcrumbs](https://www.npmjs.com/package/ng-hub-ui-breadcrumbs)
@@ -20,14 +20,16 @@ A flexible and powerful board component for Angular applications, perfect for im
20
20
 
21
21
  ## Features
22
22
 
23
- - 🎯 Standalone component
24
- - 🔄 Drag and drop support for both cards and columns
25
- - 📱 Responsive design
26
- - 🎨 Highly customizable with templates
27
- - 🔧 Bootstrap compatible
28
- - ⚡ Virtual scrolling support with end-detection
29
- - 🎭 Custom styling support for boards, columns, and cards
30
- - 🔒 Disable/enable functionality for cards and columns
23
+ - 🎯 **Standalone component** - Modern Angular approach with minimal setup
24
+ - 🔄 **Drag and drop support** - Full drag-and-drop for both cards and columns using Angular CDK
25
+ - 📱 **Responsive design** - Works seamlessly across desktop, tablet, and mobile devices
26
+ - 🎨 **Highly customizable** - Custom templates for cards, headers, and footers
27
+ - 🔧 **Bootstrap compatible** - Integrates perfectly with Bootstrap 5 design system
28
+ - ⚡ **Virtual scrolling** - Supports infinite scroll with end-detection for performance
29
+ - 🎭 **Custom styling** - CSS custom properties for easy theming and customization
30
+ - 🔒 **Granular control** - Enable/disable functionality at board, column, or card level
31
+ - 🏷️ **TypeScript support** - Full type safety with generic interfaces
32
+ - ♿ **Accessibility ready** - Follows WAI-ARIA best practices for drag-and-drop
31
33
 
32
34
  ## Installation
33
35
 
@@ -114,7 +116,7 @@ export class BoardDemoComponent {
114
116
  </hub-board>
115
117
  ```
116
118
 
117
- Este bloque de código ofrece un ejemplo mínimo y funcional tanto para principiantes como para usuarios intermedios.
119
+ This code block provides a minimal and functional example for both beginners and intermediate users.
118
120
 
119
121
  ## Usage
120
122
 
@@ -261,7 +263,7 @@ handleCardMoved(event: CdkDragDrop<BoardColumn, BoardColumn, BoardCard>) {
261
263
  Emitted when a column is reordered via drag and drop.
262
264
 
263
265
  ```html
264
- <hub-board [board]="board" (reachedEnd)="handleReachedEnd($event)"> </hub-board>
266
+ <hub-board [board]="board" (onColumnMoved)="handleColumnMoved($event)"> </hub-board>
265
267
  ```
266
268
 
267
269
  **Type:** `EventEmitter<CdkDragDrop<BoardColumn[]>>`
@@ -471,23 +473,42 @@ Each case benefits from customizable columns, card templates, and event outputs
471
473
  Here are some common issues and how to resolve them:
472
474
 
473
475
  ### 🔄 Drag and drop not working
474
- Make sure you have imported `@angular/cdk` and the necessary `DragDropModule`. Also check that your board and column data is reactive (e.g. using `signal()` or `RxJS`).
476
+ - **Check dependencies**: Ensure `@angular/cdk` is installed and imported
477
+ - **Reactive data**: Verify your board data is reactive (using `signal()`, `Observable`, or proper change detection)
478
+ - **Browser compatibility**: Ensure your target browsers support the HTML5 Drag and Drop API
475
479
 
476
480
  ### 📏 Scroll detection not triggering `reachedEnd`
477
- Ensure the `<hub-board>` element or one of its parents has a `max-height` or fixed height defined and `overflow: auto` to enable scrolling.
481
+ - **Height constraints**: The `<hub-board>` element or its parent must have a `max-height` or fixed height
482
+ - **Overflow setting**: Ensure `overflow: auto` or `overflow-y: scroll` is applied to enable scrolling
483
+ - **Content length**: Make sure there's enough content to actually trigger scrolling
478
484
 
479
485
  ### 🎨 Styles not applying
480
- Confirm you've imported the SCSS base styles in your global `styles.scss`:
481
-
482
- ```scss
483
- @use '../dist/board/src/lib/styles/base.scss' as boardBase;
484
- ```
486
+ - **Import path**: Confirm you've imported the SCSS base styles in your global `styles.scss`:
487
+ ```scss
488
+ @use '../dist/board/src/lib/styles/base.scss' as boardBase;
489
+ ```
490
+ - **CSS custom properties**: Check that your custom CSS variables follow the `--hub-*` naming convention
491
+ - **Style specificity**: Ensure your custom styles have sufficient specificity to override defaults
485
492
 
486
493
  ### 🧩 Templates not rendering
487
- If you’re using `cardTpt`, `columnHeaderTpt`, or `columnFooterTpt`, ensure you've also imported the corresponding directives into your component.
488
-
489
- ### 🛠️ Error: "Cannot read property 'cards' of undefined"
490
- Make sure your `board` signal is initialized and its `columns` array is not `undefined`.
494
+ - **Import directives**: When using standalone components, import the template directives:
495
+ ```typescript
496
+ imports: [HubBoardComponent, CardTemplateDirective, BoardColumnHeaderDirective]
497
+ ```
498
+ - **Template syntax**: Verify you're using the correct template selectors (`cardTpt`, `columnHeaderTpt`, `columnFooterTpt`)
499
+
500
+ ### 🛠️ Runtime errors
501
+ - **"Cannot read property 'cards' of undefined"**: Initialize your board signal properly:
502
+ ```typescript
503
+ board = signal<Board>({ title: 'My Board', columns: [] });
504
+ ```
505
+ - **Type errors**: Ensure your data matches the `Board`, `BoardColumn`, and `BoardCard` interfaces
506
+ - **Signal updates**: Use `.set()` or `.update()` methods to modify signal values
507
+
508
+ ### 🎯 Performance issues
509
+ - **Large datasets**: Consider implementing virtual scrolling for columns with many cards
510
+ - **Memory leaks**: Ensure proper cleanup of event listeners and subscriptions
511
+ - **Change detection**: Use `OnPush` change detection strategy when possible
491
512
 
492
513
  If problems persist, open an issue at: https://github.com/carlos-morcillo/ng-hub-ui-board/issues
493
514
 
@@ -1,17 +1,45 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, input, computed, contentChild, TemplateRef, EventEmitter, Component, Output, NgModule, Pipe } from '@angular/core';
2
+ import { Directive, input, computed, contentChild, TemplateRef, output, Component, NgModule, Pipe } from '@angular/core';
3
3
  import * as i1 from '@angular/cdk/drag-drop';
4
4
  import { moveItemInArray, transferArrayItem, DragDropModule } from '@angular/cdk/drag-drop';
5
5
  import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
6
6
 
7
+ /**
8
+ * Directive that allows customization of column footer templates within board columns.
9
+ *
10
+ * This directive enables developers to define custom templates for column footers,
11
+ * perfect for displaying summary information, quick actions, statistics,
12
+ * or any column-specific controls at the bottom of each column.
13
+ *
14
+ * @publicApi
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <ng-template columnFooterTpt let-column="column">
19
+ * <div class="custom-footer">
20
+ * <div class="column-summary">
21
+ * <span>Total: {{ column.cards.length }}</span>
22
+ * <span>Priority Items: {{ getPriorityItems(column) }}</span>
23
+ * </div>
24
+ * <button (click)="quickAddCard(column)">Quick Add</button>
25
+ * </div>
26
+ * </ng-template>
27
+ * ```
28
+ */
7
29
  class BoardColumnFooterDirective {
30
+ templateRef;
31
+ /**
32
+ * Creates a new BoardColumnFooterDirective instance.
33
+ *
34
+ * @param templateRef - The template reference that contains the custom column footer layout
35
+ */
8
36
  constructor(templateRef) {
9
37
  this.templateRef = templateRef;
10
38
  }
11
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardColumnFooterDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
12
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: BoardColumnFooterDirective, isStandalone: true, selector: "[columnFooterTpt]", ngImport: i0 }); }
39
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardColumnFooterDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
40
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.3", type: BoardColumnFooterDirective, isStandalone: true, selector: "[columnFooterTpt]", ngImport: i0 });
13
41
  }
14
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardColumnFooterDirective, decorators: [{
42
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardColumnFooterDirective, decorators: [{
15
43
  type: Directive,
16
44
  args: [{
17
45
  selector: '[columnFooterTpt]',
@@ -19,14 +47,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
19
47
  }]
20
48
  }], ctorParameters: () => [{ type: i0.TemplateRef }] });
21
49
 
50
+ /**
51
+ * Directive that allows customization of column header templates within board columns.
52
+ *
53
+ * This directive provides the ability to define custom templates for rendering column headers,
54
+ * giving developers full control over the appearance and functionality of column headers
55
+ * including titles, descriptions, actions, and metadata display.
56
+ *
57
+ * @publicApi
58
+ *
59
+ * @example
60
+ * ```html
61
+ * <ng-template columnHeaderTpt let-column="column">
62
+ * <div class="custom-header">
63
+ * <h2>{{ column.title }}</h2>
64
+ * <span class="card-count">{{ column.cards.length }} items</span>
65
+ * <button (click)="addCard(column)">Add Card</button>
66
+ * </div>
67
+ * </ng-template>
68
+ * ```
69
+ */
22
70
  class BoardColumnHeaderDirective {
71
+ templateRef;
72
+ /**
73
+ * Creates a new BoardColumnHeaderDirective instance.
74
+ *
75
+ * @param templateRef - The template reference that contains the custom column header layout
76
+ */
23
77
  constructor(templateRef) {
24
78
  this.templateRef = templateRef;
25
79
  }
26
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardColumnHeaderDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
27
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: BoardColumnHeaderDirective, isStandalone: true, selector: "[columnHeaderTpt]", ngImport: i0 }); }
80
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardColumnHeaderDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
81
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.3", type: BoardColumnHeaderDirective, isStandalone: true, selector: "[columnHeaderTpt]", ngImport: i0 });
28
82
  }
29
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardColumnHeaderDirective, decorators: [{
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardColumnHeaderDirective, decorators: [{
30
84
  type: Directive,
31
85
  args: [{
32
86
  selector: '[columnHeaderTpt]',
@@ -34,14 +88,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
34
88
  }]
35
89
  }], ctorParameters: () => [{ type: i0.TemplateRef }] });
36
90
 
91
+ /**
92
+ * Directive that allows customization of card templates within board columns.
93
+ *
94
+ * This directive is used to define custom templates for rendering board cards.
95
+ * It provides access to the template reference that can be used by the board component
96
+ * to render cards with custom layouts and styling.
97
+ *
98
+ * @publicApi
99
+ *
100
+ * @example
101
+ * ```html
102
+ * <ng-template cardTpt let-card="item" let-column="column">
103
+ * <div class="custom-card">
104
+ * <h3>{{ card.title }}</h3>
105
+ * <p>{{ card.description }}</p>
106
+ * </div>
107
+ * </ng-template>
108
+ * ```
109
+ */
37
110
  class CardTemplateDirective {
111
+ templateRef;
112
+ /**
113
+ * Creates a new CardTemplateDirective instance.
114
+ *
115
+ * @param templateRef - The template reference that contains the custom card layout
116
+ */
38
117
  constructor(templateRef) {
39
118
  this.templateRef = templateRef;
40
119
  }
41
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: CardTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
42
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: CardTemplateDirective, isStandalone: true, selector: "[cardTpt]", ngImport: i0 }); }
120
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: CardTemplateDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
121
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.3", type: CardTemplateDirective, isStandalone: true, selector: "[cardTpt]", ngImport: i0 });
43
122
  }
44
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: CardTemplateDirective, decorators: [{
123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: CardTemplateDirective, decorators: [{
45
124
  type: Directive,
46
125
  args: [{
47
126
  selector: '[cardTpt]',
@@ -49,115 +128,179 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
49
128
  }]
50
129
  }], ctorParameters: () => [{ type: i0.TemplateRef }] });
51
130
 
131
+ /**
132
+ * Standalone Kanban-style board component that provides column-based drag-and-drop,
133
+ * custom templates and infinite-scroll detection.
134
+ *
135
+ * @publicApi
136
+ */
52
137
  class HubBoardComponent {
53
- constructor() {
54
- this.board = input();
55
- this.columns = computed(() => {
56
- return this.board()?.columns ?? [];
57
- });
58
- // Used to disable the sorting of columns in the board
59
- this.columnSortingDisabled = input(false);
60
- // A template reference for the card template
61
- this.cardTpt = contentChild(CardTemplateDirective, {
138
+ /**
139
+ * Reactive input containing the full board definition (columns and cards).
140
+ */
141
+ board = input(...(ngDevMode ? [undefined, { debugName: "board" }] : []));
142
+ /**
143
+ * Pixel threshold used when determining whether a column has reached scroll end.
144
+ * Allows for fractional scroll values across different browsers.
145
+ */
146
+ scrollDetectionPadding = 1;
147
+ /**
148
+ * Derived list of board columns exposed as a signal to the template.
149
+ */
150
+ columns = computed(() => {
151
+ return this.board()?.columns ?? [];
152
+ }, ...(ngDevMode ? [{ debugName: "columns" }] : []));
153
+ /**
154
+ * When true, column reordering via drag-and-drop is disabled.
155
+ */
156
+ columnSortingDisabled = input(false, ...(ngDevMode ? [{ debugName: "columnSortingDisabled" }] : []));
157
+ /**
158
+ * Custom card template supplied via the `cardTpt` structural directive.
159
+ */
160
+ cardTpt = contentChild(CardTemplateDirective, ...(ngDevMode ? [{ debugName: "cardTpt", read: (TemplateRef) }] : [{
62
161
  read: (TemplateRef)
63
- });
64
- // A template reference for the column header template
65
- this.columnHeaderTpt = contentChild(BoardColumnHeaderDirective, {
162
+ }]));
163
+ /**
164
+ * Custom column header template supplied via the `columnHeaderTpt` structural directive.
165
+ */
166
+ columnHeaderTpt = contentChild(BoardColumnHeaderDirective, ...(ngDevMode ? [{ debugName: "columnHeaderTpt", read: (TemplateRef) }] : [{
66
167
  read: (TemplateRef)
67
- });
68
- // A template reference for the column footer template
69
- this.columnFooterTpt = contentChild(BoardColumnFooterDirective, {
168
+ }]));
169
+ /**
170
+ * Custom column footer template supplied via the `columnFooterTpt` structural directive.
171
+ */
172
+ columnFooterTpt = contentChild(BoardColumnFooterDirective, ...(ngDevMode ? [{ debugName: "columnFooterTpt", read: (TemplateRef) }] : [{
70
173
  read: (TemplateRef)
71
- });
72
- // triggered when a card is clicked
73
- this.onCardClick = new EventEmitter();
74
- // triggered when a card is moved
75
- this.onCardMoved = new EventEmitter();
76
- // triggered when a column is moved
77
- this.onColumnMoved = new EventEmitter();
78
- // emit an event when the user has scrolled to the end of a specific column in the board.
79
- this.reachedEnd = new EventEmitter();
80
- /* Defines a default enter predicate function for the drag and drop operation. */
81
- this.defaultEnterPredicateFn = () => true;
82
- }
174
+ }]));
175
+ /**
176
+ * Emits each time a card is clicked within the board.
177
+ */
178
+ onCardClick = output();
179
+ /**
180
+ * Emits when a card has been repositioned, either within the same column or into another column.
181
+ */
182
+ onCardMoved = output();
183
+ /**
184
+ * Emits when columns are reordered through drag-and-drop.
185
+ */
186
+ onColumnMoved = output();
187
+ /**
188
+ * Emits when a column body is scrolled to its end, enabling infinite-scroll behaviour.
189
+ */
190
+ reachedEnd = output();
83
191
  /**
84
- * Emits an event with the clicked item as a parameter.
192
+ * Default predicate that allows any card to be dropped into any column.
85
193
  *
86
- * @param {any} item - Represents the item that was clicked on the card.
194
+ * @returns Always `true`, indicating that drop operations are permitted.
195
+ */
196
+ defaultEnterPredicateFn = () => true;
197
+ /**
198
+ * Emits the clicked card through {@link onCardClick}.
199
+ *
200
+ * @param item - The card that triggered the click event.
87
201
  */
88
202
  cardClick(item) {
89
- this.onCardClick.next(item);
203
+ this.onCardClick.emit(item);
90
204
  }
91
205
  /**
92
- * Used to handle the event when a column is dropped in a drag and drop operation, and it moves the column in the array and
93
- * emits an event.
206
+ * Updates column order when a drag-and-drop operation completes and emits the resulting event.
94
207
  *
95
- * @param event - represents the drag and drop event that occurred.
208
+ * @param event - Drag-and-drop metadata describing the column movement.
96
209
  */
97
210
  dropColumn(event) {
98
211
  moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
99
212
  this.onColumnMoved.emit(event);
100
213
  }
101
214
  /**
102
- * Used to handle the dropping of a card in a drag and drop operation, either moving the card within the same container or
103
- * transferring it to a different container.
215
+ * Applies card reordering or transfer logic depending on the drag-drop target,
216
+ * then emits the corresponding drag event metadata.
104
217
  *
105
- * @param event - a generic type that takes three arguments:
218
+ * @param event - Drag-and-drop metadata describing the card movement.
106
219
  */
107
220
  dropCard(event) {
108
221
  if (event.previousContainer === event.container) {
222
+ // Reorder the card within the same column
109
223
  moveItemInArray(event.container.data.cards, event.previousIndex, event.currentIndex);
110
224
  }
111
225
  else {
226
+ // Transfer the card from one column to another
112
227
  transferArrayItem(event.previousContainer.data.cards, event.container.data.cards, event.previousIndex, event.currentIndex);
113
228
  }
114
229
  this.onCardMoved.emit(event);
115
230
  }
116
231
  /**
117
- * Checks if the user has scrolled to the end of a specific element and emits an event if so.
232
+ * Emits {@link reachedEnd} once a column body is scrolled to its bottom.
118
233
  *
119
- * @param {number} index - The index parameter is a number that represents the index of the column being scrolled.
120
- * @param {Event} event - The event parameter is an object that represents the scroll event. It contains information about the
121
- * scroll event, such as the source element that triggered the event, the amount of scrolling that has occurred, and the dimensions
122
- * of the scrollable area.
234
+ * @param index - Index of the scrolled column within the board.
235
+ * @param event - Browser scroll event originating from the column body element.
123
236
  */
124
237
  onScroll(index, event) {
125
238
  const el = event.target;
126
- if (el && el.scrollTop + el.clientHeight >= el.scrollHeight) {
127
- this.reachedEnd.emit({
128
- index,
129
- data: this.board()?.columns?.[index] ?? []
130
- });
239
+ if (!el) {
240
+ return;
241
+ }
242
+ const scrolledToBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - this.scrollDetectionPadding;
243
+ if (!scrolledToBottom) {
244
+ return;
131
245
  }
246
+ const column = this.board()?.columns?.[index];
247
+ if (!column) {
248
+ return;
249
+ }
250
+ this.reachedEnd.emit({
251
+ index,
252
+ data: column
253
+ });
132
254
  }
133
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: HubBoardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
134
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.8", type: HubBoardComponent, isStandalone: true, selector: "hub-board, hub-ui-board", inputs: { board: { classPropertyName: "board", publicName: "board", isSignal: true, isRequired: false, transformFunction: null }, columnSortingDisabled: { classPropertyName: "columnSortingDisabled", publicName: "columnSortingDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onCardClick: "onCardClick", onCardMoved: "onCardMoved", onColumnMoved: "onColumnMoved", reachedEnd: "reachedEnd" }, queries: [{ propertyName: "cardTpt", first: true, predicate: CardTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "columnHeaderTpt", first: true, predicate: BoardColumnHeaderDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "columnFooterTpt", first: true, predicate: BoardColumnFooterDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "@if (columns().length) {\n\t<div\n\t\tclass=\"hub-board\"\n\t\tcdkDropList\n\t\tcdkDropListOrientation=\"horizontal\"\n\t\t[cdkDropListData]=\"columns()\"\n\t\t(cdkDropListDropped)=\"dropColumn($event)\"\n\t\t[cdkDropListSortingDisabled]=\"columnSortingDisabled()\"\n\t>\n\t\t<div cdkDropListGroup class=\"hub-board__columns\">\n\t\t\t@for (column of columns(); let index = $index; track column) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"hub-board__column-container\"\n\t\t\t\t\tcdkDrag\n\t\t\t\t\t[cdkDragData]=\"column\"\n\t\t\t\t\t[cdkDragDisabled]=\"column.disabled\"\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"hub-board__column\"\n\t\t\t\t\t\t[ngClass]=\"column.classlist\"\n\t\t\t\t\t\t[ngStyle]=\"column.style\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"hub-board__column-header\">\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\tcolumnHeaderTpt() || defaultColumnHeaderTpt\n\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ column: column }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"hub-board__column-body\"\n\t\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t\t[cdkDropListData]=\"column\"\n\t\t\t\t\t\t\t(cdkDropListDropped)=\"dropCard($event)\"\n\t\t\t\t\t\t\t(scroll)=\"onScroll(index, $event)\"\n\t\t\t\t\t\t\t[cdkDropListEnterPredicate]=\"\n\t\t\t\t\t\t\t\tcolumn.predicate ?? defaultEnterPredicateFn\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t[cdkDropListSortingDisabled]=\"\n\t\t\t\t\t\t\t\tcolumn.cardSortingDisabled\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@for (\n\t\t\t\t\t\t\t\tcard of column.cards;\n\t\t\t\t\t\t\t\tlet index = $index;\n\t\t\t\t\t\t\t\ttrack card\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclass=\"hub-board__card\"\n\t\t\t\t\t\t\t\t\t[class.hub-board__card--disabled]=\"\n\t\t\t\t\t\t\t\t\t\tcard.disabled\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\tcdkDrag\n\t\t\t\t\t\t\t\t\t[cdkDragData]=\"card\"\n\t\t\t\t\t\t\t\t\t[cdkDragDisabled]=\"card.disabled\"\n\t\t\t\t\t\t\t\t\t(click)=\"cardClick(card)\"\n\t\t\t\t\t\t\t\t\t(mousedown)=\"\n\t\t\t\t\t\t\t\t\t\tcard.disabled &&\n\t\t\t\t\t\t\t\t\t\t\t$event.stopPropagation()\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t[ngClass]=\"card.classlist\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"card.style\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div class=\"hub-board__card-body\">\n\t\t\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\t\t\t\tcardTpt() || defaultCardTpt\n\t\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t\t\t\titem: card,\n\t\t\t\t\t\t\t\t\t\t\t\tcolumn\n\t\t\t\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t@if (columnFooterTpt()) {\n\t\t\t\t\t\t\t<div class=\"hub-board__column-footer\">\n\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\t\tcolumnFooterTpt() ?? null\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t\tcolumn: column\n\t\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t</div>\n}\n\n<ng-template #defaultCardTpt let-item=\"item\">\n\t<h6>{{ item.title }}</h6>\n\t<p class=\"card-text\">{{ item.description }}</p>\n</ng-template>\n\n<ng-template #defaultColumnHeaderTpt let-column=\"column\">\n\t<div class=\"d-flex flex-column\">\n\t\t<h5 class=\"hub-board__column-header-title\">\n\t\t\t{{ column.title }}\n\t\t</h5>\n\t\t<h6 class=\"hub-board__column-header-subtitle\">\n\t\t\t{{ column.description }}\n\t\t</h6>\n\t</div>\n</ng-template>\n", styles: [":host{display:block;overflow:auto;width:100%;height:100%}.hub-board__column-body{min-height:128px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] }); }
255
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HubBoardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
256
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.3", type: HubBoardComponent, isStandalone: true, selector: "hub-board, hub-ui-board", inputs: { board: { classPropertyName: "board", publicName: "board", isSignal: true, isRequired: false, transformFunction: null }, columnSortingDisabled: { classPropertyName: "columnSortingDisabled", publicName: "columnSortingDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onCardClick: "onCardClick", onCardMoved: "onCardMoved", onColumnMoved: "onColumnMoved", reachedEnd: "reachedEnd" }, queries: [{ propertyName: "cardTpt", first: true, predicate: CardTemplateDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "columnHeaderTpt", first: true, predicate: BoardColumnHeaderDirective, descendants: true, read: TemplateRef, isSignal: true }, { propertyName: "columnFooterTpt", first: true, predicate: BoardColumnFooterDirective, descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "@if (columns().length) {\n\t<div\n\t\tclass=\"hub-board\"\n\t\tcdkDropList\n\t\tcdkDropListOrientation=\"horizontal\"\n\t\t[cdkDropListData]=\"columns()\"\n\t\t(cdkDropListDropped)=\"dropColumn($event)\"\n\t\t[cdkDropListSortingDisabled]=\"columnSortingDisabled()\"\n\t>\n\t\t<div cdkDropListGroup class=\"hub-board__columns\">\n\t\t\t@for (column of columns(); let index = $index; track column) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"hub-board__column-container\"\n\t\t\t\t\tcdkDrag\n\t\t\t\t\t[cdkDragData]=\"column\"\n\t\t\t\t\t[cdkDragDisabled]=\"column.disabled\"\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"hub-board__column\"\n\t\t\t\t\t\t[ngClass]=\"column.classlist\"\n\t\t\t\t\t\t[ngStyle]=\"column.style\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"hub-board__column-header\">\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\tcolumnHeaderTpt() || defaultColumnHeaderTpt\n\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ column: column }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"hub-board__column-body\"\n\t\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t\t[cdkDropListData]=\"column\"\n\t\t\t\t\t\t\t(cdkDropListDropped)=\"dropCard($event)\"\n\t\t\t\t\t\t\t(scroll)=\"onScroll(index, $event)\"\n\t\t\t\t\t\t\t[cdkDropListEnterPredicate]=\"\n\t\t\t\t\t\t\t\tcolumn.predicate ?? defaultEnterPredicateFn\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t[cdkDropListSortingDisabled]=\"\n\t\t\t\t\t\t\t\tcolumn.cardSortingDisabled\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@for (\n\t\t\t\t\t\t\t\tcard of column.cards;\n\t\t\t\t\t\t\t\tlet index = $index;\n\t\t\t\t\t\t\t\ttrack card\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclass=\"hub-board__card\"\n\t\t\t\t\t\t\t\t\t[class.hub-board__card--disabled]=\"\n\t\t\t\t\t\t\t\t\t\tcard.disabled\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\tcdkDrag\n\t\t\t\t\t\t\t\t\t[cdkDragData]=\"card\"\n\t\t\t\t\t\t\t\t\t[cdkDragDisabled]=\"card.disabled\"\n\t\t\t\t\t\t\t\t\t(click)=\"cardClick(card)\"\n\t\t\t\t\t\t\t\t\t(mousedown)=\"\n\t\t\t\t\t\t\t\t\t\tcard.disabled &&\n\t\t\t\t\t\t\t\t\t\t\t$event.stopPropagation()\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t[ngClass]=\"card.classlist\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"card.style\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div class=\"hub-board__card-body\">\n\t\t\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\t\t\t\tcardTpt() || defaultCardTpt\n\t\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t\t\t\titem: card,\n\t\t\t\t\t\t\t\t\t\t\t\tcolumn\n\t\t\t\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t@if (columnFooterTpt()) {\n\t\t\t\t\t\t\t<div class=\"hub-board__column-footer\">\n\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\t\tcolumnFooterTpt() ?? null\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t\tcolumn: column\n\t\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t</div>\n}\n\n<ng-template #defaultCardTpt let-item=\"item\">\n\t<h6>{{ item.title }}</h6>\n\t<p class=\"card-text\">{{ item.description }}</p>\n</ng-template>\n\n<ng-template #defaultColumnHeaderTpt let-column=\"column\">\n\t<div class=\"d-flex flex-column\">\n\t\t<h5 class=\"hub-board__column-header-title\">\n\t\t\t{{ column.title }}\n\t\t</h5>\n\t\t<h6 class=\"hub-board__column-header-subtitle\">\n\t\t\t{{ column.description }}\n\t\t</h6>\n\t</div>\n</ng-template>\n", styles: [":host{display:block;overflow:auto;width:100%;height:100%}.hub-board__column-body{min-height:128px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] });
135
257
  }
136
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: HubBoardComponent, decorators: [{
258
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HubBoardComponent, decorators: [{
137
259
  type: Component,
138
260
  args: [{ selector: 'hub-board, hub-ui-board', standalone: true, imports: [NgClass, NgStyle, NgTemplateOutlet, DragDropModule], template: "@if (columns().length) {\n\t<div\n\t\tclass=\"hub-board\"\n\t\tcdkDropList\n\t\tcdkDropListOrientation=\"horizontal\"\n\t\t[cdkDropListData]=\"columns()\"\n\t\t(cdkDropListDropped)=\"dropColumn($event)\"\n\t\t[cdkDropListSortingDisabled]=\"columnSortingDisabled()\"\n\t>\n\t\t<div cdkDropListGroup class=\"hub-board__columns\">\n\t\t\t@for (column of columns(); let index = $index; track column) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"hub-board__column-container\"\n\t\t\t\t\tcdkDrag\n\t\t\t\t\t[cdkDragData]=\"column\"\n\t\t\t\t\t[cdkDragDisabled]=\"column.disabled\"\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclass=\"hub-board__column\"\n\t\t\t\t\t\t[ngClass]=\"column.classlist\"\n\t\t\t\t\t\t[ngStyle]=\"column.style\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div class=\"hub-board__column-header\">\n\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\tcolumnHeaderTpt() || defaultColumnHeaderTpt\n\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{ column: column }\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"hub-board__column-body\"\n\t\t\t\t\t\t\tcdkDropList\n\t\t\t\t\t\t\t[cdkDropListData]=\"column\"\n\t\t\t\t\t\t\t(cdkDropListDropped)=\"dropCard($event)\"\n\t\t\t\t\t\t\t(scroll)=\"onScroll(index, $event)\"\n\t\t\t\t\t\t\t[cdkDropListEnterPredicate]=\"\n\t\t\t\t\t\t\t\tcolumn.predicate ?? defaultEnterPredicateFn\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t[cdkDropListSortingDisabled]=\"\n\t\t\t\t\t\t\t\tcolumn.cardSortingDisabled\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t@for (\n\t\t\t\t\t\t\t\tcard of column.cards;\n\t\t\t\t\t\t\t\tlet index = $index;\n\t\t\t\t\t\t\t\ttrack card\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tclass=\"hub-board__card\"\n\t\t\t\t\t\t\t\t\t[class.hub-board__card--disabled]=\"\n\t\t\t\t\t\t\t\t\t\tcard.disabled\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\tcdkDrag\n\t\t\t\t\t\t\t\t\t[cdkDragData]=\"card\"\n\t\t\t\t\t\t\t\t\t[cdkDragDisabled]=\"card.disabled\"\n\t\t\t\t\t\t\t\t\t(click)=\"cardClick(card)\"\n\t\t\t\t\t\t\t\t\t(mousedown)=\"\n\t\t\t\t\t\t\t\t\t\tcard.disabled &&\n\t\t\t\t\t\t\t\t\t\t\t$event.stopPropagation()\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t[ngClass]=\"card.classlist\"\n\t\t\t\t\t\t\t\t\t[ngStyle]=\"card.style\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div class=\"hub-board__card-body\">\n\t\t\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\t\t\t\tcardTpt() || defaultCardTpt\n\t\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t\t\t\titem: card,\n\t\t\t\t\t\t\t\t\t\t\t\tcolumn\n\t\t\t\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t@if (columnFooterTpt()) {\n\t\t\t\t\t\t\t<div class=\"hub-board__column-footer\">\n\t\t\t\t\t\t\t\t<ng-container\n\t\t\t\t\t\t\t\t\t[ngTemplateOutlet]=\"\n\t\t\t\t\t\t\t\t\t\tcolumnFooterTpt() ?? null\n\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t[ngTemplateOutletContext]=\"{\n\t\t\t\t\t\t\t\t\t\tcolumn: column\n\t\t\t\t\t\t\t\t\t}\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t</ng-container>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t</div>\n}\n\n<ng-template #defaultCardTpt let-item=\"item\">\n\t<h6>{{ item.title }}</h6>\n\t<p class=\"card-text\">{{ item.description }}</p>\n</ng-template>\n\n<ng-template #defaultColumnHeaderTpt let-column=\"column\">\n\t<div class=\"d-flex flex-column\">\n\t\t<h5 class=\"hub-board__column-header-title\">\n\t\t\t{{ column.title }}\n\t\t</h5>\n\t\t<h6 class=\"hub-board__column-header-subtitle\">\n\t\t\t{{ column.description }}\n\t\t</h6>\n\t</div>\n</ng-template>\n", styles: [":host{display:block;overflow:auto;width:100%;height:100%}.hub-board__column-body{min-height:128px}.cdk-drag-preview{box-sizing:border-box;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:0}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cards.cdk-drop-list-dragging .card:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
139
- }], propDecorators: { onCardClick: [{
140
- type: Output
141
- }], onCardMoved: [{
142
- type: Output
143
- }], onColumnMoved: [{
144
- type: Output
145
- }], reachedEnd: [{
146
- type: Output
147
- }] } });
261
+ }] });
148
262
 
263
+ /**
264
+ * Angular module that provides board functionality with drag-and-drop support.
265
+ *
266
+ * This module includes all the necessary components and directives for creating
267
+ * Kanban-style boards with customizable columns, cards, and templates.
268
+ *
269
+ * @deprecated Use standalone components instead. Import individual components and directives directly.
270
+ * @publicApi
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * // Legacy module approach (not recommended)
275
+ * import { BoardModule } from 'ng-hub-ui-board';
276
+ *
277
+ * @NgModule({
278
+ * imports: [BoardModule]
279
+ * })
280
+ * export class AppModule {}
281
+ *
282
+ * // Recommended standalone approach
283
+ * import { HubBoardComponent, CardTemplateDirective } from 'ng-hub-ui-board';
284
+ *
285
+ * @Component({
286
+ * standalone: true,
287
+ * imports: [HubBoardComponent, CardTemplateDirective]
288
+ * })
289
+ * export class MyComponent {}
290
+ * ```
291
+ */
149
292
  class BoardModule {
150
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
151
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.8", ngImport: i0, type: BoardModule, imports: [HubBoardComponent,
293
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
294
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: BoardModule, imports: [HubBoardComponent,
152
295
  CardTemplateDirective,
153
296
  BoardColumnHeaderDirective,
154
297
  BoardColumnFooterDirective], exports: [HubBoardComponent,
155
298
  CardTemplateDirective,
156
299
  BoardColumnHeaderDirective,
157
- BoardColumnFooterDirective] }); }
158
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardModule, imports: [HubBoardComponent] }); }
300
+ BoardColumnFooterDirective] });
301
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardModule, imports: [HubBoardComponent] });
159
302
  }
160
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: BoardModule, decorators: [{
303
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: BoardModule, decorators: [{
161
304
  type: NgModule,
162
305
  args: [{
163
306
  declarations: [],
@@ -176,39 +319,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
176
319
  }]
177
320
  }] });
178
321
 
322
+ /**
323
+ * Converts a hexadecimal color string into its inverted counterpart, offering both
324
+ * high-contrast black/white and full-spectrum inversion modes.
325
+ *
326
+ * @publicApi
327
+ */
179
328
  class InvertColorPipe {
329
+ /**
330
+ * Inverts a HEX color value.
331
+ *
332
+ * @param hex - Color expressed as a 3- or 6-digit HEX string with or without a hash prefix.
333
+ * @param bw - When `true`, returns either black or white based on perceived brightness to maximise contrast.
334
+ * @returns The inverted color represented as a 6-digit HEX string (always prefixed with `#`).
335
+ * @throws Error if the provided value cannot be parsed as a valid HEX color.
336
+ */
180
337
  transform(hex, bw) {
181
338
  if (!hex) {
182
339
  return '#000000';
183
340
  }
184
- if (hex.indexOf('#') === 0) {
185
- hex = hex.slice(1);
341
+ let normalizedHex = hex;
342
+ if (normalizedHex.indexOf('#') === 0) {
343
+ normalizedHex = normalizedHex.slice(1);
186
344
  }
187
- // convert 3-digit hex to 6-digits.
188
- if (hex.length === 3) {
189
- hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
345
+ if (normalizedHex.length === 3) {
346
+ // Convert shorthand notation (e.g., #abc) to full length (#aabbcc)
347
+ normalizedHex =
348
+ normalizedHex[0] +
349
+ normalizedHex[0] +
350
+ normalizedHex[1] +
351
+ normalizedHex[1] +
352
+ normalizedHex[2] +
353
+ normalizedHex[2];
190
354
  }
191
- if (hex.length !== 6) {
355
+ if (normalizedHex.length !== 6) {
192
356
  throw new Error('Invalid HEX color.');
193
357
  }
194
- let r = parseInt(hex.slice(0, 2), 16);
195
- let g = parseInt(hex.slice(2, 4), 16);
196
- let b = parseInt(hex.slice(4, 6), 16);
358
+ const r = parseInt(normalizedHex.slice(0, 2), 16);
359
+ const g = parseInt(normalizedHex.slice(2, 4), 16);
360
+ const b = parseInt(normalizedHex.slice(4, 6), 16);
197
361
  if (bw) {
198
362
  // http://stackoverflow.com/a/3943023/112731
199
363
  return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#FFFFFF';
200
364
  }
201
- // invert color components
202
- r = (255 - r).toString(16);
203
- g = (255 - g).toString(16);
204
- b = (255 - b).toString(16);
205
- // pad each with zeros and return
206
- return '#' + r.padStart(2, 0) + g.padStart(2, 0) + b.padStart(2, 0);
365
+ const invertedR = (255 - r).toString(16).padStart(2, '0');
366
+ const invertedG = (255 - g).toString(16).padStart(2, '0');
367
+ const invertedB = (255 - b).toString(16).padStart(2, '0');
368
+ return `#${invertedR}${invertedG}${invertedB}`;
207
369
  }
208
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: InvertColorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
209
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.8", ngImport: i0, type: InvertColorPipe, isStandalone: true, name: "invertColor" }); }
370
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: InvertColorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
371
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.2.3", ngImport: i0, type: InvertColorPipe, isStandalone: true, name: "invertColor" });
210
372
  }
211
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: InvertColorPipe, decorators: [{
373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: InvertColorPipe, decorators: [{
212
374
  type: Pipe,
213
375
  args: [{
214
376
  name: 'invertColor',