@shival99/z-ui 1.9.12 → 1.9.13

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.
Files changed (33) hide show
  1. package/assets/css/base.css +0 -16
  2. package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
  3. package/fesm2022/shival99-z-ui-components-z-drawer.mjs +7 -2
  4. package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -1
  5. package/fesm2022/shival99-z-ui-components-z-filter.mjs +150 -3
  6. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
  7. package/fesm2022/shival99-z-ui-components-z-kanban.mjs +2 -2
  8. package/fesm2022/shival99-z-ui-components-z-kanban.mjs.map +1 -1
  9. package/fesm2022/shival99-z-ui-components-z-modal.mjs +13 -6
  10. package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -1
  11. package/fesm2022/shival99-z-ui-components-z-table.mjs +219 -0
  12. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -1
  13. package/fesm2022/shival99-z-ui-components-z-timeline.mjs +43 -261
  14. package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -1
  15. package/fesm2022/shival99-z-ui-components-z-upload.mjs +1 -4
  16. package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -1
  17. package/fesm2022/shival99-z-ui-providers.mjs +6 -2
  18. package/fesm2022/shival99-z-ui-providers.mjs.map +1 -1
  19. package/fesm2022/shival99-z-ui-services.mjs +71 -4
  20. package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
  21. package/package.json +1 -1
  22. package/types/shival99-z-ui-components-z-autocomplete.d.ts +1 -1
  23. package/types/shival99-z-ui-components-z-calendar.d.ts +4 -4
  24. package/types/shival99-z-ui-components-z-drawer.d.ts +2 -0
  25. package/types/shival99-z-ui-components-z-editor.d.ts +1 -1
  26. package/types/shival99-z-ui-components-z-filter.d.ts +17 -0
  27. package/types/shival99-z-ui-components-z-modal.d.ts +5 -2
  28. package/types/shival99-z-ui-components-z-popover.d.ts +1 -1
  29. package/types/shival99-z-ui-components-z-table.d.ts +205 -1
  30. package/types/shival99-z-ui-components-z-timeline.d.ts +20 -62
  31. package/types/shival99-z-ui-components-z-upload.d.ts +3 -3
  32. package/types/shival99-z-ui-providers.d.ts +6 -2
  33. package/types/shival99-z-ui-services.d.ts +26 -1
@@ -948,7 +948,7 @@ class ZKanbanComponent {
948
948
  return `${prefix}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
949
949
  }
950
950
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZKanbanComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
951
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZKanbanComponent, isStandalone: true, selector: "z-kanban", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zColumns: { classPropertyName: "zColumns", publicName: "zColumns", isSignal: true, isRequired: false, transformFunction: null }, zTitle: { classPropertyName: "zTitle", publicName: "zTitle", isSignal: true, isRequired: false, transformFunction: null }, zSubtitle: { classPropertyName: "zSubtitle", publicName: "zSubtitle", isSignal: true, isRequired: false, transformFunction: null }, zSearch: { classPropertyName: "zSearch", publicName: "zSearch", isSignal: true, isRequired: false, transformFunction: null }, zShowToolbar: { classPropertyName: "zShowToolbar", publicName: "zShowToolbar", isSignal: true, isRequired: false, transformFunction: null }, zAllowCreateTask: { classPropertyName: "zAllowCreateTask", publicName: "zAllowCreateTask", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zDensity: { classPropertyName: "zDensity", publicName: "zDensity", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zTaskDrop: "zTaskDrop", zTaskSave: "zTaskSave", zTaskClick: "zTaskClick", zTaskCreate: "zTaskCreate", zColumns: "zColumnsChange", zSearch: "zSearchChange" }, host: { properties: { "class": "hostClasses()" } }, viewQueries: [{ propertyName: "boardViewportRef", first: true, predicate: ["boardViewport"], descendants: true, isSignal: true }], exportAs: ["zKanban"], ngImport: i0, template: "<div class=\"flex h-full min-h-0 min-w-0 flex-col gap-5\">\n @if (zShowToolbar()) {\n <header class=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n <h2 class=\"text-foreground truncate text-xl font-bold\">{{ zTitle() | translate }}</h2>\n <p class=\"text-muted-foreground text-sm\">{{ zSubtitle() | translate }}</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center\">\n <z-input\n class=\"w-full sm:w-80\"\n zSize=\"sm\"\n [zSearch]=\"true\"\n [zDebounce]=\"200\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_search_placeholder' | translate\"\n [ngModel]=\"zSearch()\"\n (zOnSearch)=\"onBoardSearchChange($event)\" />\n\n @if (zAllowCreateTask()) {\n <z-button zType=\"outline\" zSize=\"sm\" zTypeIcon=\"lucidePlus\" (click)=\"createTaskInFirstColumn()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </z-button>\n }\n </div>\n </header>\n }\n\n @if (isSearchActive()) {\n <p class=\"text-muted-foreground text-xs\">\n {{ 'i18n_z_ui_kanban_drag_disabled_while_search' | translate }}\n </p>\n }\n\n <div #boardViewport class=\"z-kanban-board min-h-0 flex-1 overflow-x-auto pb-2\">\n <div class=\"flex h-full min-h-[25rem] min-w-max items-stretch gap-4\">\n @for (column of boardColumnsView(); track column.id) {\n <section [class]=\"columnClass()\">\n <header class=\"mb-2 flex items-center justify-between gap-2 px-0.5\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h3 class=\"text-foreground truncate text-xs font-bold tracking-wide uppercase\">\n {{ column.title | translate }}\n </h3>\n <span\n class=\"bg-muted text-muted-foreground inline-flex min-w-5 items-center justify-center rounded-full px-1.5 py-0.5 text-[10px] font-bold\">\n {{ column.taskCount }}\n </span>\n </div>\n\n @if (zAllowCreateTask()) {\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-7 cursor-pointer items-center justify-center rounded-md transition-colors\"\n (click)=\"createTask(column.id)\">\n <z-icon zType=\"lucidePlus\" zSize=\"16\" />\n </button>\n }\n </header>\n\n <div\n cdkDropList\n [id]=\"column.id\"\n [cdkDropListData]=\"column.rawTasks\"\n [cdkDropListConnectedTo]=\"connectedDropListIds()\"\n [cdkDropListDisabled]=\"zDisabled() || isSearchActive()\"\n class=\"kanban-drop-list -mr-1 flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto p-0.5 pr-1\"\n (cdkDropListDropped)=\"onTaskDrop($event, column.id)\">\n @if (column.taskCount === 0) {\n <div\n class=\"border-border/70 text-muted-foreground flex h-24 items-center justify-center rounded-lg border border-dashed px-3 text-center text-xs\">\n @if (isSearchActive()) {\n {{ 'i18n_z_ui_kanban_no_matches' | translate }}\n } @else {\n {{ 'i18n_z_ui_kanban_drop_here' | translate }}\n }\n </div>\n }\n\n @for (task of column.tasks; track task.id) {\n <article\n cdkDrag\n cdkDragPreviewClass=\"z-kanban-drag-preview\"\n cdkDragPlaceholderClass=\"z-kanban-drag-placeholder\"\n [cdkDragData]=\"{ columnId: column.id, taskId: task.id }\"\n [cdkDragDisabled]=\"zDisabled() || isSearchActive()\"\n [class]=\"'kanban-card shrink-0 ' + task.taskCardClass\"\n (cdkDragStarted)=\"onTaskDragStarted()\"\n (cdkDragMoved)=\"onTaskDragMoved($event)\"\n (cdkDragEnded)=\"onTaskDragEnded($event)\"\n (click)=\"onTaskCardClick(column.id, task.id)\">\n <div class=\"flex items-start justify-between gap-2\">\n <div class=\"min-w-0 space-y-1\">\n @if (task.code) {\n <p class=\"text-muted-foreground text-[10px] font-semibold tracking-wide uppercase\">\n {{ task.code }}\n </p>\n }\n <h4 class=\"line-clamp-2 text-sm leading-5 font-semibold\">{{ task.title }}</h4>\n </div>\n\n <button\n cdkDragHandle\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-6 shrink-0 cursor-grab items-center justify-center rounded-md transition-colors\"\n (click)=\"onTaskHandleClick($event)\">\n <z-icon zType=\"lucideGripVertical\" zSize=\"14\" />\n </button>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span [class]=\"task.priorityBadgeClass\">\n {{ task.priorityLabelKey | translate }}\n </span>\n @if (task.completed) {\n <span class=\"inline-flex items-center gap-1 text-[11px] font-semibold text-emerald-500\">\n <z-icon zType=\"lucideCircleCheck\" zSize=\"12\" />\n {{ 'i18n_z_ui_kanban_done' | translate }}\n </span>\n }\n </div>\n\n @if (task.descriptionPreview) {\n <p class=\"text-muted-foreground line-clamp-3 text-xs leading-4\">{{ task.descriptionPreview }}</p>\n }\n\n <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-[11px]\">\n @if (task.dueDateLabel) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideCalendar\" zSize=\"12\" />\n {{ task.dueDateLabel }}\n </span>\n }\n\n @if (task.commentsCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideMessageSquare\" zSize=\"12\" />\n {{ task.commentsCount }}\n </span>\n }\n\n @if (task.attachmentCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n {{ task.attachmentCount }}\n </span>\n }\n\n @if (task.checklistCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideListChecks\" zSize=\"12\" />\n {{ task.checklistDoneCount }}/{{ task.checklistCount }}\n </span>\n }\n </div>\n\n <footer class=\"flex items-center justify-between gap-2\">\n <div class=\"flex -space-x-2\">\n @for (assignee of task.visibleAssignees; track assignee.name) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"assignee.name\"\n class=\"relative inline-flex size-6 items-center justify-center rounded-full text-[10px] font-bold\"\n [class]=\"assignee.className\"\n [style.zIndex]=\"assignee.zIndex\">\n {{ assignee.initials }}\n </span>\n }\n @if (task.hiddenAssigneesCount > 0) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"task.hiddenAssigneesLabel\"\n class=\"bg-muted text-muted-foreground border-background relative inline-flex size-6 items-center justify-center rounded-full border text-[10px] font-bold shadow-xs\"\n [style.zIndex]=\"20\">\n +{{ task.hiddenAssigneesCount }}\n </span>\n }\n </div>\n\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" class=\"text-muted-foreground\" />\n </footer>\n </article>\n }\n </div>\n </section>\n }\n </div>\n </div>\n</div>\n\n<z-modal\n [zVisible]=\"editorVisible()\"\n [zTitle]=\"'i18n_z_ui_kanban_editor_title'\"\n [zDescription]=\"editorMeta()\"\n [zOkText]=\"'i18n_z_ui_common_save' | translate\"\n [zCancelText]=\"'i18n_z_ui_common_cancel' | translate\"\n zWidth=\"min(96vw, 72rem)\"\n zOverlay=\"blur\"\n [zOkDisabled]=\"isEditorSaveDisabled()\"\n (zVisibleChange)=\"onEditorVisibleChange($event)\"\n (zAfterClose)=\"onEditorAfterClose()\"\n (zOk)=\"saveTaskChanges()\"\n (zCancel)=\"closeEditor()\">\n @if (activeTask()) {\n <div class=\"grid gap-6 xl:grid-cols-[minmax(0,1fr)_20rem]\">\n <div class=\"space-y-5\">\n <section class=\"space-y-2\">\n <z-input\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_title' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_title_placeholder' | translate\"\n [zRequired]=\"true\"\n [ngModel]=\"draftTitle()\"\n (ngModelChange)=\"draftTitle.set($event)\" />\n </section>\n\n <section class=\"space-y-2\">\n <z-editor\n zSize=\"sm\"\n [zLabel]=\"'i18n_z_ui_kanban_description' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_description_placeholder' | translate\"\n [ngModel]=\"draftDescription()\"\n (ngModelChange)=\"draftDescription.set($event)\" />\n </section>\n\n <section class=\"grid gap-3 md:grid-cols-2\">\n <ng-template #statusSelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(statusIconClassByValue()[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #statusOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(statusIconClassByValue()[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #prioritySelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(priorityIconClassByValue[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #priorityOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(priorityIconClassByValue[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_status' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"statusOptions()\"\n [zSelectedTemplate]=\"statusSelectedTpl\"\n [zOptionTemplate]=\"statusOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_status_placeholder' | translate\"\n [ngModel]=\"draftStatus()\"\n (ngModelChange)=\"onEditorStatusChange($event)\" />\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_priority' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"prioritySelectOptions()\"\n [zSelectedTemplate]=\"prioritySelectedTpl\"\n [zOptionTemplate]=\"priorityOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_priority_placeholder' | translate\"\n [ngModel]=\"draftPriority()\"\n (ngModelChange)=\"onEditorPriorityChange($event)\" />\n\n <z-select\n class=\"w-full md:col-span-2\"\n zMode=\"tags\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_assignees' | translate\"\n [zAllowClear]=\"true\"\n [zOptions]=\"assigneeOptions()\"\n [zMaxTagCount]=\"5\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_assignees_select_placeholder' | translate\"\n [ngModel]=\"draftAssignees()\"\n (ngModelChange)=\"onEditorAssigneesChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_start_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_start_date' | translate\"\n [ngModel]=\"draftStartDate()\"\n (ngModelChange)=\"onEditorStartDateChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_end_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_end_date' | translate\"\n [ngModel]=\"draftEndDate()\"\n (ngModelChange)=\"onEditorEndDateChange($event)\" />\n </section>\n\n <section class=\"space-y-3\">\n <div class=\"flex items-center justify-between gap-2\">\n <h4 class=\"text-sm font-semibold\">\n {{ 'i18n_z_ui_kanban_checklist' | translate }} ({{ checklistDoneCount() }}/{{ draftChecklist().length }})\n </h4>\n <span class=\"text-muted-foreground text-xs font-semibold\">{{ checklistProgress() }}%</span>\n </div>\n\n <div class=\"bg-muted h-2 w-full rounded-full\">\n <div class=\"bg-primary h-2 rounded-full transition-all\" [style.width.%]=\"checklistProgress()\"></div>\n </div>\n\n <div class=\"max-h-44 space-y-1 overflow-y-auto\">\n @if (draftChecklist().length === 0) {\n <p class=\"text-muted-foreground bg-muted/35 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_checklist_items' | translate }}\n </p>\n }\n\n @for (item of draftChecklist(); track item.id) {\n <div [class]=\"item.done ? checklistDoneRowClass : checklistPendingRowClass\">\n <z-checkbox\n [class]=\"item.done ? 'min-w-0 flex-1 line-through' : 'min-w-0 flex-1'\"\n [zChecked]=\"item.done\"\n [zText]=\"item.label\"\n (zChange)=\"toggleChecklistItem(item.id, $event)\" />\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:text-destructive hover:bg-destructive/10 ml-auto inline-flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"removeChecklistItem(item.id)\">\n <z-icon zType=\"lucideTrash2\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n\n <div class=\"flex items-end gap-2\">\n <z-input\n class=\"flex-1\"\n zSize=\"lg\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_checklist_add_placeholder' | translate\"\n [ngModel]=\"draftChecklistItemLabel()\"\n (ngModelChange)=\"draftChecklistItemLabel.set($event)\"\n (zOnEnter)=\"addChecklistItem()\" />\n <button\n type=\"button\"\n zSize=\"lg\"\n z-button\n zType=\"outline\"\n zTypeIcon=\"lucidePlus\"\n (click)=\"addChecklistItem()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </button>\n </div>\n </section>\n\n <section class=\"space-y-2\">\n <z-upload\n [zLabel]=\"'i18n_z_ui_kanban_attachments' | translate\"\n [zNote]=\"'i18n_z_ui_kanban_attachments_note' | translate\"\n [zMultipleFile]=\"true\"\n [zShowProgress]=\"true\"\n [ngModel]=\"draftAttachments()\"\n (ngModelChange)=\"onDraftAttachmentsChange($event)\" />\n </section>\n </div>\n\n <aside\n class=\"bg-muted/25 border-border/70 flex h-[34rem] min-h-0 flex-col overflow-hidden rounded-lg border p-4 shadow-xs xl:h-[38rem]\">\n <section class=\"flex min-h-0 flex-1 flex-col gap-1.5\">\n <label class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </label>\n <div class=\"-mr-3 min-h-0 flex-1 space-y-2 overflow-y-auto pr-3 pb-2\">\n @if (activeTaskActivityView().length === 0) {\n <p class=\"text-muted-foreground bg-muted/40 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_activity' | translate }}\n </p>\n }\n\n @for (entry of activeTaskActivityView(); track entry.id) {\n <div class=\"border-border/70 bg-background/60 rounded-md border px-3 py-2\">\n <p class=\"text-xs font-semibold\">{{ entry.actor }}</p>\n <p class=\"text-muted-foreground mt-1 text-xs leading-4\">{{ entry.action }}</p>\n <p class=\"text-muted-foreground mt-1 text-[10px]\">{{ entry.createdAtLabel }}</p>\n </div>\n }\n </div>\n </section>\n\n <section class=\"border-border/70 mt-3 shrink-0 space-y-2 border-t pt-3\">\n <z-input\n zType=\"textarea\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_add_comment' | translate\"\n [zRows]=\"3\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_comment_placeholder' | translate\"\n [ngModel]=\"draftComment()\"\n (ngModelChange)=\"draftComment.set($event)\" />\n\n <div class=\"flex justify-end pt-2\">\n <button\n type=\"button\"\n [zTypeIcon]=\"'lucideSend'\"\n z-button\n [disabled]=\"isCommentSubmitDisabled()\"\n (click)=\"submitTaskComment()\">\n {{ 'i18n_z_ui_kanban_comment_submit' | translate }}\n </button>\n </div>\n </section>\n </aside>\n </div>\n }\n</z-modal>\n", styles: [":host{display:block;height:100%;min-height:0}.z-kanban-board{overscroll-behavior-x:contain;scrollbar-width:thin;scrollbar-color:color-mix(in oklab,var(--muted-foreground) 45%,transparent) transparent}.z-kanban-board::-webkit-scrollbar{height:8px}.z-kanban-board::-webkit-scrollbar-thumb{background:color-mix(in oklab,var(--muted-foreground) 38%,transparent);border-radius:9999px}.z-kanban-board::-webkit-scrollbar-track{background:transparent}.kanban-drop-list{scrollbar-width:thin}.kanban-card{cursor:pointer}.kanban-card.cdk-drag-dragging{cursor:grabbing;transform:rotate(.35deg)}.kanban-drop-list.cdk-drop-list-dragging .kanban-card:not(.cdk-drag-placeholder){transition:transform .16s cubic-bezier(.2,0,0,1)}:host ::ng-deep .z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}:host ::ng-deep .z-kanban-drag-placeholder{opacity:.2;border:1px dashed color-mix(in oklab,var(--primary) 38%,var(--border));background:color-mix(in oklab,var(--primary) 8%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: 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: 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: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowClear", "zFormat", "zMinDate", "zMaxDate", "zValueType", "zValidators", "zShowOk", "zOkText", "zShowCancel", "zCancelText", "zDisabledDate", "zScrollClose", "zDefaultTime", "zRangeDefaultTime"], outputs: ["zControl", "zChange", "zOnBlur", "zOnFocus", "zEvent"], exportAs: ["zCalendar"] }, { kind: "component", type: ZCheckboxComponent, selector: "z-checkbox", inputs: ["class", "zType", "zSize", "zLabel", "zText", "zDisabled", "zIndeterminate", "zValue", "zOptions", "zOrientation", "zCheckAll", "zCheckAllText", "zChecked", "zGroupValue"], outputs: ["zChange", "zGroupChange", "zOnBlur", "zOnFocus", "zControl", "zEvent", "zCheckedChange", "zGroupValueChange"] }, { kind: "component", type: ZEditorComponent, selector: "z-editor", inputs: ["class", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zModules", "zFormats", "zBounds", "zTheme", "zValidators"], outputs: ["zOnChange", "zOnFocus", "zOnBlur", "zControl", "zEvent"], exportAs: ["zEditor"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zAlign", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest", "zColorConfig"], outputs: ["zOnSearch", "zOnChange", "zOnBlur", "zOnFocus", "zOnKeydown", "zOnEnter", "zOnColorCollapse", "zControl", "zEvent"], exportAs: ["zInput"] }, { kind: "component", type: ZModalComponent, selector: "z-modal", inputs: ["class", "zVisible", "zTitle", "zDescription", "zWidth", "zClosable", "zMaskClosable", "zHideHeader", "zHideFooter", "zOkText", "zCancelText", "zOkDestructive", "zOkDisabled", "zLoading", "zContentLoading", "zSkeletonRows", "zOverlay"], outputs: ["zOk", "zCancel", "zAfterClose", "zScrollbar", "zVisibleChange"], exportAs: ["zModal"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zPosition", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zOnBlur", "zOnFocus", "zControl", "zEvent"], exportAs: ["zSelect"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTrigger", "zTooltipType", "zTooltipSize", "zClass", "zShowDelay", "zHideDelay", "zArrow", "zDisabled", "zOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "component", type: ZUploadComponent, selector: "z-upload", inputs: ["class", "zLabel", "zLabelClass", "zNote", "zSize", "zAcceptFile", "zMultipleFile", "zMaxSize", "zMaxFiles", "zRequired", "zDisabled", "zReadonly", "zLoading", "zShowProgress", "zValidators"], outputs: ["zOnUpload", "zOnRemove", "zOnDownload", "zOnError", "zOnFileChange", "zOnDragover", "zOnDragleave", "zOnDrop", "zControl", "zEvent"], exportAs: ["zUpload"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
951
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZKanbanComponent, isStandalone: true, selector: "z-kanban", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zColumns: { classPropertyName: "zColumns", publicName: "zColumns", isSignal: true, isRequired: false, transformFunction: null }, zTitle: { classPropertyName: "zTitle", publicName: "zTitle", isSignal: true, isRequired: false, transformFunction: null }, zSubtitle: { classPropertyName: "zSubtitle", publicName: "zSubtitle", isSignal: true, isRequired: false, transformFunction: null }, zSearch: { classPropertyName: "zSearch", publicName: "zSearch", isSignal: true, isRequired: false, transformFunction: null }, zShowToolbar: { classPropertyName: "zShowToolbar", publicName: "zShowToolbar", isSignal: true, isRequired: false, transformFunction: null }, zAllowCreateTask: { classPropertyName: "zAllowCreateTask", publicName: "zAllowCreateTask", isSignal: true, isRequired: false, transformFunction: null }, zDisabled: { classPropertyName: "zDisabled", publicName: "zDisabled", isSignal: true, isRequired: false, transformFunction: null }, zDensity: { classPropertyName: "zDensity", publicName: "zDensity", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zTaskDrop: "zTaskDrop", zTaskSave: "zTaskSave", zTaskClick: "zTaskClick", zTaskCreate: "zTaskCreate", zColumns: "zColumnsChange", zSearch: "zSearchChange" }, host: { properties: { "class": "hostClasses()" } }, viewQueries: [{ propertyName: "boardViewportRef", first: true, predicate: ["boardViewport"], descendants: true, isSignal: true }], exportAs: ["zKanban"], ngImport: i0, template: "<div class=\"flex h-full min-h-0 min-w-0 flex-col gap-5\">\n @if (zShowToolbar()) {\n <header class=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n <h2 class=\"text-foreground truncate text-xl font-bold\">{{ zTitle() | translate }}</h2>\n <p class=\"text-muted-foreground text-sm\">{{ zSubtitle() | translate }}</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center\">\n <z-input\n class=\"w-full sm:w-80\"\n zSize=\"sm\"\n [zSearch]=\"true\"\n [zDebounce]=\"200\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_search_placeholder' | translate\"\n [ngModel]=\"zSearch()\"\n (zOnSearch)=\"onBoardSearchChange($event)\" />\n\n @if (zAllowCreateTask()) {\n <z-button zType=\"outline\" zSize=\"sm\" zTypeIcon=\"lucidePlus\" (click)=\"createTaskInFirstColumn()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </z-button>\n }\n </div>\n </header>\n }\n\n @if (isSearchActive()) {\n <p class=\"text-muted-foreground text-xs\">\n {{ 'i18n_z_ui_kanban_drag_disabled_while_search' | translate }}\n </p>\n }\n\n <div #boardViewport class=\"z-kanban-board min-h-0 flex-1 overflow-x-auto pb-2\">\n <div class=\"flex h-full min-h-[25rem] min-w-max items-stretch gap-4\">\n @for (column of boardColumnsView(); track column.id) {\n <section [class]=\"columnClass()\">\n <header class=\"mb-2 flex items-center justify-between gap-2 px-0.5\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h3 class=\"text-foreground truncate text-xs font-bold tracking-wide uppercase\">\n {{ column.title | translate }}\n </h3>\n <span\n class=\"bg-muted text-muted-foreground inline-flex min-w-5 items-center justify-center rounded-full px-1.5 py-0.5 text-[10px] font-bold\">\n {{ column.taskCount }}\n </span>\n </div>\n\n @if (zAllowCreateTask()) {\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-7 cursor-pointer items-center justify-center rounded-md transition-colors\"\n (click)=\"createTask(column.id)\">\n <z-icon zType=\"lucidePlus\" zSize=\"16\" />\n </button>\n }\n </header>\n\n <div\n cdkDropList\n [id]=\"column.id\"\n [cdkDropListData]=\"column.rawTasks\"\n [cdkDropListConnectedTo]=\"connectedDropListIds()\"\n [cdkDropListDisabled]=\"zDisabled() || isSearchActive()\"\n class=\"kanban-drop-list -mr-1 flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto p-0.5 pr-1\"\n (cdkDropListDropped)=\"onTaskDrop($event, column.id)\">\n @if (column.taskCount === 0) {\n <div\n class=\"border-border/70 text-muted-foreground flex h-24 items-center justify-center rounded-lg border border-dashed px-3 text-center text-xs\">\n @if (isSearchActive()) {\n {{ 'i18n_z_ui_kanban_no_matches' | translate }}\n } @else {\n {{ 'i18n_z_ui_kanban_drop_here' | translate }}\n }\n </div>\n }\n\n @for (task of column.tasks; track task.id) {\n <article\n cdkDrag\n cdkDragPreviewClass=\"z-kanban-drag-preview\"\n cdkDragPlaceholderClass=\"z-kanban-drag-placeholder\"\n [cdkDragData]=\"{ columnId: column.id, taskId: task.id }\"\n [cdkDragDisabled]=\"zDisabled() || isSearchActive()\"\n [class]=\"'kanban-card shrink-0 ' + task.taskCardClass\"\n (cdkDragStarted)=\"onTaskDragStarted()\"\n (cdkDragMoved)=\"onTaskDragMoved($event)\"\n (cdkDragEnded)=\"onTaskDragEnded($event)\"\n (click)=\"onTaskCardClick(column.id, task.id)\">\n <div class=\"flex items-start justify-between gap-2\">\n <div class=\"min-w-0 space-y-1\">\n @if (task.code) {\n <p class=\"text-muted-foreground text-[10px] font-semibold tracking-wide uppercase\">\n {{ task.code }}\n </p>\n }\n <h4 class=\"line-clamp-2 text-sm leading-5 font-semibold\">{{ task.title }}</h4>\n </div>\n\n <button\n cdkDragHandle\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-6 shrink-0 cursor-grab items-center justify-center rounded-md transition-colors\"\n (click)=\"onTaskHandleClick($event)\">\n <z-icon zType=\"lucideGripVertical\" zSize=\"14\" />\n </button>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span [class]=\"task.priorityBadgeClass\">\n {{ task.priorityLabelKey | translate }}\n </span>\n @if (task.completed) {\n <span class=\"inline-flex items-center gap-1 text-[11px] font-semibold text-emerald-500\">\n <z-icon zType=\"lucideCircleCheck\" zSize=\"12\" />\n {{ 'i18n_z_ui_kanban_done' | translate }}\n </span>\n }\n </div>\n\n @if (task.descriptionPreview) {\n <p class=\"text-muted-foreground line-clamp-3 text-xs leading-4\">{{ task.descriptionPreview }}</p>\n }\n\n <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-[11px]\">\n @if (task.dueDateLabel) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideCalendar\" zSize=\"12\" />\n {{ task.dueDateLabel }}\n </span>\n }\n\n @if (task.commentsCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideMessageSquare\" zSize=\"12\" />\n {{ task.commentsCount }}\n </span>\n }\n\n @if (task.attachmentCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n {{ task.attachmentCount }}\n </span>\n }\n\n @if (task.checklistCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideListChecks\" zSize=\"12\" />\n {{ task.checklistDoneCount }}/{{ task.checklistCount }}\n </span>\n }\n </div>\n\n <footer class=\"flex items-center justify-between gap-2\">\n <div class=\"flex -space-x-2\">\n @for (assignee of task.visibleAssignees; track assignee.name) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"assignee.name\"\n class=\"relative inline-flex size-6 items-center justify-center rounded-full text-[10px] font-bold\"\n [class]=\"assignee.className\"\n [style.zIndex]=\"assignee.zIndex\">\n {{ assignee.initials }}\n </span>\n }\n @if (task.hiddenAssigneesCount > 0) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"task.hiddenAssigneesLabel\"\n class=\"bg-muted text-muted-foreground border-background relative inline-flex size-6 items-center justify-center rounded-full border text-[10px] font-bold shadow-xs\"\n [style.zIndex]=\"20\">\n +{{ task.hiddenAssigneesCount }}\n </span>\n }\n </div>\n\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" class=\"text-muted-foreground\" />\n </footer>\n </article>\n }\n </div>\n </section>\n }\n </div>\n </div>\n</div>\n\n<z-modal\n [zVisible]=\"editorVisible()\"\n zTitle=\"i18n_z_ui_kanban_editor_title\"\n [zDescription]=\"editorMeta()\"\n [zOkText]=\"'i18n_z_ui_common_save' | translate\"\n [zCancelText]=\"'i18n_z_ui_common_cancel' | translate\"\n zWidth=\"min(96vw, 72rem)\"\n zOverlay=\"blur\"\n [zOkDisabled]=\"isEditorSaveDisabled()\"\n (zVisibleChange)=\"onEditorVisibleChange($event)\"\n (zAfterClose)=\"onEditorAfterClose()\"\n (zOk)=\"saveTaskChanges()\"\n (zCancel)=\"closeEditor()\">\n @if (activeTask()) {\n <div class=\"grid gap-6 xl:grid-cols-[minmax(0,1fr)_20rem]\">\n <div class=\"space-y-5\">\n <section class=\"space-y-2\">\n <z-input\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_title' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_title_placeholder' | translate\"\n [zRequired]=\"true\"\n [ngModel]=\"draftTitle()\"\n (ngModelChange)=\"draftTitle.set($event)\" />\n </section>\n\n <section class=\"space-y-2\">\n <z-editor\n zSize=\"sm\"\n [zLabel]=\"'i18n_z_ui_kanban_description' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_description_placeholder' | translate\"\n [ngModel]=\"draftDescription()\"\n (ngModelChange)=\"draftDescription.set($event)\" />\n </section>\n\n <section class=\"grid gap-3 md:grid-cols-2\">\n <ng-template #statusSelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"statusIconClassByValue()[option.value] + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #statusOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"statusIconClassByValue()[option.value] + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #prioritySelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"priorityIconClassByValue[option.value] + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #priorityOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"priorityIconClassByValue[option.value] + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_status' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"statusOptions()\"\n [zSelectedTemplate]=\"statusSelectedTpl\"\n [zOptionTemplate]=\"statusOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_status_placeholder' | translate\"\n [ngModel]=\"draftStatus()\"\n (ngModelChange)=\"onEditorStatusChange($event)\" />\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_priority' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"prioritySelectOptions()\"\n [zSelectedTemplate]=\"prioritySelectedTpl\"\n [zOptionTemplate]=\"priorityOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_priority_placeholder' | translate\"\n [ngModel]=\"draftPriority()\"\n (ngModelChange)=\"onEditorPriorityChange($event)\" />\n\n <z-select\n class=\"w-full md:col-span-2\"\n zMode=\"tags\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_assignees' | translate\"\n [zAllowClear]=\"true\"\n [zOptions]=\"assigneeOptions()\"\n [zMaxTagCount]=\"5\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_assignees_select_placeholder' | translate\"\n [ngModel]=\"draftAssignees()\"\n (ngModelChange)=\"onEditorAssigneesChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_start_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_start_date' | translate\"\n [ngModel]=\"draftStartDate()\"\n (ngModelChange)=\"onEditorStartDateChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_end_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_end_date' | translate\"\n [ngModel]=\"draftEndDate()\"\n (ngModelChange)=\"onEditorEndDateChange($event)\" />\n </section>\n\n <section class=\"space-y-3\">\n <div class=\"flex items-center justify-between gap-2\">\n <h4 class=\"text-sm font-semibold\">\n {{ 'i18n_z_ui_kanban_checklist' | translate }} ({{ checklistDoneCount() }}/{{ draftChecklist().length }})\n </h4>\n <span class=\"text-muted-foreground text-xs font-semibold\">{{ checklistProgress() }}%</span>\n </div>\n\n <div class=\"bg-muted h-2 w-full rounded-full\">\n <div class=\"bg-primary h-2 rounded-full transition-all\" [style.width.%]=\"checklistProgress()\"></div>\n </div>\n\n <div class=\"max-h-44 space-y-1 overflow-y-auto\">\n @for (item of draftChecklist(); track item.id) {\n <div [class]=\"item.done ? checklistDoneRowClass : checklistPendingRowClass\">\n <z-checkbox\n [class]=\"item.done ? 'min-w-0 flex-1 line-through' : 'min-w-0 flex-1'\"\n [zChecked]=\"item.done\"\n [zText]=\"item.label\"\n (zChange)=\"toggleChecklistItem(item.id, $event)\" />\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:text-destructive hover:bg-destructive/10 ml-auto inline-flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"removeChecklistItem(item.id)\">\n <z-icon zType=\"lucideTrash2\" zSize=\"12\" />\n </button>\n </div>\n } @empty {\n <p class=\"text-muted-foreground bg-muted/35 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_checklist_items' | translate }}\n </p>\n }\n </div>\n\n <div class=\"flex items-end gap-2\">\n <z-input\n class=\"flex-1\"\n zSize=\"lg\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_checklist_add_placeholder' | translate\"\n [ngModel]=\"draftChecklistItemLabel()\"\n (ngModelChange)=\"draftChecklistItemLabel.set($event)\"\n (zOnEnter)=\"addChecklistItem()\" />\n <button\n type=\"button\"\n zSize=\"lg\"\n z-button\n zType=\"outline\"\n zTypeIcon=\"lucidePlus\"\n (click)=\"addChecklistItem()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </button>\n </div>\n </section>\n\n <section class=\"space-y-2\">\n <z-upload\n [zLabel]=\"'i18n_z_ui_kanban_attachments' | translate\"\n [zNote]=\"'i18n_z_ui_kanban_attachments_note' | translate\"\n [zMultipleFile]=\"true\"\n [zShowProgress]=\"true\"\n [ngModel]=\"draftAttachments()\"\n (ngModelChange)=\"onDraftAttachmentsChange($event)\" />\n </section>\n </div>\n\n <aside\n class=\"bg-muted/25 border-border/70 flex h-[34rem] min-h-0 flex-col overflow-hidden rounded-lg border p-4 shadow-xs xl:h-[38rem]\">\n <section class=\"flex min-h-0 flex-1 flex-col gap-1.5\">\n <label class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </label>\n <div class=\"-mr-3 min-h-0 flex-1 space-y-2 overflow-y-auto pr-3 pb-2\">\n @for (entry of activeTaskActivityView(); track entry.id) {\n <div class=\"border-border/70 bg-background/60 rounded-md border px-3 py-2\">\n <p class=\"text-xs font-semibold\">{{ entry.actor }}</p>\n <p class=\"text-muted-foreground mt-1 text-xs leading-4\">{{ entry.action }}</p>\n <p class=\"text-muted-foreground mt-1 text-[10px]\">{{ entry.createdAtLabel }}</p>\n </div>\n } @empty {\n <p class=\"text-muted-foreground bg-muted/40 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_activity' | translate }}\n </p>\n }\n </div>\n </section>\n\n <section class=\"border-border/70 mt-3 shrink-0 space-y-2 border-t pt-3\">\n <z-input\n zType=\"textarea\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_add_comment' | translate\"\n [zRows]=\"3\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_comment_placeholder' | translate\"\n [ngModel]=\"draftComment()\"\n (ngModelChange)=\"draftComment.set($event)\" />\n\n <div class=\"flex justify-end pt-2\">\n <button\n type=\"button\"\n zTypeIcon=\"lucideSend\"\n z-button\n [disabled]=\"isCommentSubmitDisabled()\"\n (click)=\"submitTaskComment()\">\n {{ 'i18n_z_ui_kanban_comment_submit' | translate }}\n </button>\n </div>\n </section>\n </aside>\n </div>\n }\n</z-modal>\n", styles: [":host{display:block;height:100%;min-height:0}.z-kanban-board{overscroll-behavior-x:contain;scrollbar-width:thin;scrollbar-color:color-mix(in oklab,var(--muted-foreground) 45%,transparent) transparent}.z-kanban-board::-webkit-scrollbar{height:8px}.z-kanban-board::-webkit-scrollbar-thumb{background:color-mix(in oklab,var(--muted-foreground) 38%,transparent);border-radius:9999px}.z-kanban-board::-webkit-scrollbar-track{background:transparent}.kanban-drop-list{scrollbar-width:thin}.kanban-card{cursor:pointer}.kanban-card.cdk-drag-dragging{cursor:grabbing;transform:rotate(.35deg)}.kanban-drop-list.cdk-drop-list-dragging .kanban-card:not(.cdk-drag-placeholder){transition:transform .16s cubic-bezier(.2,0,0,1)}:host ::ng-deep .z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}:host ::ng-deep .z-kanban-drag-placeholder{opacity:.2;border:1px dashed color-mix(in oklab,var(--primary) 38%,var(--border));background:color-mix(in oklab,var(--primary) 8%,transparent)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: 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: 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: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowClear", "zFormat", "zMinDate", "zMaxDate", "zValueType", "zValidators", "zShowOk", "zOkText", "zShowCancel", "zCancelText", "zDisabledDate", "zScrollClose", "zDefaultTime", "zRangeDefaultTime"], outputs: ["zControl", "zChange", "zOnBlur", "zOnFocus", "zEvent"], exportAs: ["zCalendar"] }, { kind: "component", type: ZCheckboxComponent, selector: "z-checkbox", inputs: ["class", "zType", "zSize", "zLabel", "zText", "zDisabled", "zIndeterminate", "zValue", "zOptions", "zOrientation", "zCheckAll", "zCheckAllText", "zChecked", "zGroupValue"], outputs: ["zChange", "zGroupChange", "zOnBlur", "zOnFocus", "zControl", "zEvent", "zCheckedChange", "zGroupValueChange"] }, { kind: "component", type: ZEditorComponent, selector: "z-editor", inputs: ["class", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zModules", "zFormats", "zBounds", "zTheme", "zValidators"], outputs: ["zOnChange", "zOnFocus", "zOnBlur", "zControl", "zEvent"], exportAs: ["zEditor"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zAlign", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zPrefix", "zSuffix", "zMin", "zMax", "zStep", "zShowArrows", "zMask", "zDecimalPlaces", "zAllowNegative", "zThousandSeparator", "zDecimalMarker", "zValidators", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zShowPasswordToggle", "zSearch", "zDebounce", "zAutofocus", "zAutoComplete", "zAllowClear", "zAutoSizeContent", "zRows", "zResize", "zMaxLength", "zAutoSuggest", "zColorConfig"], outputs: ["zOnSearch", "zOnChange", "zOnBlur", "zOnFocus", "zOnKeydown", "zOnEnter", "zOnColorCollapse", "zControl", "zEvent"], exportAs: ["zInput"] }, { kind: "component", type: ZModalComponent, selector: "z-modal", inputs: ["class", "zVisible", "zTitle", "zDescription", "zWidth", "zClosable", "zMaskClosable", "zHideHeader", "zHideFooter", "zOkText", "zCancelText", "zOkDestructive", "zOkDisabled", "zLoading", "zContentLoading", "zSkeletonRows", "zOverlay"], outputs: ["zOk", "zCancel", "zAfterClose", "zScrollbar", "zVisibleChange"], exportAs: ["zModal"] }, { kind: "component", type: ZSelectComponent, selector: "z-select", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zPrefix", "zAllowClear", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zDropdownMaxHeight", "zOptionHeight", "zVirtualScroll", "zShowAction", "zOptions", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zPosition", "zSelectedTemplate", "zOptionTemplate", "zActionTemplate", "zAsyncValidators", "zAsyncDebounce", "zAsyncValidateOn", "zValidators"], outputs: ["zOnSearch", "zOnLoadMore", "zOnBlur", "zOnFocus", "zControl", "zEvent"], exportAs: ["zSelect"] }, { kind: "directive", type: ZTooltipDirective, selector: "[z-tooltip], [zTooltip]", inputs: ["zContent", "zPosition", "zTrigger", "zTooltipType", "zTooltipSize", "zClass", "zShowDelay", "zHideDelay", "zArrow", "zDisabled", "zOffset", "zAutoDetect", "zTriggerElement", "zAlwaysShow", "zMaxWidth"], outputs: ["zShow", "zHide"], exportAs: ["zTooltip"] }, { kind: "component", type: ZUploadComponent, selector: "z-upload", inputs: ["class", "zLabel", "zLabelClass", "zNote", "zSize", "zAcceptFile", "zMultipleFile", "zMaxSize", "zMaxFiles", "zRequired", "zDisabled", "zReadonly", "zLoading", "zShowProgress", "zValidators"], outputs: ["zOnUpload", "zOnRemove", "zOnDownload", "zOnError", "zOnFileChange", "zOnDragover", "zOnDragleave", "zOnDrop", "zControl", "zEvent"], exportAs: ["zUpload"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
952
952
  }
953
953
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZKanbanComponent, decorators: [{
954
954
  type: Component,
@@ -970,7 +970,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
970
970
  TranslatePipe,
971
971
  ], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
972
972
  '[class]': 'hostClasses()',
973
- }, exportAs: 'zKanban', template: "<div class=\"flex h-full min-h-0 min-w-0 flex-col gap-5\">\n @if (zShowToolbar()) {\n <header class=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n <h2 class=\"text-foreground truncate text-xl font-bold\">{{ zTitle() | translate }}</h2>\n <p class=\"text-muted-foreground text-sm\">{{ zSubtitle() | translate }}</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center\">\n <z-input\n class=\"w-full sm:w-80\"\n zSize=\"sm\"\n [zSearch]=\"true\"\n [zDebounce]=\"200\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_search_placeholder' | translate\"\n [ngModel]=\"zSearch()\"\n (zOnSearch)=\"onBoardSearchChange($event)\" />\n\n @if (zAllowCreateTask()) {\n <z-button zType=\"outline\" zSize=\"sm\" zTypeIcon=\"lucidePlus\" (click)=\"createTaskInFirstColumn()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </z-button>\n }\n </div>\n </header>\n }\n\n @if (isSearchActive()) {\n <p class=\"text-muted-foreground text-xs\">\n {{ 'i18n_z_ui_kanban_drag_disabled_while_search' | translate }}\n </p>\n }\n\n <div #boardViewport class=\"z-kanban-board min-h-0 flex-1 overflow-x-auto pb-2\">\n <div class=\"flex h-full min-h-[25rem] min-w-max items-stretch gap-4\">\n @for (column of boardColumnsView(); track column.id) {\n <section [class]=\"columnClass()\">\n <header class=\"mb-2 flex items-center justify-between gap-2 px-0.5\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h3 class=\"text-foreground truncate text-xs font-bold tracking-wide uppercase\">\n {{ column.title | translate }}\n </h3>\n <span\n class=\"bg-muted text-muted-foreground inline-flex min-w-5 items-center justify-center rounded-full px-1.5 py-0.5 text-[10px] font-bold\">\n {{ column.taskCount }}\n </span>\n </div>\n\n @if (zAllowCreateTask()) {\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-7 cursor-pointer items-center justify-center rounded-md transition-colors\"\n (click)=\"createTask(column.id)\">\n <z-icon zType=\"lucidePlus\" zSize=\"16\" />\n </button>\n }\n </header>\n\n <div\n cdkDropList\n [id]=\"column.id\"\n [cdkDropListData]=\"column.rawTasks\"\n [cdkDropListConnectedTo]=\"connectedDropListIds()\"\n [cdkDropListDisabled]=\"zDisabled() || isSearchActive()\"\n class=\"kanban-drop-list -mr-1 flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto p-0.5 pr-1\"\n (cdkDropListDropped)=\"onTaskDrop($event, column.id)\">\n @if (column.taskCount === 0) {\n <div\n class=\"border-border/70 text-muted-foreground flex h-24 items-center justify-center rounded-lg border border-dashed px-3 text-center text-xs\">\n @if (isSearchActive()) {\n {{ 'i18n_z_ui_kanban_no_matches' | translate }}\n } @else {\n {{ 'i18n_z_ui_kanban_drop_here' | translate }}\n }\n </div>\n }\n\n @for (task of column.tasks; track task.id) {\n <article\n cdkDrag\n cdkDragPreviewClass=\"z-kanban-drag-preview\"\n cdkDragPlaceholderClass=\"z-kanban-drag-placeholder\"\n [cdkDragData]=\"{ columnId: column.id, taskId: task.id }\"\n [cdkDragDisabled]=\"zDisabled() || isSearchActive()\"\n [class]=\"'kanban-card shrink-0 ' + task.taskCardClass\"\n (cdkDragStarted)=\"onTaskDragStarted()\"\n (cdkDragMoved)=\"onTaskDragMoved($event)\"\n (cdkDragEnded)=\"onTaskDragEnded($event)\"\n (click)=\"onTaskCardClick(column.id, task.id)\">\n <div class=\"flex items-start justify-between gap-2\">\n <div class=\"min-w-0 space-y-1\">\n @if (task.code) {\n <p class=\"text-muted-foreground text-[10px] font-semibold tracking-wide uppercase\">\n {{ task.code }}\n </p>\n }\n <h4 class=\"line-clamp-2 text-sm leading-5 font-semibold\">{{ task.title }}</h4>\n </div>\n\n <button\n cdkDragHandle\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-6 shrink-0 cursor-grab items-center justify-center rounded-md transition-colors\"\n (click)=\"onTaskHandleClick($event)\">\n <z-icon zType=\"lucideGripVertical\" zSize=\"14\" />\n </button>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span [class]=\"task.priorityBadgeClass\">\n {{ task.priorityLabelKey | translate }}\n </span>\n @if (task.completed) {\n <span class=\"inline-flex items-center gap-1 text-[11px] font-semibold text-emerald-500\">\n <z-icon zType=\"lucideCircleCheck\" zSize=\"12\" />\n {{ 'i18n_z_ui_kanban_done' | translate }}\n </span>\n }\n </div>\n\n @if (task.descriptionPreview) {\n <p class=\"text-muted-foreground line-clamp-3 text-xs leading-4\">{{ task.descriptionPreview }}</p>\n }\n\n <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-[11px]\">\n @if (task.dueDateLabel) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideCalendar\" zSize=\"12\" />\n {{ task.dueDateLabel }}\n </span>\n }\n\n @if (task.commentsCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideMessageSquare\" zSize=\"12\" />\n {{ task.commentsCount }}\n </span>\n }\n\n @if (task.attachmentCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n {{ task.attachmentCount }}\n </span>\n }\n\n @if (task.checklistCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideListChecks\" zSize=\"12\" />\n {{ task.checklistDoneCount }}/{{ task.checklistCount }}\n </span>\n }\n </div>\n\n <footer class=\"flex items-center justify-between gap-2\">\n <div class=\"flex -space-x-2\">\n @for (assignee of task.visibleAssignees; track assignee.name) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"assignee.name\"\n class=\"relative inline-flex size-6 items-center justify-center rounded-full text-[10px] font-bold\"\n [class]=\"assignee.className\"\n [style.zIndex]=\"assignee.zIndex\">\n {{ assignee.initials }}\n </span>\n }\n @if (task.hiddenAssigneesCount > 0) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"task.hiddenAssigneesLabel\"\n class=\"bg-muted text-muted-foreground border-background relative inline-flex size-6 items-center justify-center rounded-full border text-[10px] font-bold shadow-xs\"\n [style.zIndex]=\"20\">\n +{{ task.hiddenAssigneesCount }}\n </span>\n }\n </div>\n\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" class=\"text-muted-foreground\" />\n </footer>\n </article>\n }\n </div>\n </section>\n }\n </div>\n </div>\n</div>\n\n<z-modal\n [zVisible]=\"editorVisible()\"\n [zTitle]=\"'i18n_z_ui_kanban_editor_title'\"\n [zDescription]=\"editorMeta()\"\n [zOkText]=\"'i18n_z_ui_common_save' | translate\"\n [zCancelText]=\"'i18n_z_ui_common_cancel' | translate\"\n zWidth=\"min(96vw, 72rem)\"\n zOverlay=\"blur\"\n [zOkDisabled]=\"isEditorSaveDisabled()\"\n (zVisibleChange)=\"onEditorVisibleChange($event)\"\n (zAfterClose)=\"onEditorAfterClose()\"\n (zOk)=\"saveTaskChanges()\"\n (zCancel)=\"closeEditor()\">\n @if (activeTask()) {\n <div class=\"grid gap-6 xl:grid-cols-[minmax(0,1fr)_20rem]\">\n <div class=\"space-y-5\">\n <section class=\"space-y-2\">\n <z-input\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_title' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_title_placeholder' | translate\"\n [zRequired]=\"true\"\n [ngModel]=\"draftTitle()\"\n (ngModelChange)=\"draftTitle.set($event)\" />\n </section>\n\n <section class=\"space-y-2\">\n <z-editor\n zSize=\"sm\"\n [zLabel]=\"'i18n_z_ui_kanban_description' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_description_placeholder' | translate\"\n [ngModel]=\"draftDescription()\"\n (ngModelChange)=\"draftDescription.set($event)\" />\n </section>\n\n <section class=\"grid gap-3 md:grid-cols-2\">\n <ng-template #statusSelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(statusIconClassByValue()[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #statusOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(statusIconClassByValue()[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #prioritySelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(priorityIconClassByValue[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #priorityOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"(priorityIconClassByValue[option.value] ?? 'text-muted-foreground') + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_status' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"statusOptions()\"\n [zSelectedTemplate]=\"statusSelectedTpl\"\n [zOptionTemplate]=\"statusOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_status_placeholder' | translate\"\n [ngModel]=\"draftStatus()\"\n (ngModelChange)=\"onEditorStatusChange($event)\" />\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_priority' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"prioritySelectOptions()\"\n [zSelectedTemplate]=\"prioritySelectedTpl\"\n [zOptionTemplate]=\"priorityOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_priority_placeholder' | translate\"\n [ngModel]=\"draftPriority()\"\n (ngModelChange)=\"onEditorPriorityChange($event)\" />\n\n <z-select\n class=\"w-full md:col-span-2\"\n zMode=\"tags\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_assignees' | translate\"\n [zAllowClear]=\"true\"\n [zOptions]=\"assigneeOptions()\"\n [zMaxTagCount]=\"5\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_assignees_select_placeholder' | translate\"\n [ngModel]=\"draftAssignees()\"\n (ngModelChange)=\"onEditorAssigneesChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_start_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_start_date' | translate\"\n [ngModel]=\"draftStartDate()\"\n (ngModelChange)=\"onEditorStartDateChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_end_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_end_date' | translate\"\n [ngModel]=\"draftEndDate()\"\n (ngModelChange)=\"onEditorEndDateChange($event)\" />\n </section>\n\n <section class=\"space-y-3\">\n <div class=\"flex items-center justify-between gap-2\">\n <h4 class=\"text-sm font-semibold\">\n {{ 'i18n_z_ui_kanban_checklist' | translate }} ({{ checklistDoneCount() }}/{{ draftChecklist().length }})\n </h4>\n <span class=\"text-muted-foreground text-xs font-semibold\">{{ checklistProgress() }}%</span>\n </div>\n\n <div class=\"bg-muted h-2 w-full rounded-full\">\n <div class=\"bg-primary h-2 rounded-full transition-all\" [style.width.%]=\"checklistProgress()\"></div>\n </div>\n\n <div class=\"max-h-44 space-y-1 overflow-y-auto\">\n @if (draftChecklist().length === 0) {\n <p class=\"text-muted-foreground bg-muted/35 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_checklist_items' | translate }}\n </p>\n }\n\n @for (item of draftChecklist(); track item.id) {\n <div [class]=\"item.done ? checklistDoneRowClass : checklistPendingRowClass\">\n <z-checkbox\n [class]=\"item.done ? 'min-w-0 flex-1 line-through' : 'min-w-0 flex-1'\"\n [zChecked]=\"item.done\"\n [zText]=\"item.label\"\n (zChange)=\"toggleChecklistItem(item.id, $event)\" />\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:text-destructive hover:bg-destructive/10 ml-auto inline-flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"removeChecklistItem(item.id)\">\n <z-icon zType=\"lucideTrash2\" zSize=\"12\" />\n </button>\n </div>\n }\n </div>\n\n <div class=\"flex items-end gap-2\">\n <z-input\n class=\"flex-1\"\n zSize=\"lg\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_checklist_add_placeholder' | translate\"\n [ngModel]=\"draftChecklistItemLabel()\"\n (ngModelChange)=\"draftChecklistItemLabel.set($event)\"\n (zOnEnter)=\"addChecklistItem()\" />\n <button\n type=\"button\"\n zSize=\"lg\"\n z-button\n zType=\"outline\"\n zTypeIcon=\"lucidePlus\"\n (click)=\"addChecklistItem()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </button>\n </div>\n </section>\n\n <section class=\"space-y-2\">\n <z-upload\n [zLabel]=\"'i18n_z_ui_kanban_attachments' | translate\"\n [zNote]=\"'i18n_z_ui_kanban_attachments_note' | translate\"\n [zMultipleFile]=\"true\"\n [zShowProgress]=\"true\"\n [ngModel]=\"draftAttachments()\"\n (ngModelChange)=\"onDraftAttachmentsChange($event)\" />\n </section>\n </div>\n\n <aside\n class=\"bg-muted/25 border-border/70 flex h-[34rem] min-h-0 flex-col overflow-hidden rounded-lg border p-4 shadow-xs xl:h-[38rem]\">\n <section class=\"flex min-h-0 flex-1 flex-col gap-1.5\">\n <label class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </label>\n <div class=\"-mr-3 min-h-0 flex-1 space-y-2 overflow-y-auto pr-3 pb-2\">\n @if (activeTaskActivityView().length === 0) {\n <p class=\"text-muted-foreground bg-muted/40 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_activity' | translate }}\n </p>\n }\n\n @for (entry of activeTaskActivityView(); track entry.id) {\n <div class=\"border-border/70 bg-background/60 rounded-md border px-3 py-2\">\n <p class=\"text-xs font-semibold\">{{ entry.actor }}</p>\n <p class=\"text-muted-foreground mt-1 text-xs leading-4\">{{ entry.action }}</p>\n <p class=\"text-muted-foreground mt-1 text-[10px]\">{{ entry.createdAtLabel }}</p>\n </div>\n }\n </div>\n </section>\n\n <section class=\"border-border/70 mt-3 shrink-0 space-y-2 border-t pt-3\">\n <z-input\n zType=\"textarea\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_add_comment' | translate\"\n [zRows]=\"3\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_comment_placeholder' | translate\"\n [ngModel]=\"draftComment()\"\n (ngModelChange)=\"draftComment.set($event)\" />\n\n <div class=\"flex justify-end pt-2\">\n <button\n type=\"button\"\n [zTypeIcon]=\"'lucideSend'\"\n z-button\n [disabled]=\"isCommentSubmitDisabled()\"\n (click)=\"submitTaskComment()\">\n {{ 'i18n_z_ui_kanban_comment_submit' | translate }}\n </button>\n </div>\n </section>\n </aside>\n </div>\n }\n</z-modal>\n", styles: [":host{display:block;height:100%;min-height:0}.z-kanban-board{overscroll-behavior-x:contain;scrollbar-width:thin;scrollbar-color:color-mix(in oklab,var(--muted-foreground) 45%,transparent) transparent}.z-kanban-board::-webkit-scrollbar{height:8px}.z-kanban-board::-webkit-scrollbar-thumb{background:color-mix(in oklab,var(--muted-foreground) 38%,transparent);border-radius:9999px}.z-kanban-board::-webkit-scrollbar-track{background:transparent}.kanban-drop-list{scrollbar-width:thin}.kanban-card{cursor:pointer}.kanban-card.cdk-drag-dragging{cursor:grabbing;transform:rotate(.35deg)}.kanban-drop-list.cdk-drop-list-dragging .kanban-card:not(.cdk-drag-placeholder){transition:transform .16s cubic-bezier(.2,0,0,1)}:host ::ng-deep .z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}:host ::ng-deep .z-kanban-drag-placeholder{opacity:.2;border:1px dashed color-mix(in oklab,var(--primary) 38%,var(--border));background:color-mix(in oklab,var(--primary) 8%,transparent)}\n"] }]
973
+ }, exportAs: 'zKanban', template: "<div class=\"flex h-full min-h-0 min-w-0 flex-col gap-5\">\n @if (zShowToolbar()) {\n <header class=\"flex flex-col gap-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n <h2 class=\"text-foreground truncate text-xl font-bold\">{{ zTitle() | translate }}</h2>\n <p class=\"text-muted-foreground text-sm\">{{ zSubtitle() | translate }}</p>\n </div>\n\n <div class=\"flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center\">\n <z-input\n class=\"w-full sm:w-80\"\n zSize=\"sm\"\n [zSearch]=\"true\"\n [zDebounce]=\"200\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_search_placeholder' | translate\"\n [ngModel]=\"zSearch()\"\n (zOnSearch)=\"onBoardSearchChange($event)\" />\n\n @if (zAllowCreateTask()) {\n <z-button zType=\"outline\" zSize=\"sm\" zTypeIcon=\"lucidePlus\" (click)=\"createTaskInFirstColumn()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </z-button>\n }\n </div>\n </header>\n }\n\n @if (isSearchActive()) {\n <p class=\"text-muted-foreground text-xs\">\n {{ 'i18n_z_ui_kanban_drag_disabled_while_search' | translate }}\n </p>\n }\n\n <div #boardViewport class=\"z-kanban-board min-h-0 flex-1 overflow-x-auto pb-2\">\n <div class=\"flex h-full min-h-[25rem] min-w-max items-stretch gap-4\">\n @for (column of boardColumnsView(); track column.id) {\n <section [class]=\"columnClass()\">\n <header class=\"mb-2 flex items-center justify-between gap-2 px-0.5\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <h3 class=\"text-foreground truncate text-xs font-bold tracking-wide uppercase\">\n {{ column.title | translate }}\n </h3>\n <span\n class=\"bg-muted text-muted-foreground inline-flex min-w-5 items-center justify-center rounded-full px-1.5 py-0.5 text-[10px] font-bold\">\n {{ column.taskCount }}\n </span>\n </div>\n\n @if (zAllowCreateTask()) {\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-7 cursor-pointer items-center justify-center rounded-md transition-colors\"\n (click)=\"createTask(column.id)\">\n <z-icon zType=\"lucidePlus\" zSize=\"16\" />\n </button>\n }\n </header>\n\n <div\n cdkDropList\n [id]=\"column.id\"\n [cdkDropListData]=\"column.rawTasks\"\n [cdkDropListConnectedTo]=\"connectedDropListIds()\"\n [cdkDropListDisabled]=\"zDisabled() || isSearchActive()\"\n class=\"kanban-drop-list -mr-1 flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto p-0.5 pr-1\"\n (cdkDropListDropped)=\"onTaskDrop($event, column.id)\">\n @if (column.taskCount === 0) {\n <div\n class=\"border-border/70 text-muted-foreground flex h-24 items-center justify-center rounded-lg border border-dashed px-3 text-center text-xs\">\n @if (isSearchActive()) {\n {{ 'i18n_z_ui_kanban_no_matches' | translate }}\n } @else {\n {{ 'i18n_z_ui_kanban_drop_here' | translate }}\n }\n </div>\n }\n\n @for (task of column.tasks; track task.id) {\n <article\n cdkDrag\n cdkDragPreviewClass=\"z-kanban-drag-preview\"\n cdkDragPlaceholderClass=\"z-kanban-drag-placeholder\"\n [cdkDragData]=\"{ columnId: column.id, taskId: task.id }\"\n [cdkDragDisabled]=\"zDisabled() || isSearchActive()\"\n [class]=\"'kanban-card shrink-0 ' + task.taskCardClass\"\n (cdkDragStarted)=\"onTaskDragStarted()\"\n (cdkDragMoved)=\"onTaskDragMoved($event)\"\n (cdkDragEnded)=\"onTaskDragEnded($event)\"\n (click)=\"onTaskCardClick(column.id, task.id)\">\n <div class=\"flex items-start justify-between gap-2\">\n <div class=\"min-w-0 space-y-1\">\n @if (task.code) {\n <p class=\"text-muted-foreground text-[10px] font-semibold tracking-wide uppercase\">\n {{ task.code }}\n </p>\n }\n <h4 class=\"line-clamp-2 text-sm leading-5 font-semibold\">{{ task.title }}</h4>\n </div>\n\n <button\n cdkDragHandle\n type=\"button\"\n class=\"text-muted-foreground hover:bg-muted hover:text-foreground inline-flex size-6 shrink-0 cursor-grab items-center justify-center rounded-md transition-colors\"\n (click)=\"onTaskHandleClick($event)\">\n <z-icon zType=\"lucideGripVertical\" zSize=\"14\" />\n </button>\n </div>\n\n <div class=\"flex items-center gap-2\">\n <span [class]=\"task.priorityBadgeClass\">\n {{ task.priorityLabelKey | translate }}\n </span>\n @if (task.completed) {\n <span class=\"inline-flex items-center gap-1 text-[11px] font-semibold text-emerald-500\">\n <z-icon zType=\"lucideCircleCheck\" zSize=\"12\" />\n {{ 'i18n_z_ui_kanban_done' | translate }}\n </span>\n }\n </div>\n\n @if (task.descriptionPreview) {\n <p class=\"text-muted-foreground line-clamp-3 text-xs leading-4\">{{ task.descriptionPreview }}</p>\n }\n\n <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-[11px]\">\n @if (task.dueDateLabel) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideCalendar\" zSize=\"12\" />\n {{ task.dueDateLabel }}\n </span>\n }\n\n @if (task.commentsCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideMessageSquare\" zSize=\"12\" />\n {{ task.commentsCount }}\n </span>\n }\n\n @if (task.attachmentCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucidePaperclip\" zSize=\"12\" />\n {{ task.attachmentCount }}\n </span>\n }\n\n @if (task.checklistCount > 0) {\n <span class=\"inline-flex items-center gap-1\">\n <z-icon zType=\"lucideListChecks\" zSize=\"12\" />\n {{ task.checklistDoneCount }}/{{ task.checklistCount }}\n </span>\n }\n </div>\n\n <footer class=\"flex items-center justify-between gap-2\">\n <div class=\"flex -space-x-2\">\n @for (assignee of task.visibleAssignees; track assignee.name) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"assignee.name\"\n class=\"relative inline-flex size-6 items-center justify-center rounded-full text-[10px] font-bold\"\n [class]=\"assignee.className\"\n [style.zIndex]=\"assignee.zIndex\">\n {{ assignee.initials }}\n </span>\n }\n @if (task.hiddenAssigneesCount > 0) {\n <span\n z-tooltip\n zAlwaysShow\n zPosition=\"top\"\n [zContent]=\"task.hiddenAssigneesLabel\"\n class=\"bg-muted text-muted-foreground border-background relative inline-flex size-6 items-center justify-center rounded-full border text-[10px] font-bold shadow-xs\"\n [style.zIndex]=\"20\">\n +{{ task.hiddenAssigneesCount }}\n </span>\n }\n </div>\n\n <z-icon zType=\"lucideChevronRight\" zSize=\"14\" class=\"text-muted-foreground\" />\n </footer>\n </article>\n }\n </div>\n </section>\n }\n </div>\n </div>\n</div>\n\n<z-modal\n [zVisible]=\"editorVisible()\"\n zTitle=\"i18n_z_ui_kanban_editor_title\"\n [zDescription]=\"editorMeta()\"\n [zOkText]=\"'i18n_z_ui_common_save' | translate\"\n [zCancelText]=\"'i18n_z_ui_common_cancel' | translate\"\n zWidth=\"min(96vw, 72rem)\"\n zOverlay=\"blur\"\n [zOkDisabled]=\"isEditorSaveDisabled()\"\n (zVisibleChange)=\"onEditorVisibleChange($event)\"\n (zAfterClose)=\"onEditorAfterClose()\"\n (zOk)=\"saveTaskChanges()\"\n (zCancel)=\"closeEditor()\">\n @if (activeTask()) {\n <div class=\"grid gap-6 xl:grid-cols-[minmax(0,1fr)_20rem]\">\n <div class=\"space-y-5\">\n <section class=\"space-y-2\">\n <z-input\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_title' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_title_placeholder' | translate\"\n [zRequired]=\"true\"\n [ngModel]=\"draftTitle()\"\n (ngModelChange)=\"draftTitle.set($event)\" />\n </section>\n\n <section class=\"space-y-2\">\n <z-editor\n zSize=\"sm\"\n [zLabel]=\"'i18n_z_ui_kanban_description' | translate\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_description_placeholder' | translate\"\n [ngModel]=\"draftDescription()\"\n (ngModelChange)=\"draftDescription.set($event)\" />\n </section>\n\n <section class=\"grid gap-3 md:grid-cols-2\">\n <ng-template #statusSelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"statusIconClassByValue()[option.value] + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #statusOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"statusIconClassByValue()[option.value] + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #prioritySelectedTpl let-option>\n <span class=\"inline-flex min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"priorityIconClassByValue[option.value] + ' shrink-0'\" />\n <span class=\"truncate\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <ng-template #priorityOptionTpl let-option let-selected=\"selected\">\n <span class=\"inline-flex w-full min-w-0 items-center gap-2\">\n <z-icon\n [zType]=\"option.icon || 'lucideCircleDot'\"\n zSize=\"14\"\n [class]=\"priorityIconClassByValue[option.value] + ' shrink-0'\" />\n <span class=\"truncate\" [class.font-medium]=\"selected\">{{ option.label }}</span>\n </span>\n </ng-template>\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_status' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"statusOptions()\"\n [zSelectedTemplate]=\"statusSelectedTpl\"\n [zOptionTemplate]=\"statusOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_status_placeholder' | translate\"\n [ngModel]=\"draftStatus()\"\n (ngModelChange)=\"onEditorStatusChange($event)\" />\n\n <z-select\n class=\"w-full\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_priority' | translate\"\n [zAllowClear]=\"false\"\n [zOptions]=\"prioritySelectOptions()\"\n [zSelectedTemplate]=\"prioritySelectedTpl\"\n [zOptionTemplate]=\"priorityOptionTpl\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_priority_placeholder' | translate\"\n [ngModel]=\"draftPriority()\"\n (ngModelChange)=\"onEditorPriorityChange($event)\" />\n\n <z-select\n class=\"w-full md:col-span-2\"\n zMode=\"tags\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_assignees' | translate\"\n [zAllowClear]=\"true\"\n [zOptions]=\"assigneeOptions()\"\n [zMaxTagCount]=\"5\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_assignees_select_placeholder' | translate\"\n [ngModel]=\"draftAssignees()\"\n (ngModelChange)=\"onEditorAssigneesChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_start_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_start_date' | translate\"\n [ngModel]=\"draftStartDate()\"\n (ngModelChange)=\"onEditorStartDateChange($event)\" />\n\n <z-calendar\n zMode=\"single\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_end_date' | translate\"\n zAllowClear\n zValueType=\"date\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_end_date' | translate\"\n [ngModel]=\"draftEndDate()\"\n (ngModelChange)=\"onEditorEndDateChange($event)\" />\n </section>\n\n <section class=\"space-y-3\">\n <div class=\"flex items-center justify-between gap-2\">\n <h4 class=\"text-sm font-semibold\">\n {{ 'i18n_z_ui_kanban_checklist' | translate }} ({{ checklistDoneCount() }}/{{ draftChecklist().length }})\n </h4>\n <span class=\"text-muted-foreground text-xs font-semibold\">{{ checklistProgress() }}%</span>\n </div>\n\n <div class=\"bg-muted h-2 w-full rounded-full\">\n <div class=\"bg-primary h-2 rounded-full transition-all\" [style.width.%]=\"checklistProgress()\"></div>\n </div>\n\n <div class=\"max-h-44 space-y-1 overflow-y-auto\">\n @for (item of draftChecklist(); track item.id) {\n <div [class]=\"item.done ? checklistDoneRowClass : checklistPendingRowClass\">\n <z-checkbox\n [class]=\"item.done ? 'min-w-0 flex-1 line-through' : 'min-w-0 flex-1'\"\n [zChecked]=\"item.done\"\n [zText]=\"item.label\"\n (zChange)=\"toggleChecklistItem(item.id, $event)\" />\n <button\n type=\"button\"\n class=\"text-muted-foreground hover:text-destructive hover:bg-destructive/10 ml-auto inline-flex size-6 shrink-0 cursor-pointer items-center justify-center rounded transition-colors\"\n (click)=\"removeChecklistItem(item.id)\">\n <z-icon zType=\"lucideTrash2\" zSize=\"12\" />\n </button>\n </div>\n } @empty {\n <p class=\"text-muted-foreground bg-muted/35 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_checklist_items' | translate }}\n </p>\n }\n </div>\n\n <div class=\"flex items-end gap-2\">\n <z-input\n class=\"flex-1\"\n zSize=\"lg\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_checklist_add_placeholder' | translate\"\n [ngModel]=\"draftChecklistItemLabel()\"\n (ngModelChange)=\"draftChecklistItemLabel.set($event)\"\n (zOnEnter)=\"addChecklistItem()\" />\n <button\n type=\"button\"\n zSize=\"lg\"\n z-button\n zType=\"outline\"\n zTypeIcon=\"lucidePlus\"\n (click)=\"addChecklistItem()\">\n {{ 'i18n_z_ui_common_add' | translate }}\n </button>\n </div>\n </section>\n\n <section class=\"space-y-2\">\n <z-upload\n [zLabel]=\"'i18n_z_ui_kanban_attachments' | translate\"\n [zNote]=\"'i18n_z_ui_kanban_attachments_note' | translate\"\n [zMultipleFile]=\"true\"\n [zShowProgress]=\"true\"\n [ngModel]=\"draftAttachments()\"\n (ngModelChange)=\"onDraftAttachmentsChange($event)\" />\n </section>\n </div>\n\n <aside\n class=\"bg-muted/25 border-border/70 flex h-[34rem] min-h-0 flex-col overflow-hidden rounded-lg border p-4 shadow-xs xl:h-[38rem]\">\n <section class=\"flex min-h-0 flex-1 flex-col gap-1.5\">\n <label class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </label>\n <div class=\"-mr-3 min-h-0 flex-1 space-y-2 overflow-y-auto pr-3 pb-2\">\n @for (entry of activeTaskActivityView(); track entry.id) {\n <div class=\"border-border/70 bg-background/60 rounded-md border px-3 py-2\">\n <p class=\"text-xs font-semibold\">{{ entry.actor }}</p>\n <p class=\"text-muted-foreground mt-1 text-xs leading-4\">{{ entry.action }}</p>\n <p class=\"text-muted-foreground mt-1 text-[10px]\">{{ entry.createdAtLabel }}</p>\n </div>\n } @empty {\n <p class=\"text-muted-foreground bg-muted/40 rounded-md px-3 py-2 text-xs\">\n {{ 'i18n_z_ui_kanban_no_activity' | translate }}\n </p>\n }\n </div>\n </section>\n\n <section class=\"border-border/70 mt-3 shrink-0 space-y-2 border-t pt-3\">\n <z-input\n zType=\"textarea\"\n zSize=\"lg\"\n [zLabel]=\"'i18n_z_ui_kanban_add_comment' | translate\"\n [zRows]=\"3\"\n [zPlaceholder]=\"'i18n_z_ui_kanban_comment_placeholder' | translate\"\n [ngModel]=\"draftComment()\"\n (ngModelChange)=\"draftComment.set($event)\" />\n\n <div class=\"flex justify-end pt-2\">\n <button\n type=\"button\"\n zTypeIcon=\"lucideSend\"\n z-button\n [disabled]=\"isCommentSubmitDisabled()\"\n (click)=\"submitTaskComment()\">\n {{ 'i18n_z_ui_kanban_comment_submit' | translate }}\n </button>\n </div>\n </section>\n </aside>\n </div>\n }\n</z-modal>\n", styles: [":host{display:block;height:100%;min-height:0}.z-kanban-board{overscroll-behavior-x:contain;scrollbar-width:thin;scrollbar-color:color-mix(in oklab,var(--muted-foreground) 45%,transparent) transparent}.z-kanban-board::-webkit-scrollbar{height:8px}.z-kanban-board::-webkit-scrollbar-thumb{background:color-mix(in oklab,var(--muted-foreground) 38%,transparent);border-radius:9999px}.z-kanban-board::-webkit-scrollbar-track{background:transparent}.kanban-drop-list{scrollbar-width:thin}.kanban-card{cursor:pointer}.kanban-card.cdk-drag-dragging{cursor:grabbing;transform:rotate(.35deg)}.kanban-drop-list.cdk-drop-list-dragging .kanban-card:not(.cdk-drag-placeholder){transition:transform .16s cubic-bezier(.2,0,0,1)}:host ::ng-deep .z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}:host ::ng-deep .z-kanban-drag-placeholder{opacity:.2;border:1px dashed color-mix(in oklab,var(--primary) 38%,var(--border));background:color-mix(in oklab,var(--primary) 8%,transparent)}\n"] }]
974
974
  }], propDecorators: { zTaskDrop: [{ type: i0.Output, args: ["zTaskDrop"] }], zTaskSave: [{ type: i0.Output, args: ["zTaskSave"] }], zTaskClick: [{ type: i0.Output, args: ["zTaskClick"] }], zTaskCreate: [{ type: i0.Output, args: ["zTaskCreate"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "zColumns", required: false }] }, { type: i0.Output, args: ["zColumnsChange"] }], zTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTitle", required: false }] }], zSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSubtitle", required: false }] }], zSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSearch", required: false }] }, { type: i0.Output, args: ["zSearchChange"] }], zShowToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowToolbar", required: false }] }], zAllowCreateTask: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowCreateTask", required: false }] }], zDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDisabled", required: false }] }], zDensity: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDensity", required: false }] }], boardViewportRef: [{ type: i0.ViewChild, args: ['boardViewport', { isSignal: true }] }] } });
975
975
 
976
976
  /**