@shival99/z-ui 2.6.5 → 2.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +5 -5
- package/assets/css/base.css +16 -16
- package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +10 -13
- package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-button.mjs +7 -7
- package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-chat.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-chat.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-command.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-command.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-editor.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-filter.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-input.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-kanban.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-kanban.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-menu.mjs +9 -7
- package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs +2 -2
- package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-select.mjs +5 -4
- package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-table.mjs +106 -29
- package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-components-z-upload.mjs +3 -2
- package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -1
- package/fesm2022/shival99-z-ui-utils.mjs +27 -1
- package/fesm2022/shival99-z-ui-utils.mjs.map +1 -1
- package/package.json +1 -1
- package/types/shival99-z-ui-components-z-autocomplete.d.ts +3 -1
- package/types/shival99-z-ui-components-z-menu.d.ts +2 -0
- package/types/shival99-z-ui-components-z-select.d.ts +1 -0
- package/types/shival99-z-ui-components-z-table.d.ts +2 -1
- package/types/shival99-z-ui-components-z-upload.d.ts +1 -0
- package/types/shival99-z-ui-utils.d.ts +8 -2
|
@@ -989,7 +989,7 @@ class ZKanbanComponent {
|
|
|
989
989
|
return `${prefix}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
|
|
990
990
|
}
|
|
991
991
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZKanbanComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
992
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.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-(--radius-pill) 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 [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-sm 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 <span class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </span>\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)}.cdk-drag-preview.z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));border-radius:var(--radius-lg);box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}.cdk-drag-placeholder.kanban-card{opacity:.8;border:2px dashed var(--primary);border-radius:var(--radius-lg);background:color-mix(in oklab,var(--primary) 12%,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", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowEdit", "zShortTime", "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", "zContentType", "zToolbar", "zTipTap", "zValidators"], outputs: ["zOnChange", "zOnFocus", "zOnBlur", "zControl", "zEvent"], exportAs: ["zEditor"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zAlign", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "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", "zBodyClass", "zVisible", "zTitle", "zDescription", "zWidth", "zClosable", "zMaskClosable", "zDisableShadow", "zHeaderBorder", "zFooterBorder", "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", "zClassSelect", "zMode", "zSize", "zVariant", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "zPrefix", "zAllowClear", "zShowCheck", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zTagWidth", "zDropdownMaxHeight", "zDropdownWidth", "zOptionHeight", "zVirtualScroll", "zDynamicSize", "zShowAction", "zOptions", "zConfig", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zSticky", "zPosition", "zTree", "zTreeRootLabel", "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", "zContext", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "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 });
|
|
992
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.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 [ngModelOptions]=\"{ standalone: true }\"\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-(--radius-pill) 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 [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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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-sm 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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 <span class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </span>\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 [ngModelOptions]=\"{ standalone: true }\"\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)}.cdk-drag-preview.z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));border-radius:var(--radius-lg);box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}.cdk-drag-placeholder.kanban-card{opacity:.8;border:2px dashed var(--primary);border-radius:var(--radius-lg);background:color-mix(in oklab,var(--primary) 12%,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", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowEdit", "zShortTime", "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", "zContentType", "zToolbar", "zTipTap", "zValidators"], outputs: ["zOnChange", "zOnFocus", "zOnBlur", "zControl", "zEvent"], exportAs: ["zEditor"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "component", type: ZInputComponent, selector: "z-input", inputs: ["class", "zType", "zSize", "zAlign", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "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", "zBodyClass", "zVisible", "zTitle", "zDescription", "zWidth", "zClosable", "zMaskClosable", "zDisableShadow", "zHeaderBorder", "zFooterBorder", "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", "zClassSelect", "zMode", "zSize", "zVariant", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "zPrefix", "zAllowClear", "zShowCheck", "zWrap", "zShowSearch", "zPlaceholderSearch", "zDebounce", "zNotFoundText", "zEmptyText", "zEmptyIcon", "zMaxTagCount", "zTagWidth", "zDropdownMaxHeight", "zDropdownWidth", "zOptionHeight", "zVirtualScroll", "zDynamicSize", "zShowAction", "zOptions", "zConfig", "zTranslateLabels", "zKey", "zSearchServer", "zLoadingMore", "zEnableLoadMore", "zScrollDistance", "zMaxVisible", "zScrollClose", "zSticky", "zPosition", "zTree", "zTreeRootLabel", "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", "zContext", "zPosition", "zTooltipPosition", "zTrigger", "zTooltipTrigger", "zTooltipType", "zTooltipSize", "zClass", "zTooltipClass", "zShowDelay", "zTooltipShowDelay", "zHideDelay", "zTooltipHideDelay", "zArrow", "zTooltipArrow", "zDisabled", "zTooltipDisabled", "zOffset", "zTooltipOffset", "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 });
|
|
993
993
|
}
|
|
994
994
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZKanbanComponent, decorators: [{
|
|
995
995
|
type: Component,
|
|
@@ -1011,7 +1011,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
1011
1011
|
TranslatePipe,
|
|
1012
1012
|
], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1013
1013
|
'[class]': 'hostClasses()',
|
|
1014
|
-
}, 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-(--radius-pill) 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 [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-sm 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 <span class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </span>\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)}.cdk-drag-preview.z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));border-radius:var(--radius-lg);box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}.cdk-drag-placeholder.kanban-card{opacity:.8;border:2px dashed var(--primary);border-radius:var(--radius-lg);background:color-mix(in oklab,var(--primary) 12%,transparent)}\n"] }]
|
|
1014
|
+
}, 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 [ngModelOptions]=\"{ standalone: true }\"\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-(--radius-pill) 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 [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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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-sm 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 [ngModelOptions]=\"{ standalone: true }\"\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 [ngModelOptions]=\"{ standalone: true }\"\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 <span class=\"text-muted-foreground text-[11px] font-semibold tracking-widest uppercase\">\n {{ 'i18n_z_ui_kanban_activity' | translate }}\n </span>\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 [ngModelOptions]=\"{ standalone: true }\"\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)}.cdk-drag-preview.z-kanban-drag-preview{border:1px solid color-mix(in oklab,var(--primary) 35%,var(--border));border-radius:var(--radius-lg);box-shadow:0 14px 32px color-mix(in oklab,var(--foreground) 15%,transparent);transform:rotate(-.2deg)}.cdk-drag-placeholder.kanban-card{opacity:.8;border:2px dashed var(--primary);border-radius:var(--radius-lg);background:color-mix(in oklab,var(--primary) 12%,transparent)}\n"] }]
|
|
1015
1015
|
}], 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 }] }] } });
|
|
1016
1016
|
|
|
1017
1017
|
/**
|