@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"muxima-ui-core-stepper.mjs","sources":["../../../projects/core/stepper/stepper.ts","../../../projects/core/stepper/muxima-ui-core-stepper.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, Directive, ViewEncapsulation, input } from '@angular/core';\n\nexport type MxStepState = 'complete' | 'current' | 'upcoming';\n\n/**\n * Indicador de etapas de um fluxo (ex.: Dados, Pagamento, Confirmação).\n * Mostra o progresso; a navegação entre etapas fica a cargo da tua aplicação.\n *\n * ```html\n * <ol mxStepper aria-label=\"Progresso da encomenda\">\n * <li mxStep state=\"complete\">Dados</li>\n * <li mxStep state=\"current\">Pagamento</li>\n * <li mxStep>Confirmação</li>\n * </ol>\n * ```\n *\n * A etapa actual recebe aria-current=\"step\" e as concluídas são anunciadas como tal.\n */\n@Directive({\n selector: 'ol[mxStepper]',\n host: { class: 'mx-stepper', '[attr.data-orientation]': 'orientation()' },\n})\nexport class MxStepper {\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n}\n\n/** Uma etapa da lista. */\n@Component({\n selector: 'li[mxStep]',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'mx-step',\n '[attr.data-state]': 'state()',\n '[attr.aria-current]': 'state() === \"current\" ? \"step\" : null',\n },\n template: `\n <span class=\"mx-step-marker\" aria-hidden=\"true\"></span>\n <span class=\"mx-step-label\">\n <ng-content />\n @if (state() === 'complete') {\n <span class=\"mx-visually-hidden\"> ({{ completeText() }})</span>\n }\n </span>\n `,\n})\nexport class MxStep {\n readonly state = input<MxStepState>('upcoming');\n /** Texto lido nas etapas concluídas. */\n readonly completeText = input(
|
|
1
|
+
{"version":3,"file":"muxima-ui-core-stepper.mjs","sources":["../../../projects/core/stepper/stepper.ts","../../../projects/core/stepper/muxima-ui-core-stepper.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, Directive, ViewEncapsulation, input } from '@angular/core';\nimport { injectMxMessages } from '@muxima-ui/core/i18n';\n\nexport type MxStepState = 'complete' | 'current' | 'upcoming';\n\n/**\n * Indicador de etapas de um fluxo (ex.: Dados, Pagamento, Confirmação).\n * Mostra o progresso; a navegação entre etapas fica a cargo da tua aplicação.\n *\n * ```html\n * <ol mxStepper aria-label=\"Progresso da encomenda\">\n * <li mxStep state=\"complete\">Dados</li>\n * <li mxStep state=\"current\">Pagamento</li>\n * <li mxStep>Confirmação</li>\n * </ol>\n * ```\n *\n * A etapa actual recebe aria-current=\"step\" e as concluídas são anunciadas como tal.\n */\n@Directive({\n selector: 'ol[mxStepper]',\n host: { class: 'mx-stepper', '[attr.data-orientation]': 'orientation()' },\n})\nexport class MxStepper {\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n}\n\n/** Uma etapa da lista. */\n@Component({\n selector: 'li[mxStep]',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'mx-step',\n '[attr.data-state]': 'state()',\n '[attr.aria-current]': 'state() === \"current\" ? \"step\" : null',\n },\n template: `\n <span class=\"mx-step-marker\" aria-hidden=\"true\"></span>\n <span class=\"mx-step-label\">\n <ng-content />\n @if (state() === 'complete') {\n <span class=\"mx-visually-hidden\"> ({{ completeText() ?? i18n().stepper.complete }})</span>\n }\n </span>\n `,\n})\nexport class MxStep {\n readonly state = input<MxStepState>('upcoming');\n /** Texto lido nas etapas concluídas. */\n readonly completeText = input<string>();\n protected readonly i18n = injectMxMessages();\n}\n\nexport const MX_STEPPER = [MxStepper, MxStep] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAKA;;;;;;;;;;;;;AAaG;MAKU,SAAS,CAAA;AACX,IAAA,WAAW,GAAG,KAAK,CAA4B,YAAY,kFAAC;wGAD1D,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAT,SAAS,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,uBAAA,EAAA,eAAA,EAAA,EAAA,cAAA,EAAA,YAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAAT,SAAS,EAAA,UAAA,EAAA,CAAA;kBAJrB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,eAAe;oBACzB,IAAI,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE;AAC1E,iBAAA;;AAKD;MAoBa,MAAM,CAAA;AACR,IAAA,KAAK,GAAG,KAAK,CAAc,UAAU,4EAAC;;IAEtC,YAAY,GAAG,KAAK,CAAA,IAAA,SAAA,GAAA,CAAA,SAAA,EAAA,EAAA,SAAA,EAAA,cAAA,EAAA,CAAA,8BAAA,EAAA,CAAA,CAAU;IACpB,IAAI,GAAG,gBAAgB,EAAE;wGAJjC,MAAM,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAN,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,MAAM,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,mBAAA,EAAA,2CAAA,EAAA,EAAA,cAAA,EAAA,SAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAVP;;;;;;;;AAQT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;4FAEU,MAAM,EAAA,UAAA,EAAA,CAAA;kBAnBlB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,YAAY;oBACtB,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,aAAa,EAAE,iBAAiB,CAAC,IAAI;AACrC,oBAAA,IAAI,EAAE;AACJ,wBAAA,KAAK,EAAE,SAAS;AAChB,wBAAA,mBAAmB,EAAE,SAAS;AAC9B,wBAAA,qBAAqB,EAAE,uCAAuC;AAC/D,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;AAQT,EAAA,CAAA;AACF,iBAAA;;MAQY,UAAU,GAAG,CAAC,SAAS,EAAE,MAAM;;ACtD5C;;AAEG;;"}
|
|
@@ -115,15 +115,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
115
115
|
}]
|
|
116
116
|
}], propDecorators: { key: [{ type: i0.Input, args: [{ isSignal: true, alias: "mxSortHeader", required: true }] }] } });
|
|
117
117
|
/**
|
|
118
|
-
* Ordena uma lista segundo o estado de `MxTable`. Texto é comparado
|
|
119
|
-
* (acentos e maiúsculas), números numericamente.
|
|
118
|
+
* Ordena uma lista segundo o estado de `MxTable`. Texto é comparado segundo `locale`
|
|
119
|
+
* (inglês por omissão; acentos e maiúsculas contam como a mesma letra), números numericamente.
|
|
120
120
|
*/
|
|
121
|
-
function mxSortData(rows, sort, accessor) {
|
|
121
|
+
function mxSortData(rows, sort, accessor, locale = 'en') {
|
|
122
122
|
if (!sort.active)
|
|
123
123
|
return [...rows];
|
|
124
124
|
const key = sort.active;
|
|
125
125
|
const get = accessor ?? ((row, k) => row[k]);
|
|
126
|
-
const collator = new Intl.Collator(
|
|
126
|
+
const collator = new Intl.Collator(locale, { numeric: true, sensitivity: 'base' });
|
|
127
127
|
const dir = sort.direction === 'asc' ? 1 : -1;
|
|
128
128
|
return [...rows].sort((a, b) => {
|
|
129
129
|
const x = get(a, key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"muxima-ui-core-table.mjs","sources":["../../../projects/core/table/table.ts","../../../projects/core/table/muxima-ui-core-table.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Directive,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n} from '@angular/core';\n\nexport type MxSortDirection = 'asc' | 'desc';\n\nexport interface MxSortState {\n /** Coluna ordenada, ou null sem ordenação. */\n active: string | null;\n direction: MxSortDirection;\n}\n\n/**\n * Estilo de tabela sobre o `<table>` nativo, com ordenação opcional.\n *\n * ```html\n * <div class=\"mx-table-container\">\n * <table mxTable [(sort)]=\"ordem\">\n * <thead><tr>\n * <th mxSortHeader=\"nome\">Nome</th>\n * <th mxSortHeader=\"valor\" data-align=\"end\">Valor</th>\n * </tr></thead>\n * <tbody>...</tbody>\n * </table>\n * </div>\n * ```\n *\n * A tabela continua a ser HTML: os leitores de ecrã anunciam linhas,\n * colunas e cabeçalhos sem configuração.\n */\n@Directive({\n selector: 'table[mxTable]',\n exportAs: 'mxTable',\n host: {\n class: 'mx-table',\n '[attr.data-density]': 'density() === \"comfortable\" ? null : density()',\n '[attr.data-variant]': 'variant() === \"default\" ? null : variant()',\n '[attr.data-sticky-header]': 'stickyHeader() ? \"\" : null',\n },\n})\nexport class MxTable {\n /** Estado da ordenação. Aceita two-way binding: `[(sort)]`. */\n readonly sort = model<MxSortState>({ active: null, direction: 'asc' });\n readonly density = input<'comfortable' | 'compact'>('comfortable');\n /** default; striped: linhas alternadas; bordered: linhas entre colunas. */\n readonly variant = input<'default' | 'striped' | 'bordered'>('default');\n /** Mantém o cabeçalho visível ao fazer scroll (dá uma altura máxima ao contentor). */\n readonly stickyHeader = input(false, { transform: booleanAttribute });\n\n /** Alterna: ascendente, descendente, sem ordenação. */\n toggleSort(key: string): void {\n const s = this.sort();\n if (s.active !== key) this.sort.set({ active: key, direction: 'asc' });\n else if (s.direction === 'asc') this.sort.set({ active: key, direction: 'desc' });\n else this.sort.set({ active: null, direction: 'asc' });\n }\n}\n\n/**\n * Cabeçalho ordenável. Coloca um botão dentro do `<th>` e mantém `aria-sort` actualizado.\n */\n@Component({\n selector: 'th[mxSortHeader]',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[attr.aria-sort]': 'ariaSort()',\n },\n template: `\n <button type=\"button\" class=\"mx-sort-button\" (click)=\"table.toggleSort(key())\">\n <ng-content />\n <svg class=\"mx-sort-icon\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n @switch (ariaSort()) {\n @case ('ascending') {\n <path d=\"M8 12V4M4.5 7.5L8 4l3.5 3.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n }\n @case ('descending') {\n <path d=\"M8 4v8M4.5 8.5L8 12l3.5-3.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n }\n @default {\n <path d=\"M5 6.5L8 3.5l3 3M5 9.5l3 3 3-3\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n }\n }\n </svg>\n </button>\n `,\n})\nexport class MxSortHeader {\n readonly key = input.required<string>({ alias: 'mxSortHeader' });\n protected readonly table = inject(MxTable);\n\n protected readonly ariaSort = computed(() => {\n const s = this.table.sort();\n if (s.active !== this.key()) return 'none';\n return s.direction === 'asc' ? 'ascending' : 'descending';\n });\n}\n\n/**\n * Ordena uma lista segundo o estado de `MxTable`. Texto é comparado
|
|
1
|
+
{"version":3,"file":"muxima-ui-core-table.mjs","sources":["../../../projects/core/table/table.ts","../../../projects/core/table/muxima-ui-core-table.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Directive,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n} from '@angular/core';\n\nexport type MxSortDirection = 'asc' | 'desc';\n\nexport interface MxSortState {\n /** Coluna ordenada, ou null sem ordenação. */\n active: string | null;\n direction: MxSortDirection;\n}\n\n/**\n * Estilo de tabela sobre o `<table>` nativo, com ordenação opcional.\n *\n * ```html\n * <div class=\"mx-table-container\">\n * <table mxTable [(sort)]=\"ordem\">\n * <thead><tr>\n * <th mxSortHeader=\"nome\">Nome</th>\n * <th mxSortHeader=\"valor\" data-align=\"end\">Valor</th>\n * </tr></thead>\n * <tbody>...</tbody>\n * </table>\n * </div>\n * ```\n *\n * A tabela continua a ser HTML: os leitores de ecrã anunciam linhas,\n * colunas e cabeçalhos sem configuração.\n */\n@Directive({\n selector: 'table[mxTable]',\n exportAs: 'mxTable',\n host: {\n class: 'mx-table',\n '[attr.data-density]': 'density() === \"comfortable\" ? null : density()',\n '[attr.data-variant]': 'variant() === \"default\" ? null : variant()',\n '[attr.data-sticky-header]': 'stickyHeader() ? \"\" : null',\n },\n})\nexport class MxTable {\n /** Estado da ordenação. Aceita two-way binding: `[(sort)]`. */\n readonly sort = model<MxSortState>({ active: null, direction: 'asc' });\n readonly density = input<'comfortable' | 'compact'>('comfortable');\n /** default; striped: linhas alternadas; bordered: linhas entre colunas. */\n readonly variant = input<'default' | 'striped' | 'bordered'>('default');\n /** Mantém o cabeçalho visível ao fazer scroll (dá uma altura máxima ao contentor). */\n readonly stickyHeader = input(false, { transform: booleanAttribute });\n\n /** Alterna: ascendente, descendente, sem ordenação. */\n toggleSort(key: string): void {\n const s = this.sort();\n if (s.active !== key) this.sort.set({ active: key, direction: 'asc' });\n else if (s.direction === 'asc') this.sort.set({ active: key, direction: 'desc' });\n else this.sort.set({ active: null, direction: 'asc' });\n }\n}\n\n/**\n * Cabeçalho ordenável. Coloca um botão dentro do `<th>` e mantém `aria-sort` actualizado.\n */\n@Component({\n selector: 'th[mxSortHeader]',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[attr.aria-sort]': 'ariaSort()',\n },\n template: `\n <button type=\"button\" class=\"mx-sort-button\" (click)=\"table.toggleSort(key())\">\n <ng-content />\n <svg class=\"mx-sort-icon\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n @switch (ariaSort()) {\n @case ('ascending') {\n <path d=\"M8 12V4M4.5 7.5L8 4l3.5 3.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n }\n @case ('descending') {\n <path d=\"M8 4v8M4.5 8.5L8 12l3.5-3.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n }\n @default {\n <path d=\"M5 6.5L8 3.5l3 3M5 9.5l3 3 3-3\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n }\n }\n </svg>\n </button>\n `,\n})\nexport class MxSortHeader {\n readonly key = input.required<string>({ alias: 'mxSortHeader' });\n protected readonly table = inject(MxTable);\n\n protected readonly ariaSort = computed(() => {\n const s = this.table.sort();\n if (s.active !== this.key()) return 'none';\n return s.direction === 'asc' ? 'ascending' : 'descending';\n });\n}\n\n/**\n * Ordena uma lista segundo o estado de `MxTable`. Texto é comparado segundo `locale`\n * (inglês por omissão; acentos e maiúsculas contam como a mesma letra), números numericamente.\n */\nexport function mxSortData<T>(\n rows: readonly T[],\n sort: MxSortState,\n accessor?: (row: T, key: string) => unknown,\n locale = 'en',\n): T[] {\n if (!sort.active) return [...rows];\n const key = sort.active;\n const get = accessor ?? ((row: T, k: string) => (row as Record<string, unknown>)[k]);\n const collator = new Intl.Collator(locale, { numeric: true, sensitivity: 'base' });\n const dir = sort.direction === 'asc' ? 1 : -1;\n return [...rows].sort((a, b) => {\n const x = get(a, key);\n const y = get(b, key);\n if (x == null && y == null) return 0;\n if (x == null) return 1;\n if (y == null) return -1;\n if (typeof x === 'number' && typeof y === 'number') return (x - y) * dir;\n return collator.compare(String(x), String(y)) * dir;\n });\n}\n\nexport const MX_TABLE = [MxTable, MxSortHeader] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { model, input, numberAttribute, booleanAttribute, inject, ElementRef, computed, signal, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { injectMxMessages } from '@muxima-ui/core/i18n';
|
|
3
4
|
import { CdkOverlayOrigin, CdkConnectedOverlay } from '@angular/cdk/overlay';
|
|
4
5
|
import { NgControl, Validators } from '@angular/forms';
|
|
5
6
|
import { MxFormField, mxUniqueId, MX_FORM_FIELD_CONTROL } from '@muxima-ui/core/form-field';
|
|
@@ -66,7 +67,8 @@ class MxTimePicker {
|
|
|
66
67
|
/** Primeira e última hora permitidas, "HH:mm". */
|
|
67
68
|
min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
68
69
|
max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
69
|
-
placeholder = input(
|
|
70
|
+
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
71
|
+
i18n = injectMxMessages();
|
|
70
72
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
71
73
|
required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
72
74
|
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
@@ -257,7 +259,7 @@ class MxTimePicker {
|
|
|
257
259
|
autocomplete="off"
|
|
258
260
|
aria-autocomplete="none"
|
|
259
261
|
[id]="controlId()"
|
|
260
|
-
[placeholder]="placeholder()"
|
|
262
|
+
[placeholder]="placeholder() ?? i18n().timePicker.placeholder"
|
|
261
263
|
[value]="text()"
|
|
262
264
|
[disabled]="isDisabled()"
|
|
263
265
|
[attr.data-size]="size() === 'md' ? null : size()"
|
|
@@ -289,7 +291,7 @@ class MxTimePicker {
|
|
|
289
291
|
(attach)="scrollToActive()"
|
|
290
292
|
(detach)="close()"
|
|
291
293
|
>
|
|
292
|
-
<ul class="mx-select-panel mx-time-picker-panel" role="listbox" [id]="listId" [attr.aria-labelledby]="field?.labelId() ?? null" [attr.aria-label]="field?.labelId() ? null : (ariaLabel() ??
|
|
294
|
+
<ul class="mx-select-panel mx-time-picker-panel" role="listbox" [id]="listId" [attr.aria-labelledby]="field?.labelId() ?? null" [attr.aria-label]="field?.labelId() ? null : (ariaLabel() ?? i18n().timePicker.label)">
|
|
293
295
|
@for (s of slots(); track s; let i = $index) {
|
|
294
296
|
<li
|
|
295
297
|
class="mx-option"
|
|
@@ -328,7 +330,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
328
330
|
autocomplete="off"
|
|
329
331
|
aria-autocomplete="none"
|
|
330
332
|
[id]="controlId()"
|
|
331
|
-
[placeholder]="placeholder()"
|
|
333
|
+
[placeholder]="placeholder() ?? i18n().timePicker.placeholder"
|
|
332
334
|
[value]="text()"
|
|
333
335
|
[disabled]="isDisabled()"
|
|
334
336
|
[attr.data-size]="size() === 'md' ? null : size()"
|
|
@@ -360,7 +362,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
360
362
|
(attach)="scrollToActive()"
|
|
361
363
|
(detach)="close()"
|
|
362
364
|
>
|
|
363
|
-
<ul class="mx-select-panel mx-time-picker-panel" role="listbox" [id]="listId" [attr.aria-labelledby]="field?.labelId() ?? null" [attr.aria-label]="field?.labelId() ? null : (ariaLabel() ??
|
|
365
|
+
<ul class="mx-select-panel mx-time-picker-panel" role="listbox" [id]="listId" [attr.aria-labelledby]="field?.labelId() ?? null" [attr.aria-label]="field?.labelId() ? null : (ariaLabel() ?? i18n().timePicker.label)">
|
|
364
366
|
@for (s of slots(); track s; let i = $index) {
|
|
365
367
|
<li
|
|
366
368
|
class="mx-option"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"muxima-ui-core-time-picker.mjs","sources":["../../../projects/core/time-picker/time-picker.ts","../../../projects/core/time-picker/muxima-ui-core-time-picker.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n numberAttribute,\n signal,\n} from '@angular/core';\nimport { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedPosition } from '@angular/cdk/overlay';\nimport { ControlValueAccessor, NgControl, Validators } from '@angular/forms';\nimport { MX_FORM_FIELD_CONTROL, MxFormField, MxFormFieldControl, mxUniqueId } from '@muxima-ui/core/form-field';\n\nconst POSITIONS: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },\n];\n\n/**\n * Converte o que se escreve numa hora \"HH:mm\". Aceita \"9\", \"930\", \"9:30\", \"9h30\", \"9.30\" e \"21h\".\n * Devolve null se não for uma hora válida.\n */\nexport function mxParseTime(text: string): string | null {\n const t = text.trim().toLowerCase().replace(/\\s+/g, '');\n if (!t) return null;\n let h: number;\n let m = 0;\n const sep = t.match(/^(\\d{1,2})[:h.](\\d{0,2})$/);\n if (sep) {\n h = Number(sep[1]);\n m = sep[2] ? Number(sep[2].padEnd(2, '0')) : 0;\n } else if (/^\\d{1,4}$/.test(t)) {\n if (t.length <= 2) h = Number(t);\n else {\n h = Number(t.slice(0, t.length - 2));\n m = Number(t.slice(-2));\n }\n } else return null;\n if (h > 23 || m > 59) return null;\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n}\n\n/** Minutos desde a meia-noite de uma hora \"HH:mm\". */\nexport function mxTimeToMinutes(time: string): number {\n const [h, m] = time.split(':').map(Number);\n return h * 60 + m;\n}\n\nfunction minutesToTime(min: number): string {\n return `${String(Math.floor(min / 60)).padStart(2, '0')}:${String(min % 60).padStart(2, '0')}`;\n}\n\n/**\n * Campo de hora: escreve-se (9, 930, 9h30, 09:30) ou escolhe-se numa lista com o intervalo\n * definido em `step`. Padrão WAI-ARIA \"combobox com lista\".\n *\n * ```html\n * <mx-form-field>\n * <label mxLabel>Hora da reunião</label>\n * <mx-time-picker formControlName=\"hora\" [step]=\"15\" min=\"08:00\" max=\"18:00\" />\n * </mx-form-field>\n * ```\n *\n * O valor é uma string \"HH:mm\" (24 horas) ou null. Uma hora fora de min/max deixa o campo com erro.\n * Para uma hora isolada sem lista, o input type=time nativo com mxInput também serve.\n */\n@Component({\n selector: 'mx-time-picker',\n exportAs: 'mxTimePicker',\n imports: [CdkOverlayOrigin, CdkConnectedOverlay],\n providers: [{ provide: MX_FORM_FIELD_CONTROL, useExisting: MxTimePicker }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-time-picker', '[attr.aria-label]': 'null' },\n template: `\n <div class=\"mx-time-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n class=\"mx-input mx-time-picker-input\"\n type=\"text\"\n role=\"combobox\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n aria-autocomplete=\"none\"\n [id]=\"controlId()\"\n [placeholder]=\"placeholder()\"\n [value]=\"text()\"\n [disabled]=\"isDisabled()\"\n [attr.data-size]=\"size() === 'md' ? null : size()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listId : null\"\n [attr.aria-activedescendant]=\"isOpen() && active() >= 0 ? optionId(active()) : null\"\n [attr.aria-invalid]=\"errorState() ? 'true' : null\"\n [attr.aria-required]=\"isRequired() ? 'true' : null\"\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n (click)=\"open()\"\n (blur)=\"onBlur()\"\n />\n <svg class=\"mx-time-picker-icon\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"8\" cy=\"8\" r=\"5.75\" stroke=\"currentColor\" stroke-width=\"1.3\" />\n <path d=\"M8 5v3.2l2 1.3\" stroke=\"currentColor\" stroke-width=\"1.3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayWidth]=\"panelWidth()\"\n (overlayOutsideClick)=\"onOutside($event)\"\n (attach)=\"scrollToActive()\"\n (detach)=\"close()\"\n >\n <ul class=\"mx-select-panel mx-time-picker-panel\" role=\"listbox\" [id]=\"listId\" [attr.aria-labelledby]=\"field?.labelId() ?? null\" [attr.aria-label]=\"field?.labelId() ? null : (ariaLabel() ?? 'Horas')\">\n @for (s of slots(); track s; let i = $index) {\n <li\n class=\"mx-option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"s === value()\"\n [attr.data-active]=\"i === active() ? '' : null\"\n (mousedown)=\"$event.preventDefault()\"\n (mousemove)=\"active.set(i)\"\n (click)=\"choose(s)\"\n >\n {{ s }}\n </li>\n }\n </ul>\n </ng-template>\n `,\n})\nexport class MxTimePicker implements ControlValueAccessor, MxFormFieldControl {\n readonly value = model<string | null>(null);\n /** Minutos entre as horas da lista. */\n readonly step = input(30, { transform: numberAttribute });\n /** Primeira e última hora permitidas, \"HH:mm\". */\n readonly min = input<string | null>(null);\n readonly max = input<string | null>(null);\n readonly placeholder = input('hh:mm');\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly required = input(false, { transform: booleanAttribute });\n readonly invalid = input(false, { transform: booleanAttribute });\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n readonly id = input<string | undefined>(undefined);\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n protected readonly field = inject(MxFormField, { optional: true });\n private readonly ngControl = inject(NgControl, { self: true, optional: true });\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n protected readonly positions = POSITIONS;\n protected readonly listId = mxUniqueId('mx-time-list');\n private readonly generatedId = mxUniqueId('mx-time');\n readonly controlId = computed(() => this.id() ?? this.generatedId);\n protected readonly isOpen = signal(false);\n protected readonly panelWidth = signal(0);\n protected readonly active = signal(-1);\n private readonly draft = signal<string | null>(null);\n private readonly formDisabled = signal(false);\n protected readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n protected readonly text = computed(() => this.draft() ?? this.value() ?? '');\n\n protected readonly slots = computed(() => {\n const step = Math.max(1, this.step());\n const from = this.min() ? mxTimeToMinutes(this.min()!) : 0;\n const to = this.max() ? mxTimeToMinutes(this.max()!) : 24 * 60 - 1;\n const out: string[] = [];\n for (let m = from; m <= to; m += step) out.push(minutesToTime(m));\n return out;\n });\n\n /** Texto que não é hora, ou hora fora de min/max. */\n readonly badValue = computed(() => {\n const d = this.draft();\n if (d && !mxParseTime(d)) return true;\n const v = this.value();\n if (!v) return false;\n const m = mxTimeToMinutes(v);\n return (!!this.min() && m < mxTimeToMinutes(this.min()!)) || (!!this.max() && m > mxTimeToMinutes(this.max()!));\n });\n\n private onChange: (value: string | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n constructor() {\n if (this.ngControl) this.ngControl.valueAccessor = this;\n }\n\n protected optionId(i: number): string {\n return `${this.listId}-${i}`;\n }\n\n /** Índice da hora da lista mais próxima de um valor (ou da hora actual). */\n private nearest(time: string | null): number {\n const slots = this.slots();\n if (!slots.length) return -1;\n const now = new Date();\n const target = time ? mxTimeToMinutes(time) : now.getHours() * 60 + now.getMinutes();\n let best = 0;\n slots.forEach((s, i) => {\n if (Math.abs(mxTimeToMinutes(s) - target) < Math.abs(mxTimeToMinutes(slots[best]) - target)) best = i;\n });\n return best;\n }\n\n open(): void {\n if (this.isDisabled() || this.isOpen()) return;\n this.panelWidth.set(this.host.getBoundingClientRect().width);\n this.active.set(this.nearest(this.value()));\n this.isOpen.set(true);\n }\n close(): void {\n if (!this.isOpen()) return;\n this.isOpen.set(false);\n this.active.set(-1);\n }\n\n protected scrollToActive(): void {\n queueMicrotask(() => document.getElementById(this.optionId(this.active()))?.scrollIntoView?.({ block: 'nearest' }));\n }\n\n protected choose(time: string): void {\n this.draft.set(null);\n this.setValue(time);\n this.close();\n }\n\n protected onInput(event: Event): void {\n const text = (event.target as HTMLInputElement).value;\n const parsed = mxParseTime(text);\n this.draft.set(text || null);\n this.setValue(parsed);\n if (this.isOpen() && parsed) {\n this.active.set(this.nearest(parsed));\n this.scrollToActive();\n }\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const n = this.slots().length;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (!this.isOpen() || event.altKey) {\n this.open();\n break;\n }\n this.active.set(Math.min(this.active() + 1, n - 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (event.altKey) this.close();\n else if (this.isOpen()) this.active.set(Math.max(this.active() - 1, 0));\n break;\n case 'PageDown':\n case 'PageUp':\n if (!this.isOpen()) return;\n event.preventDefault();\n this.active.set(Math.min(Math.max(this.active() + (event.key === 'PageDown' ? 8 : -8), 0), n - 1));\n break;\n case 'Enter':\n if (this.isOpen() && this.active() >= 0) {\n event.preventDefault();\n this.choose(this.slots()[this.active()]);\n }\n return;\n case 'Escape':\n if (this.isOpen()) {\n event.preventDefault();\n this.close();\n }\n return;\n case 'Tab':\n this.close();\n return;\n default:\n return;\n }\n this.scrollToActive();\n }\n\n protected onOutside(event: MouseEvent): void {\n if (!this.host.contains(event.target as Node)) this.close();\n }\n\n protected onBlur(): void {\n // \"930\" passa a \"09:30\" quando é válido\n if (!this.isOpen() && this.draft() && mxParseTime(this.draft()!)) this.draft.set(null);\n this.onTouched();\n }\n\n private setValue(v: string | null): void {\n if (v === this.value()) return;\n this.value.set(v);\n this.onChange(v);\n }\n\n // ---- MxFormFieldControl ----\n errorState(): boolean {\n if (this.invalid() || this.badValue()) return true;\n const c = this.ngControl;\n return !!c && !!c.invalid && !!(c.touched || c.dirty);\n }\n isRequired(): boolean {\n return this.required() || !!this.ngControl?.control?.hasValidator?.(Validators.required);\n }\n\n // ---- ControlValueAccessor ----\n writeValue(value: string | null): void {\n this.value.set(value ? mxParseTime(value) : null);\n this.draft.set(null);\n }\n registerOnChange(fn: (value: string | null) => void): void {\n this.onChange = fn;\n }\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n}\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-time-picker.mjs","sources":["../../../projects/core/time-picker/time-picker.ts","../../../projects/core/time-picker/muxima-ui-core-time-picker.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n numberAttribute,\n signal,\n} from '@angular/core';\nimport { injectMxMessages } from '@muxima-ui/core/i18n';\nimport { CdkConnectedOverlay, CdkOverlayOrigin, ConnectedPosition } from '@angular/cdk/overlay';\nimport { ControlValueAccessor, NgControl, Validators } from '@angular/forms';\nimport { MX_FORM_FIELD_CONTROL, MxFormField, MxFormFieldControl, mxUniqueId } from '@muxima-ui/core/form-field';\n\nconst POSITIONS: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },\n];\n\n/**\n * Converte o que se escreve numa hora \"HH:mm\". Aceita \"9\", \"930\", \"9:30\", \"9h30\", \"9.30\" e \"21h\".\n * Devolve null se não for uma hora válida.\n */\nexport function mxParseTime(text: string): string | null {\n const t = text.trim().toLowerCase().replace(/\\s+/g, '');\n if (!t) return null;\n let h: number;\n let m = 0;\n const sep = t.match(/^(\\d{1,2})[:h.](\\d{0,2})$/);\n if (sep) {\n h = Number(sep[1]);\n m = sep[2] ? Number(sep[2].padEnd(2, '0')) : 0;\n } else if (/^\\d{1,4}$/.test(t)) {\n if (t.length <= 2) h = Number(t);\n else {\n h = Number(t.slice(0, t.length - 2));\n m = Number(t.slice(-2));\n }\n } else return null;\n if (h > 23 || m > 59) return null;\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n}\n\n/** Minutos desde a meia-noite de uma hora \"HH:mm\". */\nexport function mxTimeToMinutes(time: string): number {\n const [h, m] = time.split(':').map(Number);\n return h * 60 + m;\n}\n\nfunction minutesToTime(min: number): string {\n return `${String(Math.floor(min / 60)).padStart(2, '0')}:${String(min % 60).padStart(2, '0')}`;\n}\n\n/**\n * Campo de hora: escreve-se (9, 930, 9h30, 09:30) ou escolhe-se numa lista com o intervalo\n * definido em `step`. Padrão WAI-ARIA \"combobox com lista\".\n *\n * ```html\n * <mx-form-field>\n * <label mxLabel>Hora da reunião</label>\n * <mx-time-picker formControlName=\"hora\" [step]=\"15\" min=\"08:00\" max=\"18:00\" />\n * </mx-form-field>\n * ```\n *\n * O valor é uma string \"HH:mm\" (24 horas) ou null. Uma hora fora de min/max deixa o campo com erro.\n * Para uma hora isolada sem lista, o input type=time nativo com mxInput também serve.\n */\n@Component({\n selector: 'mx-time-picker',\n exportAs: 'mxTimePicker',\n imports: [CdkOverlayOrigin, CdkConnectedOverlay],\n providers: [{ provide: MX_FORM_FIELD_CONTROL, useExisting: MxTimePicker }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-time-picker', '[attr.aria-label]': 'null' },\n template: `\n <div class=\"mx-time-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n class=\"mx-input mx-time-picker-input\"\n type=\"text\"\n role=\"combobox\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n aria-autocomplete=\"none\"\n [id]=\"controlId()\"\n [placeholder]=\"placeholder() ?? i18n().timePicker.placeholder\"\n [value]=\"text()\"\n [disabled]=\"isDisabled()\"\n [attr.data-size]=\"size() === 'md' ? null : size()\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"isOpen() ? listId : null\"\n [attr.aria-activedescendant]=\"isOpen() && active() >= 0 ? optionId(active()) : null\"\n [attr.aria-invalid]=\"errorState() ? 'true' : null\"\n [attr.aria-required]=\"isRequired() ? 'true' : null\"\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n (click)=\"open()\"\n (blur)=\"onBlur()\"\n />\n <svg class=\"mx-time-picker-icon\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"8\" cy=\"8\" r=\"5.75\" stroke=\"currentColor\" stroke-width=\"1.3\" />\n <path d=\"M8 5v3.2l2 1.3\" stroke=\"currentColor\" stroke-width=\"1.3\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </div>\n\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"isOpen()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayWidth]=\"panelWidth()\"\n (overlayOutsideClick)=\"onOutside($event)\"\n (attach)=\"scrollToActive()\"\n (detach)=\"close()\"\n >\n <ul class=\"mx-select-panel mx-time-picker-panel\" role=\"listbox\" [id]=\"listId\" [attr.aria-labelledby]=\"field?.labelId() ?? null\" [attr.aria-label]=\"field?.labelId() ? null : (ariaLabel() ?? i18n().timePicker.label)\">\n @for (s of slots(); track s; let i = $index) {\n <li\n class=\"mx-option\"\n role=\"option\"\n [id]=\"optionId(i)\"\n [attr.aria-selected]=\"s === value()\"\n [attr.data-active]=\"i === active() ? '' : null\"\n (mousedown)=\"$event.preventDefault()\"\n (mousemove)=\"active.set(i)\"\n (click)=\"choose(s)\"\n >\n {{ s }}\n </li>\n }\n </ul>\n </ng-template>\n `,\n})\nexport class MxTimePicker implements ControlValueAccessor, MxFormFieldControl {\n readonly value = model<string | null>(null);\n /** Minutos entre as horas da lista. */\n readonly step = input(30, { transform: numberAttribute });\n /** Primeira e última hora permitidas, \"HH:mm\". */\n readonly min = input<string | null>(null);\n readonly max = input<string | null>(null);\n readonly placeholder = input<string>();\n protected readonly i18n = injectMxMessages();\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly required = input(false, { transform: booleanAttribute });\n readonly invalid = input(false, { transform: booleanAttribute });\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n readonly id = input<string | undefined>(undefined);\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n protected readonly field = inject(MxFormField, { optional: true });\n private readonly ngControl = inject(NgControl, { self: true, optional: true });\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n protected readonly positions = POSITIONS;\n protected readonly listId = mxUniqueId('mx-time-list');\n private readonly generatedId = mxUniqueId('mx-time');\n readonly controlId = computed(() => this.id() ?? this.generatedId);\n protected readonly isOpen = signal(false);\n protected readonly panelWidth = signal(0);\n protected readonly active = signal(-1);\n private readonly draft = signal<string | null>(null);\n private readonly formDisabled = signal(false);\n protected readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n protected readonly text = computed(() => this.draft() ?? this.value() ?? '');\n\n protected readonly slots = computed(() => {\n const step = Math.max(1, this.step());\n const from = this.min() ? mxTimeToMinutes(this.min()!) : 0;\n const to = this.max() ? mxTimeToMinutes(this.max()!) : 24 * 60 - 1;\n const out: string[] = [];\n for (let m = from; m <= to; m += step) out.push(minutesToTime(m));\n return out;\n });\n\n /** Texto que não é hora, ou hora fora de min/max. */\n readonly badValue = computed(() => {\n const d = this.draft();\n if (d && !mxParseTime(d)) return true;\n const v = this.value();\n if (!v) return false;\n const m = mxTimeToMinutes(v);\n return (!!this.min() && m < mxTimeToMinutes(this.min()!)) || (!!this.max() && m > mxTimeToMinutes(this.max()!));\n });\n\n private onChange: (value: string | null) => void = () => {};\n private onTouched: () => void = () => {};\n\n constructor() {\n if (this.ngControl) this.ngControl.valueAccessor = this;\n }\n\n protected optionId(i: number): string {\n return `${this.listId}-${i}`;\n }\n\n /** Índice da hora da lista mais próxima de um valor (ou da hora actual). */\n private nearest(time: string | null): number {\n const slots = this.slots();\n if (!slots.length) return -1;\n const now = new Date();\n const target = time ? mxTimeToMinutes(time) : now.getHours() * 60 + now.getMinutes();\n let best = 0;\n slots.forEach((s, i) => {\n if (Math.abs(mxTimeToMinutes(s) - target) < Math.abs(mxTimeToMinutes(slots[best]) - target)) best = i;\n });\n return best;\n }\n\n open(): void {\n if (this.isDisabled() || this.isOpen()) return;\n this.panelWidth.set(this.host.getBoundingClientRect().width);\n this.active.set(this.nearest(this.value()));\n this.isOpen.set(true);\n }\n close(): void {\n if (!this.isOpen()) return;\n this.isOpen.set(false);\n this.active.set(-1);\n }\n\n protected scrollToActive(): void {\n queueMicrotask(() => document.getElementById(this.optionId(this.active()))?.scrollIntoView?.({ block: 'nearest' }));\n }\n\n protected choose(time: string): void {\n this.draft.set(null);\n this.setValue(time);\n this.close();\n }\n\n protected onInput(event: Event): void {\n const text = (event.target as HTMLInputElement).value;\n const parsed = mxParseTime(text);\n this.draft.set(text || null);\n this.setValue(parsed);\n if (this.isOpen() && parsed) {\n this.active.set(this.nearest(parsed));\n this.scrollToActive();\n }\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n const n = this.slots().length;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (!this.isOpen() || event.altKey) {\n this.open();\n break;\n }\n this.active.set(Math.min(this.active() + 1, n - 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (event.altKey) this.close();\n else if (this.isOpen()) this.active.set(Math.max(this.active() - 1, 0));\n break;\n case 'PageDown':\n case 'PageUp':\n if (!this.isOpen()) return;\n event.preventDefault();\n this.active.set(Math.min(Math.max(this.active() + (event.key === 'PageDown' ? 8 : -8), 0), n - 1));\n break;\n case 'Enter':\n if (this.isOpen() && this.active() >= 0) {\n event.preventDefault();\n this.choose(this.slots()[this.active()]);\n }\n return;\n case 'Escape':\n if (this.isOpen()) {\n event.preventDefault();\n this.close();\n }\n return;\n case 'Tab':\n this.close();\n return;\n default:\n return;\n }\n this.scrollToActive();\n }\n\n protected onOutside(event: MouseEvent): void {\n if (!this.host.contains(event.target as Node)) this.close();\n }\n\n protected onBlur(): void {\n // \"930\" passa a \"09:30\" quando é válido\n if (!this.isOpen() && this.draft() && mxParseTime(this.draft()!)) this.draft.set(null);\n this.onTouched();\n }\n\n private setValue(v: string | null): void {\n if (v === this.value()) return;\n this.value.set(v);\n this.onChange(v);\n }\n\n // ---- MxFormFieldControl ----\n errorState(): boolean {\n if (this.invalid() || this.badValue()) return true;\n const c = this.ngControl;\n return !!c && !!c.invalid && !!(c.touched || c.dirty);\n }\n isRequired(): boolean {\n return this.required() || !!this.ngControl?.control?.hasValidator?.(Validators.required);\n }\n\n // ---- ControlValueAccessor ----\n writeValue(value: string | null): void {\n this.value.set(value ? mxParseTime(value) : null);\n this.draft.set(null);\n }\n registerOnChange(fn: (value: string | null) => void): void {\n this.onChange = fn;\n }\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, ViewEncapsulation, ChangeDetectionStrategy, Component, inject, ApplicationRef, EnvironmentInjector, createComponent, Injectable } from '@angular/core';
|
|
3
|
+
import { injectMxMessages } from '@muxima-ui/core/i18n';
|
|
3
4
|
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
|
4
5
|
|
|
5
6
|
/** Pilha de notificações. Criada uma vez pelo MxToast; não se usa directamente. */
|
|
6
7
|
class MxToaster {
|
|
8
|
+
i18n = injectMxMessages();
|
|
7
9
|
toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
|
|
8
10
|
position = signal('bottom-right', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
9
11
|
timers = new Map();
|
|
@@ -60,7 +62,7 @@ class MxToaster {
|
|
|
60
62
|
}
|
|
61
63
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxToaster, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
62
64
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxToaster, isStandalone: true, selector: "mx-toaster", host: { properties: { "attr.data-position": "position()" }, classAttribute: "mx-toaster" }, ngImport: i0, template: `
|
|
63
|
-
<section aria-label="
|
|
65
|
+
<section [attr.aria-label]="i18n().toast.region" class="mx-toaster-region">
|
|
64
66
|
<ol class="mx-toaster-list">
|
|
65
67
|
@for (t of toasts(); track t.id) {
|
|
66
68
|
<li
|
|
@@ -86,7 +88,7 @@ class MxToaster {
|
|
|
86
88
|
@if (t.action) {
|
|
87
89
|
<button type="button" class="mx-toast-action" (click)="act(t)">{{ t.action.label }}</button>
|
|
88
90
|
}
|
|
89
|
-
<button type="button" class="mx-toast-close" aria-label="
|
|
91
|
+
<button type="button" class="mx-toast-close" [attr.aria-label]="i18n().toast.close" (click)="dismiss(t.id)">
|
|
90
92
|
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" /></svg>
|
|
91
93
|
</button>
|
|
92
94
|
</li>
|
|
@@ -103,7 +105,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
103
105
|
encapsulation: ViewEncapsulation.None,
|
|
104
106
|
host: { class: 'mx-toaster', '[attr.data-position]': 'position()' },
|
|
105
107
|
template: `
|
|
106
|
-
<section aria-label="
|
|
108
|
+
<section [attr.aria-label]="i18n().toast.region" class="mx-toaster-region">
|
|
107
109
|
<ol class="mx-toaster-list">
|
|
108
110
|
@for (t of toasts(); track t.id) {
|
|
109
111
|
<li
|
|
@@ -129,7 +131,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
129
131
|
@if (t.action) {
|
|
130
132
|
<button type="button" class="mx-toast-action" (click)="act(t)">{{ t.action.label }}</button>
|
|
131
133
|
}
|
|
132
|
-
<button type="button" class="mx-toast-close" aria-label="
|
|
134
|
+
<button type="button" class="mx-toast-close" [attr.aria-label]="i18n().toast.close" (click)="dismiss(t.id)">
|
|
133
135
|
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" /></svg>
|
|
134
136
|
</button>
|
|
135
137
|
</li>
|
|
@@ -155,6 +157,7 @@ class MxToast {
|
|
|
155
157
|
appRef = inject(ApplicationRef);
|
|
156
158
|
envInjector = inject(EnvironmentInjector);
|
|
157
159
|
announcer = inject(LiveAnnouncer);
|
|
160
|
+
i18n = injectMxMessages();
|
|
158
161
|
toaster;
|
|
159
162
|
nextId = 1;
|
|
160
163
|
positionValue = 'bottom-right';
|
|
@@ -227,7 +230,7 @@ class MxToast {
|
|
|
227
230
|
};
|
|
228
231
|
}
|
|
229
232
|
announce(item) {
|
|
230
|
-
const text = [item.title, item.description, item.action ?
|
|
233
|
+
const text = [item.title, item.description, item.action ? this.i18n().toast.action(item.action.label) : '']
|
|
231
234
|
.filter(Boolean)
|
|
232
235
|
.join('. ');
|
|
233
236
|
this.announcer.announce(text, item.variant === 'danger' ? 'assertive' : 'polite');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"muxima-ui-core-toast.mjs","sources":["../../../projects/core/toast/toast.ts","../../../projects/core/toast/muxima-ui-core-toast.ts"],"sourcesContent":["import {\n ApplicationRef,\n ChangeDetectionStrategy,\n Component,\n EnvironmentInjector,\n Injectable,\n ViewEncapsulation,\n createComponent,\n inject,\n signal,\n} from '@angular/core';\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\n\nexport type MxToastVariant = 'default' | 'info' | 'success' | 'warning' | 'danger';\nexport type MxToastPosition = 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';\n\nexport interface MxToastOptions {\n description?: string;\n /** Tipo da notificação: define a cor do fundo, da borda e do ícone. */\n variant?: MxToastVariant;\n /** Tempo em ms até desaparecer. Pára enquanto o rato ou o foco estão na notificação. 0 = não desaparece. */\n duration?: number;\n /** Botão de acção, por exemplo \"Anular\". */\n action?: { label: string; run: () => void };\n /** Mostra um indicador de espera e não desaparece sozinha (até ser actualizada). */\n loading?: boolean;\n}\n\nexport interface MxToastItem {\n id: number;\n title: string;\n description?: string;\n variant: MxToastVariant;\n duration: number;\n loading: boolean;\n action?: { label: string; run: () => void };\n}\n\n/** Pilha de notificações. Criada uma vez pelo MxToast; não se usa directamente. */\n@Component({\n selector: 'mx-toaster',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-toaster', '[attr.data-position]': 'position()' },\n template: `\n <section aria-label=\"Notificações\" class=\"mx-toaster-region\">\n <ol class=\"mx-toaster-list\">\n @for (t of toasts(); track t.id) {\n <li\n class=\"mx-toast\"\n [attr.data-variant]=\"t.variant === 'default' ? null : t.variant\"\n [attr.aria-busy]=\"t.loading ? 'true' : null\"\n (mouseenter)=\"pause(t.id)\"\n (mouseleave)=\"resume(t.id)\"\n (focusin)=\"pause(t.id)\"\n (focusout)=\"resume(t.id)\"\n >\n @if (t.loading) {\n <span class=\"mx-toast-icon mx-spinner\" aria-hidden=\"true\"></span>\n } @else if (t.variant !== 'default') {\n <span class=\"mx-toast-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"mx-toast-text\">\n <p class=\"mx-toast-title\">{{ t.title }}</p>\n @if (t.description) {\n <p class=\"mx-toast-description\">{{ t.description }}</p>\n }\n </div>\n @if (t.action) {\n <button type=\"button\" class=\"mx-toast-action\" (click)=\"act(t)\">{{ t.action.label }}</button>\n }\n <button type=\"button\" class=\"mx-toast-close\" aria-label=\"Fechar notificação\" (click)=\"dismiss(t.id)\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M4 4l8 8M12 4l-8 8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" /></svg>\n </button>\n </li>\n }\n </ol>\n </section>\n `,\n})\nexport class MxToaster {\n readonly toasts = signal<MxToastItem[]>([]);\n readonly position = signal<MxToastPosition>('bottom-right');\n private readonly timers = new Map<number, { handle?: ReturnType<typeof setTimeout>; remaining: number; started: number }>();\n\n add(t: MxToastItem): void {\n this.toasts.update((list) => [...list, t].slice(-5));\n this.startTimer(t);\n }\n\n replace(t: MxToastItem): void {\n this.clearTimer(t.id);\n this.toasts.update((list) => list.map((x) => (x.id === t.id ? t : x)));\n this.startTimer(t);\n }\n\n get(id: number): MxToastItem | undefined {\n return this.toasts().find((t) => t.id === id);\n }\n\n dismiss(id: number): void {\n this.clearTimer(id);\n this.toasts.update((list) => list.filter((t) => t.id !== id));\n }\n\n clear(): void {\n this.toasts().forEach((t) => this.clearTimer(t.id));\n this.toasts.set([]);\n }\n\n protected act(t: MxToastItem): void {\n t.action?.run();\n this.dismiss(t.id);\n }\n\n protected pause(id: number): void {\n const timer = this.timers.get(id);\n if (!timer?.handle) return;\n clearTimeout(timer.handle);\n timer.handle = undefined;\n timer.remaining -= Date.now() - timer.started;\n }\n\n protected resume(id: number): void {\n const timer = this.timers.get(id);\n if (!timer || timer.handle) return;\n timer.started = Date.now();\n timer.handle = setTimeout(() => this.dismiss(id), Math.max(timer.remaining, 1000));\n }\n\n private startTimer(t: MxToastItem): void {\n if (t.duration > 0 && !t.loading) {\n this.timers.set(t.id, { remaining: t.duration, started: 0 });\n this.resume(t.id);\n }\n }\n\n private clearTimer(id: number): void {\n const timer = this.timers.get(id);\n if (timer?.handle) clearTimeout(timer.handle);\n this.timers.delete(id);\n }\n}\n\n/**\n * Notificações temporárias. Cada tipo tem a sua cor (fundo, borda e ícone): info em Kwanza,\n * success em verde, warning em âmbar e danger em vermelho. O texto é anunciado pelo leitor de\n * ecrã (de imediato em danger) e a contagem pára com o rato ou o foco na notificação.\n *\n * ```ts\n * const toast = inject(MxToast);\n * toast.show('Factura enviada', { variant: 'success', description: 'FT 2026/0142 para Kianda Logística.' });\n * toast.show('Falha no envio', { variant: 'danger', description: 'Verifica a ligação.' });\n * toast.promise(enviar(), { loading: 'A enviar...', success: 'Enviado', error: 'Não foi possível enviar' });\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class MxToast {\n private readonly appRef = inject(ApplicationRef);\n private readonly envInjector = inject(EnvironmentInjector);\n private readonly announcer = inject(LiveAnnouncer);\n private toaster?: MxToaster;\n private nextId = 1;\n private positionValue: MxToastPosition = 'bottom-right';\n\n show(title: string, options: MxToastOptions = {}): number {\n const item = this.build(this.nextId++, title, options);\n this.ensureToaster().add(item);\n this.announce(item);\n return item.id;\n }\n\n /** Atalhos com o tipo já definido. */\n info(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'info' });\n }\n success(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'success' });\n }\n warning(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'warning' });\n }\n error(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'danger' });\n }\n\n /** Muda uma notificação já visível (por exemplo, de \"a enviar\" para \"enviado\"). */\n update(id: number, title: string, options: MxToastOptions = {}): void {\n const toaster = this.ensureToaster();\n if (!toaster.get(id)) {\n this.show(title, options);\n return;\n }\n const item = this.build(id, title, options);\n toaster.replace(item);\n this.announce(item);\n }\n\n /** Mostra \"a carregar\" enquanto a promessa corre e depois sucesso ou erro. */\n async promise<T>(\n work: Promise<T>,\n messages: { loading: string; success: string | ((value: T) => string); error: string | ((err: unknown) => string) },\n ): Promise<T> {\n const id = this.show(messages.loading, { loading: true });\n try {\n const value = await work;\n this.update(id, typeof messages.success === 'function' ? messages.success(value) : messages.success, { variant: 'success' });\n return value;\n } catch (err) {\n this.update(id, typeof messages.error === 'function' ? messages.error(err) : messages.error, { variant: 'danger' });\n throw err;\n }\n }\n\n dismiss(id: number): void {\n this.toaster?.dismiss(id);\n }\n\n /** Fecha todas as notificações. */\n clear(): void {\n this.toaster?.clear();\n }\n\n /** Canto do ecrã onde aparecem as notificações. */\n setPosition(position: MxToastPosition): void {\n this.positionValue = position;\n this.toaster?.position.set(position);\n }\n\n private build(id: number, title: string, options: MxToastOptions): MxToastItem {\n const loading = options.loading ?? false;\n return {\n id,\n title,\n description: options.description,\n variant: options.variant ?? 'default',\n loading,\n // com acção, mais tempo para a usar; a carregar, fica até ser actualizada\n duration: loading ? 0 : (options.duration ?? (options.action ? 10000 : 5000)),\n action: options.action,\n };\n }\n\n private announce(item: MxToastItem): void {\n const text = [item.title, item.description, item.action ? `Acção disponível: ${item.action.label}` : '']\n .filter(Boolean)\n .join('. ');\n this.announcer.announce(text, item.variant === 'danger' ? 'assertive' : 'polite');\n }\n\n private ensureToaster(): MxToaster {\n if (this.toaster) return this.toaster;\n const ref = createComponent(MxToaster, { environmentInjector: this.envInjector });\n this.appRef.attachView(ref.hostView);\n document.body.appendChild(ref.location.nativeElement);\n this.toaster = ref.instance;\n this.toaster.position.set(this.positionValue);\n return this.toaster;\n }\n}\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-toast.mjs","sources":["../../../projects/core/toast/toast.ts","../../../projects/core/toast/muxima-ui-core-toast.ts"],"sourcesContent":["import {\n ApplicationRef,\n ChangeDetectionStrategy,\n Component,\n EnvironmentInjector,\n Injectable,\n ViewEncapsulation,\n createComponent,\n inject,\n signal,\n} from '@angular/core';\nimport { injectMxMessages } from '@muxima-ui/core/i18n';\nimport { LiveAnnouncer } from '@angular/cdk/a11y';\n\nexport type MxToastVariant = 'default' | 'info' | 'success' | 'warning' | 'danger';\nexport type MxToastPosition = 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';\n\nexport interface MxToastOptions {\n description?: string;\n /** Tipo da notificação: define a cor do fundo, da borda e do ícone. */\n variant?: MxToastVariant;\n /** Tempo em ms até desaparecer. Pára enquanto o rato ou o foco estão na notificação. 0 = não desaparece. */\n duration?: number;\n /** Botão de acção, por exemplo \"Anular\". */\n action?: { label: string; run: () => void };\n /** Mostra um indicador de espera e não desaparece sozinha (até ser actualizada). */\n loading?: boolean;\n}\n\nexport interface MxToastItem {\n id: number;\n title: string;\n description?: string;\n variant: MxToastVariant;\n duration: number;\n loading: boolean;\n action?: { label: string; run: () => void };\n}\n\n/** Pilha de notificações. Criada uma vez pelo MxToast; não se usa directamente. */\n@Component({\n selector: 'mx-toaster',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-toaster', '[attr.data-position]': 'position()' },\n template: `\n <section [attr.aria-label]=\"i18n().toast.region\" class=\"mx-toaster-region\">\n <ol class=\"mx-toaster-list\">\n @for (t of toasts(); track t.id) {\n <li\n class=\"mx-toast\"\n [attr.data-variant]=\"t.variant === 'default' ? null : t.variant\"\n [attr.aria-busy]=\"t.loading ? 'true' : null\"\n (mouseenter)=\"pause(t.id)\"\n (mouseleave)=\"resume(t.id)\"\n (focusin)=\"pause(t.id)\"\n (focusout)=\"resume(t.id)\"\n >\n @if (t.loading) {\n <span class=\"mx-toast-icon mx-spinner\" aria-hidden=\"true\"></span>\n } @else if (t.variant !== 'default') {\n <span class=\"mx-toast-icon\" aria-hidden=\"true\"></span>\n }\n <div class=\"mx-toast-text\">\n <p class=\"mx-toast-title\">{{ t.title }}</p>\n @if (t.description) {\n <p class=\"mx-toast-description\">{{ t.description }}</p>\n }\n </div>\n @if (t.action) {\n <button type=\"button\" class=\"mx-toast-action\" (click)=\"act(t)\">{{ t.action.label }}</button>\n }\n <button type=\"button\" class=\"mx-toast-close\" [attr.aria-label]=\"i18n().toast.close\" (click)=\"dismiss(t.id)\">\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M4 4l8 8M12 4l-8 8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" /></svg>\n </button>\n </li>\n }\n </ol>\n </section>\n `,\n})\nexport class MxToaster {\n protected readonly i18n = injectMxMessages();\n readonly toasts = signal<MxToastItem[]>([]);\n readonly position = signal<MxToastPosition>('bottom-right');\n private readonly timers = new Map<number, { handle?: ReturnType<typeof setTimeout>; remaining: number; started: number }>();\n\n add(t: MxToastItem): void {\n this.toasts.update((list) => [...list, t].slice(-5));\n this.startTimer(t);\n }\n\n replace(t: MxToastItem): void {\n this.clearTimer(t.id);\n this.toasts.update((list) => list.map((x) => (x.id === t.id ? t : x)));\n this.startTimer(t);\n }\n\n get(id: number): MxToastItem | undefined {\n return this.toasts().find((t) => t.id === id);\n }\n\n dismiss(id: number): void {\n this.clearTimer(id);\n this.toasts.update((list) => list.filter((t) => t.id !== id));\n }\n\n clear(): void {\n this.toasts().forEach((t) => this.clearTimer(t.id));\n this.toasts.set([]);\n }\n\n protected act(t: MxToastItem): void {\n t.action?.run();\n this.dismiss(t.id);\n }\n\n protected pause(id: number): void {\n const timer = this.timers.get(id);\n if (!timer?.handle) return;\n clearTimeout(timer.handle);\n timer.handle = undefined;\n timer.remaining -= Date.now() - timer.started;\n }\n\n protected resume(id: number): void {\n const timer = this.timers.get(id);\n if (!timer || timer.handle) return;\n timer.started = Date.now();\n timer.handle = setTimeout(() => this.dismiss(id), Math.max(timer.remaining, 1000));\n }\n\n private startTimer(t: MxToastItem): void {\n if (t.duration > 0 && !t.loading) {\n this.timers.set(t.id, { remaining: t.duration, started: 0 });\n this.resume(t.id);\n }\n }\n\n private clearTimer(id: number): void {\n const timer = this.timers.get(id);\n if (timer?.handle) clearTimeout(timer.handle);\n this.timers.delete(id);\n }\n}\n\n/**\n * Notificações temporárias. Cada tipo tem a sua cor (fundo, borda e ícone): info em Kwanza,\n * success em verde, warning em âmbar e danger em vermelho. O texto é anunciado pelo leitor de\n * ecrã (de imediato em danger) e a contagem pára com o rato ou o foco na notificação.\n *\n * ```ts\n * const toast = inject(MxToast);\n * toast.show('Factura enviada', { variant: 'success', description: 'FT 2026/0142 para Kianda Logística.' });\n * toast.show('Falha no envio', { variant: 'danger', description: 'Verifica a ligação.' });\n * toast.promise(enviar(), { loading: 'A enviar...', success: 'Enviado', error: 'Não foi possível enviar' });\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class MxToast {\n private readonly appRef = inject(ApplicationRef);\n private readonly envInjector = inject(EnvironmentInjector);\n private readonly announcer = inject(LiveAnnouncer);\n private readonly i18n = injectMxMessages();\n private toaster?: MxToaster;\n private nextId = 1;\n private positionValue: MxToastPosition = 'bottom-right';\n\n show(title: string, options: MxToastOptions = {}): number {\n const item = this.build(this.nextId++, title, options);\n this.ensureToaster().add(item);\n this.announce(item);\n return item.id;\n }\n\n /** Atalhos com o tipo já definido. */\n info(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'info' });\n }\n success(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'success' });\n }\n warning(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'warning' });\n }\n error(title: string, options: Omit<MxToastOptions, 'variant'> = {}): number {\n return this.show(title, { ...options, variant: 'danger' });\n }\n\n /** Muda uma notificação já visível (por exemplo, de \"a enviar\" para \"enviado\"). */\n update(id: number, title: string, options: MxToastOptions = {}): void {\n const toaster = this.ensureToaster();\n if (!toaster.get(id)) {\n this.show(title, options);\n return;\n }\n const item = this.build(id, title, options);\n toaster.replace(item);\n this.announce(item);\n }\n\n /** Mostra \"a carregar\" enquanto a promessa corre e depois sucesso ou erro. */\n async promise<T>(\n work: Promise<T>,\n messages: { loading: string; success: string | ((value: T) => string); error: string | ((err: unknown) => string) },\n ): Promise<T> {\n const id = this.show(messages.loading, { loading: true });\n try {\n const value = await work;\n this.update(id, typeof messages.success === 'function' ? messages.success(value) : messages.success, { variant: 'success' });\n return value;\n } catch (err) {\n this.update(id, typeof messages.error === 'function' ? messages.error(err) : messages.error, { variant: 'danger' });\n throw err;\n }\n }\n\n dismiss(id: number): void {\n this.toaster?.dismiss(id);\n }\n\n /** Fecha todas as notificações. */\n clear(): void {\n this.toaster?.clear();\n }\n\n /** Canto do ecrã onde aparecem as notificações. */\n setPosition(position: MxToastPosition): void {\n this.positionValue = position;\n this.toaster?.position.set(position);\n }\n\n private build(id: number, title: string, options: MxToastOptions): MxToastItem {\n const loading = options.loading ?? false;\n return {\n id,\n title,\n description: options.description,\n variant: options.variant ?? 'default',\n loading,\n // com acção, mais tempo para a usar; a carregar, fica até ser actualizada\n duration: loading ? 0 : (options.duration ?? (options.action ? 10000 : 5000)),\n action: options.action,\n };\n }\n\n private announce(item: MxToastItem): void {\n const text = [item.title, item.description, item.action ? this.i18n().toast.action(item.action.label) : '']\n .filter(Boolean)\n .join('. ');\n this.announcer.announce(text, item.variant === 'danger' ? 'assertive' : 'polite');\n }\n\n private ensureToaster(): MxToaster {\n if (this.toaster) return this.toaster;\n const ref = createComponent(MxToaster, { environmentInjector: this.envInjector });\n this.appRef.attachView(ref.hostView);\n document.body.appendChild(ref.location.nativeElement);\n this.toaster = ref.instance;\n this.toaster.position.set(this.positionValue);\n return this.toaster;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, InjectionToken, inject, viewChild, NgZone, ChangeDetectorRef, DestroyRef, effect, untracked, afterNextRender, ViewEncapsulation, ChangeDetectionStrategy, Component, Injector, computed, ElementRef, Injectable, input, Directive } from '@angular/core';
|
|
3
|
+
import { MX_MESSAGES_EN, MxI18n } from '@muxima-ui/core/i18n';
|
|
3
4
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
5
|
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
5
6
|
import { createOverlayRef, createNoopScrollStrategy, createGlobalPositionStrategy } from '@angular/cdk/overlay';
|
|
@@ -7,14 +8,6 @@ import { ComponentPortal } from '@angular/cdk/portal';
|
|
|
7
8
|
import { MxButton } from '@muxima-ui/core/button';
|
|
8
9
|
import { mxUniqueId } from '@muxima-ui/core/form-field';
|
|
9
10
|
|
|
10
|
-
const MX_TOUR_LABELS = {
|
|
11
|
-
next: 'Seguinte',
|
|
12
|
-
previous: 'Anterior',
|
|
13
|
-
done: 'Concluir',
|
|
14
|
-
skip: 'Saltar',
|
|
15
|
-
close: 'Fechar a visita guiada',
|
|
16
|
-
progress: (current, total) => `Passo ${current} de ${total}`,
|
|
17
|
-
};
|
|
18
11
|
/** Referência a uma visita em curso. */
|
|
19
12
|
class MxTourRef {
|
|
20
13
|
steps;
|
|
@@ -28,10 +21,10 @@ class MxTourRef {
|
|
|
28
21
|
showDots;
|
|
29
22
|
resolve;
|
|
30
23
|
done = false;
|
|
31
|
-
constructor(steps, options, onClose) {
|
|
24
|
+
constructor(steps, options, onClose, defaults = MX_MESSAGES_EN.tour) {
|
|
32
25
|
this.steps = steps;
|
|
33
26
|
this.onClose = onClose;
|
|
34
|
-
this.labels = { ...
|
|
27
|
+
this.labels = { ...defaults, ...options.labels };
|
|
35
28
|
this.dismissible = options.dismissible ?? true;
|
|
36
29
|
this.showDots = options.showDots ?? true;
|
|
37
30
|
this.index.set(Math.min(Math.max(options.startAt ?? 0, 0), Math.max(steps.length - 1, 0)));
|
|
@@ -440,6 +433,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
440
433
|
*/
|
|
441
434
|
class MxTour {
|
|
442
435
|
injector = inject(Injector);
|
|
436
|
+
i18n = inject(MxI18n);
|
|
443
437
|
anchors = new Map();
|
|
444
438
|
overlayRef;
|
|
445
439
|
/** A visita em curso, ou null. */
|
|
@@ -455,7 +449,7 @@ class MxTour {
|
|
|
455
449
|
this.active.set(null);
|
|
456
450
|
if (before && before.isConnected)
|
|
457
451
|
before.focus({ preventScroll: true });
|
|
458
|
-
});
|
|
452
|
+
}, this.i18n.messages().tour);
|
|
459
453
|
if (!steps.length) {
|
|
460
454
|
ref.close(true);
|
|
461
455
|
return ref;
|
|
@@ -532,5 +526,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImpo
|
|
|
532
526
|
* Generated bundle index. Do not edit.
|
|
533
527
|
*/
|
|
534
528
|
|
|
535
|
-
export {
|
|
529
|
+
export { MxTour, MxTourAnchor, MxTourPanel, MxTourRef };
|
|
536
530
|
//# sourceMappingURL=muxima-ui-core-tour.mjs.map
|