@shival99/z-ui 2.1.32 → 2.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 (104) hide show
  1. package/fesm2022/shival99-z-ui-components-z-accordion.mjs +41 -25
  2. package/fesm2022/shival99-z-ui-components-z-accordion.mjs.map +1 -1
  3. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +176 -97
  4. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -1
  5. package/fesm2022/shival99-z-ui-components-z-avatar.mjs +71 -40
  6. package/fesm2022/shival99-z-ui-components-z-avatar.mjs.map +1 -1
  7. package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs +26 -15
  8. package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs.map +1 -1
  9. package/fesm2022/shival99-z-ui-components-z-button-group.mjs +33 -21
  10. package/fesm2022/shival99-z-ui-components-z-button-group.mjs.map +1 -1
  11. package/fesm2022/shival99-z-ui-components-z-button.mjs +32 -19
  12. package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -1
  13. package/fesm2022/shival99-z-ui-components-z-calendar.mjs +289 -172
  14. package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
  15. package/fesm2022/shival99-z-ui-components-z-card.mjs +34 -24
  16. package/fesm2022/shival99-z-ui-components-z-card.mjs.map +1 -1
  17. package/fesm2022/shival99-z-ui-components-z-chat.mjs +85 -47
  18. package/fesm2022/shival99-z-ui-components-z-chat.mjs.map +1 -1
  19. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +56 -31
  20. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -1
  21. package/fesm2022/shival99-z-ui-components-z-code.mjs +29 -16
  22. package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -1
  23. package/fesm2022/shival99-z-ui-components-z-command.mjs +34 -19
  24. package/fesm2022/shival99-z-ui-components-z-command.mjs.map +1 -1
  25. package/fesm2022/shival99-z-ui-components-z-drawer.mjs +310 -88
  26. package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -1
  27. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +32 -18
  28. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -1
  29. package/fesm2022/shival99-z-ui-components-z-editor.mjs +118 -62
  30. package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
  31. package/fesm2022/shival99-z-ui-components-z-empty.mjs +31 -17
  32. package/fesm2022/shival99-z-ui-components-z-empty.mjs.map +1 -1
  33. package/fesm2022/shival99-z-ui-components-z-filter.mjs +81 -54
  34. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
  35. package/fesm2022/shival99-z-ui-components-z-gallery.mjs +240 -132
  36. package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
  37. package/fesm2022/shival99-z-ui-components-z-icon.mjs +39 -21
  38. package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -1
  39. package/fesm2022/shival99-z-ui-components-z-input.mjs +173 -95
  40. package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -1
  41. package/fesm2022/shival99-z-ui-components-z-kanban.mjs +88 -47
  42. package/fesm2022/shival99-z-ui-components-z-kanban.mjs.map +1 -1
  43. package/fesm2022/shival99-z-ui-components-z-loading.mjs +31 -19
  44. package/fesm2022/shival99-z-ui-components-z-loading.mjs.map +1 -1
  45. package/fesm2022/shival99-z-ui-components-z-marquee.mjs +42 -23
  46. package/fesm2022/shival99-z-ui-components-z-marquee.mjs.map +1 -1
  47. package/fesm2022/shival99-z-ui-components-z-media-player.mjs +87 -45
  48. package/fesm2022/shival99-z-ui-components-z-media-player.mjs.map +1 -1
  49. package/fesm2022/shival99-z-ui-components-z-menu.mjs +126 -67
  50. package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
  51. package/fesm2022/shival99-z-ui-components-z-metric-card.mjs +42 -23
  52. package/fesm2022/shival99-z-ui-components-z-metric-card.mjs.map +1 -1
  53. package/fesm2022/shival99-z-ui-components-z-modal.mjs +144 -80
  54. package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -1
  55. package/fesm2022/shival99-z-ui-components-z-pagination.mjs +45 -24
  56. package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -1
  57. package/fesm2022/shival99-z-ui-components-z-popover.mjs +90 -57
  58. package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -1
  59. package/fesm2022/shival99-z-ui-components-z-qrcode.mjs +51 -29
  60. package/fesm2022/shival99-z-ui-components-z-qrcode.mjs.map +1 -1
  61. package/fesm2022/shival99-z-ui-components-z-radio.mjs +36 -20
  62. package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -1
  63. package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs +27 -15
  64. package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs.map +1 -1
  65. package/fesm2022/shival99-z-ui-components-z-select.mjs +239 -138
  66. package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -1
  67. package/fesm2022/shival99-z-ui-components-z-show-more.mjs +38 -21
  68. package/fesm2022/shival99-z-ui-components-z-show-more.mjs.map +1 -1
  69. package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs +42 -23
  70. package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs.map +1 -1
  71. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +35 -19
  72. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -1
  73. package/fesm2022/shival99-z-ui-components-z-steps.mjs +55 -31
  74. package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -1
  75. package/fesm2022/shival99-z-ui-components-z-switch.mjs +60 -33
  76. package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -1
  77. package/fesm2022/shival99-z-ui-components-z-table.mjs +10875 -0
  78. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
  79. package/fesm2022/shival99-z-ui-components-z-tabs.mjs +534 -0
  80. package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
  81. package/fesm2022/shival99-z-ui-components-z-tags.mjs +72 -46
  82. package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -1
  83. package/fesm2022/shival99-z-ui-components-z-timeline.mjs +254 -0
  84. package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
  85. package/fesm2022/shival99-z-ui-components-z-toast.mjs +53 -31
  86. package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -1
  87. package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +133 -56
  88. package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -1
  89. package/fesm2022/shival99-z-ui-components-z-upload.mjs +63 -36
  90. package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -1
  91. package/fesm2022/shival99-z-ui-i18n.mjs +2 -0
  92. package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -1
  93. package/fesm2022/shival99-z-ui-pipes.mjs +18 -18
  94. package/fesm2022/shival99-z-ui-services.mjs +35 -31
  95. package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
  96. package/package.json +16 -16
  97. package/types/shival99-z-ui-components-z-autocomplete.d.ts +2 -2
  98. package/types/shival99-z-ui-components-z-card.d.ts +1 -2
  99. package/types/shival99-z-ui-components-z-drawer.d.ts +20 -2
  100. package/types/shival99-z-ui-components-z-gallery.d.ts +1 -2
  101. package/types/shival99-z-ui-components-z-select.d.ts +2 -2
  102. package/types/shival99-z-ui-components-z-table.d.ts +2293 -0
  103. package/types/shival99-z-ui-components-z-tabs.d.ts +92 -0
  104. package/types/shival99-z-ui-components-z-timeline.d.ts +71 -0
@@ -0,0 +1,254 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { input, booleanAttribute, inject, DestroyRef, viewChildren, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
5
+ import { zMergeClasses } from '@shival99/z-ui/utils';
6
+ import { cva } from 'class-variance-authority';
7
+
8
+ // Host container
9
+ const zTimelineVariants = cva(['z-timeline relative block min-w-0'], {
10
+ variants: {
11
+ zSize: {
12
+ sm: 'text-sm',
13
+ default: 'text-base',
14
+ lg: 'text-lg',
15
+ },
16
+ },
17
+ defaultVariants: {
18
+ zSize: 'default',
19
+ },
20
+ });
21
+ // Outer dot ring
22
+ const zTimelineDotVariants = cva(['flex shrink-0 items-center justify-center rounded-full bg-primary/10 transition-colors duration-300'], {
23
+ variants: {
24
+ zSize: {
25
+ sm: 'size-4.5',
26
+ default: 'size-6',
27
+ lg: 'size-7',
28
+ },
29
+ },
30
+ defaultVariants: {
31
+ zSize: 'default',
32
+ },
33
+ });
34
+ // Inner dot
35
+ const zTimelineInnerDotVariants = cva(['rounded-full bg-primary transition-colors duration-300'], {
36
+ variants: {
37
+ zSize: {
38
+ sm: 'size-2',
39
+ default: 'size-3',
40
+ lg: 'size-3.5',
41
+ },
42
+ },
43
+ defaultVariants: {
44
+ zSize: 'default',
45
+ },
46
+ });
47
+ // Time badge
48
+ const zTimelineTimeBadgeVariants = cva([
49
+ 'inline-flex w-fit max-w-full shrink-0 items-center justify-center rounded-md bg-primary px-2 py-0.5 text-sm font-semibold leading-tight text-primary-foreground transition-colors duration-300',
50
+ ], {
51
+ variants: {
52
+ zSize: {
53
+ sm: 'text-xs',
54
+ default: 'text-sm',
55
+ lg: 'text-sm',
56
+ },
57
+ },
58
+ defaultVariants: {
59
+ zSize: 'default',
60
+ },
61
+ });
62
+ // Title
63
+ const zTimelineTitleVariants = cva(['font-medium leading-snug text-foreground'], {
64
+ variants: {
65
+ zSize: {
66
+ sm: 'text-sm',
67
+ default: 'text-base md:text-lg',
68
+ lg: 'text-lg md:text-xl',
69
+ },
70
+ },
71
+ defaultVariants: {
72
+ zSize: 'default',
73
+ },
74
+ });
75
+ // Description
76
+ const zTimelineDescriptionVariants = cva(['text-muted-foreground leading-relaxed'], {
77
+ variants: {
78
+ zSize: {
79
+ sm: 'text-xs',
80
+ default: 'text-sm',
81
+ lg: 'text-base',
82
+ },
83
+ },
84
+ defaultVariants: {
85
+ zSize: 'default',
86
+ },
87
+ });
88
+
89
+ class ZTimelineComponent {
90
+ class = input('', /* @ts-ignore */
91
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
92
+ zItems = input([], /* @ts-ignore */
93
+ ...(ngDevMode ? [{ debugName: "zItems" }] : /* istanbul ignore next */ []));
94
+ zSize = input('default', /* @ts-ignore */
95
+ ...(ngDevMode ? [{ debugName: "zSize" }] : /* istanbul ignore next */ []));
96
+ zLayout = input('default', /* @ts-ignore */
97
+ ...(ngDevMode ? [{ debugName: "zLayout" }] : /* istanbul ignore next */ []));
98
+ zScrollProgress = input(false, { ...(ngDevMode ? { debugName: "zScrollProgress" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
99
+ _destroyRef = inject(DestroyRef);
100
+ _timelineItems = viewChildren('timelineItem', /* @ts-ignore */
101
+ ...(ngDevMode ? [{ debugName: "_timelineItems" }] : /* istanbul ignore next */ []));
102
+ _progressRatio = signal(0, /* @ts-ignore */
103
+ ...(ngDevMode ? [{ debugName: "_progressRatio" }] : /* istanbul ignore next */ []));
104
+ hostClasses = computed(() => zMergeClasses(zTimelineVariants({ zSize: this.zSize() }), this.class()), /* @ts-ignore */
105
+ ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
106
+ dotClasses = computed(() => zTimelineDotVariants({ zSize: this.zSize() }), /* @ts-ignore */
107
+ ...(ngDevMode ? [{ debugName: "dotClasses" }] : /* istanbul ignore next */ []));
108
+ innerDotClasses = computed(() => zTimelineInnerDotVariants({ zSize: this.zSize() }), /* @ts-ignore */
109
+ ...(ngDevMode ? [{ debugName: "innerDotClasses" }] : /* istanbul ignore next */ []));
110
+ badgeClasses = computed(() => zTimelineTimeBadgeVariants({ zSize: this.zSize() }), /* @ts-ignore */
111
+ ...(ngDevMode ? [{ debugName: "badgeClasses" }] : /* istanbul ignore next */ []));
112
+ titleClasses = computed(() => zTimelineTitleVariants({ zSize: this.zSize() }), /* @ts-ignore */
113
+ ...(ngDevMode ? [{ debugName: "titleClasses" }] : /* istanbul ignore next */ []));
114
+ descriptionClasses = computed(() => zTimelineDescriptionVariants({ zSize: this.zSize() }), /* @ts-ignore */
115
+ ...(ngDevMode ? [{ debugName: "descriptionClasses" }] : /* istanbul ignore next */ []));
116
+ isCareer = computed(() => this.zLayout() === 'career', /* @ts-ignore */
117
+ ...(ngDevMode ? [{ debugName: "isCareer" }] : /* istanbul ignore next */ []));
118
+ isAlternate = computed(() => this.zLayout() === 'alternate', /* @ts-ignore */
119
+ ...(ngDevMode ? [{ debugName: "isAlternate" }] : /* istanbul ignore next */ []));
120
+ progressStates = computed(() => {
121
+ const items = this.zItems();
122
+ if (!this.zScrollProgress()) {
123
+ return items.map(() => true);
124
+ }
125
+ const lastIndex = items.length - 1;
126
+ const progressRatio = this._progressRatio();
127
+ if (lastIndex <= 0) {
128
+ return items.map(() => progressRatio > 0);
129
+ }
130
+ return items.map((_item, index) => {
131
+ if (index === 0) {
132
+ return progressRatio > 0;
133
+ }
134
+ return progressRatio >= index / lastIndex;
135
+ });
136
+ }, /* @ts-ignore */
137
+ ...(ngDevMode ? [{ debugName: "progressStates" }] : /* istanbul ignore next */ []));
138
+ progressLineHeight = computed(() => {
139
+ if (!this.zScrollProgress()) {
140
+ return '100%';
141
+ }
142
+ return `${this._progressRatio() * 100}%`;
143
+ }, /* @ts-ignore */
144
+ ...(ngDevMode ? [{ debugName: "progressLineHeight" }] : /* istanbul ignore next */ []));
145
+ progressSegments = computed(() => {
146
+ const items = this.zItems();
147
+ const lastIndex = items.length - 1;
148
+ if (!this.zScrollProgress()) {
149
+ return items.map(() => '100%');
150
+ }
151
+ if (lastIndex <= 0) {
152
+ return items.map(() => `${this._progressRatio() * 100}%`);
153
+ }
154
+ const progressRatio = this._progressRatio();
155
+ return items.map((_item, index) => {
156
+ const segmentStart = index / lastIndex;
157
+ const segmentEnd = (index + 1) / lastIndex;
158
+ const segmentProgress = (progressRatio - segmentStart) / (segmentEnd - segmentStart);
159
+ const boundedProgress = Math.min(Math.max(segmentProgress, 0), 1);
160
+ return `${boundedProgress * 100}%`;
161
+ });
162
+ }, /* @ts-ignore */
163
+ ...(ngDevMode ? [{ debugName: "progressSegments" }] : /* istanbul ignore next */ []));
164
+ constructor() {
165
+ effect(onCleanup => {
166
+ if (!this.zScrollProgress()) {
167
+ this._progressRatio.set(0);
168
+ return;
169
+ }
170
+ if (typeof window === 'undefined') {
171
+ this._progressRatio.set(1);
172
+ return;
173
+ }
174
+ const elements = this._timelineItems().map(item => item.nativeElement);
175
+ if (!elements.length) {
176
+ this._progressRatio.set(0);
177
+ return;
178
+ }
179
+ let animationFrame = null;
180
+ const updateProgress = () => {
181
+ this._progressRatio.set(this._calculateProgressRatio(elements));
182
+ };
183
+ const scheduleUpdate = () => {
184
+ if (animationFrame !== null) {
185
+ return;
186
+ }
187
+ animationFrame = window.requestAnimationFrame(() => {
188
+ animationFrame = null;
189
+ updateProgress();
190
+ });
191
+ };
192
+ scheduleUpdate();
193
+ window.addEventListener('scroll', scheduleUpdate, { passive: true });
194
+ window.addEventListener('resize', scheduleUpdate);
195
+ onCleanup(() => {
196
+ window.removeEventListener('scroll', scheduleUpdate);
197
+ window.removeEventListener('resize', scheduleUpdate);
198
+ if (animationFrame === null) {
199
+ return;
200
+ }
201
+ window.cancelAnimationFrame(animationFrame);
202
+ });
203
+ });
204
+ this._destroyRef.onDestroy(() => this._progressRatio.set(0));
205
+ }
206
+ _calculateProgressRatio(elements) {
207
+ if (!elements.length) {
208
+ return 0;
209
+ }
210
+ const triggerY = window.innerHeight * 0.55;
211
+ const itemTops = elements.map(element => element.getBoundingClientRect().top);
212
+ const firstTop = itemTops[0];
213
+ const lastTop = itemTops[itemTops.length - 1];
214
+ if (triggerY <= firstTop) {
215
+ return 0;
216
+ }
217
+ if (triggerY >= lastTop) {
218
+ return 1;
219
+ }
220
+ const activeSegmentIndex = itemTops.findIndex((top, index) => {
221
+ const nextTop = itemTops[index + 1];
222
+ if (nextTop === undefined) {
223
+ return false;
224
+ }
225
+ return triggerY >= top && triggerY < nextTop;
226
+ });
227
+ if (activeSegmentIndex < 0) {
228
+ return 0;
229
+ }
230
+ const segmentStart = itemTops[activeSegmentIndex];
231
+ const segmentEnd = itemTops[activeSegmentIndex + 1];
232
+ const segmentDistance = segmentEnd - segmentStart;
233
+ if (segmentDistance <= 0) {
234
+ return 0;
235
+ }
236
+ const localProgress = (triggerY - segmentStart) / segmentDistance;
237
+ return (activeSegmentIndex + localProgress) / (itemTops.length - 1);
238
+ }
239
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZTimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
240
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: ZTimelineComponent, isStandalone: true, selector: "z-timeline", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zItems: { classPropertyName: "zItems", publicName: "zItems", isSignal: true, isRequired: false, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zLayout: { classPropertyName: "zLayout", publicName: "zLayout", isSignal: true, isRequired: false, transformFunction: null }, zScrollProgress: { classPropertyName: "zScrollProgress", publicName: "zScrollProgress", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, viewQueries: [{ propertyName: "_timelineItems", predicate: ["timelineItem"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (isCareer()) {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- CAREER / EXPERIENCE LAYOUT -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @let progress = progressStates();\n <div class=\"mx-auto w-full max-w-3xl px-2 sm:px-4\">\n <div class=\"relative ml-3\">\n <div class=\"bg-border absolute top-3 bottom-3 left-0 w-0.5 overflow-hidden\">\n <div\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-0.5\"\n [style.height]=\"zScrollProgress() ? progressLineHeight() : '0%'\"></div>\n </div>\n\n @for (item of zItems(); track item.id ?? $index; let isLast = $last) {\n @let isActive = progress[$index];\n <article\n #timelineItem\n class=\"relative pb-10 pl-8\"\n [class.pb-0]=\"isLast\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <span\n class=\"bg-background border-primary absolute top-2 left-0 z-[1] size-3 -translate-x-1/2 rounded-full border-2\"\n [class.z-timeline-progress-dot]=\"zScrollProgress()\"></span>\n\n <div class=\"space-y-3\">\n <div class=\"flex items-center gap-2.5\">\n <div class=\"bg-accent flex size-9 shrink-0 items-center justify-center rounded-full\">\n <z-icon [zType]=\"item.icon ?? 'lucideBuilding2'\" zSize=\"18\" class=\"text-muted-foreground\" />\n </div>\n <span class=\"text-base font-medium\">{{ item.company ?? item.subtitle ?? 'Experience' }}</span>\n </div>\n\n <div class=\"space-y-2\">\n <h3 class=\"text-foreground text-xl leading-tight font-semibold tracking-[-0.01em]\">{{ item.title }}</h3>\n @if (item.period || item.time) {\n <div class=\"text-muted-foreground flex items-center gap-2 text-sm\">\n <z-icon zType=\"lucideCalendar\" zSize=\"15\" class=\"shrink-0\" />\n <span>{{ item.period ?? item.time }}</span>\n </div>\n }\n </div>\n\n @if (item.description) {\n <p class=\"text-muted-foreground text-sm leading-relaxed sm:text-base\">{{ item.description }}</p>\n }\n\n @if (item.technologies?.length) {\n <div class=\"flex flex-wrap gap-2\">\n @for (tech of item.technologies; track tech) {\n <span\n class=\"bg-secondary text-secondary-foreground inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-medium\">\n {{ tech }}\n </span>\n }\n </div>\n }\n\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </article>\n }\n </div>\n </div>\n} @else if (isAlternate()) {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- ALTERNATE / ZIGZAG LAYOUT -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @let progress = progressStates();\n <div class=\"relative mx-auto max-w-7xl space-y-4\">\n @for (item of zItems(); track item.id ?? $index; let isEven = $even) {\n @let isActive = progress[$index];\n <div\n #timelineItem\n class=\"flex items-start md:flex-row\"\n [class.md:flex-row-reverse]=\"!isEven\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <!-- Opposite-side badge (desktop only) -->\n <div\n class=\"hidden w-full md:flex md:flex-1 md:items-start\"\n [class.md:justify-end]=\"isEven\"\n [class.md:justify-start]=\"!isEven\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\">{{ item.time }}</span>\n }\n </div>\n\n <!-- Center marker column -->\n <div class=\"relative flex flex-col items-center pr-4 md:px-4\">\n <div class=\"z-40 flex items-center justify-center\">\n <span [class]=\"dotClasses()\" [class.z-timeline-progress-dot-ring]=\"true\">\n <span [class]=\"innerDotClasses()\" [class.z-timeline-progress-dot]=\"true\"></span>\n </span>\n </div>\n </div>\n\n <!-- Content side -->\n <div class=\"w-full md:flex md:flex-1\" [class.md:justify-start]=\"isEven\" [class.md:justify-end]=\"!isEven\">\n <!-- Mobile badge -->\n @if (item.time) {\n <span [class]=\"badgeClasses()\" class=\"mb-4 block text-left md:hidden\">{{ item.time }}</span>\n }\n\n <div>\n <!-- Card -->\n <div\n class=\"bg-card text-card-foreground mb-8 flex flex-col gap-6 overflow-hidden rounded-xl border py-6 shadow-sm md:max-w-136\">\n <div class=\"space-y-4 px-6\">\n <div [class]=\"titleClasses()\">{{ item.title }}</div>\n @if (item.description) {\n <p [class]=\"descriptionClasses()\">{{ item.description }}</p>\n }\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Vertical line (absolute, behind everything) -->\n <div class=\"bg-border absolute top-3 bottom-3 left-3 w-0.5 overflow-hidden md:left-1/2 md:-translate-x-1/2\">\n <div\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-0.5 rounded-full\"\n [style.height]=\"progressLineHeight()\"></div>\n </div>\n </div>\n} @else {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- DEFAULT / CHANGELOG LAYOUT -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @let progress = progressStates();\n @let segments = progressSegments();\n @for (item of zItems(); track item.id ?? $index; let isLast = $last) {\n @let isActive = progress[$index];\n <article\n #timelineItem\n class=\"z-timeline-default-item relative grid grid-cols-[7rem_1.5rem_minmax(0,1fr)] gap-x-3\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <!-- Left: badge + subtitle (desktop only) -->\n <div class=\"z-timeline-default-meta flex min-w-0 flex-col items-end gap-2 self-start pb-4\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\">{{ item.time }}</span>\n }\n @if (item.subtitle) {\n <div class=\"text-muted-foreground max-w-full text-right text-sm leading-snug font-medium\">\n {{ item.subtitle }}\n </div>\n }\n </div>\n\n <!-- Center: dot + line -->\n <div class=\"relative flex flex-col items-center\">\n <div class=\"bg-background relative z-[1] flex size-6 items-center justify-center rounded-full\">\n <span [class]=\"dotClasses()\" [class.z-timeline-progress-dot-ring]=\"true\">\n <span [class]=\"innerDotClasses()\" [class.z-timeline-progress-dot]=\"true\"></span>\n </span>\n </div>\n @if (!isLast) {\n <span class=\"bg-border absolute top-6 bottom-0 left-1/2 w-px -translate-x-1/2 overflow-hidden rounded-full\">\n @if (zScrollProgress()) {\n <span\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-px rounded-full\"\n [style.height]=\"segments[$index]\"></span>\n }\n </span>\n <span class=\"w-px flex-1\"></span>\n }\n </div>\n\n <!-- Right: content -->\n <div class=\"z-timeline-default-content flex min-w-0 flex-col gap-4 pb-10 pl-1\">\n <!-- Mobile badge + subtitle -->\n <div class=\"z-timeline-default-mobile-meta flex-col gap-2\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\" class=\"w-fit\">{{ item.time }}</span>\n }\n @if (item.subtitle) {\n <div class=\"text-muted-foreground text-sm font-medium\">{{ item.subtitle }}</div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"min-w-0 space-y-4\">\n <div class=\"space-y-3\">\n <h3 [class]=\"titleClasses()\">{{ item.title }}</h3>\n @if (item.description) {\n <p [class]=\"descriptionClasses()\">{{ item.description }}</p>\n }\n </div>\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </div>\n </article>\n }\n}\n", styles: [".z-timeline{container-type:inline-size}.z-timeline-default-mobile-meta{display:none}.z-timeline-progress-dot{background:var(--primary);transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease}.z-timeline-progress-dot-ring{background:color-mix(in oklab,var(--primary) 14%,transparent);transition:background-color .18s ease}.z-timeline-progress-line{background:var(--primary);transition:height .12s linear}.z-timeline-progress-inactive .z-timeline-progress-dot-ring{background:var(--border)}.z-timeline-progress-inactive .z-timeline-progress-dot{background:var(--muted-foreground);border-color:var(--border)}@container (max-width: 34rem){.z-timeline-default-item{grid-template-columns:1.5rem minmax(0,1fr)}.z-timeline-default-meta{display:none}.z-timeline-default-mobile-meta{display:flex}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
241
+ }
242
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZTimelineComponent, decorators: [{
243
+ type: Component,
244
+ args: [{ selector: 'z-timeline', imports: [NgTemplateOutlet, ZIconComponent], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
245
+ '[class]': 'hostClasses()',
246
+ }, template: "@if (isCareer()) {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- CAREER / EXPERIENCE LAYOUT -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @let progress = progressStates();\n <div class=\"mx-auto w-full max-w-3xl px-2 sm:px-4\">\n <div class=\"relative ml-3\">\n <div class=\"bg-border absolute top-3 bottom-3 left-0 w-0.5 overflow-hidden\">\n <div\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-0.5\"\n [style.height]=\"zScrollProgress() ? progressLineHeight() : '0%'\"></div>\n </div>\n\n @for (item of zItems(); track item.id ?? $index; let isLast = $last) {\n @let isActive = progress[$index];\n <article\n #timelineItem\n class=\"relative pb-10 pl-8\"\n [class.pb-0]=\"isLast\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <span\n class=\"bg-background border-primary absolute top-2 left-0 z-[1] size-3 -translate-x-1/2 rounded-full border-2\"\n [class.z-timeline-progress-dot]=\"zScrollProgress()\"></span>\n\n <div class=\"space-y-3\">\n <div class=\"flex items-center gap-2.5\">\n <div class=\"bg-accent flex size-9 shrink-0 items-center justify-center rounded-full\">\n <z-icon [zType]=\"item.icon ?? 'lucideBuilding2'\" zSize=\"18\" class=\"text-muted-foreground\" />\n </div>\n <span class=\"text-base font-medium\">{{ item.company ?? item.subtitle ?? 'Experience' }}</span>\n </div>\n\n <div class=\"space-y-2\">\n <h3 class=\"text-foreground text-xl leading-tight font-semibold tracking-[-0.01em]\">{{ item.title }}</h3>\n @if (item.period || item.time) {\n <div class=\"text-muted-foreground flex items-center gap-2 text-sm\">\n <z-icon zType=\"lucideCalendar\" zSize=\"15\" class=\"shrink-0\" />\n <span>{{ item.period ?? item.time }}</span>\n </div>\n }\n </div>\n\n @if (item.description) {\n <p class=\"text-muted-foreground text-sm leading-relaxed sm:text-base\">{{ item.description }}</p>\n }\n\n @if (item.technologies?.length) {\n <div class=\"flex flex-wrap gap-2\">\n @for (tech of item.technologies; track tech) {\n <span\n class=\"bg-secondary text-secondary-foreground inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-medium\">\n {{ tech }}\n </span>\n }\n </div>\n }\n\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </article>\n }\n </div>\n </div>\n} @else if (isAlternate()) {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- ALTERNATE / ZIGZAG LAYOUT -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @let progress = progressStates();\n <div class=\"relative mx-auto max-w-7xl space-y-4\">\n @for (item of zItems(); track item.id ?? $index; let isEven = $even) {\n @let isActive = progress[$index];\n <div\n #timelineItem\n class=\"flex items-start md:flex-row\"\n [class.md:flex-row-reverse]=\"!isEven\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <!-- Opposite-side badge (desktop only) -->\n <div\n class=\"hidden w-full md:flex md:flex-1 md:items-start\"\n [class.md:justify-end]=\"isEven\"\n [class.md:justify-start]=\"!isEven\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\">{{ item.time }}</span>\n }\n </div>\n\n <!-- Center marker column -->\n <div class=\"relative flex flex-col items-center pr-4 md:px-4\">\n <div class=\"z-40 flex items-center justify-center\">\n <span [class]=\"dotClasses()\" [class.z-timeline-progress-dot-ring]=\"true\">\n <span [class]=\"innerDotClasses()\" [class.z-timeline-progress-dot]=\"true\"></span>\n </span>\n </div>\n </div>\n\n <!-- Content side -->\n <div class=\"w-full md:flex md:flex-1\" [class.md:justify-start]=\"isEven\" [class.md:justify-end]=\"!isEven\">\n <!-- Mobile badge -->\n @if (item.time) {\n <span [class]=\"badgeClasses()\" class=\"mb-4 block text-left md:hidden\">{{ item.time }}</span>\n }\n\n <div>\n <!-- Card -->\n <div\n class=\"bg-card text-card-foreground mb-8 flex flex-col gap-6 overflow-hidden rounded-xl border py-6 shadow-sm md:max-w-136\">\n <div class=\"space-y-4 px-6\">\n <div [class]=\"titleClasses()\">{{ item.title }}</div>\n @if (item.description) {\n <p [class]=\"descriptionClasses()\">{{ item.description }}</p>\n }\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Vertical line (absolute, behind everything) -->\n <div class=\"bg-border absolute top-3 bottom-3 left-3 w-0.5 overflow-hidden md:left-1/2 md:-translate-x-1/2\">\n <div\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-0.5 rounded-full\"\n [style.height]=\"progressLineHeight()\"></div>\n </div>\n </div>\n} @else {\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n <!-- DEFAULT / CHANGELOG LAYOUT -->\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n @let progress = progressStates();\n @let segments = progressSegments();\n @for (item of zItems(); track item.id ?? $index; let isLast = $last) {\n @let isActive = progress[$index];\n <article\n #timelineItem\n class=\"z-timeline-default-item relative grid grid-cols-[7rem_1.5rem_minmax(0,1fr)] gap-x-3\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <!-- Left: badge + subtitle (desktop only) -->\n <div class=\"z-timeline-default-meta flex min-w-0 flex-col items-end gap-2 self-start pb-4\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\">{{ item.time }}</span>\n }\n @if (item.subtitle) {\n <div class=\"text-muted-foreground max-w-full text-right text-sm leading-snug font-medium\">\n {{ item.subtitle }}\n </div>\n }\n </div>\n\n <!-- Center: dot + line -->\n <div class=\"relative flex flex-col items-center\">\n <div class=\"bg-background relative z-[1] flex size-6 items-center justify-center rounded-full\">\n <span [class]=\"dotClasses()\" [class.z-timeline-progress-dot-ring]=\"true\">\n <span [class]=\"innerDotClasses()\" [class.z-timeline-progress-dot]=\"true\"></span>\n </span>\n </div>\n @if (!isLast) {\n <span class=\"bg-border absolute top-6 bottom-0 left-1/2 w-px -translate-x-1/2 overflow-hidden rounded-full\">\n @if (zScrollProgress()) {\n <span\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-px rounded-full\"\n [style.height]=\"segments[$index]\"></span>\n }\n </span>\n <span class=\"w-px flex-1\"></span>\n }\n </div>\n\n <!-- Right: content -->\n <div class=\"z-timeline-default-content flex min-w-0 flex-col gap-4 pb-10 pl-1\">\n <!-- Mobile badge + subtitle -->\n <div class=\"z-timeline-default-mobile-meta flex-col gap-2\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\" class=\"w-fit\">{{ item.time }}</span>\n }\n @if (item.subtitle) {\n <div class=\"text-muted-foreground text-sm font-medium\">{{ item.subtitle }}</div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"min-w-0 space-y-4\">\n <div class=\"space-y-3\">\n <h3 [class]=\"titleClasses()\">{{ item.title }}</h3>\n @if (item.description) {\n <p [class]=\"descriptionClasses()\">{{ item.description }}</p>\n }\n </div>\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </div>\n </article>\n }\n}\n", styles: [".z-timeline{container-type:inline-size}.z-timeline-default-mobile-meta{display:none}.z-timeline-progress-dot{background:var(--primary);transition:background-color .18s ease,border-color .18s ease,box-shadow .18s ease}.z-timeline-progress-dot-ring{background:color-mix(in oklab,var(--primary) 14%,transparent);transition:background-color .18s ease}.z-timeline-progress-line{background:var(--primary);transition:height .12s linear}.z-timeline-progress-inactive .z-timeline-progress-dot-ring{background:var(--border)}.z-timeline-progress-inactive .z-timeline-progress-dot{background:var(--muted-foreground);border-color:var(--border)}@container (max-width: 34rem){.z-timeline-default-item{grid-template-columns:1.5rem minmax(0,1fr)}.z-timeline-default-meta{display:none}.z-timeline-default-mobile-meta{display:flex}}\n"] }]
247
+ }], ctorParameters: () => [], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "zItems", required: false }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "zLayout", required: false }] }], zScrollProgress: [{ type: i0.Input, args: [{ isSignal: true, alias: "zScrollProgress", required: false }] }], _timelineItems: [{ type: i0.ViewChildren, args: ['timelineItem', { isSignal: true }] }] } });
248
+
249
+ /**
250
+ * Generated bundle index. Do not edit.
251
+ */
252
+
253
+ export { ZTimelineComponent, zTimelineDescriptionVariants, zTimelineDotVariants, zTimelineInnerDotVariants, zTimelineTimeBadgeVariants, zTimelineTitleVariants, zTimelineVariants };
254
+ //# sourceMappingURL=shival99-z-ui-components-z-timeline.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shival99-z-ui-components-z-timeline.mjs","sources":["../../../../libs/core-ui/components/z-timeline/z-timeline.variants.ts","../../../../libs/core-ui/components/z-timeline/z-timeline.component.ts","../../../../libs/core-ui/components/z-timeline/z-timeline.component.html","../../../../libs/core-ui/components/z-timeline/shival99-z-ui-components-z-timeline.ts"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\n\n// Host container\nexport const zTimelineVariants = cva(['z-timeline relative block min-w-0'], {\n variants: {\n zSize: {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n },\n },\n defaultVariants: {\n zSize: 'default',\n },\n});\n\n// Outer dot ring\nexport const zTimelineDotVariants = cva(\n ['flex shrink-0 items-center justify-center rounded-full bg-primary/10 transition-colors duration-300'],\n {\n variants: {\n zSize: {\n sm: 'size-4.5',\n default: 'size-6',\n lg: 'size-7',\n },\n },\n defaultVariants: {\n zSize: 'default',\n },\n }\n);\n\n// Inner dot\nexport const zTimelineInnerDotVariants = cva(['rounded-full bg-primary transition-colors duration-300'], {\n variants: {\n zSize: {\n sm: 'size-2',\n default: 'size-3',\n lg: 'size-3.5',\n },\n },\n defaultVariants: {\n zSize: 'default',\n },\n});\n\n// Time badge\nexport const zTimelineTimeBadgeVariants = cva(\n [\n 'inline-flex w-fit max-w-full shrink-0 items-center justify-center rounded-md bg-primary px-2 py-0.5 text-sm font-semibold leading-tight text-primary-foreground transition-colors duration-300',\n ],\n {\n variants: {\n zSize: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-sm',\n },\n },\n defaultVariants: {\n zSize: 'default',\n },\n }\n);\n\n// Title\nexport const zTimelineTitleVariants = cva(['font-medium leading-snug text-foreground'], {\n variants: {\n zSize: {\n sm: 'text-sm',\n default: 'text-base md:text-lg',\n lg: 'text-lg md:text-xl',\n },\n },\n defaultVariants: {\n zSize: 'default',\n },\n});\n\n// Description\nexport const zTimelineDescriptionVariants = cva(['text-muted-foreground leading-relaxed'], {\n variants: {\n zSize: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: {\n zSize: 'default',\n },\n});\n\nexport type ZTimelineVariants = VariantProps<typeof zTimelineVariants>;\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n signal,\n viewChildren,\n ViewEncapsulation,\n} from '@angular/core';\nimport { ZIconComponent } from '@shival99/z-ui/components/z-icon';\nimport { zMergeClasses } from '@shival99/z-ui/utils';\nimport type { ClassValue } from 'clsx';\nimport type { ZTimelineItem, ZTimelineLayout, ZTimelineSize } from './z-timeline.types';\nimport {\n zTimelineDescriptionVariants,\n zTimelineDotVariants,\n zTimelineInnerDotVariants,\n zTimelineTimeBadgeVariants,\n zTimelineTitleVariants,\n zTimelineVariants,\n} from './z-timeline.variants';\n\n@Component({\n selector: 'z-timeline',\n imports: [NgTemplateOutlet, ZIconComponent],\n standalone: true,\n templateUrl: './z-timeline.component.html',\n styles: `\n .z-timeline {\n container-type: inline-size;\n }\n\n .z-timeline-default-mobile-meta {\n display: none;\n }\n\n .z-timeline-progress-dot {\n background: var(--primary);\n transition:\n background-color 180ms ease,\n border-color 180ms ease,\n box-shadow 180ms ease;\n }\n\n .z-timeline-progress-dot-ring {\n background: color-mix(in oklab, var(--primary) 14%, transparent);\n transition: background-color 180ms ease;\n }\n\n .z-timeline-progress-line {\n background: var(--primary);\n transition: height 120ms linear;\n }\n\n .z-timeline-progress-inactive .z-timeline-progress-dot-ring {\n background: var(--border);\n }\n\n .z-timeline-progress-inactive .z-timeline-progress-dot {\n background: var(--muted-foreground);\n border-color: var(--border);\n }\n\n @container (max-width: 34rem) {\n .z-timeline-default-item {\n grid-template-columns: 1.5rem minmax(0, 1fr);\n }\n\n .z-timeline-default-meta {\n display: none;\n }\n\n .z-timeline-default-mobile-meta {\n display: flex;\n }\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ZTimelineComponent {\n public readonly class = input<ClassValue>('');\n public readonly zItems = input<ZTimelineItem[]>([]);\n public readonly zSize = input<ZTimelineSize>('default');\n public readonly zLayout = input<ZTimelineLayout>('default');\n public readonly zScrollProgress = input(false, { transform: booleanAttribute });\n\n private readonly _destroyRef = inject(DestroyRef);\n private readonly _timelineItems = viewChildren<ElementRef<HTMLElement>>('timelineItem');\n private readonly _progressRatio = signal(0);\n\n protected readonly hostClasses = computed(() =>\n zMergeClasses(zTimelineVariants({ zSize: this.zSize() }), this.class())\n );\n\n protected readonly dotClasses = computed(() => zTimelineDotVariants({ zSize: this.zSize() }));\n\n protected readonly innerDotClasses = computed(() => zTimelineInnerDotVariants({ zSize: this.zSize() }));\n\n protected readonly badgeClasses = computed(() => zTimelineTimeBadgeVariants({ zSize: this.zSize() }));\n\n protected readonly titleClasses = computed(() => zTimelineTitleVariants({ zSize: this.zSize() }));\n\n protected readonly descriptionClasses = computed(() => zTimelineDescriptionVariants({ zSize: this.zSize() }));\n\n protected readonly isCareer = computed(() => this.zLayout() === 'career');\n\n protected readonly isAlternate = computed(() => this.zLayout() === 'alternate');\n\n protected readonly progressStates = computed(() => {\n const items = this.zItems();\n\n if (!this.zScrollProgress()) {\n return items.map(() => true);\n }\n\n const lastIndex = items.length - 1;\n const progressRatio = this._progressRatio();\n if (lastIndex <= 0) {\n return items.map(() => progressRatio > 0);\n }\n\n return items.map((_item, index) => {\n if (index === 0) {\n return progressRatio > 0;\n }\n\n return progressRatio >= index / lastIndex;\n });\n });\n\n protected readonly progressLineHeight = computed(() => {\n if (!this.zScrollProgress()) {\n return '100%';\n }\n\n return `${this._progressRatio() * 100}%`;\n });\n\n protected readonly progressSegments = computed(() => {\n const items = this.zItems();\n const lastIndex = items.length - 1;\n\n if (!this.zScrollProgress()) {\n return items.map(() => '100%');\n }\n\n if (lastIndex <= 0) {\n return items.map(() => `${this._progressRatio() * 100}%`);\n }\n\n const progressRatio = this._progressRatio();\n return items.map((_item, index) => {\n const segmentStart = index / lastIndex;\n const segmentEnd = (index + 1) / lastIndex;\n const segmentProgress = (progressRatio - segmentStart) / (segmentEnd - segmentStart);\n const boundedProgress = Math.min(Math.max(segmentProgress, 0), 1);\n\n return `${boundedProgress * 100}%`;\n });\n });\n\n constructor() {\n effect(onCleanup => {\n if (!this.zScrollProgress()) {\n this._progressRatio.set(0);\n return;\n }\n\n if (typeof window === 'undefined') {\n this._progressRatio.set(1);\n return;\n }\n\n const elements = this._timelineItems().map(item => item.nativeElement);\n if (!elements.length) {\n this._progressRatio.set(0);\n return;\n }\n\n let animationFrame: number | null = null;\n\n const updateProgress = (): void => {\n this._progressRatio.set(this._calculateProgressRatio(elements));\n };\n\n const scheduleUpdate = (): void => {\n if (animationFrame !== null) {\n return;\n }\n\n animationFrame = window.requestAnimationFrame(() => {\n animationFrame = null;\n updateProgress();\n });\n };\n\n scheduleUpdate();\n window.addEventListener('scroll', scheduleUpdate, { passive: true });\n window.addEventListener('resize', scheduleUpdate);\n\n onCleanup(() => {\n window.removeEventListener('scroll', scheduleUpdate);\n window.removeEventListener('resize', scheduleUpdate);\n\n if (animationFrame === null) {\n return;\n }\n\n window.cancelAnimationFrame(animationFrame);\n });\n });\n\n this._destroyRef.onDestroy(() => this._progressRatio.set(0));\n }\n\n private _calculateProgressRatio(elements: HTMLElement[]): number {\n if (!elements.length) {\n return 0;\n }\n\n const triggerY = window.innerHeight * 0.55;\n const itemTops = elements.map(element => element.getBoundingClientRect().top);\n const firstTop = itemTops[0];\n const lastTop = itemTops[itemTops.length - 1];\n\n if (triggerY <= firstTop) {\n return 0;\n }\n\n if (triggerY >= lastTop) {\n return 1;\n }\n\n const activeSegmentIndex = itemTops.findIndex((top, index) => {\n const nextTop = itemTops[index + 1];\n if (nextTop === undefined) {\n return false;\n }\n\n return triggerY >= top && triggerY < nextTop;\n });\n\n if (activeSegmentIndex < 0) {\n return 0;\n }\n\n const segmentStart = itemTops[activeSegmentIndex];\n const segmentEnd = itemTops[activeSegmentIndex + 1];\n const segmentDistance = segmentEnd - segmentStart;\n if (segmentDistance <= 0) {\n return 0;\n }\n\n const localProgress = (triggerY - segmentStart) / segmentDistance;\n return (activeSegmentIndex + localProgress) / (itemTops.length - 1);\n }\n}\n","@if (isCareer()) {\n <!-- ══════════════════════════════════════════════════════════ -->\n <!-- CAREER / EXPERIENCE LAYOUT -->\n <!-- ══════════════════════════════════════════════════════════ -->\n @let progress = progressStates();\n <div class=\"mx-auto w-full max-w-3xl px-2 sm:px-4\">\n <div class=\"relative ml-3\">\n <div class=\"bg-border absolute top-3 bottom-3 left-0 w-0.5 overflow-hidden\">\n <div\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-0.5\"\n [style.height]=\"zScrollProgress() ? progressLineHeight() : '0%'\"></div>\n </div>\n\n @for (item of zItems(); track item.id ?? $index; let isLast = $last) {\n @let isActive = progress[$index];\n <article\n #timelineItem\n class=\"relative pb-10 pl-8\"\n [class.pb-0]=\"isLast\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <span\n class=\"bg-background border-primary absolute top-2 left-0 z-[1] size-3 -translate-x-1/2 rounded-full border-2\"\n [class.z-timeline-progress-dot]=\"zScrollProgress()\"></span>\n\n <div class=\"space-y-3\">\n <div class=\"flex items-center gap-2.5\">\n <div class=\"bg-accent flex size-9 shrink-0 items-center justify-center rounded-full\">\n <z-icon [zType]=\"item.icon ?? 'lucideBuilding2'\" zSize=\"18\" class=\"text-muted-foreground\" />\n </div>\n <span class=\"text-base font-medium\">{{ item.company ?? item.subtitle ?? 'Experience' }}</span>\n </div>\n\n <div class=\"space-y-2\">\n <h3 class=\"text-foreground text-xl leading-tight font-semibold tracking-[-0.01em]\">{{ item.title }}</h3>\n @if (item.period || item.time) {\n <div class=\"text-muted-foreground flex items-center gap-2 text-sm\">\n <z-icon zType=\"lucideCalendar\" zSize=\"15\" class=\"shrink-0\" />\n <span>{{ item.period ?? item.time }}</span>\n </div>\n }\n </div>\n\n @if (item.description) {\n <p class=\"text-muted-foreground text-sm leading-relaxed sm:text-base\">{{ item.description }}</p>\n }\n\n @if (item.technologies?.length) {\n <div class=\"flex flex-wrap gap-2\">\n @for (tech of item.technologies; track tech) {\n <span\n class=\"bg-secondary text-secondary-foreground inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-medium\">\n {{ tech }}\n </span>\n }\n </div>\n }\n\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </article>\n }\n </div>\n </div>\n} @else if (isAlternate()) {\n <!-- ══════════════════════════════════════════════════════════ -->\n <!-- ALTERNATE / ZIGZAG LAYOUT -->\n <!-- ══════════════════════════════════════════════════════════ -->\n @let progress = progressStates();\n <div class=\"relative mx-auto max-w-7xl space-y-4\">\n @for (item of zItems(); track item.id ?? $index; let isEven = $even) {\n @let isActive = progress[$index];\n <div\n #timelineItem\n class=\"flex items-start md:flex-row\"\n [class.md:flex-row-reverse]=\"!isEven\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <!-- Opposite-side badge (desktop only) -->\n <div\n class=\"hidden w-full md:flex md:flex-1 md:items-start\"\n [class.md:justify-end]=\"isEven\"\n [class.md:justify-start]=\"!isEven\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\">{{ item.time }}</span>\n }\n </div>\n\n <!-- Center marker column -->\n <div class=\"relative flex flex-col items-center pr-4 md:px-4\">\n <div class=\"z-40 flex items-center justify-center\">\n <span [class]=\"dotClasses()\" [class.z-timeline-progress-dot-ring]=\"true\">\n <span [class]=\"innerDotClasses()\" [class.z-timeline-progress-dot]=\"true\"></span>\n </span>\n </div>\n </div>\n\n <!-- Content side -->\n <div class=\"w-full md:flex md:flex-1\" [class.md:justify-start]=\"isEven\" [class.md:justify-end]=\"!isEven\">\n <!-- Mobile badge -->\n @if (item.time) {\n <span [class]=\"badgeClasses()\" class=\"mb-4 block text-left md:hidden\">{{ item.time }}</span>\n }\n\n <div>\n <!-- Card -->\n <div\n class=\"bg-card text-card-foreground mb-8 flex flex-col gap-6 overflow-hidden rounded-xl border py-6 shadow-sm md:max-w-136\">\n <div class=\"space-y-4 px-6\">\n <div [class]=\"titleClasses()\">{{ item.title }}</div>\n @if (item.description) {\n <p [class]=\"descriptionClasses()\">{{ item.description }}</p>\n }\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n }\n\n <!-- Vertical line (absolute, behind everything) -->\n <div class=\"bg-border absolute top-3 bottom-3 left-3 w-0.5 overflow-hidden md:left-1/2 md:-translate-x-1/2\">\n <div\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-0.5 rounded-full\"\n [style.height]=\"progressLineHeight()\"></div>\n </div>\n </div>\n} @else {\n <!-- ══════════════════════════════════════════════════════════ -->\n <!-- DEFAULT / CHANGELOG LAYOUT -->\n <!-- ══════════════════════════════════════════════════════════ -->\n @let progress = progressStates();\n @let segments = progressSegments();\n @for (item of zItems(); track item.id ?? $index; let isLast = $last) {\n @let isActive = progress[$index];\n <article\n #timelineItem\n class=\"z-timeline-default-item relative grid grid-cols-[7rem_1.5rem_minmax(0,1fr)] gap-x-3\"\n [class.z-timeline-progress-inactive]=\"zScrollProgress() && !isActive\">\n <!-- Left: badge + subtitle (desktop only) -->\n <div class=\"z-timeline-default-meta flex min-w-0 flex-col items-end gap-2 self-start pb-4\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\">{{ item.time }}</span>\n }\n @if (item.subtitle) {\n <div class=\"text-muted-foreground max-w-full text-right text-sm leading-snug font-medium\">\n {{ item.subtitle }}\n </div>\n }\n </div>\n\n <!-- Center: dot + line -->\n <div class=\"relative flex flex-col items-center\">\n <div class=\"bg-background relative z-[1] flex size-6 items-center justify-center rounded-full\">\n <span [class]=\"dotClasses()\" [class.z-timeline-progress-dot-ring]=\"true\">\n <span [class]=\"innerDotClasses()\" [class.z-timeline-progress-dot]=\"true\"></span>\n </span>\n </div>\n @if (!isLast) {\n <span class=\"bg-border absolute top-6 bottom-0 left-1/2 w-px -translate-x-1/2 overflow-hidden rounded-full\">\n @if (zScrollProgress()) {\n <span\n class=\"z-timeline-progress-line absolute inset-x-0 top-0 w-px rounded-full\"\n [style.height]=\"segments[$index]\"></span>\n }\n </span>\n <span class=\"w-px flex-1\"></span>\n }\n </div>\n\n <!-- Right: content -->\n <div class=\"z-timeline-default-content flex min-w-0 flex-col gap-4 pb-10 pl-1\">\n <!-- Mobile badge + subtitle -->\n <div class=\"z-timeline-default-mobile-meta flex-col gap-2\">\n @if (item.time) {\n <span [class]=\"badgeClasses()\" class=\"w-fit\">{{ item.time }}</span>\n }\n @if (item.subtitle) {\n <div class=\"text-muted-foreground text-sm font-medium\">{{ item.subtitle }}</div>\n }\n </div>\n\n <!-- Content -->\n <div class=\"min-w-0 space-y-4\">\n <div class=\"space-y-3\">\n <h3 [class]=\"titleClasses()\">{{ item.title }}</h3>\n @if (item.description) {\n <p [class]=\"descriptionClasses()\">{{ item.description }}</p>\n }\n </div>\n @if (item.contentTemplate) {\n <ng-container [ngTemplateOutlet]=\"item.contentTemplate\" />\n }\n </div>\n </div>\n </article>\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -69,26 +69,46 @@ const zToastVariants = cva('group toast group-[.toaster]:bg-background group-[.t
69
69
  class ZToastComponent {
70
70
  _themeService = inject(ZThemeService);
71
71
  _config = inject(Z_TOASTER_CONFIG, { optional: true }) ?? Z_TOASTER_DEFAULT_CONFIG;
72
- class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
73
- zVariant = input('default', ...(ngDevMode ? [{ debugName: "zVariant" }] : []));
74
- zTheme = input(...(ngDevMode ? [undefined, { debugName: "zTheme" }] : []));
75
- zPosition = input(...(ngDevMode ? [undefined, { debugName: "zPosition" }] : []));
76
- zRichColors = input(...(ngDevMode ? [undefined, { debugName: "zRichColors" }] : []));
77
- zExpand = input(...(ngDevMode ? [undefined, { debugName: "zExpand" }] : []));
78
- zDuration = input(...(ngDevMode ? [undefined, { debugName: "zDuration" }] : []));
79
- zVisibleToasts = input(...(ngDevMode ? [undefined, { debugName: "zVisibleToasts" }] : []));
80
- zCloseButton = input(...(ngDevMode ? [undefined, { debugName: "zCloseButton" }] : []));
81
- zToastOptions = input({}, ...(ngDevMode ? [{ debugName: "zToastOptions" }] : []));
82
- zDir = input(...(ngDevMode ? [undefined, { debugName: "zDir" }] : []));
83
- effectiveTheme = computed(() => this.zTheme() ?? this._config.zTheme ?? 'system', ...(ngDevMode ? [{ debugName: "effectiveTheme" }] : []));
84
- effectivePosition = computed(() => this.zPosition() ?? this._config.zPosition ?? 'bottom-right', ...(ngDevMode ? [{ debugName: "effectivePosition" }] : []));
85
- effectiveRichColors = computed(() => this.zRichColors() ?? this._config.zRichColors ?? true, ...(ngDevMode ? [{ debugName: "effectiveRichColors" }] : []));
86
- effectiveExpand = computed(() => this.zExpand() ?? this._config.zExpand ?? false, ...(ngDevMode ? [{ debugName: "effectiveExpand" }] : []));
87
- effectiveDuration = computed(() => this.zDuration() ?? this._config.zDuration ?? 4000, ...(ngDevMode ? [{ debugName: "effectiveDuration" }] : []));
88
- effectiveVisibleToasts = computed(() => this.zVisibleToasts() ?? this._config.zVisibleToasts ?? 3, ...(ngDevMode ? [{ debugName: "effectiveVisibleToasts" }] : []));
89
- effectiveCloseButton = computed(() => this.zCloseButton() ?? this._config.zCloseButton ?? false, ...(ngDevMode ? [{ debugName: "effectiveCloseButton" }] : []));
90
- effectiveDir = computed(() => this.zDir() ?? this._config.zDir ?? 'auto', ...(ngDevMode ? [{ debugName: "effectiveDir" }] : []));
91
- zClasses = computed(() => zMergeClasses('toaster group', zToastVariants({ zVariant: this.zVariant() }), this.class()), ...(ngDevMode ? [{ debugName: "zClasses" }] : []));
72
+ class = input('', /* @ts-ignore */
73
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
74
+ zVariant = input('default', /* @ts-ignore */
75
+ ...(ngDevMode ? [{ debugName: "zVariant" }] : /* istanbul ignore next */ []));
76
+ zTheme = input(/* @ts-ignore */
77
+ ...(ngDevMode ? [undefined, { debugName: "zTheme" }] : /* istanbul ignore next */ []));
78
+ zPosition = input(/* @ts-ignore */
79
+ ...(ngDevMode ? [undefined, { debugName: "zPosition" }] : /* istanbul ignore next */ []));
80
+ zRichColors = input(/* @ts-ignore */
81
+ ...(ngDevMode ? [undefined, { debugName: "zRichColors" }] : /* istanbul ignore next */ []));
82
+ zExpand = input(/* @ts-ignore */
83
+ ...(ngDevMode ? [undefined, { debugName: "zExpand" }] : /* istanbul ignore next */ []));
84
+ zDuration = input(/* @ts-ignore */
85
+ ...(ngDevMode ? [undefined, { debugName: "zDuration" }] : /* istanbul ignore next */ []));
86
+ zVisibleToasts = input(/* @ts-ignore */
87
+ ...(ngDevMode ? [undefined, { debugName: "zVisibleToasts" }] : /* istanbul ignore next */ []));
88
+ zCloseButton = input(/* @ts-ignore */
89
+ ...(ngDevMode ? [undefined, { debugName: "zCloseButton" }] : /* istanbul ignore next */ []));
90
+ zToastOptions = input({}, /* @ts-ignore */
91
+ ...(ngDevMode ? [{ debugName: "zToastOptions" }] : /* istanbul ignore next */ []));
92
+ zDir = input(/* @ts-ignore */
93
+ ...(ngDevMode ? [undefined, { debugName: "zDir" }] : /* istanbul ignore next */ []));
94
+ effectiveTheme = computed(() => this.zTheme() ?? this._config.zTheme ?? 'system', /* @ts-ignore */
95
+ ...(ngDevMode ? [{ debugName: "effectiveTheme" }] : /* istanbul ignore next */ []));
96
+ effectivePosition = computed(() => this.zPosition() ?? this._config.zPosition ?? 'bottom-right', /* @ts-ignore */
97
+ ...(ngDevMode ? [{ debugName: "effectivePosition" }] : /* istanbul ignore next */ []));
98
+ effectiveRichColors = computed(() => this.zRichColors() ?? this._config.zRichColors ?? true, /* @ts-ignore */
99
+ ...(ngDevMode ? [{ debugName: "effectiveRichColors" }] : /* istanbul ignore next */ []));
100
+ effectiveExpand = computed(() => this.zExpand() ?? this._config.zExpand ?? false, /* @ts-ignore */
101
+ ...(ngDevMode ? [{ debugName: "effectiveExpand" }] : /* istanbul ignore next */ []));
102
+ effectiveDuration = computed(() => this.zDuration() ?? this._config.zDuration ?? 4000, /* @ts-ignore */
103
+ ...(ngDevMode ? [{ debugName: "effectiveDuration" }] : /* istanbul ignore next */ []));
104
+ effectiveVisibleToasts = computed(() => this.zVisibleToasts() ?? this._config.zVisibleToasts ?? 3, /* @ts-ignore */
105
+ ...(ngDevMode ? [{ debugName: "effectiveVisibleToasts" }] : /* istanbul ignore next */ []));
106
+ effectiveCloseButton = computed(() => this.zCloseButton() ?? this._config.zCloseButton ?? false, /* @ts-ignore */
107
+ ...(ngDevMode ? [{ debugName: "effectiveCloseButton" }] : /* istanbul ignore next */ []));
108
+ effectiveDir = computed(() => this.zDir() ?? this._config.zDir ?? 'auto', /* @ts-ignore */
109
+ ...(ngDevMode ? [{ debugName: "effectiveDir" }] : /* istanbul ignore next */ []));
110
+ zClasses = computed(() => zMergeClasses('toaster group', zToastVariants({ zVariant: this.zVariant() }), this.class()), /* @ts-ignore */
111
+ ...(ngDevMode ? [{ debugName: "zClasses" }] : /* istanbul ignore next */ []));
92
112
  offsetCompatStyles = Z_TOAST_OFFSET_COMPAT_STYLES;
93
113
  detectTheme = computed(() => {
94
114
  const theme = this.effectiveTheme();
@@ -96,11 +116,12 @@ class ZToastComponent {
96
116
  return theme;
97
117
  }
98
118
  return this._themeService.isDark() ? 'dark' : 'light';
99
- }, ...(ngDevMode ? [{ debugName: "detectTheme" }] : []));
100
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
101
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.9", type: ZToastComponent, isStandalone: true, selector: "z-toast, z-toaster", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zVariant: { classPropertyName: "zVariant", publicName: "zVariant", isSignal: true, isRequired: false, transformFunction: null }, zTheme: { classPropertyName: "zTheme", publicName: "zTheme", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zRichColors: { classPropertyName: "zRichColors", publicName: "zRichColors", isSignal: true, isRequired: false, transformFunction: null }, zExpand: { classPropertyName: "zExpand", publicName: "zExpand", isSignal: true, isRequired: false, transformFunction: null }, zDuration: { classPropertyName: "zDuration", publicName: "zDuration", isSignal: true, isRequired: false, transformFunction: null }, zVisibleToasts: { classPropertyName: "zVisibleToasts", publicName: "zVisibleToasts", isSignal: true, isRequired: false, transformFunction: null }, zCloseButton: { classPropertyName: "zCloseButton", publicName: "zCloseButton", isSignal: true, isRequired: false, transformFunction: null }, zToastOptions: { classPropertyName: "zToastOptions", publicName: "zToastOptions", isSignal: true, isRequired: false, transformFunction: null }, zDir: { classPropertyName: "zDir", publicName: "zDir", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["zToast"], ngImport: i0, template: "<ngx-sonner-toaster\n [theme]=\"detectTheme()\"\n [class]=\"zClasses()\"\n [position]=\"effectivePosition()\"\n [richColors]=\"effectiveRichColors()\"\n [expand]=\"effectiveExpand()\"\n [duration]=\"effectiveDuration()\"\n [visibleToasts]=\"effectiveVisibleToasts()\"\n [closeButton]=\"effectiveCloseButton()\"\n [toastOptions]=\"zToastOptions()\"\n [dir]=\"effectiveDir()\"\n [style]=\"offsetCompatStyles\" />\n", dependencies: [{ kind: "component", type: NgxSonnerToaster, selector: "ngx-sonner-toaster", inputs: ["invert", "theme", "position", "hotKey", "richColors", "expand", "duration", "visibleToasts", "closeButton", "toastOptions", "offset", "dir", "class", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
119
+ }, /* @ts-ignore */
120
+ ...(ngDevMode ? [{ debugName: "detectTheme" }] : /* istanbul ignore next */ []));
121
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
122
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.2", type: ZToastComponent, isStandalone: true, selector: "z-toast, z-toaster", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zVariant: { classPropertyName: "zVariant", publicName: "zVariant", isSignal: true, isRequired: false, transformFunction: null }, zTheme: { classPropertyName: "zTheme", publicName: "zTheme", isSignal: true, isRequired: false, transformFunction: null }, zPosition: { classPropertyName: "zPosition", publicName: "zPosition", isSignal: true, isRequired: false, transformFunction: null }, zRichColors: { classPropertyName: "zRichColors", publicName: "zRichColors", isSignal: true, isRequired: false, transformFunction: null }, zExpand: { classPropertyName: "zExpand", publicName: "zExpand", isSignal: true, isRequired: false, transformFunction: null }, zDuration: { classPropertyName: "zDuration", publicName: "zDuration", isSignal: true, isRequired: false, transformFunction: null }, zVisibleToasts: { classPropertyName: "zVisibleToasts", publicName: "zVisibleToasts", isSignal: true, isRequired: false, transformFunction: null }, zCloseButton: { classPropertyName: "zCloseButton", publicName: "zCloseButton", isSignal: true, isRequired: false, transformFunction: null }, zToastOptions: { classPropertyName: "zToastOptions", publicName: "zToastOptions", isSignal: true, isRequired: false, transformFunction: null }, zDir: { classPropertyName: "zDir", publicName: "zDir", isSignal: true, isRequired: false, transformFunction: null } }, exportAs: ["zToast"], ngImport: i0, template: "<ngx-sonner-toaster\n [theme]=\"detectTheme()\"\n [class]=\"zClasses()\"\n [position]=\"effectivePosition()\"\n [richColors]=\"effectiveRichColors()\"\n [expand]=\"effectiveExpand()\"\n [duration]=\"effectiveDuration()\"\n [visibleToasts]=\"effectiveVisibleToasts()\"\n [closeButton]=\"effectiveCloseButton()\"\n [toastOptions]=\"zToastOptions()\"\n [dir]=\"effectiveDir()\"\n [style]=\"offsetCompatStyles\" />\n", dependencies: [{ kind: "component", type: NgxSonnerToaster, selector: "ngx-sonner-toaster", inputs: ["invert", "theme", "position", "hotKey", "richColors", "expand", "duration", "visibleToasts", "closeButton", "toastOptions", "offset", "dir", "class", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
102
123
  }
103
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastComponent, decorators: [{
124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastComponent, decorators: [{
104
125
  type: Component,
105
126
  args: [{ selector: 'z-toast, z-toaster', imports: [NgxSonnerToaster], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, exportAs: 'zToast', template: "<ngx-sonner-toaster\n [theme]=\"detectTheme()\"\n [class]=\"zClasses()\"\n [position]=\"effectivePosition()\"\n [richColors]=\"effectiveRichColors()\"\n [expand]=\"effectiveExpand()\"\n [duration]=\"effectiveDuration()\"\n [visibleToasts]=\"effectiveVisibleToasts()\"\n [closeButton]=\"effectiveCloseButton()\"\n [toastOptions]=\"zToastOptions()\"\n [dir]=\"effectiveDir()\"\n [style]=\"offsetCompatStyles\" />\n" }]
106
127
  }], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "zVariant", required: false }] }], zTheme: [{ type: i0.Input, args: [{ isSignal: true, alias: "zTheme", required: false }] }], zPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "zPosition", required: false }] }], zRichColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "zRichColors", required: false }] }], zExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "zExpand", required: false }] }], zDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDuration", required: false }] }], zVisibleToasts: [{ type: i0.Input, args: [{ isSignal: true, alias: "zVisibleToasts", required: false }] }], zCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "zCloseButton", required: false }] }], zToastOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "zToastOptions", required: false }] }], zDir: [{ type: i0.Input, args: [{ isSignal: true, alias: "zDir", required: false }] }] } });
@@ -286,17 +307,18 @@ class ZToastService {
286
307
  }
287
308
  return this._zTranslate.instant(message) || message;
288
309
  }
289
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
290
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastService, providedIn: 'root' });
310
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
311
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastService, providedIn: 'root' });
291
312
  }
292
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastService, decorators: [{
313
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastService, decorators: [{
293
314
  type: Injectable,
294
315
  args: [{ providedIn: 'root' }]
295
316
  }] });
296
317
 
297
318
  class ZToastCustomComponent {
298
319
  _toastService = inject(ZToastService);
299
- config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
320
+ config = input.required(/* @ts-ignore */
321
+ ...(ngDevMode ? [{ debugName: "config" }] : /* istanbul ignore next */ []));
300
322
  dismiss() {
301
323
  const id = this.config().toastId;
302
324
  if (id !== undefined) {
@@ -359,10 +381,10 @@ class ZToastCustomComponent {
359
381
  return 'text-zinc-500 hover:text-zinc-600 dark:text-zinc-400 dark:hover:text-zinc-300';
360
382
  }
361
383
  }
362
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastCustomComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
363
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.9", type: ZToastCustomComponent, isStandalone: true, selector: "z-toast-custom", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"border-border bg-card relative flex w-full max-w-[480px] flex-col gap-4 rounded-xl border p-4 font-sans shadow-lg md:flex-row md:items-start\"\n [class.min-w-[340px]]=\"config().type !== 'image'\"\n [class.md:p-0]=\"config().type === 'image'\"\n [class.overflow-hidden]=\"config().type === 'image'\">\n <!-- Content for layout types -->\n @if (config().type === 'image') {\n <!-- Style 1: D\u1EA1ng th\u00F4ng b\u00E1o ch\u1EE9a \u1EA3nh phong c\u1EA3nh n\u1EB1m b\u00EAn tr\u00E1i (desktop) ho\u1EB7c b\u00EAn tr\u00EAn (mobile) -->\n <div class=\"flex w-full flex-col md:flex-row\">\n <!-- \u1EA2nh tr\u00EAn Desktop -->\n @if (config().imageUrl) {\n <div class=\"border-border hidden w-32 shrink-0 overflow-hidden rounded-l-xl border-r md:block\">\n <img [src]=\"config().imageUrl\" alt=\"Notification image\" class=\"h-full w-full object-cover\" />\n </div>\n <!-- \u1EA2nh tr\u00EAn Mobile -->\n <div class=\"block h-32 w-full overflow-hidden rounded-t-xl md:hidden\">\n <img [src]=\"config().imageUrl\" alt=\"Notification image\" class=\"h-full w-full object-cover\" />\n </div>\n }\n\n <!-- N\u1ED9i dung ch\u1EEF v\u00E0 c\u00E1c n\u00FAt h\u00E0nh \u0111\u1ED9ng -->\n <div class=\"flex flex-1 flex-col gap-3 p-4\">\n <div class=\"flex flex-col gap-1 pr-6\">\n <p class=\"text-foreground text-sm font-semibold\">{{ config().title }}</p>\n @if (config().description) {\n <p class=\"text-muted-foreground text-sm\">{{ config().description }}</p>\n }\n </div>\n\n <!-- N\u00FAt h\u00E0nh \u0111\u1ED9ng -->\n @if (config().actions && config().actions!.length > 0) {\n <div class=\"flex gap-3\">\n @for (action of config().actions; track $index) {\n <button\n (click)=\"handleAction(action)\"\n class=\"cursor-pointer text-sm font-semibold hover:underline\"\n [class]=\"getActionClasses(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Style 2: C\u00E1c d\u1EA1ng th\u00F4ng b\u00E1o ti\u00EAu chu\u1EA9n (Alert, Avatar, Progress, Default) -->\n\n <!-- Icon ho\u1EB7c Avatar \u1EDF g\u00F3c tr\u00E1i -->\n @if (config().type === 'avatar' && config().avatarUrl) {\n <div class=\"relative flex size-10 shrink-0 rounded-full\">\n <img\n [src]=\"config().avatarUrl\"\n [alt]=\"config().title\"\n class=\"border-border size-full rounded-full border object-cover\" />\n @if (config().avatarOnline) {\n <span\n class=\"ring-card absolute right-0 bottom-0 flex size-2.5 justify-center rounded-full bg-emerald-500 ring-[1.5px]\"></span>\n }\n </div>\n } @else if (config().type && config().type !== 'default') {\n <!-- Featured Icon wrapper v\u1EDBi hi\u1EC7u \u1EE9ng vi\u1EC1n \u0111\u1ED3ng t\u00E2m -->\n <div\n class=\"relative flex size-10 shrink-0 items-center justify-center rounded-full\"\n [class]=\"getFeaturedIconContainerClasses()\">\n <i z-icon [zType]=\"getFeaturedIconName()\" zSize=\"20\" class=\"z-10\"></i>\n </div>\n }\n\n <!-- Ti\u00EAu \u0111\u1EC1, m\u00F4 t\u1EA3 v\u00E0 thanh ti\u1EBFn tr\u00ECnh -->\n <div class=\"flex flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-1 pr-6\">\n <p class=\"text-foreground text-sm font-semibold\">{{ config().title }}</p>\n @if (config().description) {\n <p class=\"text-muted-foreground text-sm\">{{ config().description }}</p>\n }\n </div>\n\n <!-- D\u1EA1ng Progress bar d\u00E0nh cho ti\u1EBFn tr\u00ECnh upload/t\u1EA3i xu\u1ED1ng -->\n @if (config().type === 'progress' && config().progress !== undefined) {\n <div class=\"flex w-full flex-col gap-1.5\">\n <div class=\"h-2 w-full overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-800\">\n <div\n class=\"bg-primary h-full rounded-md transition-all duration-300\"\n [style.width.%]=\"config().progress\"></div>\n </div>\n <span class=\"text-muted-foreground text-xs font-medium tabular-nums\">\n {{ config().progress }}% uploaded...\n </span>\n </div>\n }\n\n <!-- C\u00E1c n\u00FAt h\u00E0nh \u0111\u1ED9ng b\u00EAn d\u01B0\u1EDBi th\u00F4ng b\u00E1o -->\n @if (config().actions && config().actions!.length > 0) {\n <div class=\"flex gap-3\">\n @for (action of config().actions; track $index) {\n <button\n (click)=\"handleAction(action)\"\n class=\"cursor-pointer text-sm font-semibold hover:underline\"\n [class]=\"getActionClasses(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- N\u00FAt \u0111\u00F3ng/t\u1EAFt th\u00F4ng b\u00E1o g\u00F3c tr\u00EAn b\u00EAn ph\u1EA3i -->\n @if (config().closeable !== false) {\n <button\n (click)=\"dismiss()\"\n aria-label=\"Close\"\n class=\"text-muted-foreground hover:text-foreground absolute top-3 right-3 flex cursor-pointer items-center justify-center rounded-lg p-1.5 transition duration-150 hover:bg-zinc-100 dark:hover:bg-zinc-800\">\n <i z-icon zType=\"lucideX\" zSize=\"16\"></i>\n </button>\n }\n</div>\n", dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
384
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastCustomComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
385
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: ZToastCustomComponent, isStandalone: true, selector: "z-toast-custom", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"border-border bg-card relative flex w-full max-w-[480px] flex-col gap-4 rounded-xl border p-4 font-sans shadow-lg md:flex-row md:items-start\"\n [class.min-w-[340px]]=\"config().type !== 'image'\"\n [class.md:p-0]=\"config().type === 'image'\"\n [class.overflow-hidden]=\"config().type === 'image'\">\n <!-- Content for layout types -->\n @if (config().type === 'image') {\n <!-- Style 1: D\u1EA1ng th\u00F4ng b\u00E1o ch\u1EE9a \u1EA3nh phong c\u1EA3nh n\u1EB1m b\u00EAn tr\u00E1i (desktop) ho\u1EB7c b\u00EAn tr\u00EAn (mobile) -->\n <div class=\"flex w-full flex-col md:flex-row\">\n <!-- \u1EA2nh tr\u00EAn Desktop -->\n @if (config().imageUrl) {\n <div class=\"border-border hidden w-32 shrink-0 overflow-hidden rounded-l-xl border-r md:block\">\n <img [src]=\"config().imageUrl\" alt=\"Notification image\" class=\"h-full w-full object-cover\" />\n </div>\n <!-- \u1EA2nh tr\u00EAn Mobile -->\n <div class=\"block h-32 w-full overflow-hidden rounded-t-xl md:hidden\">\n <img [src]=\"config().imageUrl\" alt=\"Notification image\" class=\"h-full w-full object-cover\" />\n </div>\n }\n\n <!-- N\u1ED9i dung ch\u1EEF v\u00E0 c\u00E1c n\u00FAt h\u00E0nh \u0111\u1ED9ng -->\n <div class=\"flex flex-1 flex-col gap-3 p-4\">\n <div class=\"flex flex-col gap-1 pr-6\">\n <p class=\"text-foreground text-sm font-semibold\">{{ config().title }}</p>\n @if (config().description) {\n <p class=\"text-muted-foreground text-sm\">{{ config().description }}</p>\n }\n </div>\n\n <!-- N\u00FAt h\u00E0nh \u0111\u1ED9ng -->\n @if (config().actions && config().actions!.length > 0) {\n <div class=\"flex gap-3\">\n @for (action of config().actions; track $index) {\n <button\n (click)=\"handleAction(action)\"\n class=\"cursor-pointer text-sm font-semibold hover:underline\"\n [class]=\"getActionClasses(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Style 2: C\u00E1c d\u1EA1ng th\u00F4ng b\u00E1o ti\u00EAu chu\u1EA9n (Alert, Avatar, Progress, Default) -->\n\n <!-- Icon ho\u1EB7c Avatar \u1EDF g\u00F3c tr\u00E1i -->\n @if (config().type === 'avatar' && config().avatarUrl) {\n <div class=\"relative flex size-10 shrink-0 rounded-full\">\n <img\n [src]=\"config().avatarUrl\"\n [alt]=\"config().title\"\n class=\"border-border size-full rounded-full border object-cover\" />\n @if (config().avatarOnline) {\n <span\n class=\"ring-card absolute right-0 bottom-0 flex size-2.5 justify-center rounded-full bg-emerald-500 ring-[1.5px]\"></span>\n }\n </div>\n } @else if (config().type && config().type !== 'default') {\n <!-- Featured Icon wrapper v\u1EDBi hi\u1EC7u \u1EE9ng vi\u1EC1n \u0111\u1ED3ng t\u00E2m -->\n <div\n class=\"relative flex size-10 shrink-0 items-center justify-center rounded-full\"\n [class]=\"getFeaturedIconContainerClasses()\">\n <i z-icon [zType]=\"getFeaturedIconName()\" zSize=\"20\" class=\"z-10\"></i>\n </div>\n }\n\n <!-- Ti\u00EAu \u0111\u1EC1, m\u00F4 t\u1EA3 v\u00E0 thanh ti\u1EBFn tr\u00ECnh -->\n <div class=\"flex flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-1 pr-6\">\n <p class=\"text-foreground text-sm font-semibold\">{{ config().title }}</p>\n @if (config().description) {\n <p class=\"text-muted-foreground text-sm\">{{ config().description }}</p>\n }\n </div>\n\n <!-- D\u1EA1ng Progress bar d\u00E0nh cho ti\u1EBFn tr\u00ECnh upload/t\u1EA3i xu\u1ED1ng -->\n @if (config().type === 'progress' && config().progress !== undefined) {\n <div class=\"flex w-full flex-col gap-1.5\">\n <div class=\"h-2 w-full overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-800\">\n <div\n class=\"bg-primary h-full rounded-md transition-all duration-300\"\n [style.width.%]=\"config().progress\"></div>\n </div>\n <span class=\"text-muted-foreground text-xs font-medium tabular-nums\">\n {{ config().progress }}% uploaded...\n </span>\n </div>\n }\n\n <!-- C\u00E1c n\u00FAt h\u00E0nh \u0111\u1ED9ng b\u00EAn d\u01B0\u1EDBi th\u00F4ng b\u00E1o -->\n @if (config().actions && config().actions!.length > 0) {\n <div class=\"flex gap-3\">\n @for (action of config().actions; track $index) {\n <button\n (click)=\"handleAction(action)\"\n class=\"cursor-pointer text-sm font-semibold hover:underline\"\n [class]=\"getActionClasses(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- N\u00FAt \u0111\u00F3ng/t\u1EAFt th\u00F4ng b\u00E1o g\u00F3c tr\u00EAn b\u00EAn ph\u1EA3i -->\n @if (config().closeable !== false) {\n <button\n (click)=\"dismiss()\"\n aria-label=\"Close\"\n class=\"text-muted-foreground hover:text-foreground absolute top-3 right-3 flex cursor-pointer items-center justify-center rounded-lg p-1.5 transition duration-150 hover:bg-zinc-100 dark:hover:bg-zinc-800\">\n <i z-icon zType=\"lucideX\" zSize=\"16\"></i>\n </button>\n }\n</div>\n", dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
364
386
  }
365
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.9", ngImport: i0, type: ZToastCustomComponent, decorators: [{
387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: ZToastCustomComponent, decorators: [{
366
388
  type: Component,
367
389
  args: [{ selector: 'z-toast-custom', imports: [ZIconComponent], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div\n class=\"border-border bg-card relative flex w-full max-w-[480px] flex-col gap-4 rounded-xl border p-4 font-sans shadow-lg md:flex-row md:items-start\"\n [class.min-w-[340px]]=\"config().type !== 'image'\"\n [class.md:p-0]=\"config().type === 'image'\"\n [class.overflow-hidden]=\"config().type === 'image'\">\n <!-- Content for layout types -->\n @if (config().type === 'image') {\n <!-- Style 1: D\u1EA1ng th\u00F4ng b\u00E1o ch\u1EE9a \u1EA3nh phong c\u1EA3nh n\u1EB1m b\u00EAn tr\u00E1i (desktop) ho\u1EB7c b\u00EAn tr\u00EAn (mobile) -->\n <div class=\"flex w-full flex-col md:flex-row\">\n <!-- \u1EA2nh tr\u00EAn Desktop -->\n @if (config().imageUrl) {\n <div class=\"border-border hidden w-32 shrink-0 overflow-hidden rounded-l-xl border-r md:block\">\n <img [src]=\"config().imageUrl\" alt=\"Notification image\" class=\"h-full w-full object-cover\" />\n </div>\n <!-- \u1EA2nh tr\u00EAn Mobile -->\n <div class=\"block h-32 w-full overflow-hidden rounded-t-xl md:hidden\">\n <img [src]=\"config().imageUrl\" alt=\"Notification image\" class=\"h-full w-full object-cover\" />\n </div>\n }\n\n <!-- N\u1ED9i dung ch\u1EEF v\u00E0 c\u00E1c n\u00FAt h\u00E0nh \u0111\u1ED9ng -->\n <div class=\"flex flex-1 flex-col gap-3 p-4\">\n <div class=\"flex flex-col gap-1 pr-6\">\n <p class=\"text-foreground text-sm font-semibold\">{{ config().title }}</p>\n @if (config().description) {\n <p class=\"text-muted-foreground text-sm\">{{ config().description }}</p>\n }\n </div>\n\n <!-- N\u00FAt h\u00E0nh \u0111\u1ED9ng -->\n @if (config().actions && config().actions!.length > 0) {\n <div class=\"flex gap-3\">\n @for (action of config().actions; track $index) {\n <button\n (click)=\"handleAction(action)\"\n class=\"cursor-pointer text-sm font-semibold hover:underline\"\n [class]=\"getActionClasses(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n <!-- Style 2: C\u00E1c d\u1EA1ng th\u00F4ng b\u00E1o ti\u00EAu chu\u1EA9n (Alert, Avatar, Progress, Default) -->\n\n <!-- Icon ho\u1EB7c Avatar \u1EDF g\u00F3c tr\u00E1i -->\n @if (config().type === 'avatar' && config().avatarUrl) {\n <div class=\"relative flex size-10 shrink-0 rounded-full\">\n <img\n [src]=\"config().avatarUrl\"\n [alt]=\"config().title\"\n class=\"border-border size-full rounded-full border object-cover\" />\n @if (config().avatarOnline) {\n <span\n class=\"ring-card absolute right-0 bottom-0 flex size-2.5 justify-center rounded-full bg-emerald-500 ring-[1.5px]\"></span>\n }\n </div>\n } @else if (config().type && config().type !== 'default') {\n <!-- Featured Icon wrapper v\u1EDBi hi\u1EC7u \u1EE9ng vi\u1EC1n \u0111\u1ED3ng t\u00E2m -->\n <div\n class=\"relative flex size-10 shrink-0 items-center justify-center rounded-full\"\n [class]=\"getFeaturedIconContainerClasses()\">\n <i z-icon [zType]=\"getFeaturedIconName()\" zSize=\"20\" class=\"z-10\"></i>\n </div>\n }\n\n <!-- Ti\u00EAu \u0111\u1EC1, m\u00F4 t\u1EA3 v\u00E0 thanh ti\u1EBFn tr\u00ECnh -->\n <div class=\"flex flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-1 pr-6\">\n <p class=\"text-foreground text-sm font-semibold\">{{ config().title }}</p>\n @if (config().description) {\n <p class=\"text-muted-foreground text-sm\">{{ config().description }}</p>\n }\n </div>\n\n <!-- D\u1EA1ng Progress bar d\u00E0nh cho ti\u1EBFn tr\u00ECnh upload/t\u1EA3i xu\u1ED1ng -->\n @if (config().type === 'progress' && config().progress !== undefined) {\n <div class=\"flex w-full flex-col gap-1.5\">\n <div class=\"h-2 w-full overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-800\">\n <div\n class=\"bg-primary h-full rounded-md transition-all duration-300\"\n [style.width.%]=\"config().progress\"></div>\n </div>\n <span class=\"text-muted-foreground text-xs font-medium tabular-nums\">\n {{ config().progress }}% uploaded...\n </span>\n </div>\n }\n\n <!-- C\u00E1c n\u00FAt h\u00E0nh \u0111\u1ED9ng b\u00EAn d\u01B0\u1EDBi th\u00F4ng b\u00E1o -->\n @if (config().actions && config().actions!.length > 0) {\n <div class=\"flex gap-3\">\n @for (action of config().actions; track $index) {\n <button\n (click)=\"handleAction(action)\"\n class=\"cursor-pointer text-sm font-semibold hover:underline\"\n [class]=\"getActionClasses(action)\">\n {{ action.label }}\n </button>\n }\n </div>\n }\n </div>\n }\n\n <!-- N\u00FAt \u0111\u00F3ng/t\u1EAFt th\u00F4ng b\u00E1o g\u00F3c tr\u00EAn b\u00EAn ph\u1EA3i -->\n @if (config().closeable !== false) {\n <button\n (click)=\"dismiss()\"\n aria-label=\"Close\"\n class=\"text-muted-foreground hover:text-foreground absolute top-3 right-3 flex cursor-pointer items-center justify-center rounded-lg p-1.5 transition duration-150 hover:bg-zinc-100 dark:hover:bg-zinc-800\">\n <i z-icon zType=\"lucideX\" zSize=\"16\"></i>\n </button>\n }\n</div>\n" }]
368
390
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }] } });