@factor_ec/ui 4.0.10 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +49 -10
  2. package/fesm2022/factor_ec-ui.mjs +617 -532
  3. package/fesm2022/factor_ec-ui.mjs.map +1 -1
  4. package/lib/avatar/avatar.component.d.ts +17 -0
  5. package/lib/chart.service.d.ts +18 -0
  6. package/lib/icon/icon.component.d.ts +14 -0
  7. package/lib/message.service.d.ts +14 -4
  8. package/lib/models/chart.d.ts +12 -0
  9. package/lib/models/ui-options.d.ts +9 -0
  10. package/lib/observe-intersecting.directive.d.ts +8 -9
  11. package/lib/progress/progress.component.d.ts +10 -0
  12. package/lib/ui.service.d.ts +9 -0
  13. package/package.json +7 -7
  14. package/public-api.d.ts +8 -8
  15. package/esm2022/factor_ec-ui.mjs +0 -5
  16. package/esm2022/lib/io/avatar/avatar.component.mjs +0 -75
  17. package/esm2022/lib/io/icon/icon.component.mjs +0 -96
  18. package/esm2022/lib/io/image/image.component.mjs +0 -84
  19. package/esm2022/lib/io/progress/progress.component.mjs +0 -43
  20. package/esm2022/lib/io/rating/rating.component.mjs +0 -74
  21. package/esm2022/lib/message-content/message-content.component.mjs +0 -20
  22. package/esm2022/lib/message-dialog/message-dialog.component.mjs +0 -33
  23. package/esm2022/lib/message.service.mjs +0 -60
  24. package/esm2022/lib/models/message-content.mjs +0 -2
  25. package/esm2022/lib/models/message-options.mjs +0 -2
  26. package/esm2022/lib/models/task.mjs +0 -2
  27. package/esm2022/lib/models/ui-configuration.mjs +0 -2
  28. package/esm2022/lib/nav/timeline/timeline.component.mjs +0 -102
  29. package/esm2022/lib/observe-intersecting.directive.mjs +0 -44
  30. package/esm2022/lib/progress.service.mjs +0 -48
  31. package/esm2022/public-api.mjs +0 -13
  32. package/lib/io/avatar/avatar.component.d.ts +0 -21
  33. package/lib/io/icon/icon.component.d.ts +0 -22
  34. package/lib/io/image/image.component.d.ts +0 -15
  35. package/lib/io/progress/progress.component.d.ts +0 -14
  36. package/lib/io/rating/rating.component.d.ts +0 -22
  37. package/lib/message-content/message-content.component.d.ts +0 -7
  38. package/lib/message-dialog/message-dialog.component.d.ts +0 -10
  39. package/lib/models/task.d.ts +0 -10
  40. package/lib/models/ui-configuration.d.ts +0 -7
  41. package/lib/nav/timeline/timeline.component.d.ts +0 -18
  42. package/lib/progress.service.d.ts +0 -15
  43. package/scss/components/avatar.scss +0 -15
  44. package/scss/components/collapsible.scss +0 -46
  45. package/scss/components/dropdown.scss +0 -56
  46. package/scss/components/icon.scss +0 -40
  47. package/scss/components/image.scss +0 -62
  48. package/scss/components/index.scss +0 -10
  49. package/scss/components/list.scss +0 -63
  50. package/scss/components/ph.scss +0 -27
  51. package/scss/components/popup.scss +0 -7
  52. package/scss/components/progress.scss +0 -119
  53. package/scss/components/rating.scss +0 -61
  54. package/scss/index.scss +0 -5
  55. package/scss/mixins/breakpoints.scss +0 -123
  56. package/scss/mixins.scss +0 -1
  57. package/scss/reboot.scss +0 -586
  58. package/scss/root.scss +0 -52
  59. package/scss/variables.scss +0 -116
@@ -1,569 +1,650 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, Input, HostBinding, Inject, EventEmitter, PLATFORM_ID, Directive, Output, Injectable, ApplicationRef } from '@angular/core';
3
- import * as i1$1 from '@angular/common';
4
- import { CommonModule, isPlatformBrowser } from '@angular/common';
5
- import * as i1 from '@factor_ec/utils';
6
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
7
- import { ReplaySubject } from 'rxjs';
8
- import * as i1$2 from '@angular/material/snack-bar';
9
- import { MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar';
10
- import * as i2$1 from '@angular/material/dialog';
11
- import { MAT_DIALOG_DATA } from '@angular/material/dialog';
2
+ import { inject, input, computed, signal, effect, Component, HostBinding, Injectable, InjectionToken, Inject, output, ElementRef, PLATFORM_ID, Directive } from '@angular/core';
3
+ import { ColorService, StringService } from '@factor_ec/utils';
4
+ import * as d3 from 'd3';
5
+ import * as i3 from '@angular/material/dialog';
6
+ import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
7
+ import { MAT_SNACK_BAR_DATA, MatSnackBarModule, MatSnackBar } from '@angular/material/snack-bar';
12
8
  import * as i2 from '@angular/material/button';
13
9
  import { MatButtonModule } from '@angular/material/button';
10
+ import { ReplaySubject } from 'rxjs';
11
+ import * as i1 from '@angular/common';
12
+ import { CommonModule, isPlatformBrowser } from '@angular/common';
14
13
 
15
14
  class AvatarComponent {
16
- set src(value) {
17
- if (value && value.trim() != '') {
18
- this._src = value;
19
- let image = new Image();
20
- image.src = value;
21
- image.onload = () => {
22
- if ("decode" in image) {
23
- image.decode().then(() => {
24
- this.loaded = true;
25
- });
26
- }
27
- else {
28
- console.error('Image.decode not available.');
29
- }
30
- };
31
- }
32
- }
33
- set label(value) {
34
- this._label = value;
35
- this.initials = this.getInitials(value);
36
- }
15
+ colorService = inject(ColorService);
16
+ color = input();
17
+ initials = computed(() => {
18
+ return this.getInitials(this.label());
19
+ });
20
+ label = input.required();
21
+ loaded = signal(false);
22
+ src = input();
37
23
  get backgroundColor() {
38
- return this.color || this.colorService.hex(this._label);
24
+ return this.color() || this.colorService.hex(this.label());
39
25
  }
40
26
  get backgroundImage() {
41
- return this._src ? `url(${this._src})` : '';
27
+ return this.src() ? `url(${this.src()})` : '';
42
28
  }
29
+ class = input();
43
30
  get hostClasses() {
44
- return [
45
- 'ft-avatar',
46
- this.class
47
- ].join(' ');
48
- }
49
- constructor(colorService) {
50
- this.colorService = colorService;
51
- this.class = '';
31
+ return ['ft-avatar', this.class()].join(' ');
52
32
  }
53
- ngOnInit() {
33
+ constructor() {
34
+ // Usa `effect` para reaccionar a los cambios en el valor de `src`
35
+ effect(() => {
36
+ const value = this.src();
37
+ if (value && value.trim() !== '') {
38
+ const image = new Image();
39
+ image.src = value;
40
+ image.onload = () => {
41
+ if ('decode' in image) {
42
+ image.decode().then(() => {
43
+ this.loaded.set(true);
44
+ });
45
+ }
46
+ else {
47
+ console.error('Image.decode not available.');
48
+ }
49
+ };
50
+ }
51
+ });
54
52
  }
55
53
  getInitials(value) {
56
- let allInitials = value.match(/\b\w/g) || [];
57
- let initials = ((allInitials.shift() || '') + (allInitials.pop() || '')).toUpperCase();
54
+ const allInitials = value.match(/\b\w/g) || [];
55
+ const initials = ((allInitials.shift() || '') + (allInitials.pop() || '')).toUpperCase();
58
56
  return initials;
59
57
  }
60
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: AvatarComponent, deps: [{ token: i1.ColorService }], target: i0.ɵɵFactoryTarget.Component }); }
61
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: AvatarComponent, isStandalone: true, selector: "ft-avatar", inputs: { color: "color", src: "src", label: "label", class: "class" }, host: { properties: { "style.background-color": "this.backgroundColor", "style.background-image": "this.backgroundImage", "class": "this.hostClasses" } }, ngImport: i0, template: "<div *ngIf=\"!loaded\">{{ initials }}</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
58
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
59
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: AvatarComponent, isStandalone: true, selector: "ft-avatar", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.background-color": "this.backgroundColor", "style.background-image": "this.backgroundImage", "class": "this.hostClasses" } }, ngImport: i0, template: "@if (!loaded()) {\n<div>{{ initials() }}</div>\n}", styles: [":host{display:inline-flex;align-items:center;justify-content:center;color:var(--ft-avatar-color);background-color:var(--ft-avatar-bg);background-size:cover;background-repeat:no-repeat;border-radius:calc(var(--ft-avatar-size) / 2);font-size:calc(var(--ft-avatar-size) - var(--ft-avatar-size) * .6);min-width:var(--ft-avatar-size);min-height:var(--ft-avatar-size);cursor:default;-webkit-user-select:none;user-select:none}\n"] });
62
60
  }
63
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: AvatarComponent, decorators: [{
61
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: AvatarComponent, decorators: [{
64
62
  type: Component,
65
- args: [{ selector: 'ft-avatar', standalone: true, imports: [CommonModule], template: "<div *ngIf=\"!loaded\">{{ initials }}</div>" }]
66
- }], ctorParameters: function () { return [{ type: i1.ColorService }]; }, propDecorators: { color: [{
67
- type: Input
68
- }], src: [{
69
- type: Input
70
- }], label: [{
71
- type: Input
72
- }], backgroundColor: [{
63
+ args: [{ selector: 'ft-avatar', standalone: true, imports: [], template: "@if (!loaded()) {\n<div>{{ initials() }}</div>\n}", styles: [":host{display:inline-flex;align-items:center;justify-content:center;color:var(--ft-avatar-color);background-color:var(--ft-avatar-bg);background-size:cover;background-repeat:no-repeat;border-radius:calc(var(--ft-avatar-size) / 2);font-size:calc(var(--ft-avatar-size) - var(--ft-avatar-size) * .6);min-width:var(--ft-avatar-size);min-height:var(--ft-avatar-size);cursor:default;-webkit-user-select:none;user-select:none}\n"] }]
64
+ }], ctorParameters: () => [], propDecorators: { backgroundColor: [{
73
65
  type: HostBinding,
74
66
  args: ['style.background-color']
75
67
  }], backgroundImage: [{
76
68
  type: HostBinding,
77
69
  args: ['style.background-image']
78
- }], class: [{
79
- type: Input
80
70
  }], hostClasses: [{
81
71
  type: HostBinding,
82
72
  args: ['class']
83
73
  }] } });
84
74
 
85
- class IconComponent {
86
- set collection(collection) {
87
- this._collection = collection;
88
- this.update();
75
+ class ChartService {
76
+ resizeTimeout;
77
+ charts = new Map();
78
+ constructor() {
79
+ window.addEventListener('resize', this.handleResize.bind(this));
89
80
  }
90
- set mode(mode) {
91
- this._mode = mode;
92
- this.update();
81
+ remove(element) {
82
+ this.charts.delete(element);
93
83
  }
94
- set name(name) {
95
- this._name = name;
96
- this.update();
84
+ render(element, items) {
85
+ // Clear svg
86
+ const svg = d3.select(element).html('');
87
+ // Resize event
88
+ if (!this.charts.has(element)) {
89
+ this.charts.set(element, items);
90
+ }
91
+ const values = [0];
92
+ items.forEach((item) => {
93
+ item.data.forEach((i) => {
94
+ if (typeof i[item.field] === 'number') {
95
+ values.push(i[item.field]);
96
+ }
97
+ });
98
+ });
99
+ if (values.length > 0) {
100
+ const domain = d3.extent(values);
101
+ // Dibujo los gráficos
102
+ items.forEach((item) => {
103
+ switch (item.type) {
104
+ case 'limit':
105
+ this.drawLimitChart(svg, { ...item, domain });
106
+ break;
107
+ case 'column':
108
+ this.drawColumnChart(svg, { ...item, domain });
109
+ break;
110
+ case 'line':
111
+ this.drawLineChart(svg, { ...item, domain });
112
+ break;
113
+ case 'circle':
114
+ this.drawCircleChart(svg, { ...item, domain });
115
+ break;
116
+ case 'event':
117
+ this.drawEventsPlaceholder(svg, { ...item, domain });
118
+ break;
119
+ }
120
+ });
121
+ }
97
122
  }
98
- set path(path) {
99
- this._path = path;
100
- this.update();
123
+ drawAxis(svg, values, domain) {
124
+ const element = svg.node()?.getBoundingClientRect();
125
+ const yScale = d3
126
+ .scaleLinear()
127
+ .domain(domain)
128
+ .range([element?.height || 0 - 4, 4]);
129
+ // Dibuja el eje en X
130
+ svg.select('.x-axis').remove();
131
+ svg
132
+ .append('rect')
133
+ .attr('class', 'x-axis')
134
+ .attr('fill', 'rgba(0, 0, 0, 0.08)')
135
+ .attr('x', 0)
136
+ .attr('width', element?.width || 0)
137
+ .attr('height', 1)
138
+ .attr('shape-rendering', 'crispEdges')
139
+ .attr('y', yScale(0));
140
+ /*
141
+ const yScale = d3.scaleLinear().domain([-5000, 8000]).range([this.height, 0]);
142
+ const yAxisGenerator = d3.axisLeft(yScale).ticks(8);
143
+ this.svg.append('g').call(yAxisGenerator).style('transform', 'translateX(50px)');
144
+ */
145
+ }
146
+ drawCircleChart(svg, options) {
147
+ const domRect = svg.node().getBoundingClientRect();
148
+ const xAccessor = (d) => d[options.categoryField];
149
+ const yAccessor = (d) => d[options.field] || 0;
150
+ const xScale = d3
151
+ .scaleBand()
152
+ .domain(options.data.map(xAccessor))
153
+ .range([0, domRect.width])
154
+ .padding(typeof options.padding === 'number' ? options.padding : 0);
155
+ const yScale = d3
156
+ .scaleLinear()
157
+ .domain(options.domain ?? [
158
+ Math.min(d3.min(options.data, yAccessor), 0),
159
+ d3.max(options.data, yAccessor),
160
+ ])
161
+ .range([domRect.height - 10, 10]);
162
+ const circles = svg
163
+ .append('g')
164
+ .attr('class', 'ft-chart__circle')
165
+ .selectAll(`circle`)
166
+ .data(options.data);
167
+ circles
168
+ .enter()
169
+ .append('circle')
170
+ .style('stroke', options.color ?? '#ff9800')
171
+ .attr('stroke-width', options.strokeWidth ?? 1)
172
+ .style('fill', 'var(--ft-body-bg)')
173
+ .attr('r', 1.5)
174
+ .merge(circles)
175
+ .attr('cx', (d) => Math.round((xScale(xAccessor(d)) || 0) + xScale.bandwidth() / 2))
176
+ .attr('cy', (d) => Math.round(yScale(yAccessor(d))));
177
+ circles.exit().remove();
178
+ }
179
+ drawColumnChart(svg, options) {
180
+ const element = svg.node().getBoundingClientRect();
181
+ const xAccessor = (d) => d[options.categoryField];
182
+ //const xAccessor = (d: any) => (new Date(d[options.categoryField]))?.getTime();
183
+ const yAccessor = (d) => d[options.field] || 0;
184
+ const xScale = d3
185
+ .scaleBand()
186
+ .domain(options.data.map(xAccessor))
187
+ .range([0, element.width])
188
+ .padding(options.padding ?? 0.5);
189
+ const yScale = d3
190
+ .scaleLinear()
191
+ .domain(options.domain
192
+ ? options.domain
193
+ : [
194
+ Math.min(d3.min(options.data, yAccessor), 0),
195
+ d3.max(options.data, yAccessor),
196
+ ])
197
+ .range([element.height - 4, 4]);
198
+ const columns = svg
199
+ .append('g')
200
+ .attr('class', 'ft-chart__column')
201
+ .selectAll('rect')
202
+ .data(options.data);
203
+ columns
204
+ .enter()
205
+ .append('rect')
206
+ .attr('x', (d) => xScale(xAccessor(d)))
207
+ .attr('y', (d) => yScale(yAccessor(d)))
208
+ .attr('shape-rendering', 'crispEdges')
209
+ .attr('fill', options.color ?? '#ff9800')
210
+ .attr('title', (d) => d[options.field])
211
+ .merge(columns)
212
+ .attr('width', Math.max(1, xScale.bandwidth()))
213
+ .attr('height', (d) => Math.abs(yScale(yAccessor(d)) - yScale(0)));
214
+ columns.exit().remove();
215
+ }
216
+ drawLineChart(svg, options) {
217
+ const domRect = svg.node().getBoundingClientRect();
218
+ const xAccessor = (d) => d[options.categoryField];
219
+ const yAccessor = (d) => d[options.field] || 0;
220
+ const xScale = d3
221
+ .scaleBand()
222
+ .domain(options.data.map(xAccessor))
223
+ .range([0, domRect.width])
224
+ .padding(typeof options.padding === 'number' ? options.padding : 0);
225
+ const yScale = d3
226
+ .scaleLinear()
227
+ .domain(options.domain ?? [
228
+ Math.min(d3.min(options.data, yAccessor), 0),
229
+ d3.max(options.data, yAccessor),
230
+ ])
231
+ .range([domRect.height - 10, 10]);
232
+ const lineGenerator = d3
233
+ .line()
234
+ .x((d) => Math.round((xScale(xAccessor(d)) || 0) + xScale.bandwidth() / 2))
235
+ .y((d) => Math.round(yScale(yAccessor(d))));
236
+ svg
237
+ .append('path')
238
+ .attr('class', 'ft-chart__line')
239
+ .attr('fill', 'none')
240
+ .attr('stroke', options.color ?? '#ff9800')
241
+ .attr('stroke-width', options.strokeWidth ?? 2)
242
+ .attr('stroke-linecap', 'round')
243
+ .attr('d', lineGenerator(options.data));
244
+ }
245
+ drawLimitChart(svg, options) {
246
+ const element = svg.node().getBoundingClientRect();
247
+ const yAccessor = (d) => d[options.field] || 0;
248
+ const yScale = d3
249
+ .scaleLinear()
250
+ .domain(options.domain
251
+ ? options.domain
252
+ : [
253
+ Math.min(d3.min(options.data, yAccessor), 0),
254
+ d3.max(options.data, yAccessor),
255
+ ])
256
+ .range([element.height - 4, 4]);
257
+ const line = svg.append('g').selectAll('rect').data([options.data[0]]);
258
+ line
259
+ .enter()
260
+ .append('rect')
261
+ .attr('x', 0)
262
+ .attr('y', (d) => yScale(yAccessor(d)) + 1)
263
+ .attr('shape-rendering', 'crispEdges')
264
+ .attr('fill', options.color ?? '#ff9800')
265
+ .attr('title', 0)
266
+ .attr('width', () => '100%')
267
+ .attr('height', 1);
268
+ line.exit().remove();
269
+ line
270
+ .enter()
271
+ .append('text')
272
+ .attr('style', 'font-weight: 600; font-size: var(--ft-text-font-size-sm);')
273
+ .attr('x', 0)
274
+ .attr('y', (d) => yScale(yAccessor(d)) + 16)
275
+ .attr('fill', 'var(--ft-danger-color)')
276
+ .text(options.label);
277
+ }
278
+ drawEventsPlaceholder(svg, options) {
279
+ const domRect = svg.node().getBoundingClientRect();
280
+ const xAccessor = (d) => d[options.categoryField];
281
+ const yAccessor = (d) => d[options.field] || 0;
282
+ const xScale = d3
283
+ .scaleBand()
284
+ .domain(options.data.map(xAccessor))
285
+ .range([0, domRect.width])
286
+ .padding(typeof options.padding === 'number' ? options.padding : 0);
287
+ const yScale = d3
288
+ .scaleLinear()
289
+ .domain(options.domain ?? [
290
+ Math.min(d3.min(options.data, yAccessor), 0),
291
+ d3.max(options.data, yAccessor),
292
+ ])
293
+ .range([domRect.height, 0]);
294
+ const columns = svg
295
+ .append('g')
296
+ .attr('class', 'ft-chart__placeholder')
297
+ .selectAll('rect')
298
+ .data(options.data);
299
+ columns
300
+ .enter()
301
+ .append('rect')
302
+ .attr('x', (d) => xScale(d[options.categoryField]))
303
+ .attr('y', () => 0)
304
+ .attr('shape-rendering', 'crispEdges')
305
+ .attr('fill', 'rgba(0,0,0,0)')
306
+ .attr('tabindex', 0)
307
+ .merge(columns)
308
+ .attr('width', Math.max(1, xScale.bandwidth()))
309
+ .attr('height', () => yScale(0))
310
+ .on('click', (event, d) => {
311
+ if (options.click) {
312
+ options.click(event, d);
313
+ }
314
+ });
315
+ columns.exit().remove();
101
316
  }
102
- get hostClasses() {
103
- return [
104
- 'ft-icon',
105
- this.class
106
- ].join(' ');
317
+ handleResize() {
318
+ clearTimeout(this.resizeTimeout);
319
+ this.resizeTimeout = setTimeout(() => {
320
+ for (const [element, items] of this.charts.entries()) {
321
+ this.render(element, items);
322
+ }
323
+ }, 300);
107
324
  }
108
- constructor(configuration) {
109
- this.configuration = configuration;
110
- this.class = '';
325
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ChartService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
326
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ChartService, providedIn: 'root' });
327
+ }
328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ChartService, decorators: [{
329
+ type: Injectable,
330
+ args: [{
331
+ providedIn: 'root',
332
+ }]
333
+ }], ctorParameters: () => [] });
334
+
335
+ const UI_OPTIONS = new InjectionToken('UI_OPTIONS');
336
+
337
+ class UiService {
338
+ options;
339
+ constructor(options) {
340
+ this.options = options;
111
341
  }
112
- ngOnInit() {
113
- this.update();
342
+ get() {
343
+ return this.options;
114
344
  }
115
- update() {
345
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: UiService, deps: [{ token: UI_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable });
346
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: UiService, providedIn: 'root' });
347
+ }
348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: UiService, decorators: [{
349
+ type: Injectable,
350
+ args: [{
351
+ providedIn: 'root'
352
+ }]
353
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
354
+ type: Inject,
355
+ args: [UI_OPTIONS]
356
+ }] }] });
357
+
358
+ class IconComponent {
359
+ options = inject(UiService);
360
+ collection = input();
361
+ mode = input();
362
+ name = input.required();
363
+ path = input();
364
+ src = input();
365
+ url = computed(() => {
366
+ let collection = this.collection();
367
+ let mode = this.mode();
368
+ let path = this.path();
369
+ const options = this.options.get().iconSettings;
116
370
  // Set the default collection if the mode is external
117
- if (!this._collection) {
118
- if (this.configuration.icon && this.configuration.icon.collection) {
119
- this._collection = this.configuration.icon.collection;
371
+ if (!this.collection()) {
372
+ if (options && options.collection) {
373
+ collection = options.collection;
120
374
  }
121
- else if (this._mode === 'external') {
122
- this._collection = 'icons';
375
+ else if (this.mode() === 'external') {
376
+ collection = 'icons';
123
377
  }
124
378
  }
125
- if (!this._mode) {
126
- if (this.configuration.icon && this.configuration.icon.mode) {
127
- this._mode = this.configuration.icon.mode;
379
+ if (!this.mode()) {
380
+ if (this.options.get().iconSettings && options.mode) {
381
+ mode = options.mode;
128
382
  }
129
383
  else {
130
- this._mode = 'external';
384
+ mode = 'external';
131
385
  }
132
386
  }
133
- if (this._mode === 'external') {
387
+ if (mode === 'external') {
134
388
  // If the icon mode is external
135
- if (!this._path) {
136
- if (this.configuration.icon && this.configuration.icon.path) {
137
- this._path = this.configuration.icon.path;
389
+ if (!this.path()) {
390
+ if (options && 'path' in options) {
391
+ path = options.path;
138
392
  }
139
393
  else {
140
- this._path = 'assets';
394
+ path = 'assets';
141
395
  }
142
396
  }
143
- this.url = `${this._path}/${this._collection}.svg#${this._name}`;
397
+ return `${path}/${collection}.svg#${this.name()}`;
144
398
  }
145
399
  else {
146
400
  // If the icon mode is inline
147
- const name = this._collection && this._collection !== 'unset' ? `${this._collection}--${this._name}` : this._name;
148
- this.url = `#${name}`;
401
+ const name = this.collection() && this.collection() !== 'unset'
402
+ ? `${this.collection()}--${this.name()}`
403
+ : this.name();
404
+ return `#${name}`;
149
405
  }
150
- }
151
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: IconComponent, deps: [{ token: 'FactorUiConfiguration' }], target: i0.ɵɵFactoryTarget.Component }); }
152
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: IconComponent, isStandalone: true, selector: "ft-icon", inputs: { collection: "collection", mode: "mode", name: "name", path: "path", src: "src", class: "class" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<svg *ngIf=\"!src; else imageTemplate\">\n <use attr.xlink:href=\"{{ url }}\" attr.href=\"{{ url }}\" />\n</svg>\n<ng-template #imageTemplate>\n <img [src]=\"src\" />\n</ng-template>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
153
- }
154
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: IconComponent, decorators: [{
155
- type: Component,
156
- args: [{ selector: 'ft-icon', standalone: true, imports: [CommonModule], template: "<svg *ngIf=\"!src; else imageTemplate\">\n <use attr.xlink:href=\"{{ url }}\" attr.href=\"{{ url }}\" />\n</svg>\n<ng-template #imageTemplate>\n <img [src]=\"src\" />\n</ng-template>" }]
157
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
158
- type: Inject,
159
- args: ['FactorUiConfiguration']
160
- }] }]; }, propDecorators: { collection: [{
161
- type: Input
162
- }], mode: [{
163
- type: Input
164
- }], name: [{
165
- type: Input
166
- }], path: [{
167
- type: Input
168
- }], src: [{
169
- type: Input
170
- }], class: [{
171
- type: Input
172
- }], hostClasses: [{
173
- type: HostBinding,
174
- args: ['class']
175
- }] } });
176
-
177
- class ImageComponent {
178
- constructor(element) {
179
- this.element = element;
180
- this.class = '';
181
- this.loading = false;
182
- this.shown = false;
183
- }
184
- ngOnInit() {
185
- if ("IntersectionObserver" in window) {
186
- let elementObserver = new IntersectionObserver((entries, observer) => {
187
- entries.forEach((entry) => {
188
- if (entry.isIntersecting) {
189
- let image = new Image();
190
- image.src = this.src;
191
- setTimeout(() => {
192
- if (!this.shown && !this.error) {
193
- this.loading = true;
194
- }
195
- }, 100);
196
- image.onerror = () => {
197
- this.error = true;
198
- this.loading = false;
199
- };
200
- image.onload = () => {
201
- if ("decode" in image) {
202
- image.decode().then(() => {
203
- this.loading = false;
204
- this.shown = true;
205
- });
206
- }
207
- else {
208
- this.loading = false;
209
- this.shown = true;
210
- }
211
- };
212
- elementObserver.unobserve(this.element.nativeElement);
213
- }
214
- });
215
- }, {
216
- rootMargin: "0px 0px 200px 0px"
217
- });
218
- elementObserver.observe(this.element.nativeElement);
219
- }
220
- else {
221
- console.error('IntersectionObserver not available.');
222
- this.loading = false;
223
- this.shown = true;
224
- }
225
- }
226
- get hostClasses() {
227
- return [
228
- 'ft-image',
229
- this.class
230
- ].join(' ');
231
- }
232
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ImageComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
233
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: ImageComponent, isStandalone: true, selector: "ft-image", inputs: { class: "class", src: "src" }, host: { properties: { "class.ft-image--error": "this.error", "class.ft-image--loading": "this.loading", "class": "this.hostClasses" } }, ngImport: i0, template: "<img *ngIf=\"shown\" [src]=\"src\" />\n<ft-icon name=\"warning\" size=\"2\" *ngIf=\"error\"></ft-icon>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconComponent, selector: "ft-icon", inputs: ["collection", "mode", "name", "path", "src", "class"] }] }); }
234
- }
235
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ImageComponent, decorators: [{
236
- type: Component,
237
- args: [{ selector: 'ft-image', standalone: true, imports: [
238
- CommonModule,
239
- IconComponent
240
- ], template: "<img *ngIf=\"shown\" [src]=\"src\" />\n<ft-icon name=\"warning\" size=\"2\" *ngIf=\"error\"></ft-icon>\n" }]
241
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { class: [{
242
- type: Input
243
- }], error: [{
244
- type: HostBinding,
245
- args: ['class.ft-image--error']
246
- }], loading: [{
247
- type: HostBinding,
248
- args: ['class.ft-image--loading']
249
- }], src: [{
250
- type: Input
251
- }], hostClasses: [{
252
- type: HostBinding,
253
- args: ['class']
254
- }] } });
255
-
256
- class ProgressComponent {
257
- constructor() {
258
- this.class = '';
259
- this.mode = 'indeterminate';
260
- this.overlay = false;
261
- }
262
- ngOnInit() {
263
- this.value = 0;
264
- }
406
+ });
407
+ class = input();
265
408
  get hostClasses() {
266
- return [
267
- 'ft-progress',
268
- this.overlay ? 'ft-progress--overlay' : '',
269
- this.class
270
- ].join(' ');
409
+ return ['ft-icon', this.class()].join(' ');
271
410
  }
272
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
273
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: ProgressComponent, isStandalone: true, selector: "ft-progress", inputs: { class: "class", color: "color", mode: "mode", overlay: "overlay", size: "size", value: "value" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<svg [ngStyle]=\"{'--ft-bar-color': color}\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid\">\n <circle class=\"ft-track\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle class=\"ft-bar\" [ngClass]=\"mode === 'determinate' ? 'ft-bar--determinate' : 'ft-bar--indeterminate'\" cx=\"50\"\n cy=\"50\" r=\"40\"\n [ngStyle]=\"{'stroke-dashoffset': mode=='determinate'? 'calc((3.14159265 * 40 * 2 * (100 - '+value+')) / 100)' : null}\">\n </circle>\n</svg>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); }
411
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
412
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: IconComponent, isStandalone: true, selector: "ft-icon", inputs: { collection: { classPropertyName: "collection", publicName: "collection", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, path: { classPropertyName: "path", publicName: "path", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "@if (!src()) {\n<svg>\n <use attr.href=\"{{ url() }}\" />\n</svg>\n} @else {\n<img [src]=\"src()\" alt=\"\" />\n}", styles: [":host{line-height:0;display:inline-block}:host svg{width:1em;height:1em;vertical-align:middle;fill:currentColor;display:inline-block}:host img{height:1em;vertical-align:middle;display:inline-block}:host.ft-icon--1{font-size:1rem}:host.ft-icon--2{font-size:1.5rem}:host.ft-icon--3{font-size:2rem}:host.ft-icon--4{font-size:3rem}:host.ft-icon--5{font-size:4.5rem}:host.ft-icon--6{font-size:8rem}:host.ft-icon--7{font-size:16rem}:host.ft-icon--8{font-size:32rem}\n"] });
274
413
  }
275
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ProgressComponent, decorators: [{
414
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: IconComponent, decorators: [{
276
415
  type: Component,
277
- args: [{ selector: 'ft-progress', standalone: true, imports: [CommonModule], template: "<svg [ngStyle]=\"{'--ft-bar-color': color}\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid\">\n <circle class=\"ft-track\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle class=\"ft-bar\" [ngClass]=\"mode === 'determinate' ? 'ft-bar--determinate' : 'ft-bar--indeterminate'\" cx=\"50\"\n cy=\"50\" r=\"40\"\n [ngStyle]=\"{'stroke-dashoffset': mode=='determinate'? 'calc((3.14159265 * 40 * 2 * (100 - '+value+')) / 100)' : null}\">\n </circle>\n</svg>" }]
278
- }], ctorParameters: function () { return []; }, propDecorators: { class: [{
279
- type: Input
280
- }], color: [{
281
- type: Input
282
- }], mode: [{
283
- type: Input
284
- }], overlay: [{
285
- type: Input
286
- }], size: [{
287
- type: Input
288
- }], value: [{
289
- type: Input
290
- }], hostClasses: [{
416
+ args: [{ selector: 'ft-icon', standalone: true, imports: [], template: "@if (!src()) {\n<svg>\n <use attr.href=\"{{ url() }}\" />\n</svg>\n} @else {\n<img [src]=\"src()\" alt=\"\" />\n}", styles: [":host{line-height:0;display:inline-block}:host svg{width:1em;height:1em;vertical-align:middle;fill:currentColor;display:inline-block}:host img{height:1em;vertical-align:middle;display:inline-block}:host.ft-icon--1{font-size:1rem}:host.ft-icon--2{font-size:1.5rem}:host.ft-icon--3{font-size:2rem}:host.ft-icon--4{font-size:3rem}:host.ft-icon--5{font-size:4.5rem}:host.ft-icon--6{font-size:8rem}:host.ft-icon--7{font-size:16rem}:host.ft-icon--8{font-size:32rem}\n"] }]
417
+ }], propDecorators: { hostClasses: [{
291
418
  type: HostBinding,
292
419
  args: ['class']
293
420
  }] } });
294
421
 
295
- class RatingComponent {
296
- constructor() {
297
- this.disabled = false;
298
- this.propagateChange = (_) => { };
299
- this.readOnly = false;
300
- this.stars = [
301
- { value: 1 },
302
- { value: 2 },
303
- { value: 3 },
304
- { value: 4 },
305
- { value: 5 }
306
- ];
307
- }
308
- ngOnInit() {
309
- }
310
- get value() {
311
- return this._value;
312
- }
313
- set value(value) {
314
- this._value = value;
315
- this.propagateChange(this._value);
316
- }
317
- registerOnChange(fn) {
318
- this.propagateChange = fn;
319
- }
320
- registerOnTouched(fn) {
321
- //this.propagateChange = fn;
322
- }
323
- setDisabledState(isDisabled) {
324
- this.disabled = isDisabled;
325
- }
326
- setRate(value, isHover) {
327
- if (isHover) {
328
- this.hoverValue = value;
329
- }
330
- else {
331
- this.value = value;
332
- }
333
- }
334
- updateValue(event) {
335
- this.value = event.target.value;
336
- }
337
- writeValue(value) {
338
- this.value = value;
339
- }
340
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: RatingComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
341
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: RatingComponent, isStandalone: true, selector: "ft-rating", inputs: { readOnly: "readOnly", value: "value" }, providers: [
342
- {
343
- provide: NG_VALUE_ACCESSOR,
344
- useExisting: RatingComponent,
345
- multi: true
346
- }
347
- ], ngImport: i0, template: "<ng-container *ngFor=\"let star of stars\">\n <ng-container *ngTemplateOutlet=\"!readOnly? buttonTemplate : starTemplate; context:{star:star}\"></ng-container>\n</ng-container>\n<ng-template #buttonTemplate let-star=\"star\">\n <button type=\"button\" class=\"ft-rating__item\" *ngIf=\"!readOnly; else starTemplate\" [disabled]=\"disabled\"\n (mouseover)=\"setRate(star.value, true)\" (focus)=\"setRate(star.value, true)\" (blur)=\"setRate(0, true)\"\n (mouseout)=\"setRate(0, true)\" (click)=\"setRate(star.value)\">\n <ng-container *ngTemplateOutlet=\"starTemplate; context:{star:star}\"></ng-container>\n </button>\n</ng-template>\n<ng-template #starTemplate let-star=\"star\">\n <svg [ngClass]=\"{'ft-rating__item-icon--hover': hoverValue >= star.value, 'ft-rating__item-icon--active': value >= star.value}\"\n viewBox=\"0 0 24 24\">\n <path\n d=\"M17.93 21.315c-.534.408-5.22-3.186-5.881-3.181-.663 0-5.307 3.656-5.846 3.254-.537-.403 1.29-6.165 1.081-6.822-.209-.656-4.972-4.138-4.772-4.796.201-.658 6.015-.627 6.55-1.036.533-.41 2.233-6.215 2.895-6.219.663 0 2.43 5.779 2.968 6.182.539.403 6.352.297 6.56.953.21.656-4.513 4.197-4.714 4.856-.2.658 1.692 6.398 1.159 6.808z\" />\n </svg>\n</ng-template>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
348
- }
349
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: RatingComponent, decorators: [{
350
- type: Component,
351
- args: [{ selector: 'ft-rating', standalone: true, imports: [CommonModule], providers: [
352
- {
353
- provide: NG_VALUE_ACCESSOR,
354
- useExisting: RatingComponent,
355
- multi: true
356
- }
357
- ], template: "<ng-container *ngFor=\"let star of stars\">\n <ng-container *ngTemplateOutlet=\"!readOnly? buttonTemplate : starTemplate; context:{star:star}\"></ng-container>\n</ng-container>\n<ng-template #buttonTemplate let-star=\"star\">\n <button type=\"button\" class=\"ft-rating__item\" *ngIf=\"!readOnly; else starTemplate\" [disabled]=\"disabled\"\n (mouseover)=\"setRate(star.value, true)\" (focus)=\"setRate(star.value, true)\" (blur)=\"setRate(0, true)\"\n (mouseout)=\"setRate(0, true)\" (click)=\"setRate(star.value)\">\n <ng-container *ngTemplateOutlet=\"starTemplate; context:{star:star}\"></ng-container>\n </button>\n</ng-template>\n<ng-template #starTemplate let-star=\"star\">\n <svg [ngClass]=\"{'ft-rating__item-icon--hover': hoverValue >= star.value, 'ft-rating__item-icon--active': value >= star.value}\"\n viewBox=\"0 0 24 24\">\n <path\n d=\"M17.93 21.315c-.534.408-5.22-3.186-5.881-3.181-.663 0-5.307 3.656-5.846 3.254-.537-.403 1.29-6.165 1.081-6.822-.209-.656-4.972-4.138-4.772-4.796.201-.658 6.015-.627 6.55-1.036.533-.41 2.233-6.215 2.895-6.219.663 0 2.43 5.779 2.968 6.182.539.403 6.352.297 6.56.953.21.656-4.513 4.197-4.714 4.856-.2.658 1.692 6.398 1.159 6.808z\" />\n </svg>\n</ng-template>" }]
358
- }], ctorParameters: function () { return []; }, propDecorators: { readOnly: [{
359
- type: Input
360
- }], value: [{
361
- type: Input
362
- }] } });
363
-
364
- class TimelineComponent {
365
- get hostClasses() {
366
- return [
367
- 'ft-timeline',
368
- this.class
369
- ].join(' ');
370
- }
371
- ;
372
- constructor() {
373
- this.startDate = new Date();
374
- this.data = [];
375
- this.dataParsed = {
376
- months: [],
377
- days: [],
378
- weekends: []
379
- };
380
- this.class = '';
381
- }
382
- ngOnInit() {
383
- this.addMonth(this.calcStartDate());
384
- }
385
- addMonth(date) {
386
- const month = this.getMonth(date.getMonth(), date.getFullYear());
387
- const currentDays = this.dataParsed.days.length;
388
- this.dataParsed.months = [...this.dataParsed.months, { date: month.days[0], daysInMonth: month.days.length }];
389
- this.dataParsed.days = [...this.dataParsed.days, ...month.days];
390
- this.dataParsed.weekends = [...this.dataParsed.weekends, ...month.weekends];
391
- if (!this.currentDate && month.currentDate) {
392
- this.currentDate = currentDays + month.currentDate;
393
- }
394
- this.dataParsed.days.some((day, index) => {
395
- if ([0, 6].includes(day.getDay())) {
396
- this.dataParsed.weekendStart = index;
397
- return true;
398
- }
399
- return false;
400
- });
401
- this.parseTasks();
402
- }
403
- calcStartDate() {
404
- return new Date();
405
- }
406
- getMonth(month, year) {
407
- const days = [];
408
- const weekends = [];
409
- let currentDate = null;
410
- let today = new Date();
411
- const date = new Date(year, month + 1, 0);
412
- for (let i = 1; i <= date.getDate(); i++) {
413
- const idate = new Date(year, month, i);
414
- if ([0, 6].includes(idate.getDay())) {
415
- if (idate.getDay() === 6) {
416
- weekends.push([idate]);
417
- }
418
- else {
419
- weekends[weekends.length - 1].push(idate);
420
- }
421
- }
422
- if (idate.getTime() === new Date(today.getFullYear(), today.getMonth(), today.getDate()).getTime()) {
423
- currentDate = i - 1;
424
- }
425
- days.push(idate);
426
- }
427
- const data = { days, weekends };
428
- if (currentDate) {
429
- data.currentDate = currentDate;
430
- }
431
- return data;
432
- }
433
- parseTasks() {
434
- let tasks = this.data.filter(task => task.endAt) /*.sort((a, b) => a.)*/;
435
- this.dataParsed.tasks = tasks.map((task) => {
436
- return {
437
- label: task.label,
438
- start: 10,
439
- type: task.type,
440
- size: 1
441
- };
442
- });
443
- }
444
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
445
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: TimelineComponent, isStandalone: true, selector: "ft-timeline", inputs: { data: "data", class: "class" }, host: { properties: { "style.--current-date": "this.currentDate", "class": "this.hostClasses" } }, ngImport: i0, template: "<div class=\"ft-weekends\" [style.--start]=\"dataParsed.weekendStart\">\n <div class=\"ft-weekends__item\" [style.--weekend-size]=\"weekend.length\" *ngFor=\"let weekend of dataParsed.weekends\">\n </div>\n</div>\n<div class=\"ft-current-date\" *ngIf=\"currentDate\"></div>\n<div class=\"ft-header\">\n <div class=\"ft-header__months\">\n <div [style.--days-in-month]=\"month.daysInMonth\" *ngFor=\"let month of dataParsed.months; let i = index\">{{\n month.date\n | date: 'MMMM, yyyy' }}</div>\n </div>\n <div class=\"ft-header__days\">\n <div *ngFor=\"let day of dataParsed.days; let i = index\">\n <div [ngClass]=\"{active: currentDate && currentDate === i}\">{{ day | date:'d' }}</div>\n </div>\n </div>\n</div>\n<div class=\"ft-tasks\">\n <button type=\"button\" class=\"ft-tasks__item\" [class.tasks__item--milestone]=\"task.type === 'milestone'\"\n [style.--start]=\"task.start\" [style.--days]=\"task.type === 'milestone' ? 1 : task.size\"\n style=\" --color-rgb: 130, 121, 210;\" *ngFor=\"let task of dataParsed.tasks;\">{{ task.label }}</button>\n</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }] }); }
422
+ class MessageContentComponent {
423
+ data = inject(MAT_SNACK_BAR_DATA);
424
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
425
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: MessageContentComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
426
+ @switch (data.message?.type) { @case ('html') {
427
+ <div [innerHTML]="data.message?.content"></div>
428
+ } @default {
429
+ {{ data.message?.content }}
430
+ } }
431
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: MatSnackBarModule }] });
446
432
  }
447
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: TimelineComponent, decorators: [{
433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageContentComponent, decorators: [{
448
434
  type: Component,
449
- args: [{ selector: 'ft-timeline', standalone: true, imports: [CommonModule], template: "<div class=\"ft-weekends\" [style.--start]=\"dataParsed.weekendStart\">\n <div class=\"ft-weekends__item\" [style.--weekend-size]=\"weekend.length\" *ngFor=\"let weekend of dataParsed.weekends\">\n </div>\n</div>\n<div class=\"ft-current-date\" *ngIf=\"currentDate\"></div>\n<div class=\"ft-header\">\n <div class=\"ft-header__months\">\n <div [style.--days-in-month]=\"month.daysInMonth\" *ngFor=\"let month of dataParsed.months; let i = index\">{{\n month.date\n | date: 'MMMM, yyyy' }}</div>\n </div>\n <div class=\"ft-header__days\">\n <div *ngFor=\"let day of dataParsed.days; let i = index\">\n <div [ngClass]=\"{active: currentDate && currentDate === i}\">{{ day | date:'d' }}</div>\n </div>\n </div>\n</div>\n<div class=\"ft-tasks\">\n <button type=\"button\" class=\"ft-tasks__item\" [class.tasks__item--milestone]=\"task.type === 'milestone'\"\n [style.--start]=\"task.start\" [style.--days]=\"task.type === 'milestone' ? 1 : task.size\"\n style=\" --color-rgb: 130, 121, 210;\" *ngFor=\"let task of dataParsed.tasks;\">{{ task.label }}</button>\n</div>" }]
450
- }], ctorParameters: function () { return []; }, propDecorators: { data: [{
451
- type: Input
452
- }], currentDate: [{
453
- type: HostBinding,
454
- args: ['style.--current-date']
455
- }], class: [{
456
- type: Input
457
- }], hostClasses: [{
458
- type: HostBinding,
459
- args: ['class']
460
- }] } });
461
-
462
- class ObserveIntersectingDirective {
463
- constructor(element, platformId = {}) {
464
- this.element = element;
465
- this.platformId = platformId;
466
- this.event = new EventEmitter();
467
- }
468
- ngOnInit() {
469
- if (isPlatformBrowser(this.platformId)) {
470
- if ("IntersectionObserver" in window) {
471
- const elementObserver = new IntersectionObserver((entries, observer) => {
472
- entries.forEach((entry) => {
473
- this.event.emit(entry.isIntersecting);
474
- });
475
- }, this.options);
476
- elementObserver.observe(this.element.nativeElement);
477
- }
478
- else {
479
- console.error('ftObserveIntersecting not available in this browser.');
480
- }
481
- }
482
- }
483
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ObserveIntersectingDirective, deps: [{ token: i0.ElementRef }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Directive }); }
484
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.2", type: ObserveIntersectingDirective, isStandalone: true, selector: "[ftObserveIntersecting]", inputs: { options: ["ftObserveIntersectingOptions", "options"] }, outputs: { event: "ftObserveIntersecting" }, ngImport: i0 }); }
485
- }
486
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ObserveIntersectingDirective, decorators: [{
487
- type: Directive,
488
435
  args: [{
489
- selector: '[ftObserveIntersecting]',
490
- standalone: true
436
+ standalone: true,
437
+ imports: [MatSnackBarModule],
438
+ template: `
439
+ @switch (data.message?.type) { @case ('html') {
440
+ <div [innerHTML]="data.message?.content"></div>
441
+ } @default {
442
+ {{ data.message?.content }}
443
+ } }
444
+ `,
491
445
  }]
492
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: undefined, decorators: [{
493
- type: Inject,
494
- args: [PLATFORM_ID]
495
- }] }]; }, propDecorators: { options: [{
496
- type: Input,
497
- args: ['ftObserveIntersectingOptions']
498
- }], event: [{
499
- type: Output,
500
- args: ['ftObserveIntersecting']
501
- }] } });
502
-
503
- class MessageContentComponent {
504
- constructor(data) {
505
- this.data = data;
506
- }
507
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageContentComponent, deps: [{ token: MAT_SNACK_BAR_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
508
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: MessageContentComponent, isStandalone: true, selector: "ft-message-content", ngImport: i0, template: "<ng-container [ngSwitch]=\"data.message?.type\">\n <div *ngSwitchCase=\"'html'\" [innerHTML]=\"data.message?.content\"></div>\n <ng-container *ngSwitchDefault>{{ data.message?.content }}</ng-container>\n</ng-container>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }] }); }
509
- }
510
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageContentComponent, decorators: [{
511
- type: Component,
512
- args: [{ selector: 'ft-message-content', standalone: true, imports: [CommonModule], template: "<ng-container [ngSwitch]=\"data.message?.type\">\n <div *ngSwitchCase=\"'html'\" [innerHTML]=\"data.message?.content\"></div>\n <ng-container *ngSwitchDefault>{{ data.message?.content }}</ng-container>\n</ng-container>" }]
513
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
514
- type: Inject,
515
- args: [MAT_SNACK_BAR_DATA]
516
- }] }]; } });
517
-
446
+ }] });
518
447
  class MessageDialogComponent {
519
- constructor(data) {
520
- this.data = data;
521
- this.beforeSelect = new EventEmitter();
522
- }
448
+ data = inject(MAT_DIALOG_DATA);
449
+ beforeSelect = output();
523
450
  select(value) {
524
451
  this.beforeSelect.emit(value);
525
452
  }
526
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageDialogComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component }); }
527
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.1.2", type: MessageDialogComponent, isStandalone: true, selector: "ft-message-dialog", outputs: { beforeSelect: "beforeSelect" }, ngImport: i0, template: "<h1 mat-dialog-title class=\"ft-message__title\" *ngIf=\"data.options?.title\">\n <ft-icon *ngIf=\"data.options?.titleIcon\" [name]=\"data.options?.titleIcon?.name\"\n [collection]=\"data.options?.titleIcon?.collection\" [ngClass]=\"data.options?.titleIcon?.class\"></ft-icon>\n <div>{{ data.options?.title }}</div>\n</h1>\n<div mat-dialog-content class=\"ft-message__content\" [ngClass]=\"data.options?.class\">\n <ft-icon *ngIf=\"data.options?.icon\" [name]=\"data.options?.icon?.name\" [collection]=\"data.options?.icon?.collection\"\n [ngClass]=\"data.options?.icon?.class\"></ft-icon>\n <ng-container [ngSwitch]=\"data.message?.type\">\n <div *ngSwitchCase=\"'html'\" [innerHTML]=\"data.message?.content\"></div>\n <ng-container *ngSwitchDefault>{{ data.message?.content }}</ng-container>\n </ng-container>\n</div>\n<div mat-dialog-actions class=\"ft-message__actions\" *ngIf=\"data.options.actionsVisible\">\n <ng-container *ngIf=\"data.options?.actions?.length > 0; else acceptTemplate\">\n <ng-container *ngFor=\"let action of data.options?.actions; let i = index\">\n <ng-container [ngSwitch]=\"action.type\">\n <button type=\"button\" *ngSwitchCase=\"'raised'\" mat-raised-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n <button type=\"button\" *ngSwitchCase=\"'flat'\" mat-flat-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n <button type=\"button\" *ngSwitchCase=\"'stroked'\" mat-stroked-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n <button type=\"button\" *ngSwitchDefault mat-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n </ng-container>\n </ng-container>\n </ng-container>\n</div>\n<ng-template #acceptTemplate>\n <button type=\"button\" mat-stroked-button color=\"primary\" (click)=\"select('-1')\" i18n>Accept</button>\n</ng-template>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: IconComponent, selector: "ft-icon", inputs: ["collection", "mode", "name", "path", "src", "class"] }] }); }
453
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
454
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.6", type: MessageDialogComponent, isStandalone: true, selector: "ng-component", outputs: { beforeSelect: "beforeSelect" }, ngImport: i0, template: `
455
+ @if (data.options?.title) {
456
+ <h1 mat-dialog-title class="ft-message__title">
457
+ @if (data.options?.titleIcon) {
458
+ <ft-icon
459
+ [name]="data.options?.titleIcon?.name"
460
+ [collection]="data.options?.titleIcon?.collection"
461
+ [ngClass]="data.options?.titleIcon?.class"
462
+ ></ft-icon>
463
+ }
464
+ <div>{{ data.options?.title }}</div>
465
+ </h1>
466
+ }
467
+ <div
468
+ mat-dialog-content
469
+ class="ft-message__content"
470
+ [ngClass]="data.options?.class"
471
+ >
472
+ @if (data.options?.icon) {
473
+ <ft-icon
474
+ [name]="data.options?.icon?.name"
475
+ [collection]="data.options?.icon?.collection"
476
+ [ngClass]="data.options?.icon?.class"
477
+ ></ft-icon>
478
+ } @switch (data.message?.type) { @case ('html') {
479
+ <div [innerHTML]="data.message?.content"></div>
480
+ } @default {
481
+ {{ data.message?.content }}
482
+ } }
483
+ </div>
484
+ @if (data.options.actionsVisible) {
485
+ <div mat-dialog-actions class="ft-message__actions">
486
+ @if (data.options?.actions?.length > 0) { @for (action of
487
+ data.options?.actions; track action; let i = $index) { @switch
488
+ (action.type) { @case ('raised') {
489
+ <button
490
+ type="button"
491
+ mat-raised-button
492
+ [color]="action.metadata?.color"
493
+ (click)="select(action.value)"
494
+ >
495
+ {{ action.label }}
496
+ </button>
497
+ } @case ('flat') {
498
+ <button
499
+ type="button"
500
+ mat-flat-button
501
+ [color]="action.metadata?.color"
502
+ (click)="select(action.value)"
503
+ >
504
+ {{ action.label }}
505
+ </button>
506
+ } @case ('stroked') {
507
+ <button
508
+ type="button"
509
+ mat-stroked-button
510
+ [color]="action.metadata?.color"
511
+ (click)="select(action.value)"
512
+ >
513
+ {{ action.label }}
514
+ </button>
515
+ } @default {
516
+ <button type="button" mat-button (click)="select(action.value)">
517
+ {{ action.label }}
518
+ </button>
519
+ } } } } @else {
520
+ <button
521
+ type="button"
522
+ mat-flat-button
523
+ color="primary"
524
+ (click)="select('-1')"
525
+ i18n
526
+ >
527
+ Accept
528
+ </button>
529
+ }
530
+ </div>
531
+ }
532
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i3.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i3.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i3.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: IconComponent, selector: "ft-icon", inputs: ["collection", "mode", "name", "path", "src", "class"] }] });
528
533
  }
529
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageDialogComponent, decorators: [{
534
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageDialogComponent, decorators: [{
530
535
  type: Component,
531
- args: [{ selector: 'ft-message-dialog', standalone: true, imports: [
532
- CommonModule,
533
- MatButtonModule,
534
- IconComponent
535
- ], template: "<h1 mat-dialog-title class=\"ft-message__title\" *ngIf=\"data.options?.title\">\n <ft-icon *ngIf=\"data.options?.titleIcon\" [name]=\"data.options?.titleIcon?.name\"\n [collection]=\"data.options?.titleIcon?.collection\" [ngClass]=\"data.options?.titleIcon?.class\"></ft-icon>\n <div>{{ data.options?.title }}</div>\n</h1>\n<div mat-dialog-content class=\"ft-message__content\" [ngClass]=\"data.options?.class\">\n <ft-icon *ngIf=\"data.options?.icon\" [name]=\"data.options?.icon?.name\" [collection]=\"data.options?.icon?.collection\"\n [ngClass]=\"data.options?.icon?.class\"></ft-icon>\n <ng-container [ngSwitch]=\"data.message?.type\">\n <div *ngSwitchCase=\"'html'\" [innerHTML]=\"data.message?.content\"></div>\n <ng-container *ngSwitchDefault>{{ data.message?.content }}</ng-container>\n </ng-container>\n</div>\n<div mat-dialog-actions class=\"ft-message__actions\" *ngIf=\"data.options.actionsVisible\">\n <ng-container *ngIf=\"data.options?.actions?.length > 0; else acceptTemplate\">\n <ng-container *ngFor=\"let action of data.options?.actions; let i = index\">\n <ng-container [ngSwitch]=\"action.type\">\n <button type=\"button\" *ngSwitchCase=\"'raised'\" mat-raised-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n <button type=\"button\" *ngSwitchCase=\"'flat'\" mat-flat-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n <button type=\"button\" *ngSwitchCase=\"'stroked'\" mat-stroked-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n <button type=\"button\" *ngSwitchDefault mat-button [color]=\"action.metadata?.color\"\n (click)=\"select(action.value)\">{{ action.label }}</button>\n </ng-container>\n </ng-container>\n </ng-container>\n</div>\n<ng-template #acceptTemplate>\n <button type=\"button\" mat-stroked-button color=\"primary\" (click)=\"select('-1')\" i18n>Accept</button>\n</ng-template>" }]
536
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
537
- type: Inject,
538
- args: [MAT_DIALOG_DATA]
539
- }] }]; }, propDecorators: { beforeSelect: [{
540
- type: Output
541
- }] } });
542
-
536
+ args: [{
537
+ standalone: true,
538
+ imports: [CommonModule, MatButtonModule, MatDialogModule, IconComponent],
539
+ template: `
540
+ @if (data.options?.title) {
541
+ <h1 mat-dialog-title class="ft-message__title">
542
+ @if (data.options?.titleIcon) {
543
+ <ft-icon
544
+ [name]="data.options?.titleIcon?.name"
545
+ [collection]="data.options?.titleIcon?.collection"
546
+ [ngClass]="data.options?.titleIcon?.class"
547
+ ></ft-icon>
548
+ }
549
+ <div>{{ data.options?.title }}</div>
550
+ </h1>
551
+ }
552
+ <div
553
+ mat-dialog-content
554
+ class="ft-message__content"
555
+ [ngClass]="data.options?.class"
556
+ >
557
+ @if (data.options?.icon) {
558
+ <ft-icon
559
+ [name]="data.options?.icon?.name"
560
+ [collection]="data.options?.icon?.collection"
561
+ [ngClass]="data.options?.icon?.class"
562
+ ></ft-icon>
563
+ } @switch (data.message?.type) { @case ('html') {
564
+ <div [innerHTML]="data.message?.content"></div>
565
+ } @default {
566
+ {{ data.message?.content }}
567
+ } }
568
+ </div>
569
+ @if (data.options.actionsVisible) {
570
+ <div mat-dialog-actions class="ft-message__actions">
571
+ @if (data.options?.actions?.length > 0) { @for (action of
572
+ data.options?.actions; track action; let i = $index) { @switch
573
+ (action.type) { @case ('raised') {
574
+ <button
575
+ type="button"
576
+ mat-raised-button
577
+ [color]="action.metadata?.color"
578
+ (click)="select(action.value)"
579
+ >
580
+ {{ action.label }}
581
+ </button>
582
+ } @case ('flat') {
583
+ <button
584
+ type="button"
585
+ mat-flat-button
586
+ [color]="action.metadata?.color"
587
+ (click)="select(action.value)"
588
+ >
589
+ {{ action.label }}
590
+ </button>
591
+ } @case ('stroked') {
592
+ <button
593
+ type="button"
594
+ mat-stroked-button
595
+ [color]="action.metadata?.color"
596
+ (click)="select(action.value)"
597
+ >
598
+ {{ action.label }}
599
+ </button>
600
+ } @default {
601
+ <button type="button" mat-button (click)="select(action.value)">
602
+ {{ action.label }}
603
+ </button>
604
+ } } } } @else {
605
+ <button
606
+ type="button"
607
+ mat-flat-button
608
+ color="primary"
609
+ (click)="select('-1')"
610
+ i18n
611
+ >
612
+ Accept
613
+ </button>
614
+ }
615
+ </div>
616
+ }
617
+ `,
618
+ }]
619
+ }] });
543
620
  class MessageService {
544
- constructor(snackBar, dialog) {
545
- this.snackBar = snackBar;
546
- this.dialog = dialog;
547
- }
621
+ snackBar = inject(MatSnackBar);
622
+ dialog = inject(MatDialog);
623
+ stringService = inject(StringService);
548
624
  show(message, options) {
549
625
  const selectionSource = new ReplaySubject(undefined);
550
626
  const selection = selectionSource.asObservable();
551
627
  const defaults = {
552
628
  type: 'notification',
553
629
  duration: 2000,
554
- actionsVisible: true
630
+ actionsVisible: true,
555
631
  };
556
632
  options = Object.assign(defaults, options);
557
- const data = { message: typeof message === 'string' ? { content: message, type: 'text' } : message, options };
633
+ const data = {
634
+ message: typeof message === 'string'
635
+ ? { content: message, type: 'text' }
636
+ : message,
637
+ options,
638
+ };
558
639
  let dialogRef;
559
640
  switch (options.type) {
560
641
  default:
561
642
  case 'notification':
562
643
  this.snackBar.openFromComponent(MessageContentComponent, {
563
644
  data,
564
- panelClass: ['ft-message', 'ft-message--notification', options.class || ''],
565
- duration: options.duration || 2000,
566
- verticalPosition: options.verticalPosition || 'bottom'
645
+ panelClass: ['ft-message', 'ft-message--notification'],
646
+ duration: this.stringService.calculateReadingTime(typeof message === 'string' ? message : message.content),
647
+ verticalPosition: options.verticalPosition || 'bottom',
567
648
  });
568
649
  break;
569
650
  case 'modal':
@@ -572,79 +653,83 @@ class MessageService {
572
653
  data,
573
654
  panelClass: ['ft-message', 'ft-message--modal'],
574
655
  autoFocus: false,
575
- disableClose: true
656
+ disableClose: true,
576
657
  });
577
658
  dialogRef.componentInstance.beforeSelect.subscribe((response) => {
578
659
  selectionSource.next(response);
579
660
  dialogRef.close();
580
661
  });
581
- this.snackBar.dismiss();
582
662
  break;
583
663
  }
584
664
  return selection;
585
665
  }
586
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageService, deps: [{ token: i1$2.MatSnackBar }, { token: i2$1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable }); }
587
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageService, providedIn: 'root' }); }
666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
667
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageService, providedIn: 'root' });
588
668
  }
589
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: MessageService, decorators: [{
669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: MessageService, decorators: [{
590
670
  type: Injectable,
591
671
  args: [{
592
- providedIn: 'root'
672
+ providedIn: 'root',
593
673
  }]
594
- }], ctorParameters: function () { return [{ type: i1$2.MatSnackBar }, { type: i2$1.MatDialog }]; } });
674
+ }] });
595
675
 
596
- class ProgressService {
597
- constructor(viewContainerRef, injector) {
598
- this.viewContainerRef = viewContainerRef;
599
- this.injector = injector;
600
- }
601
- show() {
602
- if (!this.componentRef) {
603
- this.appRef = this.injector.get(ApplicationRef);
604
- // 1. Create a component reference from the component
605
- this.componentRef = this.viewContainerRef.createComponent(ProgressComponent);
606
- // 2. Attach component to the appRef so that it's inside the ng component tree
607
- this.appRef.attachView(this.componentRef.hostView);
608
- this.componentRef.instance.overlay = true;
609
- // 3. Get DOM element from component
610
- const domElem = this.componentRef.hostView
611
- .rootNodes[0];
612
- // 4. Append DOM element to the body
613
- document.body.appendChild(domElem);
614
- return true;
615
- }
616
- else {
617
- return false;
618
- }
619
- }
620
- hide() {
621
- if (this.componentRef) {
622
- this.appRef.detachView(this.componentRef.hostView);
623
- this.componentRef.destroy();
624
- this.componentRef = null;
625
- return true;
626
- }
627
- else {
628
- return false;
676
+ class ObserveIntersectingDirective {
677
+ element = inject(ElementRef);
678
+ platformId = inject(PLATFORM_ID);
679
+ ftObserveIntersectingOptions = input();
680
+ event = output({ alias: 'ftObserveIntersecting' });
681
+ ngOnInit() {
682
+ if (isPlatformBrowser(this.platformId)) {
683
+ if ('IntersectionObserver' in window) {
684
+ const elementObserver = new IntersectionObserver((entries) => {
685
+ entries.forEach((entry) => {
686
+ this.event.emit(entry.isIntersecting);
687
+ });
688
+ }, this.ftObserveIntersectingOptions());
689
+ elementObserver.observe(this.element.nativeElement);
690
+ }
691
+ else {
692
+ console.error('ftObserveIntersecting not available in this browser.');
693
+ }
629
694
  }
630
695
  }
631
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ProgressService, deps: [{ token: i0.ViewContainerRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
632
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ProgressService, providedIn: 'root' }); }
696
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ObserveIntersectingDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
697
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.0.6", type: ObserveIntersectingDirective, isStandalone: true, selector: "[ftObserveIntersecting]", inputs: { ftObserveIntersectingOptions: { classPropertyName: "ftObserveIntersectingOptions", publicName: "ftObserveIntersectingOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { event: "ftObserveIntersecting" }, ngImport: i0 });
633
698
  }
634
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.2", ngImport: i0, type: ProgressService, decorators: [{
635
- type: Injectable,
699
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ObserveIntersectingDirective, decorators: [{
700
+ type: Directive,
636
701
  args: [{
637
- providedIn: 'root'
702
+ selector: '[ftObserveIntersecting]',
703
+ standalone: true,
638
704
  }]
639
- }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.Injector }]; } });
705
+ }] });
640
706
 
641
- /*
642
- * Public API Surface of ui
643
- */
707
+ class ProgressComponent {
708
+ mode = input('indeterminate');
709
+ overlay = input(false);
710
+ value = input(0);
711
+ class = input('');
712
+ get hostClasses() {
713
+ return [
714
+ 'ft-progress',
715
+ this.overlay() ? 'ft-progress--overlay' : '',
716
+ this.class()
717
+ ].join(' ');
718
+ }
719
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
720
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.0.6", type: ProgressComponent, isStandalone: true, selector: "ft-progress", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, overlay: { classPropertyName: "overlay", publicName: "overlay", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid\">\n <circle class=\"ft-track\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle class=\"ft-bar\" [ngClass]=\"mode() === 'determinate' ? 'ft-bar--determinate' : 'ft-bar--indeterminate'\" cx=\"50\"\n cy=\"50\" r=\"40\"\n [ngStyle]=\"{'stroke-dashoffset': mode() === 'determinate'? 'calc((3.14159265 * 40 * 2 * (100 - ' + value() + ')) / 100)' : null}\">\n </circle>\n</svg>", styles: [":host{line-height:0;display:inline-block}:host.ft-progress--1{font-size:1rem}:host.ft-progress--2{font-size:1.5rem}:host.ft-progress--3{font-size:2rem}:host.ft-progress--4{font-size:3rem}:host.ft-progress--5{font-size:4.5rem}:host.ft-progress--6{font-size:8rem}:host.ft-progress--7{font-size:16rem}:host.ft-progress--8{font-size:32rem}:host.ft-progress--overlay{position:fixed;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:10000;inset:0;font-size:42px}:host.ft-progress--overlay svg{background:#fff9;-webkit-backdrop-filter:saturate(50%) blur(3px);backdrop-filter:saturate(50%) blur(3px);box-shadow:0 3px 3px -2px #0003,0 3px 4px #00000024,0 1px 8px #0000001f;border-radius:100vh;padding:.3125rem;animation:ft-progress-reveal .2s;animation-fill-mode:forwards}:host.ft-progress--overlay svg .ft-track{display:none}svg{width:1em;height:1em;vertical-align:middle}svg .ft-track{fill:none;stroke-width:10;stroke:var(--ft-progress-track-color)}svg .ft-bar{fill:none;stroke-opacity:.9;stroke-width:6;stroke:var(--ft-progress-bar-color)}svg .ft-bar--indeterminate{animation:ft-progress-rotation 2s infinite linear}svg .ft-bar--determinate{stroke-dasharray:251.327412288}@keyframes ft-progress-reveal{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes ft-progress-rotation{0%{stroke-dashoffset:0;stroke-dasharray:150.6 100.4}50%{stroke-dasharray:1 250}to{stroke-dashoffset:502;stroke-dasharray:150.6 100.4}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
721
+ }
722
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.6", ngImport: i0, type: ProgressComponent, decorators: [{
723
+ type: Component,
724
+ args: [{ selector: 'ft-progress', standalone: true, imports: [CommonModule], template: "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"xMidYMid\">\n <circle class=\"ft-track\" cx=\"50\" cy=\"50\" r=\"40\" />\n <circle class=\"ft-bar\" [ngClass]=\"mode() === 'determinate' ? 'ft-bar--determinate' : 'ft-bar--indeterminate'\" cx=\"50\"\n cy=\"50\" r=\"40\"\n [ngStyle]=\"{'stroke-dashoffset': mode() === 'determinate'? 'calc((3.14159265 * 40 * 2 * (100 - ' + value() + ')) / 100)' : null}\">\n </circle>\n</svg>", styles: [":host{line-height:0;display:inline-block}:host.ft-progress--1{font-size:1rem}:host.ft-progress--2{font-size:1.5rem}:host.ft-progress--3{font-size:2rem}:host.ft-progress--4{font-size:3rem}:host.ft-progress--5{font-size:4.5rem}:host.ft-progress--6{font-size:8rem}:host.ft-progress--7{font-size:16rem}:host.ft-progress--8{font-size:32rem}:host.ft-progress--overlay{position:fixed;display:flex;align-items:center;justify-content:center;pointer-events:none;z-index:10000;inset:0;font-size:42px}:host.ft-progress--overlay svg{background:#fff9;-webkit-backdrop-filter:saturate(50%) blur(3px);backdrop-filter:saturate(50%) blur(3px);box-shadow:0 3px 3px -2px #0003,0 3px 4px #00000024,0 1px 8px #0000001f;border-radius:100vh;padding:.3125rem;animation:ft-progress-reveal .2s;animation-fill-mode:forwards}:host.ft-progress--overlay svg .ft-track{display:none}svg{width:1em;height:1em;vertical-align:middle}svg .ft-track{fill:none;stroke-width:10;stroke:var(--ft-progress-track-color)}svg .ft-bar{fill:none;stroke-opacity:.9;stroke-width:6;stroke:var(--ft-progress-bar-color)}svg .ft-bar--indeterminate{animation:ft-progress-rotation 2s infinite linear}svg .ft-bar--determinate{stroke-dasharray:251.327412288}@keyframes ft-progress-reveal{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes ft-progress-rotation{0%{stroke-dashoffset:0;stroke-dasharray:150.6 100.4}50%{stroke-dasharray:1 250}to{stroke-dashoffset:502;stroke-dasharray:150.6 100.4}}\n"] }]
725
+ }], propDecorators: { hostClasses: [{
726
+ type: HostBinding,
727
+ args: ['class']
728
+ }] } });
644
729
 
645
730
  /**
646
731
  * Generated bundle index. Do not edit.
647
732
  */
648
733
 
649
- export { AvatarComponent, IconComponent, ImageComponent, MessageService, ObserveIntersectingDirective, ProgressComponent, ProgressService, RatingComponent, TimelineComponent };
734
+ export { AvatarComponent, ChartService, IconComponent, MessageContentComponent, MessageDialogComponent, MessageService, ObserveIntersectingDirective, ProgressComponent };
650
735
  //# sourceMappingURL=factor_ec-ui.mjs.map