@seniorsistemas/components-ai 2.2.0 → 2.3.0-master-cf18cf97
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/esm2022/lib/components/dynamic-form/dynamic-form.component.mjs +12 -3
- package/esm2022/lib/components/kanban-board/kanban-board.component.mjs +319 -0
- package/esm2022/lib/components/steps/steps.component.mjs +225 -0
- package/esm2022/public-api.mjs +5 -1
- package/fesm2022/seniorsistemas-components-ai.mjs +543 -6
- package/fesm2022/seniorsistemas-components-ai.mjs.map +1 -1
- package/lib/components/dynamic-form/dynamic-form.component.d.ts +6 -0
- package/lib/components/kanban-board/kanban-board.component.d.ts +104 -0
- package/lib/components/steps/steps.component.d.ts +63 -0
- package/package.json +2 -2
- package/public-api.d.ts +2 -0
- package/src/lib/styles/index.scss +16 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { NgModule, Injectable, Optional, Inject, Pipe, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, Directive,
|
|
2
|
+
import { NgModule, Injectable, Optional, Inject, Pipe, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, Directive, ContentChild, ViewChild, HostListener, ViewEncapsulation, APP_INITIALIZER, Injector, makeEnvironmentProviders, inject } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/common';
|
|
4
4
|
import { CommonModule, DOCUMENT } from '@angular/common';
|
|
5
5
|
import * as i1 from '@angular/common/http';
|
|
@@ -31,6 +31,11 @@ import * as i6$1 from 'primeng/tag';
|
|
|
31
31
|
import { TagModule } from 'primeng/tag';
|
|
32
32
|
import * as i1$2 from '@angular/router';
|
|
33
33
|
import { NavigationEnd, Router } from '@angular/router';
|
|
34
|
+
import * as i2$3 from '@angular/cdk/drag-drop';
|
|
35
|
+
import { moveItemInArray, transferArrayItem, DragDropModule } from '@angular/cdk/drag-drop';
|
|
36
|
+
import { CardModule } from 'primeng/card';
|
|
37
|
+
import * as i7$1 from 'primeng/tooltip';
|
|
38
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
34
39
|
import * as i6$2 from 'primeng/panel';
|
|
35
40
|
import { PanelModule } from 'primeng/panel';
|
|
36
41
|
import * as i9 from 'primeng/drawer';
|
|
@@ -43,8 +48,6 @@ import * as i4$2 from 'primeng/inputmask';
|
|
|
43
48
|
import { InputMaskModule } from 'primeng/inputmask';
|
|
44
49
|
import * as i5$1 from 'primeng/calendar';
|
|
45
50
|
import { CalendarModule } from 'primeng/calendar';
|
|
46
|
-
import * as i7$1 from 'primeng/tooltip';
|
|
47
|
-
import { TooltipModule } from 'primeng/tooltip';
|
|
48
51
|
import * as i3$1 from 'primeng/dropdown';
|
|
49
52
|
import { DropdownModule } from 'primeng/dropdown';
|
|
50
53
|
import * as i8$1 from 'primeng/table';
|
|
@@ -3186,6 +3189,531 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
3186
3189
|
type: Directive
|
|
3187
3190
|
}], ctorParameters: () => [{ type: EntityService }, { type: i2$2.MessageService }, { type: i2$2.ConfirmationService }, { type: TranslationService }, { type: i0.ChangeDetectorRef }] });
|
|
3188
3191
|
|
|
3192
|
+
class KanbanBoardComponent {
|
|
3193
|
+
ngZone;
|
|
3194
|
+
columns = [];
|
|
3195
|
+
allowReorder = true;
|
|
3196
|
+
allowDrag = true;
|
|
3197
|
+
showAddButton = false;
|
|
3198
|
+
showEditButton = false;
|
|
3199
|
+
showDeleteButton = false;
|
|
3200
|
+
canDeleteColumn;
|
|
3201
|
+
emptyMessage = 'No items';
|
|
3202
|
+
minColumnWidth = '280px';
|
|
3203
|
+
maxColumnWidth = '350px';
|
|
3204
|
+
/** Show scroll hint arrows when columns overflow horizontally. */
|
|
3205
|
+
showScrollHints = true;
|
|
3206
|
+
/** Enable item selection mode. Adds selected state management and CSS class on cards. */
|
|
3207
|
+
selectable = false;
|
|
3208
|
+
itemMoved = new EventEmitter();
|
|
3209
|
+
itemClicked = new EventEmitter();
|
|
3210
|
+
addItem = new EventEmitter();
|
|
3211
|
+
editColumn = new EventEmitter();
|
|
3212
|
+
deleteColumn = new EventEmitter();
|
|
3213
|
+
/** Emitted when selection changes. Payload is the full array of selected KanbanItems. */
|
|
3214
|
+
selectionChange = new EventEmitter();
|
|
3215
|
+
/** Custom template for the column header. Context: { $implicit: KanbanColumn } */
|
|
3216
|
+
columnHeaderTemplate;
|
|
3217
|
+
/**
|
|
3218
|
+
* Custom template for each item card.
|
|
3219
|
+
* Context: { $implicit: KanbanItem, column: KanbanColumn, selected: boolean, toggle: () => void }
|
|
3220
|
+
*/
|
|
3221
|
+
itemTemplate;
|
|
3222
|
+
scrollContainer;
|
|
3223
|
+
columnIds = [];
|
|
3224
|
+
// Scroll state
|
|
3225
|
+
hasHorizontalScroll = false;
|
|
3226
|
+
scrollPosition = 'start';
|
|
3227
|
+
// Selection state
|
|
3228
|
+
selectedIds = new Set();
|
|
3229
|
+
// Auto-scroll during drag
|
|
3230
|
+
autoScrollActive = false;
|
|
3231
|
+
autoScrollSpeed = 0;
|
|
3232
|
+
autoScrollRaf = null;
|
|
3233
|
+
resizeObserver;
|
|
3234
|
+
constructor(ngZone) {
|
|
3235
|
+
this.ngZone = ngZone;
|
|
3236
|
+
}
|
|
3237
|
+
ngOnInit() {
|
|
3238
|
+
this.updateColumnIds();
|
|
3239
|
+
}
|
|
3240
|
+
ngAfterViewInit() {
|
|
3241
|
+
if (this.showScrollHints) {
|
|
3242
|
+
this.checkScroll();
|
|
3243
|
+
this.ngZone.runOutsideAngular(() => {
|
|
3244
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
3245
|
+
this.ngZone.run(() => this.checkScroll());
|
|
3246
|
+
});
|
|
3247
|
+
if (this.scrollContainer?.nativeElement) {
|
|
3248
|
+
this.resizeObserver.observe(this.scrollContainer.nativeElement);
|
|
3249
|
+
}
|
|
3250
|
+
});
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
ngOnDestroy() {
|
|
3254
|
+
this.resizeObserver?.disconnect();
|
|
3255
|
+
this.stopAutoScroll();
|
|
3256
|
+
}
|
|
3257
|
+
ngOnChanges() {
|
|
3258
|
+
this.updateColumnIds();
|
|
3259
|
+
setTimeout(() => this.checkScroll(), 50);
|
|
3260
|
+
}
|
|
3261
|
+
updateColumnIds() {
|
|
3262
|
+
this.columnIds = this.columns.map(col => col.id);
|
|
3263
|
+
}
|
|
3264
|
+
// ==================== SELECTION ====================
|
|
3265
|
+
isSelected(item) {
|
|
3266
|
+
return this.selectedIds.has(item.id);
|
|
3267
|
+
}
|
|
3268
|
+
toggleSelection(item) {
|
|
3269
|
+
if (this.selectedIds.has(item.id)) {
|
|
3270
|
+
this.selectedIds.delete(item.id);
|
|
3271
|
+
}
|
|
3272
|
+
else {
|
|
3273
|
+
this.selectedIds.add(item.id);
|
|
3274
|
+
}
|
|
3275
|
+
this.emitSelectionChange();
|
|
3276
|
+
}
|
|
3277
|
+
/** Clear all selections. Can be called externally via ViewChild. */
|
|
3278
|
+
clearSelection() {
|
|
3279
|
+
this.selectedIds.clear();
|
|
3280
|
+
this.emitSelectionChange();
|
|
3281
|
+
}
|
|
3282
|
+
/** Get current selected items. */
|
|
3283
|
+
getSelectedItems() {
|
|
3284
|
+
const allItems = this.columns.flatMap(col => col.items);
|
|
3285
|
+
return allItems.filter(item => this.selectedIds.has(item.id));
|
|
3286
|
+
}
|
|
3287
|
+
emitSelectionChange() {
|
|
3288
|
+
this.selectionChange.emit(this.getSelectedItems());
|
|
3289
|
+
}
|
|
3290
|
+
/** Returns the template context for an item (used in the template). */
|
|
3291
|
+
getItemContext(item, column) {
|
|
3292
|
+
return {
|
|
3293
|
+
$implicit: item,
|
|
3294
|
+
column,
|
|
3295
|
+
selected: this.isSelected(item),
|
|
3296
|
+
toggle: () => this.toggleSelection(item)
|
|
3297
|
+
};
|
|
3298
|
+
}
|
|
3299
|
+
// ==================== SCROLL ====================
|
|
3300
|
+
onScroll() {
|
|
3301
|
+
this.checkScroll();
|
|
3302
|
+
}
|
|
3303
|
+
checkScroll() {
|
|
3304
|
+
const el = this.scrollContainer?.nativeElement;
|
|
3305
|
+
if (!el)
|
|
3306
|
+
return;
|
|
3307
|
+
const { scrollLeft, scrollWidth, clientWidth } = el;
|
|
3308
|
+
this.hasHorizontalScroll = scrollWidth > clientWidth + 2;
|
|
3309
|
+
if (scrollLeft <= 2) {
|
|
3310
|
+
this.scrollPosition = 'start';
|
|
3311
|
+
}
|
|
3312
|
+
else if (scrollLeft + clientWidth >= scrollWidth - 2) {
|
|
3313
|
+
this.scrollPosition = 'end';
|
|
3314
|
+
}
|
|
3315
|
+
else {
|
|
3316
|
+
this.scrollPosition = 'middle';
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
scrollLeft() {
|
|
3320
|
+
const el = this.scrollContainer?.nativeElement;
|
|
3321
|
+
if (!el)
|
|
3322
|
+
return;
|
|
3323
|
+
const column = el.querySelector('.kanban-column');
|
|
3324
|
+
const scrollAmount = column ? column.offsetWidth + 16 : 300;
|
|
3325
|
+
el.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
|
|
3326
|
+
}
|
|
3327
|
+
scrollRight() {
|
|
3328
|
+
const el = this.scrollContainer?.nativeElement;
|
|
3329
|
+
if (!el)
|
|
3330
|
+
return;
|
|
3331
|
+
const column = el.querySelector('.kanban-column');
|
|
3332
|
+
const scrollAmount = column ? column.offsetWidth + 16 : 300;
|
|
3333
|
+
el.scrollBy({ left: scrollAmount, behavior: 'smooth' });
|
|
3334
|
+
}
|
|
3335
|
+
// ==================== AUTO-SCROLL DURING DRAG ====================
|
|
3336
|
+
onDragMoved(event) {
|
|
3337
|
+
const el = this.scrollContainer?.nativeElement;
|
|
3338
|
+
if (!el)
|
|
3339
|
+
return;
|
|
3340
|
+
const rect = el.getBoundingClientRect();
|
|
3341
|
+
const pointerX = event.pointerPosition.x;
|
|
3342
|
+
const edgeZone = 80; // pixels from edge to trigger scroll
|
|
3343
|
+
if (pointerX < rect.left + edgeZone) {
|
|
3344
|
+
// Near left edge
|
|
3345
|
+
const proximity = 1 - (pointerX - rect.left) / edgeZone;
|
|
3346
|
+
this.autoScrollSpeed = -Math.max(3, proximity * 15);
|
|
3347
|
+
this.startAutoScroll();
|
|
3348
|
+
}
|
|
3349
|
+
else if (pointerX > rect.right - edgeZone) {
|
|
3350
|
+
// Near right edge
|
|
3351
|
+
const proximity = 1 - (rect.right - pointerX) / edgeZone;
|
|
3352
|
+
this.autoScrollSpeed = Math.max(3, proximity * 15);
|
|
3353
|
+
this.startAutoScroll();
|
|
3354
|
+
}
|
|
3355
|
+
else {
|
|
3356
|
+
this.stopAutoScroll();
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
onDragEnded() {
|
|
3360
|
+
this.stopAutoScroll();
|
|
3361
|
+
}
|
|
3362
|
+
startAutoScroll() {
|
|
3363
|
+
if (this.autoScrollActive)
|
|
3364
|
+
return;
|
|
3365
|
+
this.autoScrollActive = true;
|
|
3366
|
+
this.runAutoScroll();
|
|
3367
|
+
}
|
|
3368
|
+
stopAutoScroll() {
|
|
3369
|
+
this.autoScrollActive = false;
|
|
3370
|
+
this.autoScrollSpeed = 0;
|
|
3371
|
+
if (this.autoScrollRaf) {
|
|
3372
|
+
cancelAnimationFrame(this.autoScrollRaf);
|
|
3373
|
+
this.autoScrollRaf = null;
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
runAutoScroll() {
|
|
3377
|
+
if (!this.autoScrollActive)
|
|
3378
|
+
return;
|
|
3379
|
+
const el = this.scrollContainer?.nativeElement;
|
|
3380
|
+
if (el) {
|
|
3381
|
+
el.scrollLeft += this.autoScrollSpeed;
|
|
3382
|
+
}
|
|
3383
|
+
this.autoScrollRaf = requestAnimationFrame(() => this.runAutoScroll());
|
|
3384
|
+
}
|
|
3385
|
+
// ==================== DRAG & DROP ====================
|
|
3386
|
+
onDrop(event, column) {
|
|
3387
|
+
if (!this.allowDrag)
|
|
3388
|
+
return;
|
|
3389
|
+
const previousColumn = this.columns.find(col => col.id === event.previousContainer.id);
|
|
3390
|
+
if (event.previousContainer === event.container) {
|
|
3391
|
+
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
|
|
3392
|
+
}
|
|
3393
|
+
else {
|
|
3394
|
+
if (column.allowDrop === false)
|
|
3395
|
+
return;
|
|
3396
|
+
if (column.maxItems && event.container.data.length >= column.maxItems)
|
|
3397
|
+
return;
|
|
3398
|
+
const item = event.previousContainer.data[event.previousIndex];
|
|
3399
|
+
transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
|
|
3400
|
+
if (previousColumn) {
|
|
3401
|
+
this.itemMoved.emit({
|
|
3402
|
+
item,
|
|
3403
|
+
previousColumn,
|
|
3404
|
+
currentColumn: column,
|
|
3405
|
+
previousIndex: event.previousIndex,
|
|
3406
|
+
currentIndex: event.currentIndex
|
|
3407
|
+
});
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
onItemClick(item) {
|
|
3412
|
+
this.itemClicked.emit(item);
|
|
3413
|
+
}
|
|
3414
|
+
onAddItem(column) {
|
|
3415
|
+
this.addItem.emit(column);
|
|
3416
|
+
}
|
|
3417
|
+
onEditColumn(column) {
|
|
3418
|
+
this.editColumn.emit(column);
|
|
3419
|
+
}
|
|
3420
|
+
onDeleteColumn(column) {
|
|
3421
|
+
this.deleteColumn.emit(column);
|
|
3422
|
+
}
|
|
3423
|
+
canShowDeleteButton(column) {
|
|
3424
|
+
if (!this.showDeleteButton)
|
|
3425
|
+
return false;
|
|
3426
|
+
if (this.canDeleteColumn) {
|
|
3427
|
+
return this.canDeleteColumn(column);
|
|
3428
|
+
}
|
|
3429
|
+
return true;
|
|
3430
|
+
}
|
|
3431
|
+
getColumnStyle(column) {
|
|
3432
|
+
return {
|
|
3433
|
+
'min-width': this.minColumnWidth,
|
|
3434
|
+
'max-width': this.maxColumnWidth,
|
|
3435
|
+
'border-top': column.color ? `3px solid ${column.color}` : '3px solid #dee2e6'
|
|
3436
|
+
};
|
|
3437
|
+
}
|
|
3438
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KanbanBoardComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
3439
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: KanbanBoardComponent, isStandalone: true, selector: "sia-kanban-board", inputs: { columns: "columns", allowReorder: "allowReorder", allowDrag: "allowDrag", showAddButton: "showAddButton", showEditButton: "showEditButton", showDeleteButton: "showDeleteButton", canDeleteColumn: "canDeleteColumn", emptyMessage: "emptyMessage", minColumnWidth: "minColumnWidth", maxColumnWidth: "maxColumnWidth", showScrollHints: "showScrollHints", selectable: "selectable" }, outputs: { itemMoved: "itemMoved", itemClicked: "itemClicked", addItem: "addItem", editColumn: "editColumn", deleteColumn: "deleteColumn", selectionChange: "selectionChange" }, queries: [{ propertyName: "columnHeaderTemplate", first: true, predicate: ["columnHeaderTemplate"], descendants: true }, { propertyName: "itemTemplate", first: true, predicate: ["itemTemplate"], descendants: true }], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"kanban-board\">\n <!-- Scroll hint arrows -->\n <div class=\"kanban-scroll-controls\" *ngIf=\"showScrollHints && hasHorizontalScroll\">\n <button\n *ngIf=\"scrollPosition !== 'start'\"\n pButton\n type=\"button\"\n icon=\"pi pi-chevron-left\"\n [rounded]=\"true\"\n class=\"scroll-hint scroll-hint-left\"\n (click)=\"scrollLeft()\">\n </button>\n <button\n *ngIf=\"scrollPosition !== 'end'\"\n pButton\n type=\"button\"\n icon=\"pi pi-chevron-right\"\n [rounded]=\"true\"\n class=\"scroll-hint scroll-hint-right\"\n (click)=\"scrollRight()\">\n </button>\n </div>\n\n <!-- Scrollable columns container -->\n <div class=\"kanban-columns\" #scrollContainer (scroll)=\"onScroll()\">\n <div \n *ngFor=\"let column of columns\" \n class=\"kanban-column\"\n [style]=\"getColumnStyle(column)\">\n \n <!-- Column Header -->\n <div class=\"column-header\">\n <!-- Custom header template -->\n <ng-container *ngIf=\"columnHeaderTemplate; else defaultColumnHeader\"\n [ngTemplateOutlet]=\"columnHeaderTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: column }\">\n </ng-container>\n\n <ng-template #defaultColumnHeader>\n <div class=\"column-title\">\n <i *ngIf=\"column.icon\" [class]=\"'pi ' + column.icon\"></i>\n <span>{{ column.title }}</span>\n <span class=\"item-count\">{{ column.items.length }}</span>\n </div>\n <div class=\"column-actions\">\n <button \n *ngIf=\"showAddButton\"\n pButton \n type=\"button\" \n icon=\"pi pi-plus\" \n class=\"p-button-text p-button-sm p-button-rounded\"\n (click)=\"onAddItem(column)\"\n [pTooltip]=\"'Add item'\"\n tooltipPosition=\"top\">\n </button>\n <button \n *ngIf=\"showEditButton\"\n pButton \n type=\"button\" \n icon=\"pi pi-pencil\" \n class=\"p-button-text p-button-sm p-button-rounded\"\n (click)=\"onEditColumn(column)\"\n [pTooltip]=\"'Edit column'\"\n tooltipPosition=\"top\">\n </button>\n <button \n *ngIf=\"canShowDeleteButton(column)\"\n pButton \n type=\"button\" \n icon=\"pi pi-trash\" \n class=\"p-button-text p-button-sm p-button-rounded p-button-danger\"\n (click)=\"onDeleteColumn(column)\"\n [pTooltip]=\"'Delete column'\"\n tooltipPosition=\"top\">\n </button>\n </div>\n </ng-template>\n </div>\n\n <!-- Column Content -->\n <div \n class=\"column-content\"\n cdkDropList\n [id]=\"column.id\"\n [cdkDropListData]=\"column.items\"\n [cdkDropListConnectedTo]=\"columnIds\"\n (cdkDropListDropped)=\"onDrop($event, column)\">\n \n <!-- Items -->\n <div \n *ngFor=\"let item of column.items\"\n class=\"kanban-item\"\n [class.kanban-item--selected]=\"selectable && isSelected(item)\"\n cdkDrag\n [cdkDragDisabled]=\"!allowDrag\"\n (cdkDragMoved)=\"onDragMoved($event)\"\n (cdkDragEnded)=\"onDragEnded()\"\n (click)=\"onItemClick(item)\">\n \n <!-- Custom item template with selection context -->\n <ng-container *ngIf=\"itemTemplate; else defaultItem\"\n [ngTemplateOutlet]=\"itemTemplate\"\n [ngTemplateOutletContext]=\"getItemContext(item, column)\">\n </ng-container>\n\n <ng-template #defaultItem>\n <div class=\"item-content\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div *ngIf=\"item.description\" class=\"item-description\">\n {{ item.description }}\n </div>\n <div *ngIf=\"item.tags && item.tags.length > 0\" class=\"item-tags\">\n <p-tag \n *ngFor=\"let tag of item.tags\"\n [value]=\"tag.label\"\n [severity]=\"tag.severity || 'secondary'\"\n styleClass=\"item-tag\">\n </p-tag>\n </div>\n </div>\n </ng-template>\n\n <!-- Drag Placeholder -->\n <div class=\"item-placeholder\" *cdkDragPlaceholder></div>\n </div>\n\n <!-- Empty State -->\n <div *ngIf=\"column.items.length === 0\" class=\"empty-column\">\n <i class=\"pi pi-inbox\"></i>\n <p>{{ emptyMessage }}</p>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".kanban-board{position:relative;width:100%;height:100%;padding:1rem}.kanban-board .kanban-scroll-controls{position:absolute;inset:0;pointer-events:none;z-index:10}.kanban-board .kanban-scroll-controls .scroll-hint{position:absolute;top:50%;transform:translateY(-50%);pointer-events:auto;box-shadow:0 4px 12px #00000026;transition:all .3s ease}.kanban-board .kanban-scroll-controls .scroll-hint:hover{transform:translateY(-50%) scale(1.1);box-shadow:0 6px 16px #0003}.kanban-board .kanban-scroll-controls .scroll-hint.scroll-hint-left{left:.5rem}.kanban-board .kanban-scroll-controls .scroll-hint.scroll-hint-right{right:.5rem}.kanban-board .kanban-columns{display:flex;gap:1rem;min-height:500px;padding-bottom:1rem;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}.kanban-board .kanban-columns::-webkit-scrollbar{height:6px}.kanban-board .kanban-columns::-webkit-scrollbar-track{background:transparent}.kanban-board .kanban-columns::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:3px}.kanban-board .kanban-columns::-webkit-scrollbar-thumb:hover{background:#94a3b880}.kanban-board .kanban-column{flex-shrink:0;display:flex;flex-direction:column;background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000001a}.kanban-board .kanban-column .column-header{display:flex;justify-content:space-between;align-items:center;padding:1rem;border-bottom:1px solid #e9ecef;background:#fafbfc;border-radius:8px 8px 0 0}.kanban-board .kanban-column .column-header .column-title{display:flex;align-items:center;gap:.5rem;font-weight:600;color:#2c3e50;font-size:.95rem}.kanban-board .kanban-column .column-header .column-title .pi{font-size:.875rem;color:#6c757d}.kanban-board .kanban-column .column-header .column-title .item-count{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:24px;padding:0 .5rem;background:#e9ecef;border-radius:12px;font-size:.75rem;font-weight:600;color:#495057}.kanban-board .kanban-column .column-header .column-actions{display:flex;gap:.25rem}.kanban-board .kanban-column .column-content{flex:1;padding:.75rem;overflow-y:auto;min-height:200px}.kanban-board .kanban-column .column-content .kanban-item{background:#fff;border:1px solid #e9ecef;border-radius:6px;padding:.875rem;margin-bottom:.75rem;cursor:pointer;transition:all .2s ease;box-shadow:0 1px 2px #0000000d}.kanban-board .kanban-column .column-content .kanban-item:hover{border-color:#007bff;box-shadow:0 2px 8px #007bff26;transform:translateY(-1px)}.kanban-board .kanban-column .column-content .kanban-item:last-child{margin-bottom:0}.kanban-board .kanban-column .column-content .kanban-item.kanban-item--selected{border-left:3px solid #007bff;background:#f0f7ff}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-title{font-weight:500;color:#2c3e50;font-size:.875rem;margin-bottom:.5rem;line-height:1.4}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-description{font-size:.8rem;color:#6c757d;margin-bottom:.5rem;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-tags{display:flex;flex-wrap:wrap;gap:.375rem;margin-top:.5rem}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-tags ::ng-deep .item-tag{font-size:.7rem;padding:.25rem .5rem}.kanban-board .kanban-column .column-content .kanban-item .item-placeholder{background:#e9ecef;border:2px dashed #adb5bd;border-radius:6px;min-height:80px}.kanban-board .kanban-column .column-content .empty-column{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem 1rem;color:#adb5bd;text-align:center}.kanban-board .kanban-column .column-content .empty-column .pi{font-size:2.5rem;margin-bottom:.5rem;opacity:.5}.kanban-board .kanban-column .column-content .empty-column p{font-size:.875rem;margin:0}::ng-deep .cdk-drag-preview{background:#fff;border:1px solid #007bff;border-radius:6px;padding:.875rem;box-shadow:0 4px 12px #007bff4d;opacity:.9;cursor:grabbing}::ng-deep .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}::ng-deep .cdk-drop-list-dragging .kanban-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}@media (max-width: 768px){.kanban-board .kanban-columns{flex-direction:column}.kanban-board .kanban-column{min-width:100%!important;max-width:100%!important}.kanban-board .kanban-scroll-controls{display:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2$3.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: i2$3.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"] }, { kind: "directive", type: i2$3.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: CardModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i6$1.Tag, selector: "p-tag", inputs: ["style", "styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i7$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }] });
|
|
3440
|
+
}
|
|
3441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: KanbanBoardComponent, decorators: [{
|
|
3442
|
+
type: Component,
|
|
3443
|
+
args: [{ selector: 'sia-kanban-board', standalone: true, imports: [
|
|
3444
|
+
CommonModule,
|
|
3445
|
+
DragDropModule,
|
|
3446
|
+
ButtonModule,
|
|
3447
|
+
CardModule,
|
|
3448
|
+
TagModule,
|
|
3449
|
+
TooltipModule
|
|
3450
|
+
], template: "<div class=\"kanban-board\">\n <!-- Scroll hint arrows -->\n <div class=\"kanban-scroll-controls\" *ngIf=\"showScrollHints && hasHorizontalScroll\">\n <button\n *ngIf=\"scrollPosition !== 'start'\"\n pButton\n type=\"button\"\n icon=\"pi pi-chevron-left\"\n [rounded]=\"true\"\n class=\"scroll-hint scroll-hint-left\"\n (click)=\"scrollLeft()\">\n </button>\n <button\n *ngIf=\"scrollPosition !== 'end'\"\n pButton\n type=\"button\"\n icon=\"pi pi-chevron-right\"\n [rounded]=\"true\"\n class=\"scroll-hint scroll-hint-right\"\n (click)=\"scrollRight()\">\n </button>\n </div>\n\n <!-- Scrollable columns container -->\n <div class=\"kanban-columns\" #scrollContainer (scroll)=\"onScroll()\">\n <div \n *ngFor=\"let column of columns\" \n class=\"kanban-column\"\n [style]=\"getColumnStyle(column)\">\n \n <!-- Column Header -->\n <div class=\"column-header\">\n <!-- Custom header template -->\n <ng-container *ngIf=\"columnHeaderTemplate; else defaultColumnHeader\"\n [ngTemplateOutlet]=\"columnHeaderTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: column }\">\n </ng-container>\n\n <ng-template #defaultColumnHeader>\n <div class=\"column-title\">\n <i *ngIf=\"column.icon\" [class]=\"'pi ' + column.icon\"></i>\n <span>{{ column.title }}</span>\n <span class=\"item-count\">{{ column.items.length }}</span>\n </div>\n <div class=\"column-actions\">\n <button \n *ngIf=\"showAddButton\"\n pButton \n type=\"button\" \n icon=\"pi pi-plus\" \n class=\"p-button-text p-button-sm p-button-rounded\"\n (click)=\"onAddItem(column)\"\n [pTooltip]=\"'Add item'\"\n tooltipPosition=\"top\">\n </button>\n <button \n *ngIf=\"showEditButton\"\n pButton \n type=\"button\" \n icon=\"pi pi-pencil\" \n class=\"p-button-text p-button-sm p-button-rounded\"\n (click)=\"onEditColumn(column)\"\n [pTooltip]=\"'Edit column'\"\n tooltipPosition=\"top\">\n </button>\n <button \n *ngIf=\"canShowDeleteButton(column)\"\n pButton \n type=\"button\" \n icon=\"pi pi-trash\" \n class=\"p-button-text p-button-sm p-button-rounded p-button-danger\"\n (click)=\"onDeleteColumn(column)\"\n [pTooltip]=\"'Delete column'\"\n tooltipPosition=\"top\">\n </button>\n </div>\n </ng-template>\n </div>\n\n <!-- Column Content -->\n <div \n class=\"column-content\"\n cdkDropList\n [id]=\"column.id\"\n [cdkDropListData]=\"column.items\"\n [cdkDropListConnectedTo]=\"columnIds\"\n (cdkDropListDropped)=\"onDrop($event, column)\">\n \n <!-- Items -->\n <div \n *ngFor=\"let item of column.items\"\n class=\"kanban-item\"\n [class.kanban-item--selected]=\"selectable && isSelected(item)\"\n cdkDrag\n [cdkDragDisabled]=\"!allowDrag\"\n (cdkDragMoved)=\"onDragMoved($event)\"\n (cdkDragEnded)=\"onDragEnded()\"\n (click)=\"onItemClick(item)\">\n \n <!-- Custom item template with selection context -->\n <ng-container *ngIf=\"itemTemplate; else defaultItem\"\n [ngTemplateOutlet]=\"itemTemplate\"\n [ngTemplateOutletContext]=\"getItemContext(item, column)\">\n </ng-container>\n\n <ng-template #defaultItem>\n <div class=\"item-content\">\n <div class=\"item-title\">{{ item.title }}</div>\n <div *ngIf=\"item.description\" class=\"item-description\">\n {{ item.description }}\n </div>\n <div *ngIf=\"item.tags && item.tags.length > 0\" class=\"item-tags\">\n <p-tag \n *ngFor=\"let tag of item.tags\"\n [value]=\"tag.label\"\n [severity]=\"tag.severity || 'secondary'\"\n styleClass=\"item-tag\">\n </p-tag>\n </div>\n </div>\n </ng-template>\n\n <!-- Drag Placeholder -->\n <div class=\"item-placeholder\" *cdkDragPlaceholder></div>\n </div>\n\n <!-- Empty State -->\n <div *ngIf=\"column.items.length === 0\" class=\"empty-column\">\n <i class=\"pi pi-inbox\"></i>\n <p>{{ emptyMessage }}</p>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".kanban-board{position:relative;width:100%;height:100%;padding:1rem}.kanban-board .kanban-scroll-controls{position:absolute;inset:0;pointer-events:none;z-index:10}.kanban-board .kanban-scroll-controls .scroll-hint{position:absolute;top:50%;transform:translateY(-50%);pointer-events:auto;box-shadow:0 4px 12px #00000026;transition:all .3s ease}.kanban-board .kanban-scroll-controls .scroll-hint:hover{transform:translateY(-50%) scale(1.1);box-shadow:0 6px 16px #0003}.kanban-board .kanban-scroll-controls .scroll-hint.scroll-hint-left{left:.5rem}.kanban-board .kanban-scroll-controls .scroll-hint.scroll-hint-right{right:.5rem}.kanban-board .kanban-columns{display:flex;gap:1rem;min-height:500px;padding-bottom:1rem;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}.kanban-board .kanban-columns::-webkit-scrollbar{height:6px}.kanban-board .kanban-columns::-webkit-scrollbar-track{background:transparent}.kanban-board .kanban-columns::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:3px}.kanban-board .kanban-columns::-webkit-scrollbar-thumb:hover{background:#94a3b880}.kanban-board .kanban-column{flex-shrink:0;display:flex;flex-direction:column;background:#fff;border-radius:8px;box-shadow:0 1px 3px #0000001a}.kanban-board .kanban-column .column-header{display:flex;justify-content:space-between;align-items:center;padding:1rem;border-bottom:1px solid #e9ecef;background:#fafbfc;border-radius:8px 8px 0 0}.kanban-board .kanban-column .column-header .column-title{display:flex;align-items:center;gap:.5rem;font-weight:600;color:#2c3e50;font-size:.95rem}.kanban-board .kanban-column .column-header .column-title .pi{font-size:.875rem;color:#6c757d}.kanban-board .kanban-column .column-header .column-title .item-count{display:inline-flex;align-items:center;justify-content:center;min-width:24px;height:24px;padding:0 .5rem;background:#e9ecef;border-radius:12px;font-size:.75rem;font-weight:600;color:#495057}.kanban-board .kanban-column .column-header .column-actions{display:flex;gap:.25rem}.kanban-board .kanban-column .column-content{flex:1;padding:.75rem;overflow-y:auto;min-height:200px}.kanban-board .kanban-column .column-content .kanban-item{background:#fff;border:1px solid #e9ecef;border-radius:6px;padding:.875rem;margin-bottom:.75rem;cursor:pointer;transition:all .2s ease;box-shadow:0 1px 2px #0000000d}.kanban-board .kanban-column .column-content .kanban-item:hover{border-color:#007bff;box-shadow:0 2px 8px #007bff26;transform:translateY(-1px)}.kanban-board .kanban-column .column-content .kanban-item:last-child{margin-bottom:0}.kanban-board .kanban-column .column-content .kanban-item.kanban-item--selected{border-left:3px solid #007bff;background:#f0f7ff}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-title{font-weight:500;color:#2c3e50;font-size:.875rem;margin-bottom:.5rem;line-height:1.4}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-description{font-size:.8rem;color:#6c757d;margin-bottom:.5rem;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-tags{display:flex;flex-wrap:wrap;gap:.375rem;margin-top:.5rem}.kanban-board .kanban-column .column-content .kanban-item .item-content .item-tags ::ng-deep .item-tag{font-size:.7rem;padding:.25rem .5rem}.kanban-board .kanban-column .column-content .kanban-item .item-placeholder{background:#e9ecef;border:2px dashed #adb5bd;border-radius:6px;min-height:80px}.kanban-board .kanban-column .column-content .empty-column{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:2rem 1rem;color:#adb5bd;text-align:center}.kanban-board .kanban-column .column-content .empty-column .pi{font-size:2.5rem;margin-bottom:.5rem;opacity:.5}.kanban-board .kanban-column .column-content .empty-column p{font-size:.875rem;margin:0}::ng-deep .cdk-drag-preview{background:#fff;border:1px solid #007bff;border-radius:6px;padding:.875rem;box-shadow:0 4px 12px #007bff4d;opacity:.9;cursor:grabbing}::ng-deep .cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}::ng-deep .cdk-drop-list-dragging .kanban-item:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}@media (max-width: 768px){.kanban-board .kanban-columns{flex-direction:column}.kanban-board .kanban-column{min-width:100%!important;max-width:100%!important}.kanban-board .kanban-scroll-controls{display:none}}\n"] }]
|
|
3451
|
+
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { columns: [{
|
|
3452
|
+
type: Input
|
|
3453
|
+
}], allowReorder: [{
|
|
3454
|
+
type: Input
|
|
3455
|
+
}], allowDrag: [{
|
|
3456
|
+
type: Input
|
|
3457
|
+
}], showAddButton: [{
|
|
3458
|
+
type: Input
|
|
3459
|
+
}], showEditButton: [{
|
|
3460
|
+
type: Input
|
|
3461
|
+
}], showDeleteButton: [{
|
|
3462
|
+
type: Input
|
|
3463
|
+
}], canDeleteColumn: [{
|
|
3464
|
+
type: Input
|
|
3465
|
+
}], emptyMessage: [{
|
|
3466
|
+
type: Input
|
|
3467
|
+
}], minColumnWidth: [{
|
|
3468
|
+
type: Input
|
|
3469
|
+
}], maxColumnWidth: [{
|
|
3470
|
+
type: Input
|
|
3471
|
+
}], showScrollHints: [{
|
|
3472
|
+
type: Input
|
|
3473
|
+
}], selectable: [{
|
|
3474
|
+
type: Input
|
|
3475
|
+
}], itemMoved: [{
|
|
3476
|
+
type: Output
|
|
3477
|
+
}], itemClicked: [{
|
|
3478
|
+
type: Output
|
|
3479
|
+
}], addItem: [{
|
|
3480
|
+
type: Output
|
|
3481
|
+
}], editColumn: [{
|
|
3482
|
+
type: Output
|
|
3483
|
+
}], deleteColumn: [{
|
|
3484
|
+
type: Output
|
|
3485
|
+
}], selectionChange: [{
|
|
3486
|
+
type: Output
|
|
3487
|
+
}], columnHeaderTemplate: [{
|
|
3488
|
+
type: ContentChild,
|
|
3489
|
+
args: ['columnHeaderTemplate']
|
|
3490
|
+
}], itemTemplate: [{
|
|
3491
|
+
type: ContentChild,
|
|
3492
|
+
args: ['itemTemplate']
|
|
3493
|
+
}], scrollContainer: [{
|
|
3494
|
+
type: ViewChild,
|
|
3495
|
+
args: ['scrollContainer', { static: false }]
|
|
3496
|
+
}] } });
|
|
3497
|
+
|
|
3498
|
+
class StepsComponent {
|
|
3499
|
+
cdr;
|
|
3500
|
+
/** Lista de steps a serem exibidos */
|
|
3501
|
+
steps = [];
|
|
3502
|
+
/** Índice do step ativo */
|
|
3503
|
+
activeIndex = 0;
|
|
3504
|
+
/** Se permite clicar nos steps para navegar */
|
|
3505
|
+
readonly = false;
|
|
3506
|
+
/** Quantidade máxima de steps visíveis. 'auto' calcula com base no container */
|
|
3507
|
+
maxVisible = 'auto';
|
|
3508
|
+
/** Largura mínima de cada step em pixels (usado no cálculo automático) */
|
|
3509
|
+
stepMinWidth = 140;
|
|
3510
|
+
/** Se mostra animação de transição ao navegar */
|
|
3511
|
+
animated = true;
|
|
3512
|
+
/** Modo de navegação das setas: 'step' altera o activeIndex, 'scroll' apenas desloca a janela visível */
|
|
3513
|
+
navigationMode = 'step';
|
|
3514
|
+
/** Esquema de cores aplicado aos steps. Altera as cores do ativo e completados */
|
|
3515
|
+
colorScheme = 'default';
|
|
3516
|
+
/** Classe CSS customizada para o wrapper */
|
|
3517
|
+
styleClass = '';
|
|
3518
|
+
/** Emite quando o activeIndex muda por clique */
|
|
3519
|
+
activeIndexChange = new EventEmitter();
|
|
3520
|
+
/** Emite o StepItem clicado */
|
|
3521
|
+
stepClick = new EventEmitter();
|
|
3522
|
+
stepsContainer;
|
|
3523
|
+
visibleSteps = [];
|
|
3524
|
+
visibleStartIndex = 0;
|
|
3525
|
+
visibleEndIndex = 0;
|
|
3526
|
+
hasOverflowLeft = false;
|
|
3527
|
+
hasOverflowRight = false;
|
|
3528
|
+
calculatedMaxVisible = 5;
|
|
3529
|
+
resizeObserver = null;
|
|
3530
|
+
constructor(cdr) {
|
|
3531
|
+
this.cdr = cdr;
|
|
3532
|
+
}
|
|
3533
|
+
ngOnChanges(changes) {
|
|
3534
|
+
if (changes['steps'] || changes['activeIndex'] || changes['maxVisible']) {
|
|
3535
|
+
this.recalculate();
|
|
3536
|
+
}
|
|
3537
|
+
}
|
|
3538
|
+
ngAfterViewInit() {
|
|
3539
|
+
this.setupResizeObserver();
|
|
3540
|
+
// Delay para garantir que o container já tem dimensões
|
|
3541
|
+
setTimeout(() => this.recalculate(), 0);
|
|
3542
|
+
}
|
|
3543
|
+
ngOnDestroy() {
|
|
3544
|
+
this.resizeObserver?.disconnect();
|
|
3545
|
+
}
|
|
3546
|
+
onStepClick(step, visibleIndex) {
|
|
3547
|
+
if (this.readonly || step.disabled)
|
|
3548
|
+
return;
|
|
3549
|
+
const realIndex = this.visibleStartIndex + visibleIndex;
|
|
3550
|
+
this.activeIndex = realIndex;
|
|
3551
|
+
this.activeIndexChange.emit(realIndex);
|
|
3552
|
+
this.stepClick.emit(step);
|
|
3553
|
+
this.recalculate();
|
|
3554
|
+
}
|
|
3555
|
+
navigateLeft() {
|
|
3556
|
+
if (this.visibleStartIndex <= 0)
|
|
3557
|
+
return;
|
|
3558
|
+
if (this.navigationMode === 'scroll') {
|
|
3559
|
+
// Apenas desloca a janela sem alterar o activeIndex
|
|
3560
|
+
this.scrollWindow(this.visibleStartIndex - 1);
|
|
3561
|
+
}
|
|
3562
|
+
else {
|
|
3563
|
+
const newActive = Math.max(0, this.activeIndex - 1);
|
|
3564
|
+
this.activeIndex = newActive;
|
|
3565
|
+
this.activeIndexChange.emit(newActive);
|
|
3566
|
+
this.recalculate();
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3569
|
+
navigateRight() {
|
|
3570
|
+
if (this.visibleEndIndex >= this.steps.length - 1)
|
|
3571
|
+
return;
|
|
3572
|
+
if (this.navigationMode === 'scroll') {
|
|
3573
|
+
// Apenas desloca a janela sem alterar o activeIndex
|
|
3574
|
+
this.scrollWindow(this.visibleStartIndex + 1);
|
|
3575
|
+
}
|
|
3576
|
+
else {
|
|
3577
|
+
const newActive = Math.min(this.steps.length - 1, this.activeIndex + 1);
|
|
3578
|
+
this.activeIndex = newActive;
|
|
3579
|
+
this.activeIndexChange.emit(newActive);
|
|
3580
|
+
this.recalculate();
|
|
3581
|
+
}
|
|
3582
|
+
}
|
|
3583
|
+
/** Desloca a janela visível para um novo startIndex sem alterar o activeIndex */
|
|
3584
|
+
scrollWindow(newStart) {
|
|
3585
|
+
const total = this.steps.length;
|
|
3586
|
+
const max = this.calculatedMaxVisible;
|
|
3587
|
+
let start = Math.max(0, Math.min(newStart, total - max));
|
|
3588
|
+
let end = start + max - 1;
|
|
3589
|
+
if (end >= total) {
|
|
3590
|
+
end = total - 1;
|
|
3591
|
+
start = end - max + 1;
|
|
3592
|
+
}
|
|
3593
|
+
this.visibleStartIndex = start;
|
|
3594
|
+
this.visibleEndIndex = end;
|
|
3595
|
+
this.hasOverflowLeft = start > 0;
|
|
3596
|
+
this.hasOverflowRight = end < total - 1;
|
|
3597
|
+
this.visibleSteps = this.steps.slice(start, end + 1);
|
|
3598
|
+
this.cdr.markForCheck();
|
|
3599
|
+
}
|
|
3600
|
+
getStepState(visibleIndex) {
|
|
3601
|
+
const realIndex = this.visibleStartIndex + visibleIndex;
|
|
3602
|
+
if (realIndex < this.activeIndex)
|
|
3603
|
+
return 'completed';
|
|
3604
|
+
if (realIndex === this.activeIndex)
|
|
3605
|
+
return 'active';
|
|
3606
|
+
return 'pending';
|
|
3607
|
+
}
|
|
3608
|
+
getRealIndex(visibleIndex) {
|
|
3609
|
+
return this.visibleStartIndex + visibleIndex;
|
|
3610
|
+
}
|
|
3611
|
+
get hiddenLeftCount() {
|
|
3612
|
+
return this.visibleStartIndex;
|
|
3613
|
+
}
|
|
3614
|
+
get hiddenRightCount() {
|
|
3615
|
+
return Math.max(0, this.steps.length - 1 - this.visibleEndIndex);
|
|
3616
|
+
}
|
|
3617
|
+
trackByIndex(index) {
|
|
3618
|
+
return index;
|
|
3619
|
+
}
|
|
3620
|
+
setupResizeObserver() {
|
|
3621
|
+
if (!this.stepsContainer?.nativeElement)
|
|
3622
|
+
return;
|
|
3623
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
3624
|
+
this.recalculate();
|
|
3625
|
+
});
|
|
3626
|
+
this.resizeObserver.observe(this.stepsContainer.nativeElement);
|
|
3627
|
+
}
|
|
3628
|
+
recalculate() {
|
|
3629
|
+
if (!this.steps.length) {
|
|
3630
|
+
this.visibleSteps = [];
|
|
3631
|
+
this.hasOverflowLeft = false;
|
|
3632
|
+
this.hasOverflowRight = false;
|
|
3633
|
+
this.cdr.markForCheck();
|
|
3634
|
+
return;
|
|
3635
|
+
}
|
|
3636
|
+
this.calculatedMaxVisible = this.getMaxVisible();
|
|
3637
|
+
this.calculateVisibleWindow();
|
|
3638
|
+
this.cdr.markForCheck();
|
|
3639
|
+
}
|
|
3640
|
+
getMaxVisible() {
|
|
3641
|
+
if (this.maxVisible !== 'auto') {
|
|
3642
|
+
return Math.max(1, this.maxVisible);
|
|
3643
|
+
}
|
|
3644
|
+
if (!this.stepsContainer?.nativeElement) {
|
|
3645
|
+
return Math.min(5, this.steps.length);
|
|
3646
|
+
}
|
|
3647
|
+
const containerWidth = this.stepsContainer.nativeElement.offsetWidth;
|
|
3648
|
+
// Reservar espaço para os botões de navegação (40px cada lado)
|
|
3649
|
+
const availableWidth = containerWidth - 80;
|
|
3650
|
+
const maxFit = Math.max(1, Math.floor(availableWidth / this.stepMinWidth));
|
|
3651
|
+
return Math.min(maxFit, this.steps.length);
|
|
3652
|
+
}
|
|
3653
|
+
calculateVisibleWindow() {
|
|
3654
|
+
const total = this.steps.length;
|
|
3655
|
+
const max = this.calculatedMaxVisible;
|
|
3656
|
+
if (total <= max) {
|
|
3657
|
+
// Todos cabem na tela
|
|
3658
|
+
this.visibleStartIndex = 0;
|
|
3659
|
+
this.visibleEndIndex = total - 1;
|
|
3660
|
+
this.hasOverflowLeft = false;
|
|
3661
|
+
this.hasOverflowRight = false;
|
|
3662
|
+
}
|
|
3663
|
+
else {
|
|
3664
|
+
// Centralizar no activeIndex
|
|
3665
|
+
const half = Math.floor(max / 2);
|
|
3666
|
+
let start = this.activeIndex - half;
|
|
3667
|
+
let end = start + max - 1;
|
|
3668
|
+
// Ajustar limites
|
|
3669
|
+
if (start < 0) {
|
|
3670
|
+
start = 0;
|
|
3671
|
+
end = max - 1;
|
|
3672
|
+
}
|
|
3673
|
+
else if (end >= total) {
|
|
3674
|
+
end = total - 1;
|
|
3675
|
+
start = end - max + 1;
|
|
3676
|
+
}
|
|
3677
|
+
this.visibleStartIndex = start;
|
|
3678
|
+
this.visibleEndIndex = end;
|
|
3679
|
+
this.hasOverflowLeft = start > 0;
|
|
3680
|
+
this.hasOverflowRight = end < total - 1;
|
|
3681
|
+
}
|
|
3682
|
+
this.visibleSteps = this.steps.slice(this.visibleStartIndex, this.visibleEndIndex + 1);
|
|
3683
|
+
}
|
|
3684
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StepsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3685
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: StepsComponent, isStandalone: true, selector: "sia-steps", inputs: { steps: "steps", activeIndex: "activeIndex", readonly: "readonly", maxVisible: "maxVisible", stepMinWidth: "stepMinWidth", animated: "animated", navigationMode: "navigationMode", colorScheme: "colorScheme", styleClass: "styleClass" }, outputs: { activeIndexChange: "activeIndexChange", stepClick: "stepClick" }, viewQueries: [{ propertyName: "stepsContainer", first: true, predicate: ["stepsContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"sia-steps-wrapper\" [class]=\"styleClass\" [class.animated]=\"animated\"\n [class.theme-success]=\"colorScheme === 'success'\"\n [class.theme-danger]=\"colorScheme === 'danger'\"\n [class.theme-warning]=\"colorScheme === 'warning'\"\n [class.theme-info]=\"colorScheme === 'info'\"\n #stepsContainer>\n <!-- Bot\u00E3o de navega\u00E7\u00E3o esquerda -->\n <button\n *ngIf=\"hasOverflowLeft\"\n class=\"sia-steps-nav sia-steps-nav-left\"\n (click)=\"navigateLeft()\"\n [attr.aria-label]=\"'Anterior (' + hiddenLeftCount + ' ocultos)'\"\n type=\"button\">\n <span class=\"nav-badge\">{{ hiddenLeftCount }}</span>\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n\n <!-- Steps vis\u00EDveis -->\n <div class=\"sia-steps-content\" [class.has-overflow-left]=\"hasOverflowLeft\" [class.has-overflow-right]=\"hasOverflowRight\">\n <div class=\"sia-steps-list\">\n <ng-container *ngFor=\"let step of visibleSteps; let i = index; let first = first; let last = last; trackBy: trackByIndex\">\n <!-- Conector (n\u00E3o aparece antes do primeiro) -->\n <div *ngIf=\"!first\" class=\"sia-step-connector\" [class.completed]=\"getStepState(i) === 'completed' || getStepState(i - 1) === 'completed'\">\n <div class=\"connector-line\"></div>\n </div>\n\n <!-- Step item -->\n <div\n class=\"sia-step-item\"\n [class.active]=\"getStepState(i) === 'active'\"\n [class.completed]=\"getStepState(i) === 'completed'\"\n [class.pending]=\"getStepState(i) === 'pending'\"\n [class.disabled]=\"step.disabled\"\n [class.clickable]=\"!readonly && !step.disabled\"\n [class]=\"step.styleClass || ''\"\n [pTooltip]=\"step.label\"\n tooltipPosition=\"top\"\n (click)=\"onStepClick(step, i)\"\n [attr.role]=\"readonly ? 'listitem' : 'button'\"\n [attr.aria-current]=\"getStepState(i) === 'active' ? 'step' : null\"\n [attr.aria-disabled]=\"step.disabled || readonly\">\n \n <!-- \u00CDcone/n\u00FAmero do step -->\n <div class=\"sia-step-marker\">\n <i *ngIf=\"getStepState(i) === 'completed' && !step.icon\" class=\"pi pi-check\"></i>\n <i *ngIf=\"step.icon && getStepState(i) !== 'completed'\" [class]=\"'pi ' + step.icon\"></i>\n <span *ngIf=\"!step.icon && getStepState(i) !== 'completed'\">{{ getRealIndex(i) + 1 }}</span>\n </div>\n\n <!-- Label do step -->\n <div class=\"sia-step-label\">\n <span class=\"label-text\">{{ step.label }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Bot\u00E3o de navega\u00E7\u00E3o direita -->\n <button\n *ngIf=\"hasOverflowRight\"\n class=\"sia-steps-nav sia-steps-nav-right\"\n (click)=\"navigateRight()\"\n [attr.aria-label]=\"'Pr\u00F3ximo (' + hiddenRightCount + ' ocultos)'\"\n type=\"button\">\n <i class=\"pi pi-chevron-right\"></i>\n <span class=\"nav-badge\">{{ hiddenRightCount }}</span>\n </button>\n</div>\n", styles: [":host{display:block;width:100%}.sia-steps-wrapper{display:flex;align-items:center;width:100%;gap:4px;position:relative}.sia-steps-nav{display:flex;align-items:center;gap:4px;background:var(--p-surface-100, #f1f5f9);border:1px solid var(--p-surface-200, #e2e8f0);border-radius:8px;padding:6px 10px;cursor:pointer;color:var(--p-text-secondary-color, #64748b);font-size:12px;font-weight:500;transition:all .2s ease;flex-shrink:0;min-width:36px;justify-content:center}.sia-steps-nav:hover{background:var(--p-primary-50, #eff6ff);border-color:var(--p-primary-200, #bfdbfe);color:var(--p-primary-600, #2563eb)}.sia-steps-nav:active{transform:scale(.95)}.sia-steps-nav .nav-badge{background:var(--p-primary-100, #dbeafe);color:var(--p-primary-700, #1d4ed8);border-radius:10px;padding:1px 6px;font-size:11px;font-weight:600;line-height:1.4}.sia-steps-nav i{font-size:12px}.sia-steps-content{flex:1;overflow:hidden;min-width:0}.sia-steps-content.has-overflow-left{mask-image:linear-gradient(to right,transparent 0%,black 5%)}.sia-steps-content.has-overflow-right{mask-image:linear-gradient(to left,transparent 0%,black 5%)}.sia-steps-content.has-overflow-left.has-overflow-right{mask-image:linear-gradient(to right,transparent 0%,black 5%,black 95%,transparent 100%)}.sia-steps-list{display:flex;align-items:center;justify-content:center;padding:8px 4px}.sia-step-connector{flex:0 0 auto;width:32px;display:flex;align-items:center;justify-content:center}.sia-step-connector .connector-line{width:100%;height:2px;background:var(--p-surface-300, #cbd5e1);border-radius:1px;transition:background .3s ease}.sia-step-connector.completed .connector-line{background:var(--p-primary-400, #60a5fa)}.sia-step-item{display:flex;flex-direction:column;align-items:center;gap:6px;padding:8px 12px;border-radius:10px;transition:all .25s ease;min-width:80px;max-width:160px;position:relative}.sia-step-item.clickable{cursor:pointer}.sia-step-item.clickable:hover{background:var(--p-surface-50, #f8fafc);transform:translateY(-1px)}.sia-step-item.disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.sia-step-item.pending .sia-step-marker{background:var(--p-surface-100, #f1f5f9);border-color:var(--p-surface-300, #cbd5e1);color:var(--p-text-secondary-color, #64748b)}.sia-step-item.pending .sia-step-label .label-text{color:var(--p-text-secondary-color, #64748b)}.sia-step-item.active .sia-step-marker{background:var(--p-primary-500, #3b82f6);border-color:var(--p-primary-500, #3b82f6);color:#fff;box-shadow:0 0 0 4px var(--p-primary-100, #dbeafe);transform:scale(1.1)}.sia-step-item.active .sia-step-label .label-text{color:var(--p-primary-700, #1d4ed8);font-weight:600}.sia-step-item.completed .sia-step-marker{background:var(--p-primary-100, #dbeafe);border-color:var(--p-primary-300, #93c5fd);color:var(--p-primary-600, #2563eb)}.sia-step-item.completed .sia-step-label .label-text{color:var(--p-text-color, #1e293b)}.sia-step-marker{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;border:2px solid;font-size:13px;font-weight:600;transition:all .3s ease;flex-shrink:0}.sia-step-marker i{font-size:14px}.sia-step-label{text-align:center;max-width:100%;overflow:hidden}.sia-step-label .label-text{display:block;font-size:12px;font-weight:500;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--p-text-secondary-color, #64748b);transition:color .2s ease,font-weight .2s ease}.sia-steps-wrapper.animated .sia-steps-list{transition:transform .3s ease}.sia-steps-wrapper.animated .sia-step-item{animation:stepFadeIn .25s ease forwards}@keyframes stepFadeIn{0%{opacity:.6;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.sia-steps-wrapper.theme-success .sia-step-connector.completed .connector-line{background:var(--p-green-400, #4ade80)}.sia-steps-wrapper.theme-success .sia-step-item.active .sia-step-marker{background:var(--p-green-500, #22c55e);border-color:var(--p-green-500, #22c55e);box-shadow:0 0 0 4px var(--p-green-100, #dcfce7)}.sia-steps-wrapper.theme-success .sia-step-item.active .sia-step-label .label-text{color:var(--p-green-700, #15803d)}.sia-steps-wrapper.theme-success .sia-step-item.completed .sia-step-marker{background:var(--p-green-100, #dcfce7);border-color:var(--p-green-300, #86efac);color:var(--p-green-600, #16a34a)}.sia-steps-wrapper.theme-danger .sia-step-connector.completed .connector-line{background:var(--p-red-400, #f87171)}.sia-steps-wrapper.theme-danger .sia-step-item.active .sia-step-marker{background:var(--p-red-500, #ef4444);border-color:var(--p-red-500, #ef4444);box-shadow:0 0 0 4px var(--p-red-100, #fee2e2)}.sia-steps-wrapper.theme-danger .sia-step-item.active .sia-step-label .label-text{color:var(--p-red-700, #b91c1c)}.sia-steps-wrapper.theme-danger .sia-step-item.completed .sia-step-marker{background:var(--p-red-100, #fee2e2);border-color:var(--p-red-300, #fca5a5);color:var(--p-red-600, #dc2626)}.sia-steps-wrapper.theme-warning .sia-step-connector.completed .connector-line{background:var(--p-orange-400, #fb923c)}.sia-steps-wrapper.theme-warning .sia-step-item.active .sia-step-marker{background:var(--p-orange-500, #f97316);border-color:var(--p-orange-500, #f97316);box-shadow:0 0 0 4px var(--p-orange-100, #ffedd5)}.sia-steps-wrapper.theme-warning .sia-step-item.active .sia-step-label .label-text{color:var(--p-orange-700, #c2410c)}.sia-steps-wrapper.theme-warning .sia-step-item.completed .sia-step-marker{background:var(--p-orange-100, #ffedd5);border-color:var(--p-orange-300, #fdba74);color:var(--p-orange-600, #ea580c)}.sia-steps-wrapper.theme-info .sia-step-connector.completed .connector-line{background:var(--p-cyan-400, #22d3ee)}.sia-steps-wrapper.theme-info .sia-step-item.active .sia-step-marker{background:var(--p-cyan-500, #06b6d4);border-color:var(--p-cyan-500, #06b6d4);box-shadow:0 0 0 4px var(--p-cyan-100, #cffafe)}.sia-steps-wrapper.theme-info .sia-step-item.active .sia-step-label .label-text{color:var(--p-cyan-700, #0e7490)}.sia-steps-wrapper.theme-info .sia-step-item.completed .sia-step-marker{background:var(--p-cyan-100, #cffafe);border-color:var(--p-cyan-300, #67e8f9);color:var(--p-cyan-600, #0891b2)}@media (max-width: 576px){.sia-step-item{min-width:60px;max-width:100px;padding:6px 8px}.sia-step-marker{width:30px;height:30px;font-size:11px}.sia-step-marker i{font-size:12px}.sia-step-label .label-text{font-size:11px}.sia-step-connector{width:20px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i7$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3686
|
+
}
|
|
3687
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StepsComponent, decorators: [{
|
|
3688
|
+
type: Component,
|
|
3689
|
+
args: [{ selector: 'sia-steps', standalone: true, imports: [CommonModule, TooltipModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sia-steps-wrapper\" [class]=\"styleClass\" [class.animated]=\"animated\"\n [class.theme-success]=\"colorScheme === 'success'\"\n [class.theme-danger]=\"colorScheme === 'danger'\"\n [class.theme-warning]=\"colorScheme === 'warning'\"\n [class.theme-info]=\"colorScheme === 'info'\"\n #stepsContainer>\n <!-- Bot\u00E3o de navega\u00E7\u00E3o esquerda -->\n <button\n *ngIf=\"hasOverflowLeft\"\n class=\"sia-steps-nav sia-steps-nav-left\"\n (click)=\"navigateLeft()\"\n [attr.aria-label]=\"'Anterior (' + hiddenLeftCount + ' ocultos)'\"\n type=\"button\">\n <span class=\"nav-badge\">{{ hiddenLeftCount }}</span>\n <i class=\"pi pi-chevron-left\"></i>\n </button>\n\n <!-- Steps vis\u00EDveis -->\n <div class=\"sia-steps-content\" [class.has-overflow-left]=\"hasOverflowLeft\" [class.has-overflow-right]=\"hasOverflowRight\">\n <div class=\"sia-steps-list\">\n <ng-container *ngFor=\"let step of visibleSteps; let i = index; let first = first; let last = last; trackBy: trackByIndex\">\n <!-- Conector (n\u00E3o aparece antes do primeiro) -->\n <div *ngIf=\"!first\" class=\"sia-step-connector\" [class.completed]=\"getStepState(i) === 'completed' || getStepState(i - 1) === 'completed'\">\n <div class=\"connector-line\"></div>\n </div>\n\n <!-- Step item -->\n <div\n class=\"sia-step-item\"\n [class.active]=\"getStepState(i) === 'active'\"\n [class.completed]=\"getStepState(i) === 'completed'\"\n [class.pending]=\"getStepState(i) === 'pending'\"\n [class.disabled]=\"step.disabled\"\n [class.clickable]=\"!readonly && !step.disabled\"\n [class]=\"step.styleClass || ''\"\n [pTooltip]=\"step.label\"\n tooltipPosition=\"top\"\n (click)=\"onStepClick(step, i)\"\n [attr.role]=\"readonly ? 'listitem' : 'button'\"\n [attr.aria-current]=\"getStepState(i) === 'active' ? 'step' : null\"\n [attr.aria-disabled]=\"step.disabled || readonly\">\n \n <!-- \u00CDcone/n\u00FAmero do step -->\n <div class=\"sia-step-marker\">\n <i *ngIf=\"getStepState(i) === 'completed' && !step.icon\" class=\"pi pi-check\"></i>\n <i *ngIf=\"step.icon && getStepState(i) !== 'completed'\" [class]=\"'pi ' + step.icon\"></i>\n <span *ngIf=\"!step.icon && getStepState(i) !== 'completed'\">{{ getRealIndex(i) + 1 }}</span>\n </div>\n\n <!-- Label do step -->\n <div class=\"sia-step-label\">\n <span class=\"label-text\">{{ step.label }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n\n <!-- Bot\u00E3o de navega\u00E7\u00E3o direita -->\n <button\n *ngIf=\"hasOverflowRight\"\n class=\"sia-steps-nav sia-steps-nav-right\"\n (click)=\"navigateRight()\"\n [attr.aria-label]=\"'Pr\u00F3ximo (' + hiddenRightCount + ' ocultos)'\"\n type=\"button\">\n <i class=\"pi pi-chevron-right\"></i>\n <span class=\"nav-badge\">{{ hiddenRightCount }}</span>\n </button>\n</div>\n", styles: [":host{display:block;width:100%}.sia-steps-wrapper{display:flex;align-items:center;width:100%;gap:4px;position:relative}.sia-steps-nav{display:flex;align-items:center;gap:4px;background:var(--p-surface-100, #f1f5f9);border:1px solid var(--p-surface-200, #e2e8f0);border-radius:8px;padding:6px 10px;cursor:pointer;color:var(--p-text-secondary-color, #64748b);font-size:12px;font-weight:500;transition:all .2s ease;flex-shrink:0;min-width:36px;justify-content:center}.sia-steps-nav:hover{background:var(--p-primary-50, #eff6ff);border-color:var(--p-primary-200, #bfdbfe);color:var(--p-primary-600, #2563eb)}.sia-steps-nav:active{transform:scale(.95)}.sia-steps-nav .nav-badge{background:var(--p-primary-100, #dbeafe);color:var(--p-primary-700, #1d4ed8);border-radius:10px;padding:1px 6px;font-size:11px;font-weight:600;line-height:1.4}.sia-steps-nav i{font-size:12px}.sia-steps-content{flex:1;overflow:hidden;min-width:0}.sia-steps-content.has-overflow-left{mask-image:linear-gradient(to right,transparent 0%,black 5%)}.sia-steps-content.has-overflow-right{mask-image:linear-gradient(to left,transparent 0%,black 5%)}.sia-steps-content.has-overflow-left.has-overflow-right{mask-image:linear-gradient(to right,transparent 0%,black 5%,black 95%,transparent 100%)}.sia-steps-list{display:flex;align-items:center;justify-content:center;padding:8px 4px}.sia-step-connector{flex:0 0 auto;width:32px;display:flex;align-items:center;justify-content:center}.sia-step-connector .connector-line{width:100%;height:2px;background:var(--p-surface-300, #cbd5e1);border-radius:1px;transition:background .3s ease}.sia-step-connector.completed .connector-line{background:var(--p-primary-400, #60a5fa)}.sia-step-item{display:flex;flex-direction:column;align-items:center;gap:6px;padding:8px 12px;border-radius:10px;transition:all .25s ease;min-width:80px;max-width:160px;position:relative}.sia-step-item.clickable{cursor:pointer}.sia-step-item.clickable:hover{background:var(--p-surface-50, #f8fafc);transform:translateY(-1px)}.sia-step-item.disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.sia-step-item.pending .sia-step-marker{background:var(--p-surface-100, #f1f5f9);border-color:var(--p-surface-300, #cbd5e1);color:var(--p-text-secondary-color, #64748b)}.sia-step-item.pending .sia-step-label .label-text{color:var(--p-text-secondary-color, #64748b)}.sia-step-item.active .sia-step-marker{background:var(--p-primary-500, #3b82f6);border-color:var(--p-primary-500, #3b82f6);color:#fff;box-shadow:0 0 0 4px var(--p-primary-100, #dbeafe);transform:scale(1.1)}.sia-step-item.active .sia-step-label .label-text{color:var(--p-primary-700, #1d4ed8);font-weight:600}.sia-step-item.completed .sia-step-marker{background:var(--p-primary-100, #dbeafe);border-color:var(--p-primary-300, #93c5fd);color:var(--p-primary-600, #2563eb)}.sia-step-item.completed .sia-step-label .label-text{color:var(--p-text-color, #1e293b)}.sia-step-marker{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;border:2px solid;font-size:13px;font-weight:600;transition:all .3s ease;flex-shrink:0}.sia-step-marker i{font-size:14px}.sia-step-label{text-align:center;max-width:100%;overflow:hidden}.sia-step-label .label-text{display:block;font-size:12px;font-weight:500;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--p-text-secondary-color, #64748b);transition:color .2s ease,font-weight .2s ease}.sia-steps-wrapper.animated .sia-steps-list{transition:transform .3s ease}.sia-steps-wrapper.animated .sia-step-item{animation:stepFadeIn .25s ease forwards}@keyframes stepFadeIn{0%{opacity:.6;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.sia-steps-wrapper.theme-success .sia-step-connector.completed .connector-line{background:var(--p-green-400, #4ade80)}.sia-steps-wrapper.theme-success .sia-step-item.active .sia-step-marker{background:var(--p-green-500, #22c55e);border-color:var(--p-green-500, #22c55e);box-shadow:0 0 0 4px var(--p-green-100, #dcfce7)}.sia-steps-wrapper.theme-success .sia-step-item.active .sia-step-label .label-text{color:var(--p-green-700, #15803d)}.sia-steps-wrapper.theme-success .sia-step-item.completed .sia-step-marker{background:var(--p-green-100, #dcfce7);border-color:var(--p-green-300, #86efac);color:var(--p-green-600, #16a34a)}.sia-steps-wrapper.theme-danger .sia-step-connector.completed .connector-line{background:var(--p-red-400, #f87171)}.sia-steps-wrapper.theme-danger .sia-step-item.active .sia-step-marker{background:var(--p-red-500, #ef4444);border-color:var(--p-red-500, #ef4444);box-shadow:0 0 0 4px var(--p-red-100, #fee2e2)}.sia-steps-wrapper.theme-danger .sia-step-item.active .sia-step-label .label-text{color:var(--p-red-700, #b91c1c)}.sia-steps-wrapper.theme-danger .sia-step-item.completed .sia-step-marker{background:var(--p-red-100, #fee2e2);border-color:var(--p-red-300, #fca5a5);color:var(--p-red-600, #dc2626)}.sia-steps-wrapper.theme-warning .sia-step-connector.completed .connector-line{background:var(--p-orange-400, #fb923c)}.sia-steps-wrapper.theme-warning .sia-step-item.active .sia-step-marker{background:var(--p-orange-500, #f97316);border-color:var(--p-orange-500, #f97316);box-shadow:0 0 0 4px var(--p-orange-100, #ffedd5)}.sia-steps-wrapper.theme-warning .sia-step-item.active .sia-step-label .label-text{color:var(--p-orange-700, #c2410c)}.sia-steps-wrapper.theme-warning .sia-step-item.completed .sia-step-marker{background:var(--p-orange-100, #ffedd5);border-color:var(--p-orange-300, #fdba74);color:var(--p-orange-600, #ea580c)}.sia-steps-wrapper.theme-info .sia-step-connector.completed .connector-line{background:var(--p-cyan-400, #22d3ee)}.sia-steps-wrapper.theme-info .sia-step-item.active .sia-step-marker{background:var(--p-cyan-500, #06b6d4);border-color:var(--p-cyan-500, #06b6d4);box-shadow:0 0 0 4px var(--p-cyan-100, #cffafe)}.sia-steps-wrapper.theme-info .sia-step-item.active .sia-step-label .label-text{color:var(--p-cyan-700, #0e7490)}.sia-steps-wrapper.theme-info .sia-step-item.completed .sia-step-marker{background:var(--p-cyan-100, #cffafe);border-color:var(--p-cyan-300, #67e8f9);color:var(--p-cyan-600, #0891b2)}@media (max-width: 576px){.sia-step-item{min-width:60px;max-width:100px;padding:6px 8px}.sia-step-marker{width:30px;height:30px;font-size:11px}.sia-step-marker i{font-size:12px}.sia-step-label .label-text{font-size:11px}.sia-step-connector{width:20px}}\n"] }]
|
|
3690
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { steps: [{
|
|
3691
|
+
type: Input
|
|
3692
|
+
}], activeIndex: [{
|
|
3693
|
+
type: Input
|
|
3694
|
+
}], readonly: [{
|
|
3695
|
+
type: Input
|
|
3696
|
+
}], maxVisible: [{
|
|
3697
|
+
type: Input
|
|
3698
|
+
}], stepMinWidth: [{
|
|
3699
|
+
type: Input
|
|
3700
|
+
}], animated: [{
|
|
3701
|
+
type: Input
|
|
3702
|
+
}], navigationMode: [{
|
|
3703
|
+
type: Input
|
|
3704
|
+
}], colorScheme: [{
|
|
3705
|
+
type: Input
|
|
3706
|
+
}], styleClass: [{
|
|
3707
|
+
type: Input
|
|
3708
|
+
}], activeIndexChange: [{
|
|
3709
|
+
type: Output
|
|
3710
|
+
}], stepClick: [{
|
|
3711
|
+
type: Output
|
|
3712
|
+
}], stepsContainer: [{
|
|
3713
|
+
type: ViewChild,
|
|
3714
|
+
args: ['stepsContainer']
|
|
3715
|
+
}] } });
|
|
3716
|
+
|
|
3189
3717
|
/**
|
|
3190
3718
|
* Directive para máscara de código postal
|
|
3191
3719
|
* Usa o locale do cookie por padrão, ou aceita locale por parâmetro
|
|
@@ -5883,6 +6411,7 @@ class DynamicFormComponent {
|
|
|
5883
6411
|
loadEntityData() {
|
|
5884
6412
|
if (this.entityData && this.form) {
|
|
5885
6413
|
this.form.patchValue(this.processEntityData(this.entityData));
|
|
6414
|
+
this.updateDisabledFields();
|
|
5886
6415
|
}
|
|
5887
6416
|
}
|
|
5888
6417
|
processEntityData(entity) {
|
|
@@ -6022,10 +6551,10 @@ class DynamicFormComponent {
|
|
|
6022
6551
|
? [parseInt(dateParts[1], 10), parseInt(dateParts[0], 10), parseInt(dateParts[2], 10)]
|
|
6023
6552
|
: [parseInt(dateParts[0], 10), parseInt(dateParts[1], 10), parseInt(dateParts[2], 10)];
|
|
6024
6553
|
const [hours, minutes] = timePart.split(':').map(p => parseInt(p, 10));
|
|
6025
|
-
out[field.field] = new Date(year, month - 1, day, hours, minutes);
|
|
6554
|
+
out[field.field] = new Date(year, month - 1, day, hours, minutes).toISOString();
|
|
6026
6555
|
}
|
|
6027
6556
|
else if (v instanceof Date) {
|
|
6028
|
-
|
|
6557
|
+
out[field.field] = v.toISOString();
|
|
6029
6558
|
}
|
|
6030
6559
|
else if (!v || (typeof v === 'string' && v.includes('_'))) {
|
|
6031
6560
|
out[field.field] = null;
|
|
@@ -6114,6 +6643,14 @@ class DynamicFormComponent {
|
|
|
6114
6643
|
}
|
|
6115
6644
|
// --- Public methods ---
|
|
6116
6645
|
getForm() { return this.form; }
|
|
6646
|
+
/**
|
|
6647
|
+
* Returns the form values with date/time/lookup fields already converted
|
|
6648
|
+
* to the backend-expected format (date → yyyy-MM-dd, time → HH:mm:ss, lookup → object with id).
|
|
6649
|
+
* Use this instead of getForm().value when you need processed values without triggering formSubmit.
|
|
6650
|
+
*/
|
|
6651
|
+
getProcessedValue() {
|
|
6652
|
+
return this.processFormValue(this.form.getRawValue());
|
|
6653
|
+
}
|
|
6117
6654
|
open(entity) {
|
|
6118
6655
|
if (entity) {
|
|
6119
6656
|
this.entityData = entity;
|
|
@@ -7235,5 +7772,5 @@ const throttle = (func, limit) => {
|
|
|
7235
7772
|
* Generated bundle index. Do not edit.
|
|
7236
7773
|
*/
|
|
7237
7774
|
|
|
7238
|
-
export { AngularComponentsModule, AuthService, BreadcrumbComponent, BulkDeleteDialogComponent, CnpjPipe, CookieService, CpfPipe, DEFAULT_LANGUAGE, DateFormatPipe, DocumentMaskDirective, DocumentPipe, DynamicFieldCheckboxComponent, DynamicFieldDateComponent, DynamicFieldDropdownComponent, DynamicFieldImageComponent, DynamicFieldLookupComponent, DynamicFieldMultiselectComponent, DynamicFieldNumberComponent, DynamicFieldTextComponent, DynamicFieldTextareaComponent, DynamicFieldTimeComponent, DynamicFieldWrapperComponent, DynamicFormComponent, EntityListBaseComponent, EntityService, ExportDialogComponent, FieldType, IassistIconComponent, LoadingComponent, LocaleService, MaskService, MoneyMaskDirective, MoneyPipe, PermissionService, PhoneMaskDirective, PhonePipe, PostalCodeMaskDirective, PostalCodePipe, SUPPORTED_LANGUAGES, SeniorPreset, SeniorTokenService, TRANSLATION_CONFIG, TableLoadingDirective, ThemeService, TranslatePipe, TranslationHelper, TranslationService, WebSocketService, apiInterceptor, createFilterString, createFilterTokens, debounce, deepClone, deepEqual, escapeFilterValue, getEnumQuery, getLabelValueRequest, getLanguageInfo, getProp, getSuggestionValue, getTypeInformation, isValidFilter, mapTokenLocaleToLanguage, mergeUnique, provideSeniorPrimeNG, resolveRefs, setProp, throttle };
|
|
7775
|
+
export { AngularComponentsModule, AuthService, BreadcrumbComponent, BulkDeleteDialogComponent, CnpjPipe, CookieService, CpfPipe, DEFAULT_LANGUAGE, DateFormatPipe, DocumentMaskDirective, DocumentPipe, DynamicFieldCheckboxComponent, DynamicFieldDateComponent, DynamicFieldDropdownComponent, DynamicFieldImageComponent, DynamicFieldLookupComponent, DynamicFieldMultiselectComponent, DynamicFieldNumberComponent, DynamicFieldTextComponent, DynamicFieldTextareaComponent, DynamicFieldTimeComponent, DynamicFieldWrapperComponent, DynamicFormComponent, EntityListBaseComponent, EntityService, ExportDialogComponent, FieldType, IassistIconComponent, KanbanBoardComponent, LoadingComponent, LocaleService, MaskService, MoneyMaskDirective, MoneyPipe, PermissionService, PhoneMaskDirective, PhonePipe, PostalCodeMaskDirective, PostalCodePipe, SUPPORTED_LANGUAGES, SeniorPreset, SeniorTokenService, StepsComponent, TRANSLATION_CONFIG, TableLoadingDirective, ThemeService, TranslatePipe, TranslationHelper, TranslationService, WebSocketService, apiInterceptor, createFilterString, createFilterTokens, debounce, deepClone, deepEqual, escapeFilterValue, getEnumQuery, getLabelValueRequest, getLanguageInfo, getProp, getSuggestionValue, getTypeInformation, isValidFilter, mapTokenLocaleToLanguage, mergeUnique, provideSeniorPrimeNG, resolveRefs, setProp, throttle };
|
|
7239
7776
|
//# sourceMappingURL=seniorsistemas-components-ai.mjs.map
|