@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.
Files changed (55) hide show
  1. package/README.md +12 -4
  2. package/fesm2022/muxima-ui-core-carousel.mjs +377 -0
  3. package/fesm2022/muxima-ui-core-carousel.mjs.map +1 -0
  4. package/fesm2022/muxima-ui-core-chips.mjs +349 -0
  5. package/fesm2022/muxima-ui-core-chips.mjs.map +1 -0
  6. package/fesm2022/muxima-ui-core-clipboard.mjs +110 -0
  7. package/fesm2022/muxima-ui-core-clipboard.mjs.map +1 -0
  8. package/fesm2022/muxima-ui-core-color-picker.mjs +755 -0
  9. package/fesm2022/muxima-ui-core-color-picker.mjs.map +1 -0
  10. package/fesm2022/muxima-ui-core-date-picker.mjs +494 -12
  11. package/fesm2022/muxima-ui-core-date-picker.mjs.map +1 -1
  12. package/fesm2022/muxima-ui-core-file-upload.mjs +392 -0
  13. package/fesm2022/muxima-ui-core-file-upload.mjs.map +1 -0
  14. package/fesm2022/muxima-ui-core-notification-center.mjs +487 -0
  15. package/fesm2022/muxima-ui-core-notification-center.mjs.map +1 -0
  16. package/fesm2022/muxima-ui-core-rating.mjs +212 -0
  17. package/fesm2022/muxima-ui-core-rating.mjs.map +1 -0
  18. package/fesm2022/muxima-ui-core-sidebar.mjs +333 -0
  19. package/fesm2022/muxima-ui-core-sidebar.mjs.map +1 -0
  20. package/fesm2022/muxima-ui-core-slider.mjs +211 -3
  21. package/fesm2022/muxima-ui-core-slider.mjs.map +1 -1
  22. package/fesm2022/muxima-ui-core-time-picker.mjs +389 -0
  23. package/fesm2022/muxima-ui-core-time-picker.mjs.map +1 -0
  24. package/fesm2022/muxima-ui-core-timeline.mjs +117 -0
  25. package/fesm2022/muxima-ui-core-timeline.mjs.map +1 -0
  26. package/fesm2022/muxima-ui-core.mjs +1 -1
  27. package/fesm2022/muxima-ui-core.mjs.map +1 -1
  28. package/package.json +41 -1
  29. package/styles/base.css +21 -1
  30. package/styles/components/carousel.css +113 -0
  31. package/styles/components/chips.css +170 -0
  32. package/styles/components/clipboard.css +52 -0
  33. package/styles/components/color-picker.css +207 -0
  34. package/styles/components/date-picker.css +135 -0
  35. package/styles/components/file-upload.css +164 -0
  36. package/styles/components/notification-center.css +220 -0
  37. package/styles/components/rating.css +89 -0
  38. package/styles/components/sidebar.css +211 -0
  39. package/styles/components/slider.css +111 -0
  40. package/styles/components/time-picker.css +39 -0
  41. package/styles/components/timeline.css +180 -0
  42. package/styles/muxima.css +10 -0
  43. package/types/muxima-ui-core-carousel.d.ts +72 -0
  44. package/types/muxima-ui-core-chips.d.ts +120 -0
  45. package/types/muxima-ui-core-clipboard.d.ts +42 -0
  46. package/types/muxima-ui-core-color-picker.d.ts +153 -0
  47. package/types/muxima-ui-core-date-picker.d.ts +130 -2
  48. package/types/muxima-ui-core-file-upload.d.ts +96 -0
  49. package/types/muxima-ui-core-notification-center.d.ts +91 -0
  50. package/types/muxima-ui-core-rating.d.ts +64 -0
  51. package/types/muxima-ui-core-sidebar.d.ts +115 -0
  52. package/types/muxima-ui-core-slider.d.ts +68 -6
  53. package/types/muxima-ui-core-time-picker.d.ts +83 -0
  54. package/types/muxima-ui-core-timeline.d.ts +59 -0
  55. package/types/muxima-ui-core.d.ts +1 -1
package/README.md CHANGED
@@ -30,9 +30,19 @@ Cada componente tem o seu ponto de entrada, para só importares o que usas:
30
30
  | `@muxima-ui/core/checkbox` | `MxCheckbox` |
31
31
  | `@muxima-ui/core/radio` | `MxRadio` |
32
32
  | `@muxima-ui/core/switch` | `MxSwitch` |
33
- | `@muxima-ui/core/slider` | `MxSlider` |
34
- | `@muxima-ui/core/date-picker` | `MxDatePicker`, `MxCalendar`, `mxParseDate`, `mxFormatDate` |
33
+ | `@muxima-ui/core/slider` | `MxSlider`, `MxRangeSlider` (dois cursores) |
34
+ | `@muxima-ui/core/date-picker` | `MxDatePicker`, `MxDateRangePicker`, `MxCalendar`, `mxDefaultRangePresets`, `mxDateRangeComplete`, `mxParseDate`, `mxFormatDate` |
35
+ | `@muxima-ui/core/time-picker` | `MxTimePicker`, `mxParseTime` |
35
36
  | `@muxima-ui/core/otp` | `MxOtp` |
37
+ | `@muxima-ui/core/chips` | `MxChip`, `MxChipToggle`, `MxTagInput` |
38
+ | `@muxima-ui/core/file-upload` | `MxFileUpload`, `mxFormatBytes` |
39
+ | `@muxima-ui/core/rating` | `MxRating` |
40
+ | `@muxima-ui/core/clipboard` | `MxCopy`, `MxCopyButton` |
41
+ | `@muxima-ui/core/color-picker` | `MxColorPicker`, `MxColorPanel`, `mxParseColor`, `mxColorName`, `mxContrast` |
42
+ | `@muxima-ui/core/sidebar` | `MX_SIDEBAR` |
43
+ | `@muxima-ui/core/timeline` | `MX_TIMELINE` |
44
+ | `@muxima-ui/core/carousel` | `MxCarousel`, `MxCarouselSlide` |
45
+ | `@muxima-ui/core/notification-center` | `MxNotificationCenter`, `MxNotificationBell`, `mxRelativeTime` |
36
46
  | `@muxima-ui/core/table` | `MX_TABLE`, `mxSortData` |
37
47
  | `@muxima-ui/core/card` | `MX_CARD` |
38
48
  | `@muxima-ui/core/badge` | `MxBadge` |
@@ -54,6 +64,4 @@ Cada componente tem o seu ponto de entrada, para só importares o que usas:
54
64
  | `@muxima-ui/core/skeleton` | `MxSkeleton` |
55
65
  | `@muxima-ui/core/toast` | `MxToast` |
56
66
 
57
- Time picker usa `input[type=time][mxInput]`, sem componente próprio.
58
-
59
67
  Licença MIT.
@@ -0,0 +1,377 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, inject, forwardRef, ElementRef, computed, ViewEncapsulation, ChangeDetectionStrategy, Component, model, numberAttribute, booleanAttribute, contentChildren, viewChild, signal, Injector, effect, afterNextRender, DestroyRef } from '@angular/core';
3
+
4
+ /** Um diapositivo. O carrossel dá-lhe o nome "2 de 5" e tira do teclado os que não se vêem. */
5
+ class MxCarouselSlide {
6
+ /** Nome próprio do diapositivo; por omissão "2 de 5". */
7
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
8
+ carousel = inject(forwardRef(() => MxCarousel));
9
+ el = inject(ElementRef).nativeElement;
10
+ index = computed(() => this.carousel.slides().indexOf(this), ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
11
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxCarouselSlide, deps: [], target: i0.ɵɵFactoryTarget.Component });
12
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.25", type: MxCarouselSlide, isStandalone: true, selector: "mx-carousel-slide", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group", "aria-roledescription": "diapositivo" }, properties: { "attr.aria-label": "label() || carousel.slideLabel(index())", "attr.inert": "carousel.isVisible(index()) ? null : \"\"", "attr.aria-hidden": "carousel.isVisible(index()) ? null : \"true\"" }, classAttribute: "mx-carousel-slide" }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13
+ }
14
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxCarouselSlide, decorators: [{
15
+ type: Component,
16
+ args: [{
17
+ selector: 'mx-carousel-slide',
18
+ changeDetection: ChangeDetectionStrategy.OnPush,
19
+ encapsulation: ViewEncapsulation.None,
20
+ host: {
21
+ class: 'mx-carousel-slide',
22
+ role: 'group',
23
+ 'aria-roledescription': 'diapositivo',
24
+ '[attr.aria-label]': 'label() || carousel.slideLabel(index())',
25
+ '[attr.inert]': 'carousel.isVisible(index()) ? null : ""',
26
+ '[attr.aria-hidden]': 'carousel.isVisible(index()) ? null : "true"',
27
+ },
28
+ template: `<ng-content />`,
29
+ }]
30
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
31
+ /**
32
+ * Carrossel acessível (padrão WAI-ARIA Carousel): botões anterior e seguinte, indicadores,
33
+ * deslizar com o dedo (scroll nativo com snap) e, opcionalmente, rotação automática com
34
+ * botão de pausa. A rotação pára com o rato ou o foco dentro e não arranca com
35
+ * "reduzir movimento" activo.
36
+ *
37
+ * ```html
38
+ * <mx-carousel aria-label="Novidades" [perView]="1" [autoplay]="6000">
39
+ * <mx-carousel-slide>...</mx-carousel-slide>
40
+ * <mx-carousel-slide>...</mx-carousel-slide>
41
+ * </mx-carousel>
42
+ * ```
43
+ */
44
+ class MxCarousel {
45
+ /** Índice do primeiro diapositivo visível. */
46
+ index = model(0, ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
47
+ /** Diapositivos visíveis de cada vez. */
48
+ perView = input(1, { ...(ngDevMode ? { debugName: "perView" } : /* istanbul ignore next */ {}), transform: numberAttribute });
49
+ /** Espaço entre diapositivos, em px. */
50
+ gap = input(16, { ...(ngDevMode ? { debugName: "gap" } : /* istanbul ignore next */ {}), transform: numberAttribute });
51
+ /** Ms entre diapositivos; 0 = sem rotação automática. */
52
+ autoplay = input(0, { ...(ngDevMode ? { debugName: "autoplay" } : /* istanbul ignore next */ {}), transform: numberAttribute });
53
+ /** Depois do último volta ao primeiro. */
54
+ loop = input(false, { ...(ngDevMode ? { debugName: "loop" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
55
+ indicators = input(true, { ...(ngDevMode ? { debugName: "indicators" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
56
+ /** Botões anterior e seguinte. Sem eles, dá à pessoa outra forma de mudar ([(index)]). */
57
+ controls = input(true, { ...(ngDevMode ? { debugName: "controls" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
58
+ prevLabel = input('Diapositivo anterior', ...(ngDevMode ? [{ debugName: "prevLabel" }] : /* istanbul ignore next */ []));
59
+ nextLabel = input('Diapositivo seguinte', ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
60
+ slides = contentChildren(MxCarouselSlide, ...(ngDevMode ? [{ debugName: "slides" }] : /* istanbul ignore next */ []));
61
+ viewport = viewChild.required('viewport');
62
+ reducedMotion = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
63
+ hovering = signal(false, ...(ngDevMode ? [{ debugName: "hovering" }] : /* istanbul ignore next */ []));
64
+ focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
65
+ /** Rotação ligada pela pessoa (botão de pausa). */
66
+ playing = signal(true, ...(ngDevMode ? [{ debugName: "playing" }] : /* istanbul ignore next */ []));
67
+ /** A rodar agora: ligada, sem rato nem foco dentro, e sem reduzir movimento. */
68
+ running = computed(() => !!this.autoplay() &&
69
+ this.playing() &&
70
+ !this.hovering() &&
71
+ !this.focused() &&
72
+ !this.reducedMotion, ...(ngDevMode ? [{ debugName: "running" }] : /* istanbul ignore next */ []));
73
+ lastIndex = computed(() => Math.max(0, this.slides().length - this.perView()), ...(ngDevMode ? [{ debugName: "lastIndex" }] : /* istanbul ignore next */ []));
74
+ pages = computed(() => Array.from({ length: this.lastIndex() + 1 }, (_, i) => i), ...(ngDevMode ? [{ debugName: "pages" }] : /* istanbul ignore next */ []));
75
+ scrollFrame = 0;
76
+ scrolling = false;
77
+ /** O índice mudou porque a pessoa deslizou: não volta a mexer no scroll. */
78
+ fromScroll = false;
79
+ injector = inject(Injector);
80
+ constructor() {
81
+ if (this.reducedMotion)
82
+ this.playing.set(false);
83
+ effect((onCleanup) => {
84
+ if (!this.running())
85
+ return;
86
+ const t = setInterval(() => this.next(true), this.autoplay());
87
+ onCleanup(() => clearInterval(t));
88
+ });
89
+ // o índice pode mudar por [(index)]: alinha o scroll
90
+ effect(() => {
91
+ const i = this.index();
92
+ if (this.fromScroll) {
93
+ this.fromScroll = false;
94
+ return;
95
+ }
96
+ if (!this.scrolling)
97
+ afterNextRender(() => this.scrollTo(i, false), { injector: this.injector });
98
+ });
99
+ inject(DestroyRef).onDestroy(() => cancelAnimationFrame(this.scrollFrame));
100
+ }
101
+ slideLabel(i) {
102
+ return `${i + 1} de ${this.slides().length}`;
103
+ }
104
+ isVisible(i) {
105
+ const start = this.index();
106
+ return i >= start && i < start + this.perView();
107
+ }
108
+ go(i) {
109
+ const target = Math.min(Math.max(i, 0), this.lastIndex());
110
+ this.index.set(target);
111
+ this.scrollTo(target, true);
112
+ }
113
+ next(auto = false) {
114
+ if (this.index() >= this.lastIndex()) {
115
+ if (this.loop() || auto)
116
+ this.go(0);
117
+ return;
118
+ }
119
+ this.go(this.index() + 1);
120
+ }
121
+ prev() {
122
+ if (this.index() === 0) {
123
+ if (this.loop())
124
+ this.go(this.lastIndex());
125
+ return;
126
+ }
127
+ this.go(this.index() - 1);
128
+ }
129
+ togglePlay() {
130
+ this.playing.update((p) => !p);
131
+ }
132
+ onFocusOut(event) {
133
+ const host = this.viewport().nativeElement.parentElement;
134
+ if (!host.contains(event.relatedTarget))
135
+ this.focused.set(false);
136
+ }
137
+ scrollTo(i, smooth) {
138
+ const vp = this.viewport().nativeElement;
139
+ const slide = this.slides()[i]?.el;
140
+ if (!slide)
141
+ return;
142
+ this.scrolling = true;
143
+ const first = this.slides()[0].el;
144
+ const left = slide.offsetLeft - first.offsetLeft;
145
+ if (typeof vp.scrollTo === 'function')
146
+ vp.scrollTo({ left, behavior: smooth && !this.reducedMotion ? 'smooth' : 'auto' });
147
+ else
148
+ vp.scrollLeft = left;
149
+ setTimeout(() => (this.scrolling = false), smooth ? 450 : 0);
150
+ }
151
+ onScroll() {
152
+ if (this.scrolling)
153
+ return;
154
+ cancelAnimationFrame(this.scrollFrame);
155
+ this.scrollFrame = requestAnimationFrame(() => {
156
+ const vp = this.viewport().nativeElement;
157
+ const slides = this.slides();
158
+ if (!slides.length)
159
+ return;
160
+ const step = slides.length > 1 ? slides[1].el.offsetLeft - slides[0].el.offsetLeft : vp.clientWidth;
161
+ const i = Math.min(Math.round(vp.scrollLeft / step), this.lastIndex());
162
+ if (i !== this.index()) {
163
+ this.fromScroll = true;
164
+ this.index.set(i);
165
+ }
166
+ });
167
+ }
168
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxCarousel, deps: [], target: i0.ɵɵFactoryTarget.Component });
169
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.25", type: MxCarousel, isStandalone: true, selector: "mx-carousel", inputs: { index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, perView: { classPropertyName: "perView", publicName: "perView", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, indicators: { classPropertyName: "indicators", publicName: "indicators", isSignal: true, isRequired: false, transformFunction: null }, controls: { classPropertyName: "controls", publicName: "controls", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { index: "indexChange" }, host: { attributes: { "role": "region", "aria-roledescription": "carrossel" }, listeners: { "mouseenter": "hovering.set(true)", "mouseleave": "hovering.set(false)", "focusin": "focused.set(true)", "focusout": "onFocusOut($event)" }, properties: { "attr.data-indicators": "indicators() ? \"\" : null", "style.--mx-carousel-per-view": "perView()", "style.--mx-carousel-gap.px": "gap()" }, classAttribute: "mx-carousel" }, queries: [{ propertyName: "slides", predicate: MxCarouselSlide, isSignal: true }], viewQueries: [{ propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true, isSignal: true }], exportAs: ["mxCarousel"], ngImport: i0, template: `
170
+ @if (autoplay()) {
171
+ <button
172
+ type="button"
173
+ class="mx-carousel-play"
174
+ [attr.aria-label]="
175
+ playing() ? 'Parar a rotação automática' : 'Iniciar a rotação automática'
176
+ "
177
+ (click)="togglePlay()"
178
+ >
179
+ @if (playing()) {
180
+ <svg viewBox="0 0 16 16" aria-hidden="true">
181
+ <path
182
+ d="M5.5 3.5v9M10.5 3.5v9"
183
+ fill="none"
184
+ stroke="currentColor"
185
+ stroke-width="1.6"
186
+ stroke-linecap="round"
187
+ />
188
+ </svg>
189
+ } @else {
190
+ <svg viewBox="0 0 16 16" aria-hidden="true">
191
+ <path d="M5 3.5l7 4.5-7 4.5z" fill="currentColor" />
192
+ </svg>
193
+ }
194
+ </button>
195
+ }
196
+ <div class="mx-carousel-viewport" #viewport (scroll)="onScroll()">
197
+ <div class="mx-carousel-track" [attr.aria-live]="running() ? 'off' : 'polite'">
198
+ <ng-content />
199
+ </div>
200
+ </div>
201
+ @if (controls() || indicators()) {
202
+ <div class="mx-carousel-nav">
203
+ @if (controls()) {
204
+ <button
205
+ type="button"
206
+ class="mx-carousel-button mx-carousel-prev"
207
+ [disabled]="!loop() && index() === 0"
208
+ [attr.aria-label]="prevLabel()"
209
+ (click)="prev()"
210
+ >
211
+ <svg viewBox="0 0 16 16" aria-hidden="true">
212
+ <path
213
+ d="M10 4L6 8l4 4"
214
+ fill="none"
215
+ stroke="currentColor"
216
+ stroke-width="1.5"
217
+ stroke-linecap="round"
218
+ stroke-linejoin="round"
219
+ />
220
+ </svg>
221
+ </button>
222
+ }
223
+ @if (indicators()) {
224
+ <div class="mx-carousel-dots" role="group" aria-label="Escolher diapositivo">
225
+ @for (p of pages(); track p) {
226
+ <button
227
+ type="button"
228
+ class="mx-carousel-dot"
229
+ [attr.aria-label]="'Diapositivo ' + (p + 1)"
230
+ [attr.aria-current]="p === index() ? 'true' : null"
231
+ (click)="go(p)"
232
+ ></button>
233
+ }
234
+ </div>
235
+ }
236
+ @if (controls()) {
237
+ <button
238
+ type="button"
239
+ class="mx-carousel-button mx-carousel-next"
240
+ [disabled]="!loop() && index() >= lastIndex()"
241
+ [attr.aria-label]="nextLabel()"
242
+ (click)="next()"
243
+ >
244
+ <svg viewBox="0 0 16 16" aria-hidden="true">
245
+ <path
246
+ d="M6 4l4 4-4 4"
247
+ fill="none"
248
+ stroke="currentColor"
249
+ stroke-width="1.5"
250
+ stroke-linecap="round"
251
+ stroke-linejoin="round"
252
+ />
253
+ </svg>
254
+ </button>
255
+ }
256
+ </div>
257
+ }
258
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
259
+ }
260
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.25", ngImport: i0, type: MxCarousel, decorators: [{
261
+ type: Component,
262
+ args: [{
263
+ selector: 'mx-carousel',
264
+ exportAs: 'mxCarousel',
265
+ changeDetection: ChangeDetectionStrategy.OnPush,
266
+ encapsulation: ViewEncapsulation.None,
267
+ host: {
268
+ class: 'mx-carousel',
269
+ role: 'region',
270
+ 'aria-roledescription': 'carrossel',
271
+ '[attr.data-indicators]': 'indicators() ? "" : null',
272
+ '[style.--mx-carousel-per-view]': 'perView()',
273
+ '[style.--mx-carousel-gap.px]': 'gap()',
274
+ '(mouseenter)': 'hovering.set(true)',
275
+ '(mouseleave)': 'hovering.set(false)',
276
+ '(focusin)': 'focused.set(true)',
277
+ '(focusout)': 'onFocusOut($event)',
278
+ },
279
+ template: `
280
+ @if (autoplay()) {
281
+ <button
282
+ type="button"
283
+ class="mx-carousel-play"
284
+ [attr.aria-label]="
285
+ playing() ? 'Parar a rotação automática' : 'Iniciar a rotação automática'
286
+ "
287
+ (click)="togglePlay()"
288
+ >
289
+ @if (playing()) {
290
+ <svg viewBox="0 0 16 16" aria-hidden="true">
291
+ <path
292
+ d="M5.5 3.5v9M10.5 3.5v9"
293
+ fill="none"
294
+ stroke="currentColor"
295
+ stroke-width="1.6"
296
+ stroke-linecap="round"
297
+ />
298
+ </svg>
299
+ } @else {
300
+ <svg viewBox="0 0 16 16" aria-hidden="true">
301
+ <path d="M5 3.5l7 4.5-7 4.5z" fill="currentColor" />
302
+ </svg>
303
+ }
304
+ </button>
305
+ }
306
+ <div class="mx-carousel-viewport" #viewport (scroll)="onScroll()">
307
+ <div class="mx-carousel-track" [attr.aria-live]="running() ? 'off' : 'polite'">
308
+ <ng-content />
309
+ </div>
310
+ </div>
311
+ @if (controls() || indicators()) {
312
+ <div class="mx-carousel-nav">
313
+ @if (controls()) {
314
+ <button
315
+ type="button"
316
+ class="mx-carousel-button mx-carousel-prev"
317
+ [disabled]="!loop() && index() === 0"
318
+ [attr.aria-label]="prevLabel()"
319
+ (click)="prev()"
320
+ >
321
+ <svg viewBox="0 0 16 16" aria-hidden="true">
322
+ <path
323
+ d="M10 4L6 8l4 4"
324
+ fill="none"
325
+ stroke="currentColor"
326
+ stroke-width="1.5"
327
+ stroke-linecap="round"
328
+ stroke-linejoin="round"
329
+ />
330
+ </svg>
331
+ </button>
332
+ }
333
+ @if (indicators()) {
334
+ <div class="mx-carousel-dots" role="group" aria-label="Escolher diapositivo">
335
+ @for (p of pages(); track p) {
336
+ <button
337
+ type="button"
338
+ class="mx-carousel-dot"
339
+ [attr.aria-label]="'Diapositivo ' + (p + 1)"
340
+ [attr.aria-current]="p === index() ? 'true' : null"
341
+ (click)="go(p)"
342
+ ></button>
343
+ }
344
+ </div>
345
+ }
346
+ @if (controls()) {
347
+ <button
348
+ type="button"
349
+ class="mx-carousel-button mx-carousel-next"
350
+ [disabled]="!loop() && index() >= lastIndex()"
351
+ [attr.aria-label]="nextLabel()"
352
+ (click)="next()"
353
+ >
354
+ <svg viewBox="0 0 16 16" aria-hidden="true">
355
+ <path
356
+ d="M6 4l4 4-4 4"
357
+ fill="none"
358
+ stroke="currentColor"
359
+ stroke-width="1.5"
360
+ stroke-linecap="round"
361
+ stroke-linejoin="round"
362
+ />
363
+ </svg>
364
+ </button>
365
+ }
366
+ </div>
367
+ }
368
+ `,
369
+ }]
370
+ }], ctorParameters: () => [], propDecorators: { index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }, { type: i0.Output, args: ["indexChange"] }], perView: [{ type: i0.Input, args: [{ isSignal: true, alias: "perView", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], indicators: [{ type: i0.Input, args: [{ isSignal: true, alias: "indicators", required: false }] }], controls: [{ type: i0.Input, args: [{ isSignal: true, alias: "controls", required: false }] }], prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], slides: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => MxCarouselSlide), { isSignal: true }] }], viewport: [{ type: i0.ViewChild, args: ['viewport', { isSignal: true }] }] } });
371
+
372
+ /**
373
+ * Generated bundle index. Do not edit.
374
+ */
375
+
376
+ export { MxCarousel, MxCarouselSlide };
377
+ //# sourceMappingURL=muxima-ui-core-carousel.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"muxima-ui-core-carousel.mjs","sources":["../../../projects/core/carousel/carousel.ts","../../../projects/core/carousel/muxima-ui-core-carousel.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n ViewEncapsulation,\n afterNextRender,\n booleanAttribute,\n computed,\n contentChildren,\n effect,\n forwardRef,\n inject,\n input,\n model,\n numberAttribute,\n signal,\n viewChild,\n} from '@angular/core';\n\n/** Um diapositivo. O carrossel dá-lhe o nome \"2 de 5\" e tira do teclado os que não se vêem. */\n@Component({\n selector: 'mx-carousel-slide',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'mx-carousel-slide',\n role: 'group',\n 'aria-roledescription': 'diapositivo',\n '[attr.aria-label]': 'label() || carousel.slideLabel(index())',\n '[attr.inert]': 'carousel.isVisible(index()) ? null : \"\"',\n '[attr.aria-hidden]': 'carousel.isVisible(index()) ? null : \"true\"',\n },\n template: `<ng-content />`,\n})\nexport class MxCarouselSlide {\n /** Nome próprio do diapositivo; por omissão \"2 de 5\". */\n readonly label = input('');\n protected readonly carousel = inject(forwardRef(() => MxCarousel));\n readonly el = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n protected readonly index = computed(() => this.carousel.slides().indexOf(this));\n}\n\n/**\n * Carrossel acessível (padrão WAI-ARIA Carousel): botões anterior e seguinte, indicadores,\n * deslizar com o dedo (scroll nativo com snap) e, opcionalmente, rotação automática com\n * botão de pausa. A rotação pára com o rato ou o foco dentro e não arranca com\n * \"reduzir movimento\" activo.\n *\n * ```html\n * <mx-carousel aria-label=\"Novidades\" [perView]=\"1\" [autoplay]=\"6000\">\n * <mx-carousel-slide>...</mx-carousel-slide>\n * <mx-carousel-slide>...</mx-carousel-slide>\n * </mx-carousel>\n * ```\n */\n@Component({\n selector: 'mx-carousel',\n exportAs: 'mxCarousel',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'mx-carousel',\n role: 'region',\n 'aria-roledescription': 'carrossel',\n '[attr.data-indicators]': 'indicators() ? \"\" : null',\n '[style.--mx-carousel-per-view]': 'perView()',\n '[style.--mx-carousel-gap.px]': 'gap()',\n '(mouseenter)': 'hovering.set(true)',\n '(mouseleave)': 'hovering.set(false)',\n '(focusin)': 'focused.set(true)',\n '(focusout)': 'onFocusOut($event)',\n },\n template: `\n @if (autoplay()) {\n <button\n type=\"button\"\n class=\"mx-carousel-play\"\n [attr.aria-label]=\"\n playing() ? 'Parar a rotação automática' : 'Iniciar a rotação automática'\n \"\n (click)=\"togglePlay()\"\n >\n @if (playing()) {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M5.5 3.5v9M10.5 3.5v9\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n />\n </svg>\n } @else {\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path d=\"M5 3.5l7 4.5-7 4.5z\" fill=\"currentColor\" />\n </svg>\n }\n </button>\n }\n <div class=\"mx-carousel-viewport\" #viewport (scroll)=\"onScroll()\">\n <div class=\"mx-carousel-track\" [attr.aria-live]=\"running() ? 'off' : 'polite'\">\n <ng-content />\n </div>\n </div>\n @if (controls() || indicators()) {\n <div class=\"mx-carousel-nav\">\n @if (controls()) {\n <button\n type=\"button\"\n class=\"mx-carousel-button mx-carousel-prev\"\n [disabled]=\"!loop() && index() === 0\"\n [attr.aria-label]=\"prevLabel()\"\n (click)=\"prev()\"\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <path\n d=\"M10 4L6 8l4 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 }\n @if (indicators()) {\n <div class=\"mx-carousel-dots\" role=\"group\" aria-label=\"Escolher diapositivo\">\n @for (p of pages(); track p) {\n <button\n type=\"button\"\n class=\"mx-carousel-dot\"\n [attr.aria-label]=\"'Diapositivo ' + (p + 1)\"\n [attr.aria-current]=\"p === index() ? 'true' : null\"\n (click)=\"go(p)\"\n ></button>\n }\n </div>\n }\n @if (controls()) {\n <button\n type=\"button\"\n class=\"mx-carousel-button mx-carousel-next\"\n [disabled]=\"!loop() && index() >= lastIndex()\"\n [attr.aria-label]=\"nextLabel()\"\n (click)=\"next()\"\n >\n <svg 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 }\n </div>\n }\n `,\n})\nexport class MxCarousel {\n /** Índice do primeiro diapositivo visível. */\n readonly index = model(0);\n /** Diapositivos visíveis de cada vez. */\n readonly perView = input(1, { transform: numberAttribute });\n /** Espaço entre diapositivos, em px. */\n readonly gap = input(16, { transform: numberAttribute });\n /** Ms entre diapositivos; 0 = sem rotação automática. */\n readonly autoplay = input(0, { transform: numberAttribute });\n /** Depois do último volta ao primeiro. */\n readonly loop = input(false, { transform: booleanAttribute });\n readonly indicators = input(true, { transform: booleanAttribute });\n /** Botões anterior e seguinte. Sem eles, dá à pessoa outra forma de mudar ([(index)]). */\n readonly controls = input(true, { transform: booleanAttribute });\n readonly prevLabel = input('Diapositivo anterior');\n readonly nextLabel = input('Diapositivo seguinte');\n\n readonly slides = contentChildren(MxCarouselSlide);\n private readonly viewport = viewChild.required<ElementRef<HTMLElement>>('viewport');\n private readonly reducedMotion =\n typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n protected readonly hovering = signal(false);\n protected readonly focused = signal(false);\n /** Rotação ligada pela pessoa (botão de pausa). */\n readonly playing = signal(true);\n /** A rodar agora: ligada, sem rato nem foco dentro, e sem reduzir movimento. */\n protected readonly running = computed(\n () =>\n !!this.autoplay() &&\n this.playing() &&\n !this.hovering() &&\n !this.focused() &&\n !this.reducedMotion,\n );\n protected readonly lastIndex = computed(() => Math.max(0, this.slides().length - this.perView()));\n protected readonly pages = computed(() =>\n Array.from({ length: this.lastIndex() + 1 }, (_, i) => i),\n );\n private scrollFrame = 0;\n private scrolling = false;\n /** O índice mudou porque a pessoa deslizou: não volta a mexer no scroll. */\n private fromScroll = false;\n private readonly injector = inject(Injector);\n\n constructor() {\n if (this.reducedMotion) this.playing.set(false);\n effect((onCleanup) => {\n if (!this.running()) return;\n const t = setInterval(() => this.next(true), this.autoplay());\n onCleanup(() => clearInterval(t));\n });\n // o índice pode mudar por [(index)]: alinha o scroll\n effect(() => {\n const i = this.index();\n if (this.fromScroll) {\n this.fromScroll = false;\n return;\n }\n if (!this.scrolling)\n afterNextRender(() => this.scrollTo(i, false), { injector: this.injector });\n });\n inject(DestroyRef).onDestroy(() => cancelAnimationFrame(this.scrollFrame));\n }\n\n slideLabel(i: number): string {\n return `${i + 1} de ${this.slides().length}`;\n }\n isVisible(i: number): boolean {\n const start = this.index();\n return i >= start && i < start + this.perView();\n }\n\n go(i: number): void {\n const target = Math.min(Math.max(i, 0), this.lastIndex());\n this.index.set(target);\n this.scrollTo(target, true);\n }\n next(auto = false): void {\n if (this.index() >= this.lastIndex()) {\n if (this.loop() || auto) this.go(0);\n return;\n }\n this.go(this.index() + 1);\n }\n prev(): void {\n if (this.index() === 0) {\n if (this.loop()) this.go(this.lastIndex());\n return;\n }\n this.go(this.index() - 1);\n }\n togglePlay(): void {\n this.playing.update((p) => !p);\n }\n\n protected onFocusOut(event: FocusEvent): void {\n const host = this.viewport().nativeElement.parentElement!;\n if (!host.contains(event.relatedTarget as Node)) this.focused.set(false);\n }\n\n private scrollTo(i: number, smooth: boolean): void {\n const vp = this.viewport().nativeElement;\n const slide = this.slides()[i]?.el;\n if (!slide) return;\n this.scrolling = true;\n const first = this.slides()[0].el;\n const left = slide.offsetLeft - first.offsetLeft;\n if (typeof vp.scrollTo === 'function')\n vp.scrollTo({ left, behavior: smooth && !this.reducedMotion ? 'smooth' : 'auto' });\n else vp.scrollLeft = left;\n setTimeout(() => (this.scrolling = false), smooth ? 450 : 0);\n }\n\n protected onScroll(): void {\n if (this.scrolling) return;\n cancelAnimationFrame(this.scrollFrame);\n this.scrollFrame = requestAnimationFrame(() => {\n const vp = this.viewport().nativeElement;\n const slides = this.slides();\n if (!slides.length) return;\n const step =\n slides.length > 1 ? slides[1].el.offsetLeft - slides[0].el.offsetLeft : vp.clientWidth;\n const i = Math.min(Math.round(vp.scrollLeft / step), this.lastIndex());\n if (i !== this.index()) {\n this.fromScroll = true;\n this.index.set(i);\n }\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}