@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.
Files changed (89) hide show
  1. package/README.md +11 -0
  2. package/fesm2022/muxima-ui-core-alert.mjs +5 -3
  3. package/fesm2022/muxima-ui-core-alert.mjs.map +1 -1
  4. package/fesm2022/muxima-ui-core-breadcrumb.mjs +5 -3
  5. package/fesm2022/muxima-ui-core-breadcrumb.mjs.map +1 -1
  6. package/fesm2022/muxima-ui-core-carousel.mjs +19 -17
  7. package/fesm2022/muxima-ui-core-carousel.mjs.map +1 -1
  8. package/fesm2022/muxima-ui-core-chips.mjs +19 -14
  9. package/fesm2022/muxima-ui-core-chips.mjs.map +1 -1
  10. package/fesm2022/muxima-ui-core-clipboard.mjs +10 -6
  11. package/fesm2022/muxima-ui-core-clipboard.mjs.map +1 -1
  12. package/fesm2022/muxima-ui-core-color-picker.mjs +53 -50
  13. package/fesm2022/muxima-ui-core-color-picker.mjs.map +1 -1
  14. package/fesm2022/muxima-ui-core-combobox.mjs +15 -12
  15. package/fesm2022/muxima-ui-core-combobox.mjs.map +1 -1
  16. package/fesm2022/muxima-ui-core-command.mjs +21 -16
  17. package/fesm2022/muxima-ui-core-command.mjs.map +1 -1
  18. package/fesm2022/muxima-ui-core-data-grid.mjs +50 -52
  19. package/fesm2022/muxima-ui-core-data-grid.mjs.map +1 -1
  20. package/fesm2022/muxima-ui-core-date-picker.mjs +102 -69
  21. package/fesm2022/muxima-ui-core-date-picker.mjs.map +1 -1
  22. package/fesm2022/muxima-ui-core-editor.mjs +25 -19
  23. package/fesm2022/muxima-ui-core-editor.mjs.map +1 -1
  24. package/fesm2022/muxima-ui-core-file-upload.mjs +32 -27
  25. package/fesm2022/muxima-ui-core-file-upload.mjs.map +1 -1
  26. package/fesm2022/muxima-ui-core-form-field.mjs +2 -2
  27. package/fesm2022/muxima-ui-core-form-field.mjs.map +1 -1
  28. package/fesm2022/muxima-ui-core-i18n.mjs +550 -0
  29. package/fesm2022/muxima-ui-core-i18n.mjs.map +1 -0
  30. package/fesm2022/muxima-ui-core-image-cropper.mjs +27 -24
  31. package/fesm2022/muxima-ui-core-image-cropper.mjs.map +1 -1
  32. package/fesm2022/muxima-ui-core-kanban.mjs +22 -19
  33. package/fesm2022/muxima-ui-core-kanban.mjs.map +1 -1
  34. package/fesm2022/muxima-ui-core-notification-center.mjs +42 -37
  35. package/fesm2022/muxima-ui-core-notification-center.mjs.map +1 -1
  36. package/fesm2022/muxima-ui-core-pagination.mjs +29 -26
  37. package/fesm2022/muxima-ui-core-pagination.mjs.map +1 -1
  38. package/fesm2022/muxima-ui-core-progress.mjs +5 -3
  39. package/fesm2022/muxima-ui-core-progress.mjs.map +1 -1
  40. package/fesm2022/muxima-ui-core-rating.mjs +12 -8
  41. package/fesm2022/muxima-ui-core-rating.mjs.map +1 -1
  42. package/fesm2022/muxima-ui-core-select.mjs +14 -11
  43. package/fesm2022/muxima-ui-core-select.mjs.map +1 -1
  44. package/fesm2022/muxima-ui-core-sidebar.mjs +10 -7
  45. package/fesm2022/muxima-ui-core-sidebar.mjs.map +1 -1
  46. package/fesm2022/muxima-ui-core-slider.mjs +10 -8
  47. package/fesm2022/muxima-ui-core-slider.mjs.map +1 -1
  48. package/fesm2022/muxima-ui-core-stepper.mjs +5 -3
  49. package/fesm2022/muxima-ui-core-stepper.mjs.map +1 -1
  50. package/fesm2022/muxima-ui-core-table.mjs +4 -4
  51. package/fesm2022/muxima-ui-core-table.mjs.map +1 -1
  52. package/fesm2022/muxima-ui-core-time-picker.mjs +7 -5
  53. package/fesm2022/muxima-ui-core-time-picker.mjs.map +1 -1
  54. package/fesm2022/muxima-ui-core-toast.mjs +8 -5
  55. package/fesm2022/muxima-ui-core-toast.mjs.map +1 -1
  56. package/fesm2022/muxima-ui-core-tour.mjs +6 -12
  57. package/fesm2022/muxima-ui-core-tour.mjs.map +1 -1
  58. package/fesm2022/muxima-ui-core.mjs +1 -1
  59. package/fesm2022/muxima-ui-core.mjs.map +1 -1
  60. package/package.json +5 -1
  61. package/types/muxima-ui-core-alert.d.ts +3 -1
  62. package/types/muxima-ui-core-breadcrumb.d.ts +6 -4
  63. package/types/muxima-ui-core-carousel.d.ts +4 -2
  64. package/types/muxima-ui-core-chips.d.ts +23 -3
  65. package/types/muxima-ui-core-clipboard.d.ts +6 -3
  66. package/types/muxima-ui-core-color-picker.d.ts +40 -7
  67. package/types/muxima-ui-core-combobox.d.ts +6 -3
  68. package/types/muxima-ui-core-command.d.ts +7 -3
  69. package/types/muxima-ui-core-data-grid.d.ts +30 -10
  70. package/types/muxima-ui-core-date-picker.d.ts +64 -15
  71. package/types/muxima-ui-core-editor.d.ts +13 -2
  72. package/types/muxima-ui-core-file-upload.d.ts +23 -7
  73. package/types/muxima-ui-core-form-field.d.ts +2 -2
  74. package/types/muxima-ui-core-i18n.d.ts +322 -0
  75. package/types/muxima-ui-core-image-cropper.d.ts +19 -6
  76. package/types/muxima-ui-core-kanban.d.ts +16 -3
  77. package/types/muxima-ui-core-notification-center.d.ts +31 -9
  78. package/types/muxima-ui-core-pagination.d.ts +16 -1
  79. package/types/muxima-ui-core-progress.d.ts +10 -8
  80. package/types/muxima-ui-core-rating.d.ts +6 -2
  81. package/types/muxima-ui-core-select.d.ts +6 -3
  82. package/types/muxima-ui-core-sidebar.d.ts +6 -3
  83. package/types/muxima-ui-core-slider.d.ts +6 -4
  84. package/types/muxima-ui-core-stepper.d.ts +10 -8
  85. package/types/muxima-ui-core-table.d.ts +3 -3
  86. package/types/muxima-ui-core-time-picker.d.ts +3 -1
  87. package/types/muxima-ui-core-toast.d.ts +3 -0
  88. package/types/muxima-ui-core-tour.d.ts +3 -3
  89. 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('Quadro', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
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('Sem cartões', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
48
- helpText = input('Espaço para agarrar. Setas para mover. Espaço para largar, Esc para cancelar.', ...(ngDevMode ? [{ debugName: "helpText" }] : /* istanbul ignore next */ []));
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 `${c.title}, posição ${index + 1} de ${c.items.length}`;
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(`${this.labelOf(cols[ci].items[ii])} agarrado. ${this.where(ci, ii)}.`, 'assertive');
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(`${this.labelOf(item)} largado. ${this.where(g.col, g.index)}.`, 'assertive');
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(`Movimento cancelado. ${this.labelOf(item)} voltou a ${this.where(g.fromCol, g.fromIndex)}.`, 'assertive');
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(`${target.title} está cheia, máximo ${target.limit}.`, 'assertive');
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 === 1 ? 'cartão' : 'cartões') + (col.limit ? ', máximo ' + col.limit : '')
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) + ', agarrado' : null"
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 === 1 ? 'cartão' : 'cartões') + (col.limit ? ', máximo ' + col.limit : '')
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) + ', agarrado' : null"
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, computed, DestroyRef, effect, untracked, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
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
- /** "agora", "há 5 min", "ontem", "há 3 dias" e, depois de uma semana, a data. */
8
- function mxRelativeTime(date, now = new Date(), locale = 'pt-AO') {
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 'agora';
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('Notificações', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
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('Marcar todas como lidas', ...(ngDevMode ? [{ debugName: "markAllText" }] : /* istanbul ignore next */ []));
50
- emptyText = input('Sem notificações.', ...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
51
- emptyUnreadText = input('Está tudo lido.', ...(ngDevMode ? [{ debugName: "emptyUnreadText" }] : /* istanbul ignore next */ []));
52
- filterLabel = input('Mostrar', ...(ngDevMode ? [{ debugName: "filterLabel" }] : /* istanbul ignore next */ []));
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
- locale = input('pt-AO', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
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
- ? `Nova notificação: ${fresh[0].title}`
99
- : `${fresh.length} notificações novas`);
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(`${n.title} removida.`);
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"> por ler</span></span
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
- Todas
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
- Por ler ({{ unread() }})
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">Por ler: </span>
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]="'Marcar como lida: ' + n.title"
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]="'Remover: ' + n.title"
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"> por ler</span></span
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
- Todas
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
- Por ler ({{ unread() }})
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">Por ler: </span>
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]="'Marcar como lida: ' + n.title"
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]="'Remover: ' + n.title"
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('Notificações', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
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() + \", \" + count() + \" por ler\" : label()" }, classAttribute: "mx-notification-bell" }, exportAs: ["mxNotificationBell"], ngImport: i0, template: `
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() + ", " + count() + " por ler" : 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">