@muxima-ui/core 1.0.0 → 1.2.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 +12 -4
- package/fesm2022/muxima-ui-core-carousel.mjs +377 -0
- package/fesm2022/muxima-ui-core-carousel.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-chips.mjs +349 -0
- package/fesm2022/muxima-ui-core-chips.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-clipboard.mjs +110 -0
- package/fesm2022/muxima-ui-core-clipboard.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-color-picker.mjs +755 -0
- package/fesm2022/muxima-ui-core-color-picker.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-date-picker.mjs +494 -12
- package/fesm2022/muxima-ui-core-date-picker.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-file-upload.mjs +392 -0
- package/fesm2022/muxima-ui-core-file-upload.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-notification-center.mjs +487 -0
- package/fesm2022/muxima-ui-core-notification-center.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-rating.mjs +212 -0
- package/fesm2022/muxima-ui-core-rating.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-sidebar.mjs +333 -0
- package/fesm2022/muxima-ui-core-sidebar.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-slider.mjs +211 -3
- package/fesm2022/muxima-ui-core-slider.mjs.map +1 -1
- package/fesm2022/muxima-ui-core-time-picker.mjs +389 -0
- package/fesm2022/muxima-ui-core-time-picker.mjs.map +1 -0
- package/fesm2022/muxima-ui-core-timeline.mjs +117 -0
- package/fesm2022/muxima-ui-core-timeline.mjs.map +1 -0
- package/fesm2022/muxima-ui-core.mjs +1 -1
- package/fesm2022/muxima-ui-core.mjs.map +1 -1
- package/package.json +41 -1
- package/styles/base.css +21 -1
- package/styles/components/carousel.css +113 -0
- package/styles/components/chips.css +170 -0
- package/styles/components/clipboard.css +52 -0
- package/styles/components/color-picker.css +207 -0
- package/styles/components/date-picker.css +135 -0
- package/styles/components/file-upload.css +164 -0
- package/styles/components/notification-center.css +220 -0
- package/styles/components/rating.css +89 -0
- package/styles/components/sidebar.css +211 -0
- package/styles/components/slider.css +111 -0
- package/styles/components/time-picker.css +39 -0
- package/styles/components/timeline.css +180 -0
- package/styles/muxima.css +10 -0
- package/types/muxima-ui-core-carousel.d.ts +72 -0
- package/types/muxima-ui-core-chips.d.ts +120 -0
- package/types/muxima-ui-core-clipboard.d.ts +42 -0
- package/types/muxima-ui-core-color-picker.d.ts +153 -0
- package/types/muxima-ui-core-date-picker.d.ts +130 -2
- package/types/muxima-ui-core-file-upload.d.ts +96 -0
- package/types/muxima-ui-core-notification-center.d.ts +91 -0
- package/types/muxima-ui-core-rating.d.ts +64 -0
- package/types/muxima-ui-core-sidebar.d.ts +115 -0
- package/types/muxima-ui-core-slider.d.ts +68 -6
- package/types/muxima-ui-core-time-picker.d.ts +83 -0
- package/types/muxima-ui-core-timeline.d.ts +59 -0
- package/types/muxima-ui-core.d.ts +1 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { model, input, numberAttribute, booleanAttribute, inject, computed, signal, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { NgControl, Validators } from '@angular/forms';
|
|
4
|
+
import { MxFormField, mxUniqueId, MX_FORM_FIELD_CONTROL } from '@muxima-ui/core/form-field';
|
|
5
|
+
|
|
6
|
+
const STAR = 'M12 3.2l2.7 5.6 6.1.8-4.5 4.2 1.1 6.1L12 17l-5.4 2.9 1.1-6.1-4.5-4.2 6.1-.8z';
|
|
7
|
+
/**
|
|
8
|
+
* Avaliação com estrelas. Para escolher, são botões de rádio nativos (setas mudam a nota,
|
|
9
|
+
* Tab sai do grupo); em `readonly` é uma imagem com o texto "4 de 5 estrelas".
|
|
10
|
+
*
|
|
11
|
+
* ```html
|
|
12
|
+
* <mx-form-field>
|
|
13
|
+
* <label mxLabel>Como correu o atendimento?</label>
|
|
14
|
+
* <mx-rating formControlName="nota" />
|
|
15
|
+
* </mx-form-field>
|
|
16
|
+
* <mx-rating [value]="4.5" readonly />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
class MxRating {
|
|
20
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
21
|
+
max = input(5, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
22
|
+
/** Só mostra a nota (aceita meias estrelas, ex.: 4,5). */
|
|
23
|
+
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
24
|
+
/** Carregar outra vez na nota escolhida limpa a avaliação. */
|
|
25
|
+
clearable = input(false, { ...(ngDevMode ? { debugName: "clearable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
26
|
+
/** Mostra o número ao lado ("4,5"). */
|
|
27
|
+
showValue = input(false, { ...(ngDevMode ? { debugName: "showValue" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
28
|
+
starLabel = input((n) => (n === 1 ? '1 estrela' : `${n} estrelas`), ...(ngDevMode ? [{ debugName: "starLabel" }] : /* istanbul ignore next */ []));
|
|
29
|
+
locale = input('pt-AO', ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
|
|
30
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
31
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
32
|
+
required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
33
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
34
|
+
id = input(undefined, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
35
|
+
ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
36
|
+
field = inject(MxFormField, { optional: true });
|
|
37
|
+
ngControl = inject(NgControl, { self: true, optional: true });
|
|
38
|
+
star = STAR;
|
|
39
|
+
name = mxUniqueId('mx-rating');
|
|
40
|
+
generatedId = mxUniqueId('mx-rating-input');
|
|
41
|
+
controlId = computed(() => this.id() ?? this.generatedId, ...(ngDevMode ? [{ debugName: "controlId" }] : /* istanbul ignore next */ []));
|
|
42
|
+
hover = signal(0, ...(ngDevMode ? [{ debugName: "hover" }] : /* istanbul ignore next */ []));
|
|
43
|
+
formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
|
|
44
|
+
isDisabled = computed(() => this.disabled() || this.formDisabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
45
|
+
stars = computed(() => Array.from({ length: this.max() }, (_, i) => i + 1), ...(ngDevMode ? [{ debugName: "stars" }] : /* istanbul ignore next */ []));
|
|
46
|
+
shown = computed(() => this.hover() || this.value() || 0, ...(ngDevMode ? [{ debugName: "shown" }] : /* istanbul ignore next */ []));
|
|
47
|
+
valueText = computed(() => new Intl.NumberFormat(this.locale(), { maximumFractionDigits: 1 }).format(this.value() ?? 0), ...(ngDevMode ? [{ debugName: "valueText" }] : /* istanbul ignore next */ []));
|
|
48
|
+
readonlyLabel = computed(() => `${this.valueText()} de ${this.max()} estrelas`, ...(ngDevMode ? [{ debugName: "readonlyLabel" }] : /* istanbul ignore next */ []));
|
|
49
|
+
onChange = () => { };
|
|
50
|
+
onTouched = () => { };
|
|
51
|
+
constructor() {
|
|
52
|
+
if (this.ngControl)
|
|
53
|
+
this.ngControl.valueAccessor = this;
|
|
54
|
+
}
|
|
55
|
+
fillPct(s) {
|
|
56
|
+
const v = this.value() ?? 0;
|
|
57
|
+
return Math.max(0, Math.min(1, v - (s - 1))) * 100;
|
|
58
|
+
}
|
|
59
|
+
choose(s) {
|
|
60
|
+
this.set(s);
|
|
61
|
+
}
|
|
62
|
+
onClick(s) {
|
|
63
|
+
// um clique na nota já escolhida não dispara "change": limpa se clearable
|
|
64
|
+
if (this.clearable() && this.value() === s) {
|
|
65
|
+
this.set(null);
|
|
66
|
+
this.hover.set(0);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
set(v) {
|
|
70
|
+
this.value.set(v);
|
|
71
|
+
this.onChange(v);
|
|
72
|
+
}
|
|
73
|
+
// ---- MxFormFieldControl ----
|
|
74
|
+
errorState() {
|
|
75
|
+
if (this.invalid())
|
|
76
|
+
return true;
|
|
77
|
+
const c = this.ngControl;
|
|
78
|
+
return !!c && !!c.invalid && !!(c.touched || c.dirty);
|
|
79
|
+
}
|
|
80
|
+
isRequired() {
|
|
81
|
+
return this.required() || !!this.ngControl?.control?.hasValidator?.(Validators.required);
|
|
82
|
+
}
|
|
83
|
+
// ---- ControlValueAccessor ----
|
|
84
|
+
writeValue(value) {
|
|
85
|
+
this.value.set(value ?? null);
|
|
86
|
+
}
|
|
87
|
+
registerOnChange(fn) {
|
|
88
|
+
this.onChange = fn;
|
|
89
|
+
}
|
|
90
|
+
registerOnTouched(fn) {
|
|
91
|
+
this.onTouched = fn;
|
|
92
|
+
}
|
|
93
|
+
setDisabledState(isDisabled) {
|
|
94
|
+
this.formDisabled.set(isDisabled);
|
|
95
|
+
}
|
|
96
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxRating, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
97
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxRating, isStandalone: true, selector: "mx-rating", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, starLabel: { classPropertyName: "starLabel", publicName: "starLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "attr.data-size": "size() === \"md\" ? null : size()", "attr.data-readonly": "readonly() ? \"\" : null", "attr.data-disabled": "isDisabled() ? \"\" : null", "attr.data-invalid": "errorState() ? \"\" : null", "attr.aria-label": "null" }, classAttribute: "mx-rating" }, providers: [{ provide: MX_FORM_FIELD_CONTROL, useExisting: MxRating }], exportAs: ["mxRating"], ngImport: i0, template: `
|
|
98
|
+
@if (readonly()) {
|
|
99
|
+
<span class="mx-rating-stars" role="img" [attr.aria-label]="readonlyLabel()">
|
|
100
|
+
@for (s of stars(); track s) {
|
|
101
|
+
<span class="mx-rating-star" aria-hidden="true">
|
|
102
|
+
<svg viewBox="0 0 24 24"><path [attr.d]="star" /></svg>
|
|
103
|
+
<span class="mx-rating-star-fill" [style.width.%]="fillPct(s)"><svg viewBox="0 0 24 24"><path [attr.d]="star" /></svg></span>
|
|
104
|
+
</span>
|
|
105
|
+
}
|
|
106
|
+
</span>
|
|
107
|
+
} @else {
|
|
108
|
+
<div
|
|
109
|
+
class="mx-rating-stars"
|
|
110
|
+
role="radiogroup"
|
|
111
|
+
[attr.aria-labelledby]="field?.labelId() ?? null"
|
|
112
|
+
[attr.aria-label]="field?.labelId() ? null : (ariaLabel() ?? 'Avaliação')"
|
|
113
|
+
[attr.aria-describedby]="field?.describedBy() ?? null"
|
|
114
|
+
[attr.aria-required]="isRequired() ? 'true' : null"
|
|
115
|
+
[attr.aria-invalid]="errorState() ? 'true' : null"
|
|
116
|
+
(mouseleave)="hover.set(0)"
|
|
117
|
+
>
|
|
118
|
+
@for (s of stars(); track s) {
|
|
119
|
+
<label class="mx-rating-star" [attr.data-on]="s <= shown() ? '' : null" (mouseenter)="hover.set(isDisabled() ? 0 : s)">
|
|
120
|
+
<input
|
|
121
|
+
type="radio"
|
|
122
|
+
class="mx-rating-input"
|
|
123
|
+
[id]="s === 1 ? controlId() : null"
|
|
124
|
+
[name]="name"
|
|
125
|
+
[value]="s"
|
|
126
|
+
[checked]="value() === s"
|
|
127
|
+
[disabled]="isDisabled()"
|
|
128
|
+
(change)="choose(s)"
|
|
129
|
+
(click)="onClick(s)"
|
|
130
|
+
(blur)="onTouched()"
|
|
131
|
+
/>
|
|
132
|
+
<span class="mx-visually-hidden">{{ starLabel()(s) }}</span>
|
|
133
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path [attr.d]="star" /></svg>
|
|
134
|
+
</label>
|
|
135
|
+
}
|
|
136
|
+
</div>
|
|
137
|
+
}
|
|
138
|
+
@if (showValue() && (readonly() || value())) {
|
|
139
|
+
<span class="mx-rating-value" aria-hidden="true">{{ valueText() }}</span>
|
|
140
|
+
}
|
|
141
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
142
|
+
}
|
|
143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxRating, decorators: [{
|
|
144
|
+
type: Component,
|
|
145
|
+
args: [{
|
|
146
|
+
selector: 'mx-rating',
|
|
147
|
+
exportAs: 'mxRating',
|
|
148
|
+
providers: [{ provide: MX_FORM_FIELD_CONTROL, useExisting: MxRating }],
|
|
149
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
150
|
+
encapsulation: ViewEncapsulation.None,
|
|
151
|
+
host: {
|
|
152
|
+
class: 'mx-rating',
|
|
153
|
+
'[attr.data-size]': 'size() === "md" ? null : size()',
|
|
154
|
+
'[attr.data-readonly]': 'readonly() ? "" : null',
|
|
155
|
+
'[attr.data-disabled]': 'isDisabled() ? "" : null',
|
|
156
|
+
'[attr.data-invalid]': 'errorState() ? "" : null',
|
|
157
|
+
'[attr.aria-label]': 'null',
|
|
158
|
+
},
|
|
159
|
+
template: `
|
|
160
|
+
@if (readonly()) {
|
|
161
|
+
<span class="mx-rating-stars" role="img" [attr.aria-label]="readonlyLabel()">
|
|
162
|
+
@for (s of stars(); track s) {
|
|
163
|
+
<span class="mx-rating-star" aria-hidden="true">
|
|
164
|
+
<svg viewBox="0 0 24 24"><path [attr.d]="star" /></svg>
|
|
165
|
+
<span class="mx-rating-star-fill" [style.width.%]="fillPct(s)"><svg viewBox="0 0 24 24"><path [attr.d]="star" /></svg></span>
|
|
166
|
+
</span>
|
|
167
|
+
}
|
|
168
|
+
</span>
|
|
169
|
+
} @else {
|
|
170
|
+
<div
|
|
171
|
+
class="mx-rating-stars"
|
|
172
|
+
role="radiogroup"
|
|
173
|
+
[attr.aria-labelledby]="field?.labelId() ?? null"
|
|
174
|
+
[attr.aria-label]="field?.labelId() ? null : (ariaLabel() ?? 'Avaliação')"
|
|
175
|
+
[attr.aria-describedby]="field?.describedBy() ?? null"
|
|
176
|
+
[attr.aria-required]="isRequired() ? 'true' : null"
|
|
177
|
+
[attr.aria-invalid]="errorState() ? 'true' : null"
|
|
178
|
+
(mouseleave)="hover.set(0)"
|
|
179
|
+
>
|
|
180
|
+
@for (s of stars(); track s) {
|
|
181
|
+
<label class="mx-rating-star" [attr.data-on]="s <= shown() ? '' : null" (mouseenter)="hover.set(isDisabled() ? 0 : s)">
|
|
182
|
+
<input
|
|
183
|
+
type="radio"
|
|
184
|
+
class="mx-rating-input"
|
|
185
|
+
[id]="s === 1 ? controlId() : null"
|
|
186
|
+
[name]="name"
|
|
187
|
+
[value]="s"
|
|
188
|
+
[checked]="value() === s"
|
|
189
|
+
[disabled]="isDisabled()"
|
|
190
|
+
(change)="choose(s)"
|
|
191
|
+
(click)="onClick(s)"
|
|
192
|
+
(blur)="onTouched()"
|
|
193
|
+
/>
|
|
194
|
+
<span class="mx-visually-hidden">{{ starLabel()(s) }}</span>
|
|
195
|
+
<svg viewBox="0 0 24 24" aria-hidden="true"><path [attr.d]="star" /></svg>
|
|
196
|
+
</label>
|
|
197
|
+
}
|
|
198
|
+
</div>
|
|
199
|
+
}
|
|
200
|
+
@if (showValue() && (readonly() || value())) {
|
|
201
|
+
<span class="mx-rating-value" aria-hidden="true">{{ valueText() }}</span>
|
|
202
|
+
}
|
|
203
|
+
`,
|
|
204
|
+
}]
|
|
205
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], starLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "starLabel", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }] } });
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Generated bundle index. Do not edit.
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
export { MxRating };
|
|
212
|
+
//# sourceMappingURL=muxima-ui-core-rating.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"muxima-ui-core-rating.mjs","sources":["../../../projects/core/rating/rating.ts","../../../projects/core/rating/muxima-ui-core-rating.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n numberAttribute,\n signal,\n} from '@angular/core';\nimport { ControlValueAccessor, NgControl, Validators } from '@angular/forms';\nimport { MX_FORM_FIELD_CONTROL, MxFormField, MxFormFieldControl, mxUniqueId } from '@muxima-ui/core/form-field';\n\nconst STAR = 'M12 3.2l2.7 5.6 6.1.8-4.5 4.2 1.1 6.1L12 17l-5.4 2.9 1.1-6.1-4.5-4.2 6.1-.8z';\n\n/**\n * Avaliação com estrelas. Para escolher, são botões de rádio nativos (setas mudam a nota,\n * Tab sai do grupo); em `readonly` é uma imagem com o texto \"4 de 5 estrelas\".\n *\n * ```html\n * <mx-form-field>\n * <label mxLabel>Como correu o atendimento?</label>\n * <mx-rating formControlName=\"nota\" />\n * </mx-form-field>\n * <mx-rating [value]=\"4.5\" readonly />\n * ```\n */\n@Component({\n selector: 'mx-rating',\n exportAs: 'mxRating',\n providers: [{ provide: MX_FORM_FIELD_CONTROL, useExisting: MxRating }],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'mx-rating',\n '[attr.data-size]': 'size() === \"md\" ? null : size()',\n '[attr.data-readonly]': 'readonly() ? \"\" : null',\n '[attr.data-disabled]': 'isDisabled() ? \"\" : null',\n '[attr.data-invalid]': 'errorState() ? \"\" : null',\n '[attr.aria-label]': 'null',\n },\n template: `\n @if (readonly()) {\n <span class=\"mx-rating-stars\" role=\"img\" [attr.aria-label]=\"readonlyLabel()\">\n @for (s of stars(); track s) {\n <span class=\"mx-rating-star\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\"><path [attr.d]=\"star\" /></svg>\n <span class=\"mx-rating-star-fill\" [style.width.%]=\"fillPct(s)\"><svg viewBox=\"0 0 24 24\"><path [attr.d]=\"star\" /></svg></span>\n </span>\n }\n </span>\n } @else {\n <div\n class=\"mx-rating-stars\"\n role=\"radiogroup\"\n [attr.aria-labelledby]=\"field?.labelId() ?? null\"\n [attr.aria-label]=\"field?.labelId() ? null : (ariaLabel() ?? 'Avaliação')\"\n [attr.aria-describedby]=\"field?.describedBy() ?? null\"\n [attr.aria-required]=\"isRequired() ? 'true' : null\"\n [attr.aria-invalid]=\"errorState() ? 'true' : null\"\n (mouseleave)=\"hover.set(0)\"\n >\n @for (s of stars(); track s) {\n <label class=\"mx-rating-star\" [attr.data-on]=\"s <= shown() ? '' : null\" (mouseenter)=\"hover.set(isDisabled() ? 0 : s)\">\n <input\n type=\"radio\"\n class=\"mx-rating-input\"\n [id]=\"s === 1 ? controlId() : null\"\n [name]=\"name\"\n [value]=\"s\"\n [checked]=\"value() === s\"\n [disabled]=\"isDisabled()\"\n (change)=\"choose(s)\"\n (click)=\"onClick(s)\"\n (blur)=\"onTouched()\"\n />\n <span class=\"mx-visually-hidden\">{{ starLabel()(s) }}</span>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path [attr.d]=\"star\" /></svg>\n </label>\n }\n </div>\n }\n @if (showValue() && (readonly() || value())) {\n <span class=\"mx-rating-value\" aria-hidden=\"true\">{{ valueText() }}</span>\n }\n `,\n})\nexport class MxRating implements ControlValueAccessor, MxFormFieldControl {\n readonly value = model<number | null>(null);\n readonly max = input(5, { transform: numberAttribute });\n /** Só mostra a nota (aceita meias estrelas, ex.: 4,5). */\n readonly readonly = input(false, { transform: booleanAttribute });\n /** Carregar outra vez na nota escolhida limpa a avaliação. */\n readonly clearable = input(false, { transform: booleanAttribute });\n /** Mostra o número ao lado (\"4,5\"). */\n readonly showValue = input(false, { transform: booleanAttribute });\n readonly starLabel = input<(n: number) => string>((n) => (n === 1 ? '1 estrela' : `${n} estrelas`));\n readonly locale = input('pt-AO');\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly required = input(false, { transform: booleanAttribute });\n readonly invalid = input(false, { transform: booleanAttribute });\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 protected readonly star = STAR;\n protected readonly name = mxUniqueId('mx-rating');\n private readonly generatedId = mxUniqueId('mx-rating-input');\n readonly controlId = computed(() => this.id() ?? this.generatedId);\n protected readonly hover = signal(0);\n private readonly formDisabled = signal(false);\n protected readonly isDisabled = computed(() => this.disabled() || this.formDisabled());\n protected readonly stars = computed(() => Array.from({ length: this.max() }, (_, i) => i + 1));\n protected readonly shown = computed(() => this.hover() || this.value() || 0);\n protected readonly valueText = computed(() =>\n new Intl.NumberFormat(this.locale(), { maximumFractionDigits: 1 }).format(this.value() ?? 0),\n );\n protected readonly readonlyLabel = computed(() => `${this.valueText()} de ${this.max()} estrelas`);\n\n private onChange: (value: number | null) => void = () => {};\n protected onTouched: () => void = () => {};\n\n constructor() {\n if (this.ngControl) this.ngControl.valueAccessor = this;\n }\n\n protected fillPct(s: number): number {\n const v = this.value() ?? 0;\n return Math.max(0, Math.min(1, v - (s - 1))) * 100;\n }\n\n protected choose(s: number): void {\n this.set(s);\n }\n\n protected onClick(s: number): void {\n // um clique na nota já escolhida não dispara \"change\": limpa se clearable\n if (this.clearable() && this.value() === s) {\n this.set(null);\n this.hover.set(0);\n }\n }\n\n private set(v: number | null): void {\n this.value.set(v);\n this.onChange(v);\n }\n\n // ---- MxFormFieldControl ----\n errorState(): boolean {\n if (this.invalid()) 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: number | null): void {\n this.value.set(value ?? null);\n }\n registerOnChange(fn: (value: number | 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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"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { model, input, inject, DOCUMENT, DestroyRef, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, Directive, booleanAttribute, computed } from '@angular/core';
|
|
3
|
+
import { mxUniqueId } from '@muxima-ui/core/form-field';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Navegação lateral que recolhe para só ícones. O conteúdo fica dentro de um `<nav>`;
|
|
7
|
+
* recolhida, os nomes continuam lá para o leitor de ecrã e aparecem numa dica ao passar
|
|
8
|
+
* o rato ou com o foco.
|
|
9
|
+
*
|
|
10
|
+
* ```html
|
|
11
|
+
* <mx-sidebar [(collapsed)]="recolhida" aria-label="Principal">
|
|
12
|
+
* <div mxSidebarHeader>Kianda</div>
|
|
13
|
+
* <mx-sidebar-group label="Gestão">
|
|
14
|
+
* <li><a mxSidebarItem routerLink="/facturas" routerLinkActive ariaCurrentWhenActive="page">
|
|
15
|
+
* <svg mxSidebarIcon>...</svg><span mxSidebarLabel>Facturas</span>
|
|
16
|
+
* </a></li>
|
|
17
|
+
* </mx-sidebar-group>
|
|
18
|
+
* <div mxSidebarFooter>...</div>
|
|
19
|
+
* </mx-sidebar>
|
|
20
|
+
* <button mxSidebarToggle [sidebar]="menu">...</button>
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* O item da página actual leva aria-current="page" (o routerLinkActive faz isso com
|
|
24
|
+
* ariaCurrentWhenActive).
|
|
25
|
+
*/
|
|
26
|
+
class MxSidebar {
|
|
27
|
+
collapsed = model(false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
28
|
+
ariaLabel = input('Principal', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
|
|
29
|
+
/** `default` com fundo de superfície; `subtle` com o fundo do papel. */
|
|
30
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
31
|
+
id = input(mxUniqueId('mx-sidebar'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
32
|
+
doc = inject(DOCUMENT);
|
|
33
|
+
/** A dica vive no body, para não ser cortada nem deslocada por contentores da página. */
|
|
34
|
+
tipEl;
|
|
35
|
+
constructor() {
|
|
36
|
+
inject(DestroyRef).onDestroy(() => this.tipEl?.remove());
|
|
37
|
+
}
|
|
38
|
+
toggle() {
|
|
39
|
+
this.collapsed.update((c) => !c);
|
|
40
|
+
this.hideTip();
|
|
41
|
+
}
|
|
42
|
+
/** Mostra a dica de um item (só com a barra recolhida). */
|
|
43
|
+
showTip(el) {
|
|
44
|
+
if (!this.collapsed())
|
|
45
|
+
return;
|
|
46
|
+
const text = el.querySelector('.mx-sidebar-label')?.textContent?.trim() ||
|
|
47
|
+
el.getAttribute('aria-label') ||
|
|
48
|
+
'';
|
|
49
|
+
if (!text)
|
|
50
|
+
return;
|
|
51
|
+
const r = el.getBoundingClientRect();
|
|
52
|
+
if (!this.tipEl) {
|
|
53
|
+
this.tipEl = this.doc.createElement('div');
|
|
54
|
+
this.tipEl.className = 'mx-tooltip mx-sidebar-tip';
|
|
55
|
+
this.tipEl.setAttribute('aria-hidden', 'true');
|
|
56
|
+
}
|
|
57
|
+
this.tipEl.textContent = text;
|
|
58
|
+
this.tipEl.style.top = `${r.top + r.height / 2}px`;
|
|
59
|
+
this.tipEl.style.left = `${r.right + 8}px`;
|
|
60
|
+
if (!this.tipEl.isConnected)
|
|
61
|
+
this.doc.body.appendChild(this.tipEl);
|
|
62
|
+
}
|
|
63
|
+
hideTip() {
|
|
64
|
+
this.tipEl?.remove();
|
|
65
|
+
}
|
|
66
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
67
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.25", type: MxSidebar, isStandalone: true, selector: "mx-sidebar", inputs: { collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { collapsed: "collapsedChange" }, host: { properties: { "id": "id()", "attr.data-collapsed": "collapsed() ? \"\" : null", "attr.data-variant": "variant() === \"default\" ? null : variant()", "attr.aria-label": "null" }, classAttribute: "mx-sidebar" }, exportAs: ["mxSidebar"], ngImport: i0, template: `
|
|
68
|
+
<ng-content select="[mxSidebarHeader]" />
|
|
69
|
+
<nav class="mx-sidebar-nav" [attr.aria-label]="ariaLabel()">
|
|
70
|
+
<ng-content />
|
|
71
|
+
</nav>
|
|
72
|
+
<ng-content select="[mxSidebarFooter]" />
|
|
73
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
74
|
+
}
|
|
75
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebar, decorators: [{
|
|
76
|
+
type: Component,
|
|
77
|
+
args: [{
|
|
78
|
+
selector: 'mx-sidebar',
|
|
79
|
+
exportAs: 'mxSidebar',
|
|
80
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
81
|
+
encapsulation: ViewEncapsulation.None,
|
|
82
|
+
host: {
|
|
83
|
+
class: 'mx-sidebar',
|
|
84
|
+
'[id]': 'id()',
|
|
85
|
+
'[attr.data-collapsed]': 'collapsed() ? "" : null',
|
|
86
|
+
'[attr.data-variant]': 'variant() === "default" ? null : variant()',
|
|
87
|
+
'[attr.aria-label]': 'null',
|
|
88
|
+
},
|
|
89
|
+
template: `
|
|
90
|
+
<ng-content select="[mxSidebarHeader]" />
|
|
91
|
+
<nav class="mx-sidebar-nav" [attr.aria-label]="ariaLabel()">
|
|
92
|
+
<ng-content />
|
|
93
|
+
</nav>
|
|
94
|
+
<ng-content select="[mxSidebarFooter]" />
|
|
95
|
+
`,
|
|
96
|
+
}]
|
|
97
|
+
}], ctorParameters: () => [], propDecorators: { collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }, { type: i0.Output, args: ["collapsedChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
98
|
+
/** Link ou botão da barra. Põe o texto em `mxSidebarLabel` e o ícone em `mxSidebarIcon`. */
|
|
99
|
+
class MxSidebarItem {
|
|
100
|
+
sidebar = inject(MxSidebar, { optional: true });
|
|
101
|
+
el = inject(ElementRef).nativeElement;
|
|
102
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
103
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: MxSidebarItem, isStandalone: true, selector: "a[mxSidebarItem], button[mxSidebarItem]", host: { listeners: { "mouseenter": "sidebar?.showTip(el)", "focus": "sidebar?.showTip(el)", "mouseleave": "sidebar?.hideTip()", "blur": "sidebar?.hideTip()" }, classAttribute: "mx-sidebar-item" }, exportAs: ["mxSidebarItem"], ngImport: i0 });
|
|
104
|
+
}
|
|
105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarItem, decorators: [{
|
|
106
|
+
type: Directive,
|
|
107
|
+
args: [{
|
|
108
|
+
selector: 'a[mxSidebarItem], button[mxSidebarItem]',
|
|
109
|
+
exportAs: 'mxSidebarItem',
|
|
110
|
+
host: {
|
|
111
|
+
class: 'mx-sidebar-item',
|
|
112
|
+
'(mouseenter)': 'sidebar?.showTip(el)',
|
|
113
|
+
'(focus)': 'sidebar?.showTip(el)',
|
|
114
|
+
'(mouseleave)': 'sidebar?.hideTip()',
|
|
115
|
+
'(blur)': 'sidebar?.hideTip()',
|
|
116
|
+
},
|
|
117
|
+
}]
|
|
118
|
+
}] });
|
|
119
|
+
class MxSidebarLabel {
|
|
120
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarLabel, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
121
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: MxSidebarLabel, isStandalone: true, selector: "[mxSidebarLabel]", host: { classAttribute: "mx-sidebar-label" }, ngImport: i0 });
|
|
122
|
+
}
|
|
123
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarLabel, decorators: [{
|
|
124
|
+
type: Directive,
|
|
125
|
+
args: [{ selector: '[mxSidebarLabel]', host: { class: 'mx-sidebar-label' } }]
|
|
126
|
+
}] });
|
|
127
|
+
class MxSidebarIcon {
|
|
128
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
129
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: MxSidebarIcon, isStandalone: true, selector: "[mxSidebarIcon]", host: { attributes: { "aria-hidden": "true" }, classAttribute: "mx-sidebar-icon" }, ngImport: i0 });
|
|
130
|
+
}
|
|
131
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarIcon, decorators: [{
|
|
132
|
+
type: Directive,
|
|
133
|
+
args: [{
|
|
134
|
+
selector: '[mxSidebarIcon]',
|
|
135
|
+
host: { class: 'mx-sidebar-icon', 'aria-hidden': 'true' },
|
|
136
|
+
}]
|
|
137
|
+
}] });
|
|
138
|
+
/** Contagem ou estado à direita do item; recolhida, passa a ponto. */
|
|
139
|
+
class MxSidebarBadge {
|
|
140
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarBadge, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
141
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: MxSidebarBadge, isStandalone: true, selector: "[mxSidebarBadge]", host: { classAttribute: "mx-sidebar-badge" }, ngImport: i0 });
|
|
142
|
+
}
|
|
143
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarBadge, decorators: [{
|
|
144
|
+
type: Directive,
|
|
145
|
+
args: [{ selector: '[mxSidebarBadge]', host: { class: 'mx-sidebar-badge' } }]
|
|
146
|
+
}] });
|
|
147
|
+
class MxSidebarHeader {
|
|
148
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
149
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: MxSidebarHeader, isStandalone: true, selector: "[mxSidebarHeader]", host: { classAttribute: "mx-sidebar-header" }, ngImport: i0 });
|
|
150
|
+
}
|
|
151
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarHeader, decorators: [{
|
|
152
|
+
type: Directive,
|
|
153
|
+
args: [{ selector: '[mxSidebarHeader]', host: { class: 'mx-sidebar-header' } }]
|
|
154
|
+
}] });
|
|
155
|
+
class MxSidebarFooter {
|
|
156
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarFooter, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
157
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.25", type: MxSidebarFooter, isStandalone: true, selector: "[mxSidebarFooter]", host: { classAttribute: "mx-sidebar-footer" }, ngImport: i0 });
|
|
158
|
+
}
|
|
159
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarFooter, decorators: [{
|
|
160
|
+
type: Directive,
|
|
161
|
+
args: [{ selector: '[mxSidebarFooter]', host: { class: 'mx-sidebar-footer' } }]
|
|
162
|
+
}] });
|
|
163
|
+
/**
|
|
164
|
+
* Grupo de itens com título. O título dá nome à lista (aria-labelledby); recolhida,
|
|
165
|
+
* o título fica escondido só visualmente. Os itens vão em `<li>`.
|
|
166
|
+
*/
|
|
167
|
+
class MxSidebarGroup {
|
|
168
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
169
|
+
labelId = mxUniqueId('mx-sidebar-group');
|
|
170
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
171
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxSidebarGroup, isStandalone: true, selector: "mx-sidebar-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "mx-sidebar-group" }, ngImport: i0, template: `
|
|
172
|
+
@if (label()) {
|
|
173
|
+
<p class="mx-sidebar-group-label" [id]="labelId">{{ label() }}</p>
|
|
174
|
+
}
|
|
175
|
+
<ul class="mx-sidebar-list" [attr.aria-labelledby]="label() ? labelId : null">
|
|
176
|
+
<ng-content />
|
|
177
|
+
</ul>
|
|
178
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
179
|
+
}
|
|
180
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarGroup, decorators: [{
|
|
181
|
+
type: Component,
|
|
182
|
+
args: [{
|
|
183
|
+
selector: 'mx-sidebar-group',
|
|
184
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
185
|
+
encapsulation: ViewEncapsulation.None,
|
|
186
|
+
host: { class: 'mx-sidebar-group' },
|
|
187
|
+
template: `
|
|
188
|
+
@if (label()) {
|
|
189
|
+
<p class="mx-sidebar-group-label" [id]="labelId">{{ label() }}</p>
|
|
190
|
+
}
|
|
191
|
+
<ul class="mx-sidebar-list" [attr.aria-labelledby]="label() ? labelId : null">
|
|
192
|
+
<ng-content />
|
|
193
|
+
</ul>
|
|
194
|
+
`,
|
|
195
|
+
}]
|
|
196
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
197
|
+
/**
|
|
198
|
+
* Secção que abre e fecha (botão com aria-expanded). Com a barra recolhida, carregar na
|
|
199
|
+
* secção expande a barra e abre a secção.
|
|
200
|
+
*
|
|
201
|
+
* ```html
|
|
202
|
+
* <li><mx-sidebar-section label="Relatórios" [(open)]="aberta">
|
|
203
|
+
* <svg mxSidebarIcon>...</svg>
|
|
204
|
+
* <li><a mxSidebarItem routerLink="/vendas"><span mxSidebarLabel>Vendas</span></a></li>
|
|
205
|
+
* </mx-sidebar-section></li>
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
class MxSidebarSection {
|
|
209
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
210
|
+
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
211
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
212
|
+
sidebar = inject(MxSidebar, { optional: true });
|
|
213
|
+
listId = mxUniqueId('mx-sidebar-section');
|
|
214
|
+
/** Recolhida, a secção não mostra os filhos. */
|
|
215
|
+
isOpen = computed(() => this.open() && !this.sidebar?.collapsed(), ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
216
|
+
toggle() {
|
|
217
|
+
if (this.sidebar?.collapsed()) {
|
|
218
|
+
this.sidebar.collapsed.set(false);
|
|
219
|
+
this.sidebar.hideTip();
|
|
220
|
+
this.open.set(true);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
this.open.update((o) => !o);
|
|
224
|
+
}
|
|
225
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
226
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.25", type: MxSidebarSection, isStandalone: true, selector: "mx-sidebar-section", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { properties: { "attr.data-open": "isOpen() ? \"\" : null" }, classAttribute: "mx-sidebar-section" }, ngImport: i0, template: `
|
|
227
|
+
<button
|
|
228
|
+
type="button"
|
|
229
|
+
mxSidebarItem
|
|
230
|
+
class="mx-sidebar-item mx-sidebar-section-trigger"
|
|
231
|
+
[attr.aria-expanded]="isOpen()"
|
|
232
|
+
[attr.aria-controls]="listId"
|
|
233
|
+
(click)="toggle()"
|
|
234
|
+
>
|
|
235
|
+
<ng-content select="[mxSidebarIcon]" />
|
|
236
|
+
<span class="mx-sidebar-label">{{ label() }}</span>
|
|
237
|
+
<svg class="mx-sidebar-chevron" viewBox="0 0 16 16" aria-hidden="true">
|
|
238
|
+
<path
|
|
239
|
+
d="M6 4l4 4-4 4"
|
|
240
|
+
fill="none"
|
|
241
|
+
stroke="currentColor"
|
|
242
|
+
stroke-width="1.5"
|
|
243
|
+
stroke-linecap="round"
|
|
244
|
+
stroke-linejoin="round"
|
|
245
|
+
/>
|
|
246
|
+
</svg>
|
|
247
|
+
</button>
|
|
248
|
+
<ul class="mx-sidebar-list mx-sidebar-sublist" [id]="listId" [hidden]="!isOpen()">
|
|
249
|
+
<ng-content />
|
|
250
|
+
</ul>
|
|
251
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: MxSidebarItem, selector: "a[mxSidebarItem], button[mxSidebarItem]", exportAs: ["mxSidebarItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
252
|
+
}
|
|
253
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarSection, decorators: [{
|
|
254
|
+
type: Component,
|
|
255
|
+
args: [{
|
|
256
|
+
selector: 'mx-sidebar-section',
|
|
257
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
258
|
+
encapsulation: ViewEncapsulation.None,
|
|
259
|
+
host: { class: 'mx-sidebar-section', '[attr.data-open]': 'isOpen() ? "" : null' },
|
|
260
|
+
template: `
|
|
261
|
+
<button
|
|
262
|
+
type="button"
|
|
263
|
+
mxSidebarItem
|
|
264
|
+
class="mx-sidebar-item mx-sidebar-section-trigger"
|
|
265
|
+
[attr.aria-expanded]="isOpen()"
|
|
266
|
+
[attr.aria-controls]="listId"
|
|
267
|
+
(click)="toggle()"
|
|
268
|
+
>
|
|
269
|
+
<ng-content select="[mxSidebarIcon]" />
|
|
270
|
+
<span class="mx-sidebar-label">{{ label() }}</span>
|
|
271
|
+
<svg class="mx-sidebar-chevron" viewBox="0 0 16 16" aria-hidden="true">
|
|
272
|
+
<path
|
|
273
|
+
d="M6 4l4 4-4 4"
|
|
274
|
+
fill="none"
|
|
275
|
+
stroke="currentColor"
|
|
276
|
+
stroke-width="1.5"
|
|
277
|
+
stroke-linecap="round"
|
|
278
|
+
stroke-linejoin="round"
|
|
279
|
+
/>
|
|
280
|
+
</svg>
|
|
281
|
+
</button>
|
|
282
|
+
<ul class="mx-sidebar-list mx-sidebar-sublist" [id]="listId" [hidden]="!isOpen()">
|
|
283
|
+
<ng-content />
|
|
284
|
+
</ul>
|
|
285
|
+
`,
|
|
286
|
+
imports: [MxSidebarItem],
|
|
287
|
+
}]
|
|
288
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
289
|
+
/**
|
|
290
|
+
* Botão que recolhe e expande a barra. Tem aria-expanded e aria-controls; o nome muda
|
|
291
|
+
* entre "Recolher menu" e "Expandir menu" (ou os textos que passares).
|
|
292
|
+
*/
|
|
293
|
+
class MxSidebarToggle {
|
|
294
|
+
sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
|
|
295
|
+
collapseLabel = input('Recolher menu', ...(ngDevMode ? [{ debugName: "collapseLabel" }] : /* istanbul ignore next */ []));
|
|
296
|
+
expandLabel = input('Expandir menu', ...(ngDevMode ? [{ debugName: "expandLabel" }] : /* istanbul ignore next */ []));
|
|
297
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarToggle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
298
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.25", type: MxSidebarToggle, isStandalone: true, selector: "button[mxSidebarToggle]", inputs: { sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null }, collapseLabel: { classPropertyName: "collapseLabel", publicName: "collapseLabel", isSignal: true, isRequired: false, transformFunction: null }, expandLabel: { classPropertyName: "expandLabel", publicName: "expandLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button" }, listeners: { "click": "sidebar().toggle()" }, properties: { "attr.aria-expanded": "!sidebar().collapsed()", "attr.aria-controls": "sidebar().id()", "attr.aria-label": "sidebar().collapsed() ? expandLabel() : collapseLabel()" }, classAttribute: "mx-sidebar-toggle" }, exportAs: ["mxSidebarToggle"], ngImport: i0 });
|
|
299
|
+
}
|
|
300
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxSidebarToggle, decorators: [{
|
|
301
|
+
type: Directive,
|
|
302
|
+
args: [{
|
|
303
|
+
selector: 'button[mxSidebarToggle]',
|
|
304
|
+
exportAs: 'mxSidebarToggle',
|
|
305
|
+
host: {
|
|
306
|
+
class: 'mx-sidebar-toggle',
|
|
307
|
+
type: 'button',
|
|
308
|
+
'[attr.aria-expanded]': '!sidebar().collapsed()',
|
|
309
|
+
'[attr.aria-controls]': 'sidebar().id()',
|
|
310
|
+
'[attr.aria-label]': 'sidebar().collapsed() ? expandLabel() : collapseLabel()',
|
|
311
|
+
'(click)': 'sidebar().toggle()',
|
|
312
|
+
},
|
|
313
|
+
}]
|
|
314
|
+
}], propDecorators: { sidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebar", required: true }] }], collapseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseLabel", required: false }] }], expandLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandLabel", required: false }] }] } });
|
|
315
|
+
const MX_SIDEBAR = [
|
|
316
|
+
MxSidebar,
|
|
317
|
+
MxSidebarItem,
|
|
318
|
+
MxSidebarLabel,
|
|
319
|
+
MxSidebarIcon,
|
|
320
|
+
MxSidebarBadge,
|
|
321
|
+
MxSidebarHeader,
|
|
322
|
+
MxSidebarFooter,
|
|
323
|
+
MxSidebarGroup,
|
|
324
|
+
MxSidebarSection,
|
|
325
|
+
MxSidebarToggle,
|
|
326
|
+
];
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Generated bundle index. Do not edit.
|
|
330
|
+
*/
|
|
331
|
+
|
|
332
|
+
export { MX_SIDEBAR, MxSidebar, MxSidebarBadge, MxSidebarFooter, MxSidebarGroup, MxSidebarHeader, MxSidebarIcon, MxSidebarItem, MxSidebarLabel, MxSidebarSection, MxSidebarToggle };
|
|
333
|
+
//# sourceMappingURL=muxima-ui-core-sidebar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"muxima-ui-core-sidebar.mjs","sources":["../../../projects/core/sidebar/sidebar.ts","../../../projects/core/sidebar/muxima-ui-core-sidebar.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DOCUMENT,\n DestroyRef,\n Directive,\n ElementRef,\n ViewEncapsulation,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n} from '@angular/core';\nimport { mxUniqueId } from '@muxima-ui/core/form-field';\n\n/**\n * Navegação lateral que recolhe para só ícones. O conteúdo fica dentro de um `<nav>`;\n * recolhida, os nomes continuam lá para o leitor de ecrã e aparecem numa dica ao passar\n * o rato ou com o foco.\n *\n * ```html\n * <mx-sidebar [(collapsed)]=\"recolhida\" aria-label=\"Principal\">\n * <div mxSidebarHeader>Kianda</div>\n * <mx-sidebar-group label=\"Gestão\">\n * <li><a mxSidebarItem routerLink=\"/facturas\" routerLinkActive ariaCurrentWhenActive=\"page\">\n * <svg mxSidebarIcon>...</svg><span mxSidebarLabel>Facturas</span>\n * </a></li>\n * </mx-sidebar-group>\n * <div mxSidebarFooter>...</div>\n * </mx-sidebar>\n * <button mxSidebarToggle [sidebar]=\"menu\">...</button>\n * ```\n *\n * O item da página actual leva aria-current=\"page\" (o routerLinkActive faz isso com\n * ariaCurrentWhenActive).\n */\n@Component({\n selector: 'mx-sidebar',\n exportAs: 'mxSidebar',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'mx-sidebar',\n '[id]': 'id()',\n '[attr.data-collapsed]': 'collapsed() ? \"\" : null',\n '[attr.data-variant]': 'variant() === \"default\" ? null : variant()',\n '[attr.aria-label]': 'null',\n },\n template: `\n <ng-content select=\"[mxSidebarHeader]\" />\n <nav class=\"mx-sidebar-nav\" [attr.aria-label]=\"ariaLabel()\">\n <ng-content />\n </nav>\n <ng-content select=\"[mxSidebarFooter]\" />\n `,\n})\nexport class MxSidebar {\n readonly collapsed = model(false);\n readonly ariaLabel = input('Principal', { alias: 'aria-label' });\n /** `default` com fundo de superfície; `subtle` com o fundo do papel. */\n readonly variant = input<'default' | 'subtle'>('default');\n readonly id = input(mxUniqueId('mx-sidebar'));\n\n private readonly doc = inject(DOCUMENT);\n /** A dica vive no body, para não ser cortada nem deslocada por contentores da página. */\n private tipEl?: HTMLElement;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.tipEl?.remove());\n }\n\n toggle(): void {\n this.collapsed.update((c) => !c);\n this.hideTip();\n }\n\n /** Mostra a dica de um item (só com a barra recolhida). */\n showTip(el: HTMLElement): void {\n if (!this.collapsed()) return;\n const text =\n el.querySelector('.mx-sidebar-label')?.textContent?.trim() ||\n el.getAttribute('aria-label') ||\n '';\n if (!text) return;\n const r = el.getBoundingClientRect();\n if (!this.tipEl) {\n this.tipEl = this.doc.createElement('div');\n this.tipEl.className = 'mx-tooltip mx-sidebar-tip';\n this.tipEl.setAttribute('aria-hidden', 'true');\n }\n this.tipEl.textContent = text;\n this.tipEl.style.top = `${r.top + r.height / 2}px`;\n this.tipEl.style.left = `${r.right + 8}px`;\n if (!this.tipEl.isConnected) this.doc.body.appendChild(this.tipEl);\n }\n hideTip(): void {\n this.tipEl?.remove();\n }\n}\n\n/** Link ou botão da barra. Põe o texto em `mxSidebarLabel` e o ícone em `mxSidebarIcon`. */\n@Directive({\n selector: 'a[mxSidebarItem], button[mxSidebarItem]',\n exportAs: 'mxSidebarItem',\n host: {\n class: 'mx-sidebar-item',\n '(mouseenter)': 'sidebar?.showTip(el)',\n '(focus)': 'sidebar?.showTip(el)',\n '(mouseleave)': 'sidebar?.hideTip()',\n '(blur)': 'sidebar?.hideTip()',\n },\n})\nexport class MxSidebarItem {\n protected readonly sidebar = inject(MxSidebar, { optional: true });\n protected readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n}\n\n@Directive({ selector: '[mxSidebarLabel]', host: { class: 'mx-sidebar-label' } })\nexport class MxSidebarLabel {}\n\n@Directive({\n selector: '[mxSidebarIcon]',\n host: { class: 'mx-sidebar-icon', 'aria-hidden': 'true' },\n})\nexport class MxSidebarIcon {}\n\n/** Contagem ou estado à direita do item; recolhida, passa a ponto. */\n@Directive({ selector: '[mxSidebarBadge]', host: { class: 'mx-sidebar-badge' } })\nexport class MxSidebarBadge {}\n\n@Directive({ selector: '[mxSidebarHeader]', host: { class: 'mx-sidebar-header' } })\nexport class MxSidebarHeader {}\n\n@Directive({ selector: '[mxSidebarFooter]', host: { class: 'mx-sidebar-footer' } })\nexport class MxSidebarFooter {}\n\n/**\n * Grupo de itens com título. O título dá nome à lista (aria-labelledby); recolhida,\n * o título fica escondido só visualmente. Os itens vão em `<li>`.\n */\n@Component({\n selector: 'mx-sidebar-group',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-sidebar-group' },\n template: `\n @if (label()) {\n <p class=\"mx-sidebar-group-label\" [id]=\"labelId\">{{ label() }}</p>\n }\n <ul class=\"mx-sidebar-list\" [attr.aria-labelledby]=\"label() ? labelId : null\">\n <ng-content />\n </ul>\n `,\n})\nexport class MxSidebarGroup {\n readonly label = input('');\n protected readonly labelId = mxUniqueId('mx-sidebar-group');\n}\n\n/**\n * Secção que abre e fecha (botão com aria-expanded). Com a barra recolhida, carregar na\n * secção expande a barra e abre a secção.\n *\n * ```html\n * <li><mx-sidebar-section label=\"Relatórios\" [(open)]=\"aberta\">\n * <svg mxSidebarIcon>...</svg>\n * <li><a mxSidebarItem routerLink=\"/vendas\"><span mxSidebarLabel>Vendas</span></a></li>\n * </mx-sidebar-section></li>\n * ```\n */\n@Component({\n selector: 'mx-sidebar-section',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'mx-sidebar-section', '[attr.data-open]': 'isOpen() ? \"\" : null' },\n template: `\n <button\n type=\"button\"\n mxSidebarItem\n class=\"mx-sidebar-item mx-sidebar-section-trigger\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-controls]=\"listId\"\n (click)=\"toggle()\"\n >\n <ng-content select=\"[mxSidebarIcon]\" />\n <span class=\"mx-sidebar-label\">{{ label() }}</span>\n <svg class=\"mx-sidebar-chevron\" viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M6 4l4 4-4 4\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </button>\n <ul class=\"mx-sidebar-list mx-sidebar-sublist\" [id]=\"listId\" [hidden]=\"!isOpen()\">\n <ng-content />\n </ul>\n `,\n imports: [MxSidebarItem],\n})\nexport class MxSidebarSection {\n readonly label = input.required<string>();\n readonly open = model(false);\n readonly disabled = input(false, { transform: booleanAttribute });\n private readonly sidebar = inject(MxSidebar, { optional: true });\n protected readonly listId = mxUniqueId('mx-sidebar-section');\n /** Recolhida, a secção não mostra os filhos. */\n protected readonly isOpen = computed(() => this.open() && !this.sidebar?.collapsed());\n\n protected toggle(): void {\n if (this.sidebar?.collapsed()) {\n this.sidebar.collapsed.set(false);\n this.sidebar.hideTip();\n this.open.set(true);\n return;\n }\n this.open.update((o) => !o);\n }\n}\n\n/**\n * Botão que recolhe e expande a barra. Tem aria-expanded e aria-controls; o nome muda\n * entre \"Recolher menu\" e \"Expandir menu\" (ou os textos que passares).\n */\n@Directive({\n selector: 'button[mxSidebarToggle]',\n exportAs: 'mxSidebarToggle',\n host: {\n class: 'mx-sidebar-toggle',\n type: 'button',\n '[attr.aria-expanded]': '!sidebar().collapsed()',\n '[attr.aria-controls]': 'sidebar().id()',\n '[attr.aria-label]': 'sidebar().collapsed() ? expandLabel() : collapseLabel()',\n '(click)': 'sidebar().toggle()',\n },\n})\nexport class MxSidebarToggle {\n readonly sidebar = input.required<MxSidebar>();\n readonly collapseLabel = input('Recolher menu');\n readonly expandLabel = input('Expandir menu');\n}\n\nexport const MX_SIDEBAR = [\n MxSidebar,\n MxSidebarItem,\n MxSidebarLabel,\n MxSidebarIcon,\n MxSidebarBadge,\n MxSidebarHeader,\n MxSidebarFooter,\n MxSidebarGroup,\n MxSidebarSection,\n MxSidebarToggle,\n] as const;\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|