@muxima-ui/core 1.4.1 → 2.0.0
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/README.md +11 -0
- package/fesm2022/muxima-ui-core-alert.mjs +5 -3
- package/fesm2022/muxima-ui-core-alert.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-breadcrumb.mjs +5 -3
- package/fesm2022/muxima-ui-core-breadcrumb.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-carousel.mjs +19 -17
- package/fesm2022/muxima-ui-core-carousel.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-chips.mjs +19 -14
- package/fesm2022/muxima-ui-core-chips.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-clipboard.mjs +10 -6
- package/fesm2022/muxima-ui-core-clipboard.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-color-picker.mjs +53 -50
- package/fesm2022/muxima-ui-core-color-picker.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-combobox.mjs +15 -12
- package/fesm2022/muxima-ui-core-combobox.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-command.mjs +21 -16
- package/fesm2022/muxima-ui-core-command.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-data-grid.mjs +50 -52
- package/fesm2022/muxima-ui-core-data-grid.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-date-picker.mjs +102 -69
- package/fesm2022/muxima-ui-core-date-picker.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-editor.mjs +25 -19
- package/fesm2022/muxima-ui-core-editor.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-file-upload.mjs +32 -27
- package/fesm2022/muxima-ui-core-file-upload.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-form-field.mjs +2 -2
- package/fesm2022/muxima-ui-core-form-field.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-i18n.mjs +550 -0
- package/fesm2022/muxima-ui-core-i18n.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-image-cropper.mjs +27 -24
- package/fesm2022/muxima-ui-core-image-cropper.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-kanban.mjs +22 -19
- package/fesm2022/muxima-ui-core-kanban.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-notification-center.mjs +42 -37
- package/fesm2022/muxima-ui-core-notification-center.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-pagination.mjs +29 -26
- package/fesm2022/muxima-ui-core-pagination.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-progress.mjs +5 -3
- package/fesm2022/muxima-ui-core-progress.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-rating.mjs +12 -8
- package/fesm2022/muxima-ui-core-rating.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-select.mjs +14 -11
- package/fesm2022/muxima-ui-core-select.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-sidebar.mjs +10 -7
- package/fesm2022/muxima-ui-core-sidebar.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-slider.mjs +10 -8
- package/fesm2022/muxima-ui-core-slider.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-stepper.mjs +5 -3
- package/fesm2022/muxima-ui-core-stepper.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-table.mjs +4 -4
- package/fesm2022/muxima-ui-core-table.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-time-picker.mjs +7 -5
- package/fesm2022/muxima-ui-core-time-picker.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-toast.mjs +8 -5
- package/fesm2022/muxima-ui-core-toast.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-tour.mjs +6 -12
- package/fesm2022/muxima-ui-core-tour.mjs.map +1 -1
- package/fesm2022/muxima-ui-core.mjs +1 -1
- package/fesm2022/muxima-ui-core.mjs.map +1 -1
- package/package.json +5 -1
- package/types/muxima-ui-core-alert.d.ts +3 -1
- package/types/muxima-ui-core-breadcrumb.d.ts +6 -4
- package/types/muxima-ui-core-carousel.d.ts +4 -2
- package/types/muxima-ui-core-chips.d.ts +23 -3
- package/types/muxima-ui-core-clipboard.d.ts +6 -3
- package/types/muxima-ui-core-color-picker.d.ts +40 -7
- package/types/muxima-ui-core-combobox.d.ts +6 -3
- package/types/muxima-ui-core-command.d.ts +7 -3
- package/types/muxima-ui-core-data-grid.d.ts +30 -10
- package/types/muxima-ui-core-date-picker.d.ts +64 -15
- package/types/muxima-ui-core-editor.d.ts +13 -2
- package/types/muxima-ui-core-file-upload.d.ts +23 -7
- package/types/muxima-ui-core-form-field.d.ts +2 -2
- package/types/muxima-ui-core-i18n.d.ts +322 -0
- package/types/muxima-ui-core-image-cropper.d.ts +19 -6
- package/types/muxima-ui-core-kanban.d.ts +16 -3
- package/types/muxima-ui-core-notification-center.d.ts +31 -9
- package/types/muxima-ui-core-pagination.d.ts +16 -1
- package/types/muxima-ui-core-progress.d.ts +10 -8
- package/types/muxima-ui-core-rating.d.ts +6 -2
- package/types/muxima-ui-core-select.d.ts +6 -3
- package/types/muxima-ui-core-sidebar.d.ts +6 -3
- package/types/muxima-ui-core-slider.d.ts +6 -4
- package/types/muxima-ui-core-stepper.d.ts +10 -8
- package/types/muxima-ui-core-table.d.ts +3 -3
- package/types/muxima-ui-core-time-picker.d.ts +3 -1
- package/types/muxima-ui-core-toast.d.ts +3 -0
- package/types/muxima-ui-core-tour.d.ts +3 -3
- package/types/muxima-ui-core.d.ts +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, TemplateRef, Directive, model, input, output, contentChild, ElementRef, Injector, signal, afterNextRender, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { inject, TemplateRef, Directive, model, input, computed, output, contentChild, ElementRef, Injector, signal, afterNextRender, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { injectMxMessages } from '@muxima-ui/core/i18n';
|
|
3
4
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
5
|
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
|
5
6
|
import { CdkDropListGroup, CdkDropList, CdkDrag, CdkDragPlaceholder } from '@angular/cdk/drag-drop';
|
|
@@ -42,10 +43,12 @@ class MxKanban {
|
|
|
42
43
|
itemKey = input('id', ...(ngDevMode ? [{ debugName: "itemKey" }] : /* istanbul ignore next */ []));
|
|
43
44
|
/** Nome do cartão nos anúncios. Por omissão o campo `title` ou `titulo`. */
|
|
44
45
|
itemLabel = input((i) => String(i?.title ?? i?.titulo ?? i?.id ?? ''), ...(ngDevMode ? [{ debugName: "itemLabel" }] : /* istanbul ignore next */ []));
|
|
45
|
-
ariaLabel = input(
|
|
46
|
+
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
47
|
+
i18n = injectMxMessages();
|
|
48
|
+
msg = computed(() => this.i18n().kanban, ...(ngDevMode ? [{ debugName: "msg" }] : /* istanbul ignore next */ []));
|
|
46
49
|
headingLevel = input(3, ...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
|
|
47
|
-
emptyText = input(
|
|
48
|
-
helpText = input(
|
|
50
|
+
emptyText = input(...(ngDevMode ? [undefined, { debugName: "emptyText" }] : /* istanbul ignore next */ []));
|
|
51
|
+
helpText = input(...(ngDevMode ? [undefined, { debugName: "helpText" }] : /* istanbul ignore next */ []));
|
|
49
52
|
moved = output();
|
|
50
53
|
cardTpl = contentChild(MxKanbanCard, ...(ngDevMode ? [{ debugName: "cardTpl" }] : /* istanbul ignore next */ []));
|
|
51
54
|
footerTpl = contentChild(MxKanbanColumnFooter, ...(ngDevMode ? [{ debugName: "footerTpl" }] : /* istanbul ignore next */ []));
|
|
@@ -107,7 +110,7 @@ class MxKanban {
|
|
|
107
110
|
}
|
|
108
111
|
where(col, index) {
|
|
109
112
|
const c = this.columns()[col];
|
|
110
|
-
return
|
|
113
|
+
return this.msg().position(c.title, index + 1, c.items.length);
|
|
111
114
|
}
|
|
112
115
|
onKeydown(event, ci, ii) {
|
|
113
116
|
if (event.target !== event.currentTarget)
|
|
@@ -119,7 +122,7 @@ class MxKanban {
|
|
|
119
122
|
if (key === ' ' || key === 'Enter') {
|
|
120
123
|
event.preventDefault();
|
|
121
124
|
this.grabbed.set({ col: ci, index: ii, fromCol: ci, fromIndex: ii, snapshot: cols });
|
|
122
|
-
this.announcer.announce(
|
|
125
|
+
this.announcer.announce(this.msg().pickedUp(this.labelOf(cols[ci].items[ii]), this.where(ci, ii)), 'assertive');
|
|
123
126
|
return;
|
|
124
127
|
}
|
|
125
128
|
// navegar entre cartões
|
|
@@ -154,7 +157,7 @@ class MxKanban {
|
|
|
154
157
|
this.grabbed.set(null);
|
|
155
158
|
if (g.col !== g.fromCol || g.index !== g.fromIndex)
|
|
156
159
|
this.emitMove(item, g.fromCol, g.fromIndex, g.col, g.index);
|
|
157
|
-
this.announcer.announce(
|
|
160
|
+
this.announcer.announce(this.msg().dropped(this.labelOf(item), this.where(g.col, g.index)), 'assertive');
|
|
158
161
|
this.focusCard(g.col, g.index);
|
|
159
162
|
return;
|
|
160
163
|
}
|
|
@@ -162,7 +165,7 @@ class MxKanban {
|
|
|
162
165
|
event.preventDefault();
|
|
163
166
|
this.columns.set(g.snapshot);
|
|
164
167
|
this.grabbed.set(null);
|
|
165
|
-
this.announcer.announce(
|
|
168
|
+
this.announcer.announce(this.msg().cancelled(this.labelOf(item), this.where(g.fromCol, g.fromIndex)), 'assertive');
|
|
166
169
|
this.focusCard(g.fromCol, g.fromIndex);
|
|
167
170
|
return;
|
|
168
171
|
}
|
|
@@ -177,7 +180,7 @@ class MxKanban {
|
|
|
177
180
|
const target = cols[c];
|
|
178
181
|
if (target.limit && target.items.length >= target.limit) {
|
|
179
182
|
event.preventDefault();
|
|
180
|
-
this.announcer.announce(
|
|
183
|
+
this.announcer.announce(this.msg().full(target.title, target.limit), 'assertive');
|
|
181
184
|
return;
|
|
182
185
|
}
|
|
183
186
|
to = [c, Math.min(g.index, target.items.length)];
|
|
@@ -208,8 +211,8 @@ class MxKanban {
|
|
|
208
211
|
}
|
|
209
212
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxKanban, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
210
213
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxKanban, isStandalone: true, selector: "mx-kanban", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, itemKey: { classPropertyName: "itemKey", publicName: "itemKey", isSignal: true, isRequired: false, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, helpText: { classPropertyName: "helpText", publicName: "helpText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columns: "columnsChange", moved: "moved" }, host: { properties: { "attr.aria-label": "null" }, classAttribute: "mx-kanban" }, queries: [{ propertyName: "cardTpl", first: true, predicate: MxKanbanCard, descendants: true, isSignal: true }, { propertyName: "footerTpl", first: true, predicate: MxKanbanColumnFooter, descendants: true, isSignal: true }], exportAs: ["mxKanban"], ngImport: i0, template: `
|
|
211
|
-
<p class="mx-visually-hidden" [id]="helpId">{{ helpText() }}</p>
|
|
212
|
-
<div class="mx-kanban-board" cdkDropListGroup role="group" [attr.aria-label]="ariaLabel()">
|
|
214
|
+
<p class="mx-visually-hidden" [id]="helpId">{{ (helpText() ?? msg().help) }}</p>
|
|
215
|
+
<div class="mx-kanban-board" cdkDropListGroup role="group" [attr.aria-label]="(ariaLabel() ?? msg().label)">
|
|
213
216
|
@for (col of columns(); track col.id; let ci = $index) {
|
|
214
217
|
<div
|
|
215
218
|
class="mx-kanban-column"
|
|
@@ -229,7 +232,7 @@ class MxKanban {
|
|
|
229
232
|
<span class="mx-kanban-count">
|
|
230
233
|
{{ col.items.length }}{{ col.limit ? ' / ' + col.limit : '' }}
|
|
231
234
|
<span class="mx-visually-hidden">{{
|
|
232
|
-
(col.items.length
|
|
235
|
+
msg().cards(col.items.length, col.limit ?? null)
|
|
233
236
|
}}</span>
|
|
234
237
|
</span>
|
|
235
238
|
</div>
|
|
@@ -251,7 +254,7 @@ class MxKanban {
|
|
|
251
254
|
[attr.data-kanban]="ci + ':' + ii"
|
|
252
255
|
[attr.data-grabbed]="isGrabbed(ci, ii) ? '' : null"
|
|
253
256
|
[attr.aria-describedby]="helpId"
|
|
254
|
-
[attr.aria-label]="isGrabbed(ci, ii) ? labelOf(item)
|
|
257
|
+
[attr.aria-label]="isGrabbed(ci, ii) ? msg().grabbed(labelOf(item)) : null"
|
|
255
258
|
(keydown)="onKeydown($event, ci, ii)"
|
|
256
259
|
(blur)="onBlur(ci, ii)"
|
|
257
260
|
>
|
|
@@ -265,7 +268,7 @@ class MxKanban {
|
|
|
265
268
|
<div class="mx-kanban-placeholder" *cdkDragPlaceholder></div>
|
|
266
269
|
</li>
|
|
267
270
|
} @empty {
|
|
268
|
-
<li class="mx-kanban-empty">{{ emptyText() }}</li>
|
|
271
|
+
<li class="mx-kanban-empty">{{ (emptyText() ?? msg().empty) }}</li>
|
|
269
272
|
}
|
|
270
273
|
</ul>
|
|
271
274
|
@if (footerTpl(); as f) {
|
|
@@ -288,8 +291,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
288
291
|
encapsulation: ViewEncapsulation.None,
|
|
289
292
|
host: { class: 'mx-kanban', '[attr.aria-label]': 'null' },
|
|
290
293
|
template: `
|
|
291
|
-
<p class="mx-visually-hidden" [id]="helpId">{{ helpText() }}</p>
|
|
292
|
-
<div class="mx-kanban-board" cdkDropListGroup role="group" [attr.aria-label]="ariaLabel()">
|
|
294
|
+
<p class="mx-visually-hidden" [id]="helpId">{{ (helpText() ?? msg().help) }}</p>
|
|
295
|
+
<div class="mx-kanban-board" cdkDropListGroup role="group" [attr.aria-label]="(ariaLabel() ?? msg().label)">
|
|
293
296
|
@for (col of columns(); track col.id; let ci = $index) {
|
|
294
297
|
<div
|
|
295
298
|
class="mx-kanban-column"
|
|
@@ -309,7 +312,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
309
312
|
<span class="mx-kanban-count">
|
|
310
313
|
{{ col.items.length }}{{ col.limit ? ' / ' + col.limit : '' }}
|
|
311
314
|
<span class="mx-visually-hidden">{{
|
|
312
|
-
(col.items.length
|
|
315
|
+
msg().cards(col.items.length, col.limit ?? null)
|
|
313
316
|
}}</span>
|
|
314
317
|
</span>
|
|
315
318
|
</div>
|
|
@@ -331,7 +334,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
331
334
|
[attr.data-kanban]="ci + ':' + ii"
|
|
332
335
|
[attr.data-grabbed]="isGrabbed(ci, ii) ? '' : null"
|
|
333
336
|
[attr.aria-describedby]="helpId"
|
|
334
|
-
[attr.aria-label]="isGrabbed(ci, ii) ? labelOf(item)
|
|
337
|
+
[attr.aria-label]="isGrabbed(ci, ii) ? msg().grabbed(labelOf(item)) : null"
|
|
335
338
|
(keydown)="onKeydown($event, ci, ii)"
|
|
336
339
|
(blur)="onBlur(ci, ii)"
|
|
337
340
|
>
|
|
@@ -345,7 +348,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
345
348
|
<div class="mx-kanban-placeholder" *cdkDragPlaceholder></div>
|
|
346
349
|
</li>
|
|
347
350
|
} @empty {
|
|
348
|
-
<li class="mx-kanban-empty">{{ emptyText() }}</li>
|
|
351
|
+
<li class="mx-kanban-empty">{{ (emptyText() ?? msg().empty) }}</li>
|
|
349
352
|
}
|
|
350
353
|
</ul>
|
|
351
354
|
@if (footerTpl(); as f) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"muxima-ui-core-kanban.mjs","sources":["../../../projects/core/kanban/kanban.ts","../../../projects/core/kanban/muxima-ui-core-kanban.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Directive,\n ElementRef,\n Injector,\n TemplateRef,\n ViewEncapsulation,\n afterNextRender,\n computed,\n contentChild,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\nimport {\n CdkDrag,\n CdkDragDrop,\n CdkDragPlaceholder,\n CdkDropList,\n CdkDropListGroup,\n} from '@angular/cdk/drag-drop';\nimport { mxUniqueId } from '@muxima-ui/core/form-field';\n\nexport interface MxKanbanColumn<T = any> {\n id: string;\n title: string;\n items: T[];\n /** Máximo de cartões na coluna (WIP). Acima disso não se larga lá. */\n limit?: number;\n}\n\nexport interface MxKanbanMove<T = any> {\n item: T;\n from: string;\n to: string;\n fromIndex: number;\n toIndex: number;\n}\n\n/** Conteúdo do cartão: `<ng-template mxKanbanCard let-item let-column=\"column\">`. */\n@Directive({ selector: 'ng-template[mxKanbanCard]' })\nexport class MxKanbanCard {\n readonly template = inject(TemplateRef);\n}\n\n/** Rodapé de cada coluna (ex.: botão \"Adicionar\"): `<ng-template mxKanbanColumnFooter let-column>`. */\n@Directive({ selector: 'ng-template[mxKanbanColumnFooter]' })\nexport class MxKanbanColumnFooter {\n readonly template = inject(TemplateRef);\n}\n\n/**\n * Quadro Kanban: cartões em colunas, com arrastar e largar (rato e toque) e mover com\n * o teclado. Num cartão: Espaço agarra, setas movem (cima e baixo na coluna, esquerda e\n * direita entre colunas), Espaço larga e Esc cancela. Cada passo é anunciado.\n *\n * ```html\n * <mx-kanban [(columns)]=\"quadro\" [itemLabel]=\"titulo\" (moved)=\"guardar($event)\">\n * <ng-template mxKanbanCard let-tarefa>{{ tarefa.titulo }}</ng-template>\n * </mx-kanban>\n * ```\n */\n@Component({\n selector: 'mx-kanban',\n exportAs: 'mxKanban',\n imports: [NgTemplateOutlet, CdkDropListGroup, CdkDropList, CdkDrag, CdkDragPlaceholder],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-kanban', '[attr.aria-label]': 'null' },\n template: `\n <p class=\"mx-visually-hidden\" [id]=\"helpId\">{{ helpText() }}</p>\n <div class=\"mx-kanban-board\" cdkDropListGroup role=\"group\" [attr.aria-label]=\"ariaLabel()\">\n @for (col of columns(); track col.id; let ci = $index) {\n <div\n class=\"mx-kanban-column\"\n role=\"group\"\n [attr.aria-labelledby]=\"titleId(ci)\"\n [attr.data-full]=\"isFull(col) ? '' : null\"\n >\n <div class=\"mx-kanban-column-head\">\n <p\n class=\"mx-kanban-column-title\"\n role=\"heading\"\n [attr.aria-level]=\"headingLevel()\"\n [id]=\"titleId(ci)\"\n >\n {{ col.title }}\n </p>\n <span class=\"mx-kanban-count\">\n {{ col.items.length }}{{ col.limit ? ' / ' + col.limit : '' }}\n <span class=\"mx-visually-hidden\">{{\n (col.items.length === 1 ? 'cartão' : 'cartões') + (col.limit ? ', máximo ' + col.limit : '')\n }}</span>\n </span>\n </div>\n <ul\n class=\"mx-kanban-list\"\n cdkDropList\n [id]=\"listId(ci)\"\n [cdkDropListData]=\"ci\"\n [cdkDropListEnterPredicate]=\"canEnter(ci)\"\n [attr.aria-labelledby]=\"titleId(ci)\"\n (cdkDropListDropped)=\"onDrop($event)\"\n >\n @for (item of col.items; track keyOf(item); let ii = $index) {\n <li\n class=\"mx-kanban-card\"\n cdkDrag\n [cdkDragData]=\"item\"\n tabindex=\"0\"\n [attr.data-kanban]=\"ci + ':' + ii\"\n [attr.data-grabbed]=\"isGrabbed(ci, ii) ? '' : null\"\n [attr.aria-describedby]=\"helpId\"\n [attr.aria-label]=\"isGrabbed(ci, ii) ? labelOf(item) + ', agarrado' : null\"\n (keydown)=\"onKeydown($event, ci, ii)\"\n (blur)=\"onBlur(ci, ii)\"\n >\n @if (cardTpl(); as tpl) {\n <ng-container\n *ngTemplateOutlet=\"tpl.template; context: { $implicit: item, column: col }\"\n />\n } @else {\n {{ labelOf(item) }}\n }\n <div class=\"mx-kanban-placeholder\" *cdkDragPlaceholder></div>\n </li>\n } @empty {\n <li class=\"mx-kanban-empty\">{{ emptyText() }}</li>\n }\n </ul>\n @if (footerTpl(); as f) {\n <div class=\"mx-kanban-column-foot\">\n <ng-container *ngTemplateOutlet=\"f.template; context: { $implicit: col }\" />\n </div>\n }\n </div>\n }\n </div>\n `,\n})\nexport class MxKanban<T = any> {\n readonly columns = model.required<MxKanbanColumn<T>[]>();\n /** Chave única de cada cartão: nome do campo ou função. */\n readonly itemKey = input<string | ((item: T) => unknown)>('id');\n /** Nome do cartão nos anúncios. Por omissão o campo `title` ou `titulo`. */\n readonly itemLabel = input<(item: T) => string>((i) =>\n String((i as any)?.title ?? (i as any)?.titulo ?? (i as any)?.id ?? ''),\n );\n readonly ariaLabel = input('Quadro', { alias: 'aria-label' });\n readonly headingLevel = input(3);\n readonly emptyText = input('Sem cartões');\n readonly helpText = input(\n 'Espaço para agarrar. Setas para mover. Espaço para largar, Esc para cancelar.',\n );\n readonly moved = output<MxKanbanMove<T>>();\n\n protected readonly cardTpl = contentChild(MxKanbanCard);\n protected readonly footerTpl = contentChild(MxKanbanColumnFooter);\n private readonly announcer = inject(LiveAnnouncer);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly injector = inject(Injector);\n private readonly uid = mxUniqueId('mx-kanban');\n protected readonly helpId = `${this.uid}-help`;\n\n /** Cartão agarrado com o teclado: posição actual e de onde saiu. */\n private readonly grabbed = signal<{\n col: number;\n index: number;\n fromCol: number;\n fromIndex: number;\n snapshot: MxKanbanColumn<T>[];\n } | null>(null);\n\n protected titleId(i: number): string {\n return `${this.uid}-t${i}`;\n }\n protected listId(i: number): string {\n return `${this.uid}-l${i}`;\n }\n keyOf(item: T): unknown {\n const k = this.itemKey();\n return typeof k === 'function' ? k(item) : (item as Record<string, unknown>)[k];\n }\n protected labelOf(item: T): string {\n return this.itemLabel()(item);\n }\n protected isGrabbed(c: number, i: number): boolean {\n const g = this.grabbed();\n return !!g && g.col === c && g.index === i;\n }\n protected isFull(col: MxKanbanColumn<T>): boolean {\n return !!col.limit && col.items.length >= col.limit;\n }\n protected canEnter(ci: number) {\n return (drag: CdkDrag, drop: CdkDropList) => {\n const col = this.columns()[ci];\n return !col.limit || col.items.length < col.limit || drag.dropContainer === drop;\n };\n }\n\n /** Move um cartão e devolve as colunas novas (sem mudar as antigas). */\n private move(\n cols: MxKanbanColumn<T>[],\n from: number,\n fromIndex: number,\n to: number,\n toIndex: number,\n ): MxKanbanColumn<T>[] {\n const next = cols.map((c) => ({ ...c, items: [...c.items] }));\n const [item] = next[from].items.splice(fromIndex, 1);\n next[to].items.splice(Math.min(toIndex, next[to].items.length), 0, item);\n return next;\n }\n\n protected onDrop(e: CdkDragDrop<number>): void {\n const from = e.previousContainer.data;\n const to = e.container.data;\n if (from === to && e.previousIndex === e.currentIndex) return;\n const item = this.columns()[from].items[e.previousIndex];\n this.columns.set(this.move(this.columns(), from, e.previousIndex, to, e.currentIndex));\n this.emitMove(item, from, e.previousIndex, to, e.currentIndex);\n }\n\n private emitMove(item: T, from: number, fromIndex: number, to: number, toIndex: number): void {\n const cols = this.columns();\n this.moved.emit({ item, from: cols[from].id, to: cols[to].id, fromIndex, toIndex });\n }\n\n private focusCard(col: number, index: number): void {\n afterNextRender(\n () => this.host.querySelector<HTMLElement>(`[data-kanban=\"${col}:${index}\"]`)?.focus(),\n { injector: this.injector },\n );\n }\n\n private where(col: number, index: number): string {\n const c = this.columns()[col];\n return `${c.title}, posição ${index + 1} de ${c.items.length}`;\n }\n\n protected onKeydown(event: KeyboardEvent, ci: number, ii: number): void {\n if (event.target !== event.currentTarget) return; // teclas dentro de botões do cartão\n const g = this.grabbed();\n const cols = this.columns();\n const key = event.key;\n\n if (!g) {\n if (key === ' ' || key === 'Enter') {\n event.preventDefault();\n this.grabbed.set({ col: ci, index: ii, fromCol: ci, fromIndex: ii, snapshot: cols });\n this.announcer.announce(\n `${this.labelOf(cols[ci].items[ii])} agarrado. ${this.where(ci, ii)}.`,\n 'assertive',\n );\n return;\n }\n // navegar entre cartões\n let target: [number, number] | null = null;\n if (key === 'ArrowDown') target = [ci, ii + 1];\n else if (key === 'ArrowUp') target = [ci, ii - 1];\n else if (key === 'ArrowRight' || key === 'ArrowLeft') {\n const step = key === 'ArrowRight' ? 1 : -1;\n for (let c = ci + step; c >= 0 && c < cols.length; c += step) {\n if (cols[c].items.length) {\n target = [c, Math.min(ii, cols[c].items.length - 1)];\n break;\n }\n }\n } else if (key === 'Home') target = [ci, 0];\n else if (key === 'End') target = [ci, cols[ci].items.length - 1];\n if (target && target[1] >= 0 && target[1] < cols[target[0]].items.length) {\n event.preventDefault();\n this.focusCard(target[0], target[1]);\n }\n return;\n }\n\n // a mover\n const item = cols[g.col].items[g.index];\n if (key === ' ' || key === 'Enter') {\n event.preventDefault();\n this.grabbed.set(null);\n if (g.col !== g.fromCol || g.index !== g.fromIndex)\n this.emitMove(item, g.fromCol, g.fromIndex, g.col, g.index);\n this.announcer.announce(\n `${this.labelOf(item)} largado. ${this.where(g.col, g.index)}.`,\n 'assertive',\n );\n this.focusCard(g.col, g.index);\n return;\n }\n if (key === 'Escape') {\n event.preventDefault();\n this.columns.set(g.snapshot);\n this.grabbed.set(null);\n this.announcer.announce(\n `Movimento cancelado. ${this.labelOf(item)} voltou a ${this.where(g.fromCol, g.fromIndex)}.`,\n 'assertive',\n );\n this.focusCard(g.fromCol, g.fromIndex);\n return;\n }\n let to: [number, number] | null = null;\n if (key === 'ArrowDown' && g.index < cols[g.col].items.length - 1) to = [g.col, g.index + 1];\n else if (key === 'ArrowUp' && g.index > 0) to = [g.col, g.index - 1];\n else if (key === 'ArrowRight' || key === 'ArrowLeft') {\n const c = g.col + (key === 'ArrowRight' ? 1 : -1);\n if (c >= 0 && c < cols.length) {\n const target = cols[c];\n if (target.limit && target.items.length >= target.limit) {\n event.preventDefault();\n this.announcer.announce(\n `${target.title} está cheia, máximo ${target.limit}.`,\n 'assertive',\n );\n return;\n }\n to = [c, Math.min(g.index, target.items.length)];\n }\n }\n if (!to) return;\n event.preventDefault();\n this.columns.set(this.move(cols, g.col, g.index, to[0], to[1]));\n this.grabbed.set({ ...g, col: to[0], index: to[1] });\n this.announcer.announce(this.where(to[0], to[1]), 'assertive');\n this.focusCard(to[0], to[1]);\n }\n\n protected onBlur(ci: number, ii: number): void {\n // o foco saiu do cartão agarrado (ex.: clique fora): larga onde está\n queueMicrotask(() => {\n const g = this.grabbed();\n if (!g || g.col !== ci || g.index !== ii) return;\n const active = document.activeElement as HTMLElement | null;\n if (active?.dataset['kanban'] === `${g.col}:${g.index}`) return;\n this.grabbed.set(null);\n const item = this.columns()[g.col].items[g.index];\n if (g.col !== g.fromCol || g.index !== g.fromIndex)\n this.emitMove(item, g.fromCol, g.fromIndex, g.col, g.index);\n });\n }\n}\n\nexport const MX_KANBAN = [MxKanban, MxKanbanCard, MxKanbanColumnFooter] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"muxima-ui-core-kanban.mjs","sources":["../../../projects/core/kanban/kanban.ts","../../../projects/core/kanban/muxima-ui-core-kanban.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Directive,\n ElementRef,\n Injector,\n TemplateRef,\n ViewEncapsulation,\n afterNextRender,\n computed,\n contentChild,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { injectMxMessages } from '@muxima-ui/core/i18n';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\nimport {\n CdkDrag,\n CdkDragDrop,\n CdkDragPlaceholder,\n CdkDropList,\n CdkDropListGroup,\n} from '@angular/cdk/drag-drop';\nimport { mxUniqueId } from '@muxima-ui/core/form-field';\n\nexport interface MxKanbanColumn<T = any> {\n id: string;\n title: string;\n items: T[];\n /** Máximo de cartões na coluna (WIP). Acima disso não se larga lá. */\n limit?: number;\n}\n\nexport interface MxKanbanMove<T = any> {\n item: T;\n from: string;\n to: string;\n fromIndex: number;\n toIndex: number;\n}\n\n/** Conteúdo do cartão: `<ng-template mxKanbanCard let-item let-column=\"column\">`. */\n@Directive({ selector: 'ng-template[mxKanbanCard]' })\nexport class MxKanbanCard {\n readonly template = inject(TemplateRef);\n}\n\n/** Rodapé de cada coluna (ex.: botão \"Adicionar\"): `<ng-template mxKanbanColumnFooter let-column>`. */\n@Directive({ selector: 'ng-template[mxKanbanColumnFooter]' })\nexport class MxKanbanColumnFooter {\n readonly template = inject(TemplateRef);\n}\n\n/**\n * Quadro Kanban: cartões em colunas, com arrastar e largar (rato e toque) e mover com\n * o teclado. Num cartão: Espaço agarra, setas movem (cima e baixo na coluna, esquerda e\n * direita entre colunas), Espaço larga e Esc cancela. Cada passo é anunciado.\n *\n * ```html\n * <mx-kanban [(columns)]=\"quadro\" [itemLabel]=\"titulo\" (moved)=\"guardar($event)\">\n * <ng-template mxKanbanCard let-tarefa>{{ tarefa.titulo }}</ng-template>\n * </mx-kanban>\n * ```\n */\n@Component({\n selector: 'mx-kanban',\n exportAs: 'mxKanban',\n imports: [NgTemplateOutlet, CdkDropListGroup, CdkDropList, CdkDrag, CdkDragPlaceholder],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-kanban', '[attr.aria-label]': 'null' },\n template: `\n <p class=\"mx-visually-hidden\" [id]=\"helpId\">{{ (helpText() ?? msg().help) }}</p>\n <div class=\"mx-kanban-board\" cdkDropListGroup role=\"group\" [attr.aria-label]=\"(ariaLabel() ?? msg().label)\">\n @for (col of columns(); track col.id; let ci = $index) {\n <div\n class=\"mx-kanban-column\"\n role=\"group\"\n [attr.aria-labelledby]=\"titleId(ci)\"\n [attr.data-full]=\"isFull(col) ? '' : null\"\n >\n <div class=\"mx-kanban-column-head\">\n <p\n class=\"mx-kanban-column-title\"\n role=\"heading\"\n [attr.aria-level]=\"headingLevel()\"\n [id]=\"titleId(ci)\"\n >\n {{ col.title }}\n </p>\n <span class=\"mx-kanban-count\">\n {{ col.items.length }}{{ col.limit ? ' / ' + col.limit : '' }}\n <span class=\"mx-visually-hidden\">{{\n msg().cards(col.items.length, col.limit ?? null)\n }}</span>\n </span>\n </div>\n <ul\n class=\"mx-kanban-list\"\n cdkDropList\n [id]=\"listId(ci)\"\n [cdkDropListData]=\"ci\"\n [cdkDropListEnterPredicate]=\"canEnter(ci)\"\n [attr.aria-labelledby]=\"titleId(ci)\"\n (cdkDropListDropped)=\"onDrop($event)\"\n >\n @for (item of col.items; track keyOf(item); let ii = $index) {\n <li\n class=\"mx-kanban-card\"\n cdkDrag\n [cdkDragData]=\"item\"\n tabindex=\"0\"\n [attr.data-kanban]=\"ci + ':' + ii\"\n [attr.data-grabbed]=\"isGrabbed(ci, ii) ? '' : null\"\n [attr.aria-describedby]=\"helpId\"\n [attr.aria-label]=\"isGrabbed(ci, ii) ? msg().grabbed(labelOf(item)) : null\"\n (keydown)=\"onKeydown($event, ci, ii)\"\n (blur)=\"onBlur(ci, ii)\"\n >\n @if (cardTpl(); as tpl) {\n <ng-container\n *ngTemplateOutlet=\"tpl.template; context: { $implicit: item, column: col }\"\n />\n } @else {\n {{ labelOf(item) }}\n }\n <div class=\"mx-kanban-placeholder\" *cdkDragPlaceholder></div>\n </li>\n } @empty {\n <li class=\"mx-kanban-empty\">{{ (emptyText() ?? msg().empty) }}</li>\n }\n </ul>\n @if (footerTpl(); as f) {\n <div class=\"mx-kanban-column-foot\">\n <ng-container *ngTemplateOutlet=\"f.template; context: { $implicit: col }\" />\n </div>\n }\n </div>\n }\n </div>\n `,\n})\nexport class MxKanban<T = any> {\n readonly columns = model.required<MxKanbanColumn<T>[]>();\n /** Chave única de cada cartão: nome do campo ou função. */\n readonly itemKey = input<string | ((item: T) => unknown)>('id');\n /** Nome do cartão nos anúncios. Por omissão o campo `title` ou `titulo`. */\n readonly itemLabel = input<(item: T) => string>((i) =>\n String((i as any)?.title ?? (i as any)?.titulo ?? (i as any)?.id ?? ''),\n );\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n private readonly i18n = injectMxMessages();\n protected readonly msg = computed(() => this.i18n().kanban);\n readonly headingLevel = input(3);\n readonly emptyText = input<string>();\n readonly helpText = input<string>();\n readonly moved = output<MxKanbanMove<T>>();\n\n protected readonly cardTpl = contentChild(MxKanbanCard);\n protected readonly footerTpl = contentChild(MxKanbanColumnFooter);\n private readonly announcer = inject(LiveAnnouncer);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly injector = inject(Injector);\n private readonly uid = mxUniqueId('mx-kanban');\n protected readonly helpId = `${this.uid}-help`;\n\n /** Cartão agarrado com o teclado: posição actual e de onde saiu. */\n private readonly grabbed = signal<{\n col: number;\n index: number;\n fromCol: number;\n fromIndex: number;\n snapshot: MxKanbanColumn<T>[];\n } | null>(null);\n\n protected titleId(i: number): string {\n return `${this.uid}-t${i}`;\n }\n protected listId(i: number): string {\n return `${this.uid}-l${i}`;\n }\n keyOf(item: T): unknown {\n const k = this.itemKey();\n return typeof k === 'function' ? k(item) : (item as Record<string, unknown>)[k];\n }\n protected labelOf(item: T): string {\n return this.itemLabel()(item);\n }\n protected isGrabbed(c: number, i: number): boolean {\n const g = this.grabbed();\n return !!g && g.col === c && g.index === i;\n }\n protected isFull(col: MxKanbanColumn<T>): boolean {\n return !!col.limit && col.items.length >= col.limit;\n }\n protected canEnter(ci: number) {\n return (drag: CdkDrag, drop: CdkDropList) => {\n const col = this.columns()[ci];\n return !col.limit || col.items.length < col.limit || drag.dropContainer === drop;\n };\n }\n\n /** Move um cartão e devolve as colunas novas (sem mudar as antigas). */\n private move(\n cols: MxKanbanColumn<T>[],\n from: number,\n fromIndex: number,\n to: number,\n toIndex: number,\n ): MxKanbanColumn<T>[] {\n const next = cols.map((c) => ({ ...c, items: [...c.items] }));\n const [item] = next[from].items.splice(fromIndex, 1);\n next[to].items.splice(Math.min(toIndex, next[to].items.length), 0, item);\n return next;\n }\n\n protected onDrop(e: CdkDragDrop<number>): void {\n const from = e.previousContainer.data;\n const to = e.container.data;\n if (from === to && e.previousIndex === e.currentIndex) return;\n const item = this.columns()[from].items[e.previousIndex];\n this.columns.set(this.move(this.columns(), from, e.previousIndex, to, e.currentIndex));\n this.emitMove(item, from, e.previousIndex, to, e.currentIndex);\n }\n\n private emitMove(item: T, from: number, fromIndex: number, to: number, toIndex: number): void {\n const cols = this.columns();\n this.moved.emit({ item, from: cols[from].id, to: cols[to].id, fromIndex, toIndex });\n }\n\n private focusCard(col: number, index: number): void {\n afterNextRender(\n () => this.host.querySelector<HTMLElement>(`[data-kanban=\"${col}:${index}\"]`)?.focus(),\n { injector: this.injector },\n );\n }\n\n private where(col: number, index: number): string {\n const c = this.columns()[col];\n return this.msg().position(c.title, index + 1, c.items.length);\n }\n\n protected onKeydown(event: KeyboardEvent, ci: number, ii: number): void {\n if (event.target !== event.currentTarget) return; // teclas dentro de botões do cartão\n const g = this.grabbed();\n const cols = this.columns();\n const key = event.key;\n\n if (!g) {\n if (key === ' ' || key === 'Enter') {\n event.preventDefault();\n this.grabbed.set({ col: ci, index: ii, fromCol: ci, fromIndex: ii, snapshot: cols });\n this.announcer.announce(\n this.msg().pickedUp(this.labelOf(cols[ci].items[ii]), this.where(ci, ii)),\n 'assertive',\n );\n return;\n }\n // navegar entre cartões\n let target: [number, number] | null = null;\n if (key === 'ArrowDown') target = [ci, ii + 1];\n else if (key === 'ArrowUp') target = [ci, ii - 1];\n else if (key === 'ArrowRight' || key === 'ArrowLeft') {\n const step = key === 'ArrowRight' ? 1 : -1;\n for (let c = ci + step; c >= 0 && c < cols.length; c += step) {\n if (cols[c].items.length) {\n target = [c, Math.min(ii, cols[c].items.length - 1)];\n break;\n }\n }\n } else if (key === 'Home') target = [ci, 0];\n else if (key === 'End') target = [ci, cols[ci].items.length - 1];\n if (target && target[1] >= 0 && target[1] < cols[target[0]].items.length) {\n event.preventDefault();\n this.focusCard(target[0], target[1]);\n }\n return;\n }\n\n // a mover\n const item = cols[g.col].items[g.index];\n if (key === ' ' || key === 'Enter') {\n event.preventDefault();\n this.grabbed.set(null);\n if (g.col !== g.fromCol || g.index !== g.fromIndex)\n this.emitMove(item, g.fromCol, g.fromIndex, g.col, g.index);\n this.announcer.announce(\n this.msg().dropped(this.labelOf(item), this.where(g.col, g.index)),\n 'assertive',\n );\n this.focusCard(g.col, g.index);\n return;\n }\n if (key === 'Escape') {\n event.preventDefault();\n this.columns.set(g.snapshot);\n this.grabbed.set(null);\n this.announcer.announce(\n this.msg().cancelled(this.labelOf(item), this.where(g.fromCol, g.fromIndex)),\n 'assertive',\n );\n this.focusCard(g.fromCol, g.fromIndex);\n return;\n }\n let to: [number, number] | null = null;\n if (key === 'ArrowDown' && g.index < cols[g.col].items.length - 1) to = [g.col, g.index + 1];\n else if (key === 'ArrowUp' && g.index > 0) to = [g.col, g.index - 1];\n else if (key === 'ArrowRight' || key === 'ArrowLeft') {\n const c = g.col + (key === 'ArrowRight' ? 1 : -1);\n if (c >= 0 && c < cols.length) {\n const target = cols[c];\n if (target.limit && target.items.length >= target.limit) {\n event.preventDefault();\n this.announcer.announce(\n this.msg().full(target.title, target.limit),\n 'assertive',\n );\n return;\n }\n to = [c, Math.min(g.index, target.items.length)];\n }\n }\n if (!to) return;\n event.preventDefault();\n this.columns.set(this.move(cols, g.col, g.index, to[0], to[1]));\n this.grabbed.set({ ...g, col: to[0], index: to[1] });\n this.announcer.announce(this.where(to[0], to[1]), 'assertive');\n this.focusCard(to[0], to[1]);\n }\n\n protected onBlur(ci: number, ii: number): void {\n // o foco saiu do cartão agarrado (ex.: clique fora): larga onde está\n queueMicrotask(() => {\n const g = this.grabbed();\n if (!g || g.col !== ci || g.index !== ii) return;\n const active = document.activeElement as HTMLElement | null;\n if (active?.dataset['kanban'] === `${g.col}:${g.index}`) return;\n this.grabbed.set(null);\n const item = this.columns()[g.col].items[g.index];\n if (g.col !== g.fromCol || g.index !== g.fromIndex)\n this.emitMove(item, g.fromCol, g.fromIndex, g.col, g.index);\n });\n }\n}\n\nexport const MX_KANBAN = [MxKanban, MxKanbanCard, MxKanbanColumnFooter] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, TemplateRef, Directive, input, booleanAttribute, output, contentChild, signal,
|
|
2
|
+
import { inject, TemplateRef, Directive, input, booleanAttribute, computed, output, contentChild, signal, DestroyRef, effect, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
|
5
5
|
import { mxUniqueId } from '@muxima-ui/core/form-field';
|
|
6
|
+
import { MX_MESSAGES_EN, injectMxMessages } from '@muxima-ui/core/i18n';
|
|
6
7
|
|
|
7
|
-
/** "
|
|
8
|
-
function mxRelativeTime(date, now = new Date(), locale = '
|
|
8
|
+
/** "now", "5 min ago", "yesterday", "3 days ago" e, depois de uma semana, a data (em inglês por omissão). */
|
|
9
|
+
function mxRelativeTime(date, now = new Date(), locale = 'en-US', nowText = MX_MESSAGES_EN.notifications.now) {
|
|
9
10
|
const diff = (date.getTime() - now.getTime()) / 1000;
|
|
10
11
|
const abs = Math.abs(diff);
|
|
11
12
|
if (abs < 45)
|
|
12
|
-
return
|
|
13
|
+
return nowText;
|
|
13
14
|
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
14
15
|
if (abs < 3600)
|
|
15
16
|
return rtf.format(Math.round(diff / 60), 'minute');
|
|
@@ -43,13 +44,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
43
44
|
*/
|
|
44
45
|
class MxNotificationCenter {
|
|
45
46
|
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
46
|
-
title = input(
|
|
47
|
+
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : /* istanbul ignore next */ []));
|
|
47
48
|
/** Nível do título para o leitor de ecrã (h2 por omissão). */
|
|
48
49
|
headingLevel = input(2, ...(ngDevMode ? [{ debugName: "headingLevel" }] : /* istanbul ignore next */ []));
|
|
49
|
-
markAllText = input(
|
|
50
|
-
emptyText = input(
|
|
51
|
-
emptyUnreadText = input(
|
|
52
|
-
filterLabel = input(
|
|
50
|
+
markAllText = input(...(ngDevMode ? [undefined, { debugName: "markAllText" }] : /* istanbul ignore next */ []));
|
|
51
|
+
emptyText = input(...(ngDevMode ? [undefined, { debugName: "emptyText" }] : /* istanbul ignore next */ []));
|
|
52
|
+
emptyUnreadText = input(...(ngDevMode ? [undefined, { debugName: "emptyUnreadText" }] : /* istanbul ignore next */ []));
|
|
53
|
+
filterLabel = input(...(ngDevMode ? [undefined, { debugName: "filterLabel" }] : /* istanbul ignore next */ []));
|
|
53
54
|
/** Mostra os filtros Todas, Por ler e as categorias. */
|
|
54
55
|
showFilter = input(true, { ...(ngDevMode ? { debugName: "showFilter" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
55
56
|
/** Mostra o botão de remover em cada notificação. */
|
|
@@ -58,7 +59,10 @@ class MxNotificationCenter {
|
|
|
58
59
|
markReadOnOpen = input(true, { ...(ngDevMode ? { debugName: "markReadOnOpen" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
59
60
|
/** Anuncia ao leitor de ecrã quando chegam notificações por ler. */
|
|
60
61
|
announce = input(true, { ...(ngDevMode ? { debugName: "announce" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
61
|
-
|
|
62
|
+
/** Locale das datas; por omissão o do idioma activo. */
|
|
63
|
+
locale = input(...(ngDevMode ? [undefined, { debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
64
|
+
i18n = injectMxMessages();
|
|
65
|
+
msg = computed(() => this.i18n().notifications, ...(ngDevMode ? [{ debugName: "msg" }] : /* istanbul ignore next */ []));
|
|
62
66
|
opened = output();
|
|
63
67
|
markRead = output();
|
|
64
68
|
markAllRead = output();
|
|
@@ -95,14 +99,14 @@ class MxNotificationCenter {
|
|
|
95
99
|
const fresh = items.filter((n) => !n.read && !previous.has(n.id));
|
|
96
100
|
if (fresh.length)
|
|
97
101
|
this.announcer.announce(fresh.length === 1
|
|
98
|
-
?
|
|
99
|
-
:
|
|
102
|
+
? untracked(() => this.msg().newOne(fresh[0].title))
|
|
103
|
+
: untracked(() => this.msg().newMany(fresh.length)));
|
|
100
104
|
}
|
|
101
105
|
previous = ids;
|
|
102
106
|
});
|
|
103
107
|
}
|
|
104
108
|
relative(d) {
|
|
105
|
-
return mxRelativeTime(d, this.now(), this.locale());
|
|
109
|
+
return mxRelativeTime(d, this.now(), this.locale() ?? this.i18n().intlLocale, this.msg().now);
|
|
106
110
|
}
|
|
107
111
|
open(n) {
|
|
108
112
|
if (!n.read && this.markReadOnOpen())
|
|
@@ -111,7 +115,7 @@ class MxNotificationCenter {
|
|
|
111
115
|
}
|
|
112
116
|
dismissItem(n) {
|
|
113
117
|
this.dismiss.emit(n);
|
|
114
|
-
this.announcer.announce(
|
|
118
|
+
this.announcer.announce(this.msg().removed(n.title));
|
|
115
119
|
}
|
|
116
120
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxNotificationCenter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
117
121
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxNotificationCenter, isStandalone: true, selector: "mx-notification-center", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, headingLevel: { classPropertyName: "headingLevel", publicName: "headingLevel", isSignal: true, isRequired: false, transformFunction: null }, markAllText: { classPropertyName: "markAllText", publicName: "markAllText", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, emptyUnreadText: { classPropertyName: "emptyUnreadText", publicName: "emptyUnreadText", isSignal: true, isRequired: false, transformFunction: null }, filterLabel: { classPropertyName: "filterLabel", publicName: "filterLabel", isSignal: true, isRequired: false, transformFunction: null }, showFilter: { classPropertyName: "showFilter", publicName: "showFilter", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, markReadOnOpen: { classPropertyName: "markReadOnOpen", publicName: "markReadOnOpen", isSignal: true, isRequired: false, transformFunction: null }, announce: { classPropertyName: "announce", publicName: "announce", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", markRead: "markRead", markAllRead: "markAllRead", dismiss: "dismiss" }, host: { properties: { "attr.aria-label": "null" }, classAttribute: "mx-notification-center" }, queries: [{ propertyName: "contentTpl", first: true, predicate: MxNotificationContent, descendants: true, isSignal: true }], exportAs: ["mxNotificationCenter"], ngImport: i0, template: `
|
|
@@ -122,11 +126,11 @@ class MxNotificationCenter {
|
|
|
122
126
|
[attr.aria-level]="headingLevel()"
|
|
123
127
|
[id]="titleId"
|
|
124
128
|
>
|
|
125
|
-
{{ title() }}
|
|
129
|
+
{{ title() ?? msg().title }}
|
|
126
130
|
</p>
|
|
127
131
|
@if (unread()) {
|
|
128
132
|
<span class="mx-notification-count"
|
|
129
|
-
>{{ unread() }}<span class="mx-visually-hidden">
|
|
133
|
+
>{{ unread() }}<span class="mx-visually-hidden"> {{ msg().unreadCount(unread()) }}</span></span
|
|
130
134
|
>
|
|
131
135
|
}
|
|
132
136
|
<button
|
|
@@ -135,12 +139,12 @@ class MxNotificationCenter {
|
|
|
135
139
|
[disabled]="!unread()"
|
|
136
140
|
(click)="markAllRead.emit()"
|
|
137
141
|
>
|
|
138
|
-
{{ markAllText() }}
|
|
142
|
+
{{ markAllText() ?? msg().markAll }}
|
|
139
143
|
</button>
|
|
140
144
|
</div>
|
|
141
145
|
|
|
142
146
|
@if (showFilter()) {
|
|
143
|
-
<div class="mx-notification-filters" role="group" [attr.aria-label]="filterLabel()">
|
|
147
|
+
<div class="mx-notification-filters" role="group" [attr.aria-label]="filterLabel() ?? msg().filter">
|
|
144
148
|
<button
|
|
145
149
|
type="button"
|
|
146
150
|
class="mx-chip mx-chip-toggle"
|
|
@@ -148,7 +152,7 @@ class MxNotificationCenter {
|
|
|
148
152
|
[attr.aria-pressed]="filter() === 'all'"
|
|
149
153
|
(click)="filter.set('all')"
|
|
150
154
|
>
|
|
151
|
-
|
|
155
|
+
{{ msg().all }}
|
|
152
156
|
</button>
|
|
153
157
|
<button
|
|
154
158
|
type="button"
|
|
@@ -157,7 +161,7 @@ class MxNotificationCenter {
|
|
|
157
161
|
[attr.aria-pressed]="filter() === 'unread'"
|
|
158
162
|
(click)="filter.set('unread')"
|
|
159
163
|
>
|
|
160
|
-
|
|
164
|
+
{{ msg().unread }} ({{ unread() }})
|
|
161
165
|
</button>
|
|
162
166
|
@for (c of categories(); track c) {
|
|
163
167
|
<button
|
|
@@ -184,7 +188,7 @@ class MxNotificationCenter {
|
|
|
184
188
|
<span class="mx-notification-dot" aria-hidden="true"></span>
|
|
185
189
|
<button type="button" class="mx-notification-main" (click)="open(n)">
|
|
186
190
|
@if (!n.read) {
|
|
187
|
-
<span class="mx-visually-hidden">
|
|
191
|
+
<span class="mx-visually-hidden">{{ msg().unreadPrefix }}</span>
|
|
188
192
|
}
|
|
189
193
|
@if (contentTpl(); as tpl) {
|
|
190
194
|
<ng-container *ngTemplateOutlet="tpl.template; context: { $implicit: n }" />
|
|
@@ -203,7 +207,7 @@ class MxNotificationCenter {
|
|
|
203
207
|
<button
|
|
204
208
|
type="button"
|
|
205
209
|
class="mx-notification-action"
|
|
206
|
-
[attr.aria-label]="
|
|
210
|
+
[attr.aria-label]="msg().markRead(n.title)"
|
|
207
211
|
(click)="markRead.emit(n)"
|
|
208
212
|
>
|
|
209
213
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
|
@@ -222,7 +226,7 @@ class MxNotificationCenter {
|
|
|
222
226
|
<button
|
|
223
227
|
type="button"
|
|
224
228
|
class="mx-notification-action"
|
|
225
|
-
[attr.aria-label]="
|
|
229
|
+
[attr.aria-label]="msg().remove(n.title)"
|
|
226
230
|
(click)="dismissItem(n)"
|
|
227
231
|
>
|
|
228
232
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
|
@@ -250,7 +254,7 @@ class MxNotificationCenter {
|
|
|
250
254
|
stroke-linejoin="round"
|
|
251
255
|
/>
|
|
252
256
|
</svg>
|
|
253
|
-
<p>{{ filter() === 'unread' ? emptyUnreadText() : emptyText() }}</p>
|
|
257
|
+
<p>{{ filter() === 'unread' ? (emptyUnreadText() ?? msg().emptyUnread) : (emptyText() ?? msg().empty) }}</p>
|
|
254
258
|
</div>
|
|
255
259
|
}
|
|
256
260
|
<ng-content select="[mxNotificationFooter]" />
|
|
@@ -273,11 +277,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
273
277
|
[attr.aria-level]="headingLevel()"
|
|
274
278
|
[id]="titleId"
|
|
275
279
|
>
|
|
276
|
-
{{ title() }}
|
|
280
|
+
{{ title() ?? msg().title }}
|
|
277
281
|
</p>
|
|
278
282
|
@if (unread()) {
|
|
279
283
|
<span class="mx-notification-count"
|
|
280
|
-
>{{ unread() }}<span class="mx-visually-hidden">
|
|
284
|
+
>{{ unread() }}<span class="mx-visually-hidden"> {{ msg().unreadCount(unread()) }}</span></span
|
|
281
285
|
>
|
|
282
286
|
}
|
|
283
287
|
<button
|
|
@@ -286,12 +290,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
286
290
|
[disabled]="!unread()"
|
|
287
291
|
(click)="markAllRead.emit()"
|
|
288
292
|
>
|
|
289
|
-
{{ markAllText() }}
|
|
293
|
+
{{ markAllText() ?? msg().markAll }}
|
|
290
294
|
</button>
|
|
291
295
|
</div>
|
|
292
296
|
|
|
293
297
|
@if (showFilter()) {
|
|
294
|
-
<div class="mx-notification-filters" role="group" [attr.aria-label]="filterLabel()">
|
|
298
|
+
<div class="mx-notification-filters" role="group" [attr.aria-label]="filterLabel() ?? msg().filter">
|
|
295
299
|
<button
|
|
296
300
|
type="button"
|
|
297
301
|
class="mx-chip mx-chip-toggle"
|
|
@@ -299,7 +303,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
299
303
|
[attr.aria-pressed]="filter() === 'all'"
|
|
300
304
|
(click)="filter.set('all')"
|
|
301
305
|
>
|
|
302
|
-
|
|
306
|
+
{{ msg().all }}
|
|
303
307
|
</button>
|
|
304
308
|
<button
|
|
305
309
|
type="button"
|
|
@@ -308,7 +312,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
308
312
|
[attr.aria-pressed]="filter() === 'unread'"
|
|
309
313
|
(click)="filter.set('unread')"
|
|
310
314
|
>
|
|
311
|
-
|
|
315
|
+
{{ msg().unread }} ({{ unread() }})
|
|
312
316
|
</button>
|
|
313
317
|
@for (c of categories(); track c) {
|
|
314
318
|
<button
|
|
@@ -335,7 +339,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
335
339
|
<span class="mx-notification-dot" aria-hidden="true"></span>
|
|
336
340
|
<button type="button" class="mx-notification-main" (click)="open(n)">
|
|
337
341
|
@if (!n.read) {
|
|
338
|
-
<span class="mx-visually-hidden">
|
|
342
|
+
<span class="mx-visually-hidden">{{ msg().unreadPrefix }}</span>
|
|
339
343
|
}
|
|
340
344
|
@if (contentTpl(); as tpl) {
|
|
341
345
|
<ng-container *ngTemplateOutlet="tpl.template; context: { $implicit: n }" />
|
|
@@ -354,7 +358,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
354
358
|
<button
|
|
355
359
|
type="button"
|
|
356
360
|
class="mx-notification-action"
|
|
357
|
-
[attr.aria-label]="
|
|
361
|
+
[attr.aria-label]="msg().markRead(n.title)"
|
|
358
362
|
(click)="markRead.emit(n)"
|
|
359
363
|
>
|
|
360
364
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
|
@@ -373,7 +377,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
373
377
|
<button
|
|
374
378
|
type="button"
|
|
375
379
|
class="mx-notification-action"
|
|
376
|
-
[attr.aria-label]="
|
|
380
|
+
[attr.aria-label]="msg().remove(n.title)"
|
|
377
381
|
(click)="dismissItem(n)"
|
|
378
382
|
>
|
|
379
383
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
|
@@ -401,7 +405,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
401
405
|
stroke-linejoin="round"
|
|
402
406
|
/>
|
|
403
407
|
</svg>
|
|
404
|
-
<p>{{ filter() === 'unread' ? emptyUnreadText() : emptyText() }}</p>
|
|
408
|
+
<p>{{ filter() === 'unread' ? (emptyUnreadText() ?? msg().emptyUnread) : (emptyText() ?? msg().empty) }}</p>
|
|
405
409
|
</div>
|
|
406
410
|
}
|
|
407
411
|
<ng-content select="[mxNotificationFooter]" />
|
|
@@ -419,9 +423,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
419
423
|
class MxNotificationBell {
|
|
420
424
|
count = input(0, ...(ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []));
|
|
421
425
|
max = input(99, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
422
|
-
label = input(
|
|
426
|
+
label = input(...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
427
|
+
i18n = injectMxMessages();
|
|
423
428
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxNotificationBell, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
424
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxNotificationBell, isStandalone: true, selector: "button[mxNotificationBell]", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button" }, properties: { "attr.aria-label": "count() ? label()
|
|
429
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxNotificationBell, isStandalone: true, selector: "button[mxNotificationBell]", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button" }, properties: { "attr.aria-label": "count() ? i18n().notifications.bellCount(label() ?? i18n().notifications.title, count()) : (label() ?? i18n().notifications.title)" }, classAttribute: "mx-notification-bell" }, exportAs: ["mxNotificationBell"], ngImport: i0, template: `
|
|
425
430
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
426
431
|
<path
|
|
427
432
|
d="M6 16.5V11a6 6 0 1 1 12 0v5.5l1.5 2h-15l1.5-2z"
|
|
@@ -453,7 +458,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
453
458
|
host: {
|
|
454
459
|
class: 'mx-notification-bell',
|
|
455
460
|
type: 'button',
|
|
456
|
-
'[attr.aria-label]': 'count() ? label()
|
|
461
|
+
'[attr.aria-label]': 'count() ? i18n().notifications.bellCount(label() ?? i18n().notifications.title, count()) : (label() ?? i18n().notifications.title)',
|
|
457
462
|
},
|
|
458
463
|
template: `
|
|
459
464
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
|