shirkasoft-ui-components 1.2.0 → 1.3.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 (79) hide show
  1. package/fesm2022/shirkasoft-ui-components-breadcrumb.mjs +199 -0
  2. package/fesm2022/shirkasoft-ui-components-breadcrumb.mjs.map +1 -0
  3. package/fesm2022/shirkasoft-ui-components-button.mjs +148 -0
  4. package/fesm2022/shirkasoft-ui-components-button.mjs.map +1 -0
  5. package/fesm2022/shirkasoft-ui-components-chart.mjs +153 -0
  6. package/fesm2022/shirkasoft-ui-components-chart.mjs.map +1 -0
  7. package/fesm2022/shirkasoft-ui-components-confirm-dialog.mjs +143 -0
  8. package/fesm2022/shirkasoft-ui-components-confirm-dialog.mjs.map +1 -0
  9. package/fesm2022/shirkasoft-ui-components-date-picker.mjs +638 -0
  10. package/fesm2022/shirkasoft-ui-components-date-picker.mjs.map +1 -0
  11. package/fesm2022/shirkasoft-ui-components-fieldset.mjs +94 -0
  12. package/fesm2022/shirkasoft-ui-components-fieldset.mjs.map +1 -0
  13. package/fesm2022/shirkasoft-ui-components-file-upload.mjs +242 -0
  14. package/fesm2022/shirkasoft-ui-components-file-upload.mjs.map +1 -0
  15. package/fesm2022/shirkasoft-ui-components-knob.mjs +269 -0
  16. package/fesm2022/shirkasoft-ui-components-knob.mjs.map +1 -0
  17. package/fesm2022/shirkasoft-ui-components-loading.mjs +255 -0
  18. package/fesm2022/shirkasoft-ui-components-loading.mjs.map +1 -0
  19. package/fesm2022/shirkasoft-ui-components-modal.mjs +290 -0
  20. package/fesm2022/shirkasoft-ui-components-modal.mjs.map +1 -0
  21. package/fesm2022/shirkasoft-ui-components-notification.mjs +143 -0
  22. package/fesm2022/shirkasoft-ui-components-notification.mjs.map +1 -0
  23. package/fesm2022/shirkasoft-ui-components-price-input.mjs +64 -0
  24. package/fesm2022/shirkasoft-ui-components-price-input.mjs.map +1 -0
  25. package/fesm2022/shirkasoft-ui-components-rail-sidebar.mjs +205 -0
  26. package/fesm2022/shirkasoft-ui-components-rail-sidebar.mjs.map +1 -0
  27. package/fesm2022/shirkasoft-ui-components-select.mjs +737 -0
  28. package/fesm2022/shirkasoft-ui-components-select.mjs.map +1 -0
  29. package/fesm2022/shirkasoft-ui-components-sidebar.mjs +185 -0
  30. package/fesm2022/shirkasoft-ui-components-sidebar.mjs.map +1 -0
  31. package/fesm2022/shirkasoft-ui-components-skeleton.mjs +74 -0
  32. package/fesm2022/shirkasoft-ui-components-skeleton.mjs.map +1 -0
  33. package/fesm2022/shirkasoft-ui-components-table.mjs +689 -0
  34. package/fesm2022/shirkasoft-ui-components-table.mjs.map +1 -0
  35. package/fesm2022/shirkasoft-ui-components-tabs.mjs +249 -0
  36. package/fesm2022/shirkasoft-ui-components-tabs.mjs.map +1 -0
  37. package/fesm2022/shirkasoft-ui-components-tag.mjs +70 -0
  38. package/fesm2022/shirkasoft-ui-components-tag.mjs.map +1 -0
  39. package/fesm2022/shirkasoft-ui-components-text-field.mjs +370 -0
  40. package/fesm2022/shirkasoft-ui-components-text-field.mjs.map +1 -0
  41. package/fesm2022/shirkasoft-ui-components-timeline.mjs +222 -0
  42. package/fesm2022/shirkasoft-ui-components-timeline.mjs.map +1 -0
  43. package/fesm2022/shirkasoft-ui-components-toggle.mjs +186 -0
  44. package/fesm2022/shirkasoft-ui-components-toggle.mjs.map +1 -0
  45. package/fesm2022/shirkasoft-ui-components-tooltip.mjs +169 -0
  46. package/fesm2022/shirkasoft-ui-components-tooltip.mjs.map +1 -0
  47. package/fesm2022/shirkasoft-ui-components-utils.mjs +64 -0
  48. package/fesm2022/shirkasoft-ui-components-utils.mjs.map +1 -0
  49. package/fesm2022/shirkasoft-ui-components-wizard.mjs +167 -0
  50. package/fesm2022/shirkasoft-ui-components-wizard.mjs.map +1 -0
  51. package/fesm2022/shirkasoft-ui-components.mjs +0 -5729
  52. package/fesm2022/shirkasoft-ui-components.mjs.map +1 -1
  53. package/package.json +101 -1
  54. package/types/shirkasoft-ui-components-breadcrumb.d.ts +68 -0
  55. package/types/shirkasoft-ui-components-button.d.ts +59 -0
  56. package/types/shirkasoft-ui-components-chart.d.ts +65 -0
  57. package/types/shirkasoft-ui-components-confirm-dialog.d.ts +88 -0
  58. package/types/shirkasoft-ui-components-date-picker.d.ts +200 -0
  59. package/types/shirkasoft-ui-components-fieldset.d.ts +72 -0
  60. package/types/shirkasoft-ui-components-file-upload.d.ts +87 -0
  61. package/types/shirkasoft-ui-components-knob.d.ts +69 -0
  62. package/types/shirkasoft-ui-components-loading.d.ts +94 -0
  63. package/types/shirkasoft-ui-components-modal.d.ts +139 -0
  64. package/types/shirkasoft-ui-components-notification.d.ts +82 -0
  65. package/types/shirkasoft-ui-components-price-input.d.ts +41 -0
  66. package/types/shirkasoft-ui-components-rail-sidebar.d.ts +121 -0
  67. package/types/shirkasoft-ui-components-select.d.ts +182 -0
  68. package/types/shirkasoft-ui-components-sidebar.d.ts +106 -0
  69. package/types/shirkasoft-ui-components-skeleton.d.ts +36 -0
  70. package/types/shirkasoft-ui-components-table.d.ts +293 -0
  71. package/types/shirkasoft-ui-components-tabs.d.ts +102 -0
  72. package/types/shirkasoft-ui-components-tag.d.ts +31 -0
  73. package/types/shirkasoft-ui-components-text-field.d.ts +120 -0
  74. package/types/shirkasoft-ui-components-timeline.d.ts +178 -0
  75. package/types/shirkasoft-ui-components-toggle.d.ts +48 -0
  76. package/types/shirkasoft-ui-components-tooltip.d.ts +47 -0
  77. package/types/shirkasoft-ui-components-utils.d.ts +9 -0
  78. package/types/shirkasoft-ui-components-wizard.d.ts +101 -0
  79. package/types/shirkasoft-ui-components.d.ts +1 -2333
@@ -0,0 +1,222 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import { LucideTag, LucidePackage, LucideUserRound, LucideMapPin, LucideUtensils, LucideShield, LucideShip, LucideBus, LucideMountain, LucideCar, LucideTicket, LucideHotel, LucideCircleQuestionMark, LucideDynamicIcon } from '@lucide/angular';
6
+ import { getIcon } from 'shirkasoft-ui-components/utils';
7
+
8
+ const DEFAULT_MARKER_GRADIENTS = [
9
+ 'bg-gradient-to-br from-blue-500 to-blue-600',
10
+ 'bg-gradient-to-br from-emerald-500 to-emerald-600',
11
+ 'bg-gradient-to-br from-violet-500 to-violet-600',
12
+ 'bg-gradient-to-br from-orange-500 to-orange-600',
13
+ 'bg-gradient-to-br from-rose-500 to-rose-600',
14
+ 'bg-gradient-to-br from-cyan-500 to-cyan-600',
15
+ 'bg-gradient-to-br from-amber-500 to-amber-600',
16
+ 'bg-gradient-to-br from-indigo-500 to-indigo-600',
17
+ 'bg-gradient-to-br from-teal-500 to-teal-600',
18
+ 'bg-gradient-to-br from-pink-500 to-pink-600',
19
+ ];
20
+ /** Supplier-type style palette used by the original wac-app timeline. */
21
+ const DEFAULT_SUPPLIER_ICON_COLORS = {
22
+ accommodation: { bg: '#3d5a80', text: '#ffffff' },
23
+ air_tickets: { bg: '#98c1d9', text: '#293241' },
24
+ rent_a_car: { bg: '#ee6c4d', text: '#ffffff' },
25
+ excursion: { bg: '#e0fbfc', text: '#293241' },
26
+ transfer: { bg: '#293241', text: '#ffffff' },
27
+ cruise: { bg: '#3d5a80', text: '#ffffff' },
28
+ insurance: { bg: '#98c1d9', text: '#293241' },
29
+ restaurant: { bg: '#6b7280', text: '#ffffff' },
30
+ visit: { bg: '#14b8a6', text: '#ffffff' },
31
+ guide: { bg: '#06b6d4', text: '#ffffff' },
32
+ package: { bg: '#84cc16', text: '#ffffff' },
33
+ other: { bg: '#e0fbfc', text: '#293241' },
34
+ };
35
+ /** Maps a sub-item `type` to a lucide icon component. */
36
+ const DEFAULT_SUPPLIER_TYPE_ICONS = {
37
+ accommodation: LucideHotel,
38
+ air_tickets: LucideTicket,
39
+ rent_a_car: LucideCar,
40
+ excursion: LucideMountain,
41
+ transfer: LucideBus,
42
+ cruise: LucideShip,
43
+ insurance: LucideShield,
44
+ restaurant: LucideUtensils,
45
+ visit: LucideMapPin,
46
+ guide: LucideUserRound,
47
+ package: LucidePackage,
48
+ other: LucideTag,
49
+ };
50
+ class TimelineComponent {
51
+ constructor() {
52
+ this.getIcon = (name) => getIcon(name, LucideCircleQuestionMark);
53
+ /** Timeline data. */
54
+ this.items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
55
+ // ---------- Layout ----------
56
+ /** 'left' = line and markers on the left; 'alternate' = cards alternate around a centered line on lg+. */
57
+ this.alignment = input('alternate', ...(ngDevMode ? [{ debugName: "alignment" }] : /* istanbul ignore next */ []));
58
+ /** Shows/hides the vertical connector line. */
59
+ this.showLine = input(true, ...(ngDevMode ? [{ debugName: "showLine" }] : /* istanbul ignore next */ []));
60
+ /** Marker diameter. */
61
+ this.markerSize = input('md', ...(ngDevMode ? [{ debugName: "markerSize" }] : /* istanbul ignore next */ []));
62
+ /** Gradient classes cycled across markers when the item has no `color`. */
63
+ this.markerGradients = input(DEFAULT_MARKER_GRADIENTS, ...(ngDevMode ? [{ debugName: "markerGradients" }] : /* istanbul ignore next */ []));
64
+ /** Shows the info column on the opposite side of the card (alternate mode, lg+). */
65
+ this.showOpposite = input(true, ...(ngDevMode ? [{ debugName: "showOpposite" }] : /* istanbul ignore next */ []));
66
+ /** Shows the item description. */
67
+ this.showDescription = input(true, ...(ngDevMode ? [{ debugName: "showDescription" }] : /* istanbul ignore next */ []));
68
+ /** Shows meta chips inside sub items. */
69
+ this.showSubItemMeta = input(true, ...(ngDevMode ? [{ debugName: "showSubItemMeta" }] : /* istanbul ignore next */ []));
70
+ /** Shows the price of each sub item. */
71
+ this.showSubItemPrice = input(true, ...(ngDevMode ? [{ debugName: "showSubItemPrice" }] : /* istanbul ignore next */ []));
72
+ /** Auto-append "N {subItemCountLabel}" under the title when the item has no subtitle. */
73
+ this.showSubItemCount = input(false, ...(ngDevMode ? [{ debugName: "showSubItemCount" }] : /* istanbul ignore next */ []));
74
+ this.subItemCountLabel = input('elementos', ...(ngDevMode ? [{ debugName: "subItemCountLabel" }] : /* istanbul ignore next */ []));
75
+ // ---------- Header ----------
76
+ this.showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
77
+ this.headerTitle = input('', ...(ngDevMode ? [{ debugName: "headerTitle" }] : /* istanbul ignore next */ []));
78
+ /** Convenience "add" button in the header. */
79
+ this.showAddItem = input(false, ...(ngDevMode ? [{ debugName: "showAddItem" }] : /* istanbul ignore next */ []));
80
+ this.addItemLabel = input('Añadir', ...(ngDevMode ? [{ debugName: "addItemLabel" }] : /* istanbul ignore next */ []));
81
+ this.addItemIcon = input('plus', ...(ngDevMode ? [{ debugName: "addItemIcon" }] : /* istanbul ignore next */ []));
82
+ this.addItemTooltip = input('Añadir elemento', ...(ngDevMode ? [{ debugName: "addItemTooltip" }] : /* istanbul ignore next */ []));
83
+ this.headerActions = input([], ...(ngDevMode ? [{ debugName: "headerActions" }] : /* istanbul ignore next */ []));
84
+ // ---------- Actions ----------
85
+ /** Renders "+ Añadir sub-elemento" in each card footer. */
86
+ this.showAddSubItem = input(false, ...(ngDevMode ? [{ debugName: "showAddSubItem" }] : /* istanbul ignore next */ []));
87
+ this.addSubItemLabel = input('Añadir', ...(ngDevMode ? [{ debugName: "addSubItemLabel" }] : /* istanbul ignore next */ []));
88
+ this.addSubItemTooltip = input('Añadir sub-elemento', ...(ngDevMode ? [{ debugName: "addSubItemTooltip" }] : /* istanbul ignore next */ []));
89
+ this.itemActions = input([], ...(ngDevMode ? [{ debugName: "itemActions" }] : /* istanbul ignore next */ []));
90
+ this.subItemActions = input([], ...(ngDevMode ? [{ debugName: "subItemActions" }] : /* istanbul ignore next */ []));
91
+ // ---------- Sub-item icon mapping ----------
92
+ /** Maps a sub-item `type` to a lucide icon (name or component). */
93
+ this.iconMap = input({}, ...(ngDevMode ? [{ debugName: "iconMap" }] : /* istanbul ignore next */ []));
94
+ /** Maps a sub-item `type` to its icon-box colors. */
95
+ this.iconColors = input({}, ...(ngDevMode ? [{ debugName: "iconColors" }] : /* istanbul ignore next */ []));
96
+ /** Icon used when nothing matches. */
97
+ this.fallbackIcon = input('circle-help', ...(ngDevMode ? [{ debugName: "fallbackIcon" }] : /* istanbul ignore next */ []));
98
+ // ---------- Empty state ----------
99
+ this.showEmptyState = input(true, ...(ngDevMode ? [{ debugName: "showEmptyState" }] : /* istanbul ignore next */ []));
100
+ this.emptyMessage = input('Sin elementos', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
101
+ this.emptyIcon = input('calendar-days', ...(ngDevMode ? [{ debugName: "emptyIcon" }] : /* istanbul ignore next */ []));
102
+ // ---------- Labels ----------
103
+ this.editTooltip = input('Editar', ...(ngDevMode ? [{ debugName: "editTooltip" }] : /* istanbul ignore next */ []));
104
+ this.deleteTooltip = input('Eliminar', ...(ngDevMode ? [{ debugName: "deleteTooltip" }] : /* istanbul ignore next */ []));
105
+ this.optionalLabel = input('Opcional', ...(ngDevMode ? [{ debugName: "optionalLabel" }] : /* istanbul ignore next */ []));
106
+ this.noSubItemsMessage = input('', ...(ngDevMode ? [{ debugName: "noSubItemsMessage" }] : /* istanbul ignore next */ []));
107
+ /** Custom content templates: keys 'marker', 'opposite', 'content', 'description', 'subItem', 'empty'. */
108
+ this.customTemplates = input({}, ...(ngDevMode ? [{ debugName: "customTemplates" }] : /* istanbul ignore next */ []));
109
+ // ---------- Outputs ----------
110
+ this.addItem = output();
111
+ this.addSubItem = output();
112
+ this.itemClick = output();
113
+ this.subItemClick = output();
114
+ }
115
+ // ---------- Helpers ----------
116
+ markerText(item, index) {
117
+ return item.markerText ?? index + 1;
118
+ }
119
+ markerClass(item, index) {
120
+ const base = 'flex items-center justify-center rounded-full text-white shadow-md';
121
+ const size = this.markerSize() === 'sm'
122
+ ? 'w-8 h-8 text-xs'
123
+ : this.markerSize() === 'lg'
124
+ ? 'w-12 h-12 text-base'
125
+ : 'w-10 h-10 text-sm';
126
+ const color = item.color || this.markerGradients()[index % this.markerGradients().length];
127
+ return `${base} ${size} ${color}`;
128
+ }
129
+ markerColumnClass() {
130
+ const size = this.markerSize() === 'sm' ? 'w-8' : this.markerSize() === 'lg' ? 'w-12' : 'w-10';
131
+ return `relative z-10 flex justify-center shrink-0 ${size}`;
132
+ }
133
+ alternateMarkerColumnClass() {
134
+ return `${this.markerColumnClass()} lg:absolute lg:left-1/2 lg:-translate-x-1/2 lg:top-0`;
135
+ }
136
+ lineClass() {
137
+ const pos = this.markerSize() === 'sm' ? 'left-4' : this.markerSize() === 'lg' ? 'left-6' : 'left-5';
138
+ const base = `absolute top-4 bottom-4 w-px _shk-bg-surface-200 dark:[background-color:var(--shk-surface-200)] ${pos}`;
139
+ if (this.alignment() === 'alternate') {
140
+ return `${base} lg:left-1/2 lg:-translate-x-1/2`;
141
+ }
142
+ return base;
143
+ }
144
+ subItemIconName(sub) {
145
+ const type = sub.type || '';
146
+ return sub.icon || this.iconMap()[type] || this.fallbackIcon();
147
+ }
148
+ subItemStyle(sub) {
149
+ const palette = this.iconColors()[sub.type || ''];
150
+ if (palette)
151
+ return { 'background-color': palette.bg, color: palette.text };
152
+ return {
153
+ 'background-color': sub.color || '#6b7280',
154
+ color: sub.colorText || '#ffffff',
155
+ };
156
+ }
157
+ // ---------- Header actions ----------
158
+ isHeaderActionVisible(action) {
159
+ return action.isVisible ? action.isVisible() : true;
160
+ }
161
+ isHeaderActionDisabled(action) {
162
+ return action.isDisabled ? action.isDisabled() : false;
163
+ }
164
+ // ---------- Item actions ----------
165
+ getItemActionLabel(action, item) {
166
+ return typeof action.label === 'function' ? action.label(item) : action.label;
167
+ }
168
+ getItemActionIconName(action, item) {
169
+ const icon = action.icon;
170
+ if (typeof icon === 'function') {
171
+ if (icon.prototype === undefined) {
172
+ return icon(item);
173
+ }
174
+ return icon;
175
+ }
176
+ return icon;
177
+ }
178
+ getItemActionClass(action, item) {
179
+ if (!action.class)
180
+ return '';
181
+ return typeof action.class === 'function' ? action.class(item) : action.class;
182
+ }
183
+ isItemActionVisible(action, item) {
184
+ return action.isVisible ? action.isVisible(item) : true;
185
+ }
186
+ isItemActionDisabled(action, item) {
187
+ return action.isDisabled ? action.isDisabled(item) : false;
188
+ }
189
+ // ---------- Sub-item actions ----------
190
+ getSubItemActionLabel(action, item, sub) {
191
+ return typeof action.label === 'function' ? action.label(item, sub) : action.label;
192
+ }
193
+ getSubItemActionIconName(action, item, sub) {
194
+ const icon = action.icon;
195
+ if (typeof icon === 'function') {
196
+ if (icon.prototype === undefined) {
197
+ return icon(item, sub);
198
+ }
199
+ return icon;
200
+ }
201
+ return icon;
202
+ }
203
+ isSubItemActionVisible(action, item, sub) {
204
+ return action.isVisible ? action.isVisible(item, sub) : true;
205
+ }
206
+ isSubItemActionDisabled(action, item, sub) {
207
+ return action.isDisabled ? action.isDisabled(item, sub) : false;
208
+ }
209
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: TimelineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
210
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: TimelineComponent, isStandalone: true, selector: "shk-timeline", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, alignment: { classPropertyName: "alignment", publicName: "alignment", isSignal: true, isRequired: false, transformFunction: null }, showLine: { classPropertyName: "showLine", publicName: "showLine", isSignal: true, isRequired: false, transformFunction: null }, markerSize: { classPropertyName: "markerSize", publicName: "markerSize", isSignal: true, isRequired: false, transformFunction: null }, markerGradients: { classPropertyName: "markerGradients", publicName: "markerGradients", isSignal: true, isRequired: false, transformFunction: null }, showOpposite: { classPropertyName: "showOpposite", publicName: "showOpposite", isSignal: true, isRequired: false, transformFunction: null }, showDescription: { classPropertyName: "showDescription", publicName: "showDescription", isSignal: true, isRequired: false, transformFunction: null }, showSubItemMeta: { classPropertyName: "showSubItemMeta", publicName: "showSubItemMeta", isSignal: true, isRequired: false, transformFunction: null }, showSubItemPrice: { classPropertyName: "showSubItemPrice", publicName: "showSubItemPrice", isSignal: true, isRequired: false, transformFunction: null }, showSubItemCount: { classPropertyName: "showSubItemCount", publicName: "showSubItemCount", isSignal: true, isRequired: false, transformFunction: null }, subItemCountLabel: { classPropertyName: "subItemCountLabel", publicName: "subItemCountLabel", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, headerTitle: { classPropertyName: "headerTitle", publicName: "headerTitle", isSignal: true, isRequired: false, transformFunction: null }, showAddItem: { classPropertyName: "showAddItem", publicName: "showAddItem", isSignal: true, isRequired: false, transformFunction: null }, addItemLabel: { classPropertyName: "addItemLabel", publicName: "addItemLabel", isSignal: true, isRequired: false, transformFunction: null }, addItemIcon: { classPropertyName: "addItemIcon", publicName: "addItemIcon", isSignal: true, isRequired: false, transformFunction: null }, addItemTooltip: { classPropertyName: "addItemTooltip", publicName: "addItemTooltip", isSignal: true, isRequired: false, transformFunction: null }, headerActions: { classPropertyName: "headerActions", publicName: "headerActions", isSignal: true, isRequired: false, transformFunction: null }, showAddSubItem: { classPropertyName: "showAddSubItem", publicName: "showAddSubItem", isSignal: true, isRequired: false, transformFunction: null }, addSubItemLabel: { classPropertyName: "addSubItemLabel", publicName: "addSubItemLabel", isSignal: true, isRequired: false, transformFunction: null }, addSubItemTooltip: { classPropertyName: "addSubItemTooltip", publicName: "addSubItemTooltip", isSignal: true, isRequired: false, transformFunction: null }, itemActions: { classPropertyName: "itemActions", publicName: "itemActions", isSignal: true, isRequired: false, transformFunction: null }, subItemActions: { classPropertyName: "subItemActions", publicName: "subItemActions", isSignal: true, isRequired: false, transformFunction: null }, iconMap: { classPropertyName: "iconMap", publicName: "iconMap", isSignal: true, isRequired: false, transformFunction: null }, iconColors: { classPropertyName: "iconColors", publicName: "iconColors", isSignal: true, isRequired: false, transformFunction: null }, fallbackIcon: { classPropertyName: "fallbackIcon", publicName: "fallbackIcon", isSignal: true, isRequired: false, transformFunction: null }, showEmptyState: { classPropertyName: "showEmptyState", publicName: "showEmptyState", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyIcon: { classPropertyName: "emptyIcon", publicName: "emptyIcon", isSignal: true, isRequired: false, transformFunction: null }, editTooltip: { classPropertyName: "editTooltip", publicName: "editTooltip", isSignal: true, isRequired: false, transformFunction: null }, deleteTooltip: { classPropertyName: "deleteTooltip", publicName: "deleteTooltip", isSignal: true, isRequired: false, transformFunction: null }, optionalLabel: { classPropertyName: "optionalLabel", publicName: "optionalLabel", isSignal: true, isRequired: false, transformFunction: null }, noSubItemsMessage: { classPropertyName: "noSubItemsMessage", publicName: "noSubItemsMessage", isSignal: true, isRequired: false, transformFunction: null }, customTemplates: { classPropertyName: "customTemplates", publicName: "customTemplates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { addItem: "addItem", addSubItem: "addSubItem", itemClick: "itemClick", subItemClick: "subItemClick" }, ngImport: i0, template: "<div class=\"space-y-4\">\n\n <!-- ============ Header ============ -->\n @if (showHeader() && (headerTitle() || showAddItem() || headerActions().length > 0)) {\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n @if (headerTitle()) {\n <div class=\"text-sm font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ headerTitle() }}\n </div>\n }\n <div class=\"flex items-center gap-1.5 ml-auto\">\n @if (showAddItem()) {\n <button\n type=\"button\"\n (click)=\"addItem.emit()\"\n [attr.aria-label]=\"addItemTooltip()\"\n class=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md _shk-bg-primary text-white hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon(addItemIcon())\" class=\"w-3.5 h-3.5\"></svg>\n {{ addItemLabel() }}\n </button>\n }\n @for (action of headerActions(); track $index) {\n @if (isHeaderActionVisible(action)) {\n <button\n type=\"button\"\n [class]=\"action.class || 'inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md _shk-bg-primary text-white hover:[background-color:var(--shk-primary-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed'\"\n [disabled]=\"isHeaderActionDisabled(action)\"\n (click)=\"action.onClick()\"\n >\n @if (action.icon) {\n <svg [lucideIcon]=\"getIcon(action.icon)\" class=\"w-3.5 h-3.5\"></svg>\n }\n {{ action.label }}\n </button>\n }\n }\n </div>\n </div>\n }\n\n <!-- ============ Timeline ============ -->\n @if (items().length > 0) {\n <div class=\"relative\">\n @if (showLine()) {\n <div [class]=\"lineClass()\" aria-hidden=\"true\"></div>\n }\n\n @for (item of items(); track item.id; let i = $index) {\n @if (alignment() === 'alternate') {\n <div class=\"relative flex items-start gap-4 lg:grid lg:grid-cols-2 lg:gap-0\">\n <!-- Marker (centered on desktop) -->\n <div [class]=\"alternateMarkerColumnClass()\">\n <span [class]=\"markerClass(item, i)\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['marker'] || defaultMarker; context: { $implicit: item, index: i }\"\n ></ng-container>\n </span>\n </div>\n\n <!-- Content card -->\n <div\n class=\"flex-1 min-w-0\"\n [class.lg:order-1]=\"$even\"\n [class.lg:order-2]=\"!$even\"\n [class.lg:pr-12]=\"$even\"\n [class.lg:pl-12]=\"!$even\"\n >\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['content'] || card; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n\n <!-- Opposite info -->\n @if (showOpposite()) {\n <div\n class=\"hidden lg:flex lg:items-center\"\n [class.lg:order-2]=\"$even\"\n [class.lg:order-1]=\"!$even\"\n [class.lg:pl-12]=\"$even\"\n [class.lg:justify-end]=\"!$even\"\n [class.lg:pr-12]=\"!$even\"\n >\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['opposite'] || itemInfo; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n }\n </div>\n } @else {\n <!-- Left alignment -->\n <div class=\"relative flex items-start gap-4\">\n <div [class]=\"markerColumnClass()\">\n <span [class]=\"markerClass(item, i)\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['marker'] || defaultMarker; context: { $implicit: item, index: i }\"\n ></ng-container>\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['content'] || card; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n </div>\n }\n }\n </div>\n } @else if (showEmptyState()) {\n <!-- ============ Empty state ============ -->\n <div class=\"text-center py-12\">\n @if (customTemplates()['empty']) {\n <ng-container *ngTemplateOutlet=\"customTemplates()['empty']\"></ng-container>\n } @else {\n <div class=\"w-16 h-16 mx-auto mb-4 _shk-bg-surface-100 dark:[background-color:var(--shk-surface-100)] rounded-full flex items-center justify-center\">\n <svg [lucideIcon]=\"getIcon(emptyIcon())\" class=\"w-8 h-8 _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\"></svg>\n </div>\n <p class=\"text-sm _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\">{{ emptyMessage() }}</p>\n }\n </div>\n }\n\n <!-- ============ Templates ============ -->\n\n <ng-template #defaultMarker let-item let-index=\"index\">\n <span class=\"font-bold\">{{ markerText(item, index) }}</span>\n </ng-template>\n\n <ng-template #itemInfo let-item>\n <div>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <div class=\"mb-2\">\n <span class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-semibold _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] _shk-text-surface-600 dark:[color:var(--shk-surface-600)]\">\n @if (item.badgeIcon) {\n <svg [lucideIcon]=\"getIcon(item.badgeIcon)\" class=\"w-3 h-3\"></svg>\n }\n {{ item.badge }}\n </span>\n </div>\n }\n @if (item.title) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">{{ item.title }}</div>\n }\n @let subCount = (item.subItems?.length || 0);\n @if (item.subtitle || (showSubItemCount() && subCount > 0)) {\n <div class=\"text-xs _shk-text-surface-400 dark:[color:var(--shk-surface-500)] mt-1\">\n {{ item.subtitle || (subCount + ' ' + subItemCountLabel()) }}\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #card let-item>\n @let subItems = item.subItems || [];\n <div class=\"shk-timeline-card mb-4 bg-white dark:[background-color:var(--shk-surface-50)] rounded-xl border _shk-border dark:[border-color:var(--shk-surface-200)] shadow-sm overflow-hidden\">\n <!-- Header (mobile in alternate, always in left) -->\n <div class=\"flex items-center gap-2 px-4 pt-4 pb-2\" [class.lg:hidden]=\"alignment() === 'alternate'\">\n <ng-container *ngTemplateOutlet=\"itemInfo; context: { $implicit: item }\"></ng-container>\n </div>\n\n <!-- Description -->\n @if (showDescription() && item.description) {\n <div class=\"px-4 pt-3\">\n @if (customTemplates()['description']) {\n <ng-container *ngTemplateOutlet=\"customTemplates()['description']; context: { $implicit: item }\"></ng-container>\n } @else {\n <p class=\"text-sm _shk-text-surface-600 dark:[color:var(--shk-surface-600)] leading-relaxed\">{{ item.description }}</p>\n }\n </div>\n }\n\n <!-- Sub items -->\n @if (subItems.length > 0) {\n <div class=\"mt-2\">\n @for (sub of subItems; track sub.id) {\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['subItem'] || defaultSubItem; context: { $implicit: item, subItem: sub }\"\n ></ng-container>\n }\n </div>\n } @else if (noSubItemsMessage()) {\n <div class=\"px-4 py-6 text-center\">\n <div class=\"inline-flex items-center gap-2 text-sm _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\">\n <svg [lucideIcon]=\"getIcon('info')\" class=\"w-4 h-4\"></svg>\n <span class=\"italic\">{{ noSubItemsMessage() }}</span>\n </div>\n </div>\n }\n\n <!-- Footer actions -->\n @if (showAddSubItem() || itemActions().length > 0) {\n <div class=\"flex items-center gap-1 px-4 py-2 _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border-t _shk-border dark:[border-color:var(--shk-surface-100)]\">\n @if (showAddSubItem()) {\n <button\n type=\"button\"\n (click)=\"addSubItem.emit(item)\"\n class=\"relative group inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium _shk-text-primary hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] rounded-lg transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('circle-plus')\" class=\"w-3.5 h-3.5\"></svg>\n {{ addSubItemLabel() }}\n <span class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ addSubItemTooltip() }}\n </span>\n </button>\n }\n <div class=\"flex-1\"></div>\n @for (action of itemActions(); track $index) {\n @if (isItemActionVisible(action, item)) {\n <div class=\"relative group\">\n <button\n type=\"button\"\n (click)=\"action.onClick(item)\"\n [class]=\"'timeline-icon-btn ' + getItemActionClass(action, item)\"\n [disabled]=\"isItemActionDisabled(action, item)\"\n [attr.aria-label]=\"getItemActionLabel(action, item)\"\n >\n <svg [lucideIcon]=\"getIcon(getItemActionIconName(action, item))\" class=\"w-3.5 h-3.5\"></svg>\n </button>\n <span class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ getItemActionLabel(action, item) }}\n </span>\n </div>\n }\n }\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #defaultSubItem let-item let-sub=\"subItem\">\n <div class=\"px-4 py-3 border-t [border-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-700)] hover:[background-color:color-mix(in srgb,var(--shk-primary-50)30%,transparent)] dark:hover:[background-color:color-mix(in srgb,var(--shk-primary-900)10%,transparent)] transition-colors duration-200 group\">\n <div class=\"flex items-start gap-3\">\n <span\n [class]=\"sub.iconClass || 'flex items-center justify-center w-9 h-9 rounded-lg shrink-0 mt-0.5'\"\n [style]=\"sub.iconClass ? undefined : subItemStyle(sub)\"\n >\n <svg [lucideIcon]=\"getIcon(subItemIconName(sub))\" class=\"w-4 h-4\"></svg>\n </span>\n\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex items-center gap-2 flex-wrap\">\n @if (sub.optional) {\n <span class=\"text-[10px] font-semibold uppercase tracking-wide px-1.5 py-0.5 rounded _shk-bg-amber-soft _shk-text-amber-600 dark:[color:var(--shk-amber-400)]\">\n {{ sub.optionalLabel || optionalLabel() }}\n </span>\n }\n <span class=\"font-medium _shk-text-surface-800 dark:[color:var(--shk-surface-800)] text-sm truncate\">{{ sub.title }}</span>\n @if (sub.subtitle) {\n <span class=\"text-xs _shk-text-surface-400 dark:[color:var(--shk-surface-500)] truncate\">\u00B7 {{ sub.subtitle }}</span>\n }\n </div>\n\n @if (showSubItemMeta() && (sub.meta?.length || 0) > 0) {\n <div class=\"flex flex-wrap items-center gap-x-3 gap-y-1 mt-1.5 text-xs _shk-text-surface-500 dark:[color:var(--shk-surface-500)]\">\n @for (m of sub.meta!; track $index) {\n <span class=\"flex items-center gap-1\">\n <svg [lucideIcon]=\"getIcon(m.icon)\" class=\"w-3 h-3\"></svg>\n @if (m.label) {\n <span class=\"font-medium\">{{ m.label }}:</span>\n }\n {{ m.value }}\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"flex items-center gap-0.5 shrink-0\">\n @if (showSubItemPrice() && sub.price !== undefined && sub.price !== null && sub.price !== '') {\n <span class=\"font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)] text-xs mr-1\">{{ sub.price }}</span>\n }\n @for (action of subItemActions(); track $index) {\n @if (isSubItemActionVisible(action, item, sub)) {\n <div class=\"relative group\">\n <button\n type=\"button\"\n (click)=\"action.onClick(item, sub)\"\n class=\"timeline-icon-btn opacity-100 lg:opacity-0 lg:group-hover:opacity-100 transition-opacity\"\n [disabled]=\"isSubItemActionDisabled(action, item, sub)\"\n [attr.aria-label]=\"getSubItemActionLabel(action, item, sub)\"\n >\n <svg [lucideIcon]=\"getIcon(getSubItemActionIconName(action, item, sub))\" class=\"w-3.5 h-3.5\"></svg>\n </button>\n <span class=\"absolute top-full left-1/2 -translate-x-1/2 mt-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ getSubItemActionLabel(action, item, sub) }}\n </span>\n </div>\n }\n }\n </div>\n </div>\n </div>\n </ng-template>\n\n</div>\n", styles: [":host{display:block}.timeline-icon-btn{padding:.375rem;display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;color:var(--shk-primary-600);transition:background-color .15s ease-in-out,color .15s ease-in-out,opacity .15s ease-in-out}.timeline-icon-btn:hover:not(:disabled){background-color:color-mix(in srgb,var(--shk-primary-50) 60%,transparent);color:var(--shk-primary-700)}.timeline-icon-btn:disabled{opacity:.4;cursor:not-allowed}.timeline-icon-btn svg{width:.875rem!important;height:.875rem!important}.shk-timeline-card{animation:shk-timeline-fade-in .3s ease-out}@keyframes shk-timeline-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
211
+ }
212
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: TimelineComponent, decorators: [{
213
+ type: Component,
214
+ args: [{ selector: 'shk-timeline', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, LucideDynamicIcon], template: "<div class=\"space-y-4\">\n\n <!-- ============ Header ============ -->\n @if (showHeader() && (headerTitle() || showAddItem() || headerActions().length > 0)) {\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n @if (headerTitle()) {\n <div class=\"text-sm font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ headerTitle() }}\n </div>\n }\n <div class=\"flex items-center gap-1.5 ml-auto\">\n @if (showAddItem()) {\n <button\n type=\"button\"\n (click)=\"addItem.emit()\"\n [attr.aria-label]=\"addItemTooltip()\"\n class=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md _shk-bg-primary text-white hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon(addItemIcon())\" class=\"w-3.5 h-3.5\"></svg>\n {{ addItemLabel() }}\n </button>\n }\n @for (action of headerActions(); track $index) {\n @if (isHeaderActionVisible(action)) {\n <button\n type=\"button\"\n [class]=\"action.class || 'inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md _shk-bg-primary text-white hover:[background-color:var(--shk-primary-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed'\"\n [disabled]=\"isHeaderActionDisabled(action)\"\n (click)=\"action.onClick()\"\n >\n @if (action.icon) {\n <svg [lucideIcon]=\"getIcon(action.icon)\" class=\"w-3.5 h-3.5\"></svg>\n }\n {{ action.label }}\n </button>\n }\n }\n </div>\n </div>\n }\n\n <!-- ============ Timeline ============ -->\n @if (items().length > 0) {\n <div class=\"relative\">\n @if (showLine()) {\n <div [class]=\"lineClass()\" aria-hidden=\"true\"></div>\n }\n\n @for (item of items(); track item.id; let i = $index) {\n @if (alignment() === 'alternate') {\n <div class=\"relative flex items-start gap-4 lg:grid lg:grid-cols-2 lg:gap-0\">\n <!-- Marker (centered on desktop) -->\n <div [class]=\"alternateMarkerColumnClass()\">\n <span [class]=\"markerClass(item, i)\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['marker'] || defaultMarker; context: { $implicit: item, index: i }\"\n ></ng-container>\n </span>\n </div>\n\n <!-- Content card -->\n <div\n class=\"flex-1 min-w-0\"\n [class.lg:order-1]=\"$even\"\n [class.lg:order-2]=\"!$even\"\n [class.lg:pr-12]=\"$even\"\n [class.lg:pl-12]=\"!$even\"\n >\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['content'] || card; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n\n <!-- Opposite info -->\n @if (showOpposite()) {\n <div\n class=\"hidden lg:flex lg:items-center\"\n [class.lg:order-2]=\"$even\"\n [class.lg:order-1]=\"!$even\"\n [class.lg:pl-12]=\"$even\"\n [class.lg:justify-end]=\"!$even\"\n [class.lg:pr-12]=\"!$even\"\n >\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['opposite'] || itemInfo; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n }\n </div>\n } @else {\n <!-- Left alignment -->\n <div class=\"relative flex items-start gap-4\">\n <div [class]=\"markerColumnClass()\">\n <span [class]=\"markerClass(item, i)\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['marker'] || defaultMarker; context: { $implicit: item, index: i }\"\n ></ng-container>\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['content'] || card; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n </div>\n }\n }\n </div>\n } @else if (showEmptyState()) {\n <!-- ============ Empty state ============ -->\n <div class=\"text-center py-12\">\n @if (customTemplates()['empty']) {\n <ng-container *ngTemplateOutlet=\"customTemplates()['empty']\"></ng-container>\n } @else {\n <div class=\"w-16 h-16 mx-auto mb-4 _shk-bg-surface-100 dark:[background-color:var(--shk-surface-100)] rounded-full flex items-center justify-center\">\n <svg [lucideIcon]=\"getIcon(emptyIcon())\" class=\"w-8 h-8 _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\"></svg>\n </div>\n <p class=\"text-sm _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\">{{ emptyMessage() }}</p>\n }\n </div>\n }\n\n <!-- ============ Templates ============ -->\n\n <ng-template #defaultMarker let-item let-index=\"index\">\n <span class=\"font-bold\">{{ markerText(item, index) }}</span>\n </ng-template>\n\n <ng-template #itemInfo let-item>\n <div>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <div class=\"mb-2\">\n <span class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-semibold _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] _shk-text-surface-600 dark:[color:var(--shk-surface-600)]\">\n @if (item.badgeIcon) {\n <svg [lucideIcon]=\"getIcon(item.badgeIcon)\" class=\"w-3 h-3\"></svg>\n }\n {{ item.badge }}\n </span>\n </div>\n }\n @if (item.title) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">{{ item.title }}</div>\n }\n @let subCount = (item.subItems?.length || 0);\n @if (item.subtitle || (showSubItemCount() && subCount > 0)) {\n <div class=\"text-xs _shk-text-surface-400 dark:[color:var(--shk-surface-500)] mt-1\">\n {{ item.subtitle || (subCount + ' ' + subItemCountLabel()) }}\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #card let-item>\n @let subItems = item.subItems || [];\n <div class=\"shk-timeline-card mb-4 bg-white dark:[background-color:var(--shk-surface-50)] rounded-xl border _shk-border dark:[border-color:var(--shk-surface-200)] shadow-sm overflow-hidden\">\n <!-- Header (mobile in alternate, always in left) -->\n <div class=\"flex items-center gap-2 px-4 pt-4 pb-2\" [class.lg:hidden]=\"alignment() === 'alternate'\">\n <ng-container *ngTemplateOutlet=\"itemInfo; context: { $implicit: item }\"></ng-container>\n </div>\n\n <!-- Description -->\n @if (showDescription() && item.description) {\n <div class=\"px-4 pt-3\">\n @if (customTemplates()['description']) {\n <ng-container *ngTemplateOutlet=\"customTemplates()['description']; context: { $implicit: item }\"></ng-container>\n } @else {\n <p class=\"text-sm _shk-text-surface-600 dark:[color:var(--shk-surface-600)] leading-relaxed\">{{ item.description }}</p>\n }\n </div>\n }\n\n <!-- Sub items -->\n @if (subItems.length > 0) {\n <div class=\"mt-2\">\n @for (sub of subItems; track sub.id) {\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['subItem'] || defaultSubItem; context: { $implicit: item, subItem: sub }\"\n ></ng-container>\n }\n </div>\n } @else if (noSubItemsMessage()) {\n <div class=\"px-4 py-6 text-center\">\n <div class=\"inline-flex items-center gap-2 text-sm _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\">\n <svg [lucideIcon]=\"getIcon('info')\" class=\"w-4 h-4\"></svg>\n <span class=\"italic\">{{ noSubItemsMessage() }}</span>\n </div>\n </div>\n }\n\n <!-- Footer actions -->\n @if (showAddSubItem() || itemActions().length > 0) {\n <div class=\"flex items-center gap-1 px-4 py-2 _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border-t _shk-border dark:[border-color:var(--shk-surface-100)]\">\n @if (showAddSubItem()) {\n <button\n type=\"button\"\n (click)=\"addSubItem.emit(item)\"\n class=\"relative group inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium _shk-text-primary hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] rounded-lg transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('circle-plus')\" class=\"w-3.5 h-3.5\"></svg>\n {{ addSubItemLabel() }}\n <span class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ addSubItemTooltip() }}\n </span>\n </button>\n }\n <div class=\"flex-1\"></div>\n @for (action of itemActions(); track $index) {\n @if (isItemActionVisible(action, item)) {\n <div class=\"relative group\">\n <button\n type=\"button\"\n (click)=\"action.onClick(item)\"\n [class]=\"'timeline-icon-btn ' + getItemActionClass(action, item)\"\n [disabled]=\"isItemActionDisabled(action, item)\"\n [attr.aria-label]=\"getItemActionLabel(action, item)\"\n >\n <svg [lucideIcon]=\"getIcon(getItemActionIconName(action, item))\" class=\"w-3.5 h-3.5\"></svg>\n </button>\n <span class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ getItemActionLabel(action, item) }}\n </span>\n </div>\n }\n }\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #defaultSubItem let-item let-sub=\"subItem\">\n <div class=\"px-4 py-3 border-t [border-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-700)] hover:[background-color:color-mix(in srgb,var(--shk-primary-50)30%,transparent)] dark:hover:[background-color:color-mix(in srgb,var(--shk-primary-900)10%,transparent)] transition-colors duration-200 group\">\n <div class=\"flex items-start gap-3\">\n <span\n [class]=\"sub.iconClass || 'flex items-center justify-center w-9 h-9 rounded-lg shrink-0 mt-0.5'\"\n [style]=\"sub.iconClass ? undefined : subItemStyle(sub)\"\n >\n <svg [lucideIcon]=\"getIcon(subItemIconName(sub))\" class=\"w-4 h-4\"></svg>\n </span>\n\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex items-center gap-2 flex-wrap\">\n @if (sub.optional) {\n <span class=\"text-[10px] font-semibold uppercase tracking-wide px-1.5 py-0.5 rounded _shk-bg-amber-soft _shk-text-amber-600 dark:[color:var(--shk-amber-400)]\">\n {{ sub.optionalLabel || optionalLabel() }}\n </span>\n }\n <span class=\"font-medium _shk-text-surface-800 dark:[color:var(--shk-surface-800)] text-sm truncate\">{{ sub.title }}</span>\n @if (sub.subtitle) {\n <span class=\"text-xs _shk-text-surface-400 dark:[color:var(--shk-surface-500)] truncate\">\u00B7 {{ sub.subtitle }}</span>\n }\n </div>\n\n @if (showSubItemMeta() && (sub.meta?.length || 0) > 0) {\n <div class=\"flex flex-wrap items-center gap-x-3 gap-y-1 mt-1.5 text-xs _shk-text-surface-500 dark:[color:var(--shk-surface-500)]\">\n @for (m of sub.meta!; track $index) {\n <span class=\"flex items-center gap-1\">\n <svg [lucideIcon]=\"getIcon(m.icon)\" class=\"w-3 h-3\"></svg>\n @if (m.label) {\n <span class=\"font-medium\">{{ m.label }}:</span>\n }\n {{ m.value }}\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"flex items-center gap-0.5 shrink-0\">\n @if (showSubItemPrice() && sub.price !== undefined && sub.price !== null && sub.price !== '') {\n <span class=\"font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)] text-xs mr-1\">{{ sub.price }}</span>\n }\n @for (action of subItemActions(); track $index) {\n @if (isSubItemActionVisible(action, item, sub)) {\n <div class=\"relative group\">\n <button\n type=\"button\"\n (click)=\"action.onClick(item, sub)\"\n class=\"timeline-icon-btn opacity-100 lg:opacity-0 lg:group-hover:opacity-100 transition-opacity\"\n [disabled]=\"isSubItemActionDisabled(action, item, sub)\"\n [attr.aria-label]=\"getSubItemActionLabel(action, item, sub)\"\n >\n <svg [lucideIcon]=\"getIcon(getSubItemActionIconName(action, item, sub))\" class=\"w-3.5 h-3.5\"></svg>\n </button>\n <span class=\"absolute top-full left-1/2 -translate-x-1/2 mt-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ getSubItemActionLabel(action, item, sub) }}\n </span>\n </div>\n }\n }\n </div>\n </div>\n </div>\n </ng-template>\n\n</div>\n", styles: [":host{display:block}.timeline-icon-btn{padding:.375rem;display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;color:var(--shk-primary-600);transition:background-color .15s ease-in-out,color .15s ease-in-out,opacity .15s ease-in-out}.timeline-icon-btn:hover:not(:disabled){background-color:color-mix(in srgb,var(--shk-primary-50) 60%,transparent);color:var(--shk-primary-700)}.timeline-icon-btn:disabled{opacity:.4;cursor:not-allowed}.timeline-icon-btn svg{width:.875rem!important;height:.875rem!important}.shk-timeline-card{animation:shk-timeline-fade-in .3s ease-out}@keyframes shk-timeline-fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}\n"] }]
215
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], alignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignment", required: false }] }], showLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLine", required: false }] }], markerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "markerSize", required: false }] }], markerGradients: [{ type: i0.Input, args: [{ isSignal: true, alias: "markerGradients", required: false }] }], showOpposite: [{ type: i0.Input, args: [{ isSignal: true, alias: "showOpposite", required: false }] }], showDescription: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDescription", required: false }] }], showSubItemMeta: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubItemMeta", required: false }] }], showSubItemPrice: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubItemPrice", required: false }] }], showSubItemCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSubItemCount", required: false }] }], subItemCountLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "subItemCountLabel", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], headerTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerTitle", required: false }] }], showAddItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddItem", required: false }] }], addItemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addItemLabel", required: false }] }], addItemIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "addItemIcon", required: false }] }], addItemTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "addItemTooltip", required: false }] }], headerActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerActions", required: false }] }], showAddSubItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAddSubItem", required: false }] }], addSubItemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addSubItemLabel", required: false }] }], addSubItemTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "addSubItemTooltip", required: false }] }], itemActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemActions", required: false }] }], subItemActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "subItemActions", required: false }] }], iconMap: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconMap", required: false }] }], iconColors: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconColors", required: false }] }], fallbackIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "fallbackIcon", required: false }] }], showEmptyState: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEmptyState", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], emptyIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyIcon", required: false }] }], editTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "editTooltip", required: false }] }], deleteTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteTooltip", required: false }] }], optionalLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionalLabel", required: false }] }], noSubItemsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSubItemsMessage", required: false }] }], customTemplates: [{ type: i0.Input, args: [{ isSignal: true, alias: "customTemplates", required: false }] }], addItem: [{ type: i0.Output, args: ["addItem"] }], addSubItem: [{ type: i0.Output, args: ["addSubItem"] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], subItemClick: [{ type: i0.Output, args: ["subItemClick"] }] } });
216
+
217
+ /**
218
+ * Generated bundle index. Do not edit.
219
+ */
220
+
221
+ export { DEFAULT_MARKER_GRADIENTS, DEFAULT_SUPPLIER_ICON_COLORS, DEFAULT_SUPPLIER_TYPE_ICONS, TimelineComponent };
222
+ //# sourceMappingURL=shirkasoft-ui-components-timeline.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shirkasoft-ui-components-timeline.mjs","sources":["../../../projects/ui-components/timeline/timeline.component.ts","../../../projects/ui-components/timeline/timeline.component.html","../../../projects/ui-components/timeline/shirkasoft-ui-components-timeline.ts"],"sourcesContent":["import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport {\n LucideDynamicIcon,\n LucideCircleQuestionMark,\n LucideBus,\n LucideCar,\n LucideHotel,\n LucideMapPin,\n LucideMountain,\n LucidePackage,\n LucideShield,\n LucideShip,\n LucideTag,\n LucideTicket,\n LucideUserRound,\n LucideUtensils,\n} from '@lucide/angular';\nimport { getIcon as getIconFromCentral } from 'shirkasoft-ui-components/utils';\n\n/**\n * Shirkasoft UI Components.\n * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).\n * Belongs to Shirkasoft.\n */\n\n/** A chip shown under a sub item (time, pricing model, quantity, etc). */\nexport interface TimelineMeta {\n icon: string | any;\n label?: string;\n value: string;\n}\n\n/** A row inside a timeline item (e.g. an activity of a tour day). */\nexport interface TimelineSubItem {\n id: string | number;\n title: string;\n subtitle?: string;\n /** Used to look up icon / color in `iconMap` and `iconColors`. */\n type?: string;\n /** Overrides the resolved icon (name or component). */\n icon?: string | any;\n /** Hex background for the icon box (fallback). */\n color?: string;\n /** Hex text color for the icon (fallback). */\n colorText?: string;\n /** Custom CSS classes for the icon box (takes precedence over inline colors). */\n iconClass?: string;\n optional?: boolean;\n optionalLabel?: string;\n meta?: TimelineMeta[];\n price?: string | number;\n}\n\n/** A single event in the timeline (e.g. a tour day). */\nexport interface TimelineItem {\n id: string | number;\n /** Text shown inside the marker (falls back to the auto index). */\n markerText?: string | number;\n title?: string;\n subtitle?: string;\n description?: string;\n /** Small pill shown above the title (e.g. \"Día 1\"). */\n badge?: string | number;\n badgeIcon?: string | any;\n /** CSS classes for the marker (falls back to the cycled gradient palette). */\n color?: string;\n subItems?: TimelineSubItem[];\n}\n\n/** A button rendered in the header. */\nexport interface TimelineAction {\n label: string;\n icon: string | any;\n onClick: () => void;\n class?: string;\n isVisible?: () => boolean;\n isDisabled?: () => boolean;\n}\n\n/** An action rendered in the item card footer. */\nexport interface TimelineItemAction {\n label: string | ((item: TimelineItem) => string);\n icon: string | any | ((item: TimelineItem) => string | any);\n onClick: (item: TimelineItem) => void;\n class?: string | ((item: TimelineItem) => string);\n isVisible?: (item: TimelineItem) => boolean;\n isDisabled?: (item: TimelineItem) => boolean;\n}\n\n/** An action rendered on hover over a sub item. */\nexport interface TimelineSubItemAction {\n label: string | ((item: TimelineItem, subItem: TimelineSubItem) => string);\n icon: string | any | ((item: TimelineItem, subItem: TimelineSubItem) => string | any);\n onClick: (item: TimelineItem, subItem: TimelineSubItem) => void;\n isVisible?: (item: TimelineItem, subItem: TimelineSubItem) => boolean;\n isDisabled?: (item: TimelineItem, subItem: TimelineSubItem) => boolean;\n}\n\nexport type TimelineAlignment = 'left' | 'alternate';\nexport type TimelineMarkerSize = 'sm' | 'md' | 'lg';\n\nexport const DEFAULT_MARKER_GRADIENTS: string[] = [\n 'bg-gradient-to-br from-blue-500 to-blue-600',\n 'bg-gradient-to-br from-emerald-500 to-emerald-600',\n 'bg-gradient-to-br from-violet-500 to-violet-600',\n 'bg-gradient-to-br from-orange-500 to-orange-600',\n 'bg-gradient-to-br from-rose-500 to-rose-600',\n 'bg-gradient-to-br from-cyan-500 to-cyan-600',\n 'bg-gradient-to-br from-amber-500 to-amber-600',\n 'bg-gradient-to-br from-indigo-500 to-indigo-600',\n 'bg-gradient-to-br from-teal-500 to-teal-600',\n 'bg-gradient-to-br from-pink-500 to-pink-600',\n];\n\n/** Supplier-type style palette used by the original wac-app timeline. */\nexport const DEFAULT_SUPPLIER_ICON_COLORS: Record<\n string,\n { bg: string; text: string }\n> = {\n accommodation: { bg: '#3d5a80', text: '#ffffff' },\n air_tickets: { bg: '#98c1d9', text: '#293241' },\n rent_a_car: { bg: '#ee6c4d', text: '#ffffff' },\n excursion: { bg: '#e0fbfc', text: '#293241' },\n transfer: { bg: '#293241', text: '#ffffff' },\n cruise: { bg: '#3d5a80', text: '#ffffff' },\n insurance: { bg: '#98c1d9', text: '#293241' },\n restaurant: { bg: '#6b7280', text: '#ffffff' },\n visit: { bg: '#14b8a6', text: '#ffffff' },\n guide: { bg: '#06b6d4', text: '#ffffff' },\n package: { bg: '#84cc16', text: '#ffffff' },\n other: { bg: '#e0fbfc', text: '#293241' },\n};\n\n/** Maps a sub-item `type` to a lucide icon component. */\nexport const DEFAULT_SUPPLIER_TYPE_ICONS: Record<string, any> = {\n accommodation: LucideHotel,\n air_tickets: LucideTicket,\n rent_a_car: LucideCar,\n excursion: LucideMountain,\n transfer: LucideBus,\n cruise: LucideShip,\n insurance: LucideShield,\n restaurant: LucideUtensils,\n visit: LucideMapPin,\n guide: LucideUserRound,\n package: LucidePackage,\n other: LucideTag,\n};\n\n@Component({\n selector: 'shk-timeline',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CommonModule, LucideDynamicIcon],\n templateUrl: './timeline.component.html',\n styles: [\n `\n :host {\n display: block;\n }\n .timeline-icon-btn {\n padding: 0.375rem;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 0.5rem;\n color: var(--shk-primary-600);\n transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out,\n opacity 0.15s ease-in-out;\n }\n .timeline-icon-btn:hover:not(:disabled) {\n background-color: color-mix(in srgb, var(--shk-primary-50) 60%, transparent);\n color: var(--shk-primary-700);\n }\n .timeline-icon-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n }\n .timeline-icon-btn svg {\n width: 0.875rem !important;\n height: 0.875rem !important;\n }\n .shk-timeline-card {\n animation: shk-timeline-fade-in 0.3s ease-out;\n }\n @keyframes shk-timeline-fade-in {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n `,\n ],\n})\nexport class TimelineComponent {\n protected getIcon = (name: any) => getIconFromCentral(name, LucideCircleQuestionMark);\n\n /** Timeline data. */\n items = input<TimelineItem[]>([]);\n\n // ---------- Layout ----------\n /** 'left' = line and markers on the left; 'alternate' = cards alternate around a centered line on lg+. */\n alignment = input<TimelineAlignment>('alternate');\n /** Shows/hides the vertical connector line. */\n showLine = input<boolean>(true);\n /** Marker diameter. */\n markerSize = input<TimelineMarkerSize>('md');\n /** Gradient classes cycled across markers when the item has no `color`. */\n markerGradients = input<string[]>(DEFAULT_MARKER_GRADIENTS);\n /** Shows the info column on the opposite side of the card (alternate mode, lg+). */\n showOpposite = input<boolean>(true);\n /** Shows the item description. */\n showDescription = input<boolean>(true);\n /** Shows meta chips inside sub items. */\n showSubItemMeta = input<boolean>(true);\n /** Shows the price of each sub item. */\n showSubItemPrice = input<boolean>(true);\n /** Auto-append \"N {subItemCountLabel}\" under the title when the item has no subtitle. */\n showSubItemCount = input<boolean>(false);\n subItemCountLabel = input<string>('elementos');\n\n // ---------- Header ----------\n showHeader = input<boolean>(true);\n headerTitle = input<string>('');\n /** Convenience \"add\" button in the header. */\n showAddItem = input<boolean>(false);\n addItemLabel = input<string>('Añadir');\n addItemIcon = input<string>('plus');\n addItemTooltip = input<string>('Añadir elemento');\n headerActions = input<TimelineAction[]>([]);\n\n // ---------- Actions ----------\n /** Renders \"+ Añadir sub-elemento\" in each card footer. */\n showAddSubItem = input<boolean>(false);\n addSubItemLabel = input<string>('Añadir');\n addSubItemTooltip = input<string>('Añadir sub-elemento');\n itemActions = input<TimelineItemAction[]>([]);\n subItemActions = input<TimelineSubItemAction[]>([]);\n\n // ---------- Sub-item icon mapping ----------\n /** Maps a sub-item `type` to a lucide icon (name or component). */\n iconMap = input<{ [type: string]: string | any }>({});\n /** Maps a sub-item `type` to its icon-box colors. */\n iconColors = input<{ [type: string]: { bg: string; text: string } }>({});\n /** Icon used when nothing matches. */\n fallbackIcon = input<string | any>('circle-help');\n\n // ---------- Empty state ----------\n showEmptyState = input<boolean>(true);\n emptyMessage = input<string>('Sin elementos');\n emptyIcon = input<string | any>('calendar-days');\n\n // ---------- Labels ----------\n editTooltip = input<string>('Editar');\n deleteTooltip = input<string>('Eliminar');\n optionalLabel = input<string>('Opcional');\n noSubItemsMessage = input<string>('');\n\n /** Custom content templates: keys 'marker', 'opposite', 'content', 'description', 'subItem', 'empty'. */\n customTemplates = input<{ [key: string]: any }>({});\n\n // ---------- Outputs ----------\n addItem = output<void>();\n addSubItem = output<TimelineItem>();\n itemClick = output<TimelineItem>();\n subItemClick = output<{ item: TimelineItem; subItem: TimelineSubItem }>();\n\n // ---------- Helpers ----------\n markerText(item: TimelineItem, index: number): string | number {\n return item.markerText ?? index + 1;\n }\n\n markerClass(item: TimelineItem, index: number): string {\n const base = 'flex items-center justify-center rounded-full text-white shadow-md';\n const size =\n this.markerSize() === 'sm'\n ? 'w-8 h-8 text-xs'\n : this.markerSize() === 'lg'\n ? 'w-12 h-12 text-base'\n : 'w-10 h-10 text-sm';\n const color = item.color || this.markerGradients()[index % this.markerGradients().length];\n return `${base} ${size} ${color}`;\n }\n\n markerColumnClass(): string {\n const size =\n this.markerSize() === 'sm' ? 'w-8' : this.markerSize() === 'lg' ? 'w-12' : 'w-10';\n return `relative z-10 flex justify-center shrink-0 ${size}`;\n }\n\n alternateMarkerColumnClass(): string {\n return `${this.markerColumnClass()} lg:absolute lg:left-1/2 lg:-translate-x-1/2 lg:top-0`;\n }\n\n lineClass(): string {\n const pos =\n this.markerSize() === 'sm' ? 'left-4' : this.markerSize() === 'lg' ? 'left-6' : 'left-5';\n const base = `absolute top-4 bottom-4 w-px _shk-bg-surface-200 dark:[background-color:var(--shk-surface-200)] ${pos}`;\n if (this.alignment() === 'alternate') {\n return `${base} lg:left-1/2 lg:-translate-x-1/2`;\n }\n return base;\n }\n\n subItemIconName(sub: TimelineSubItem): string {\n const type = sub.type || '';\n return sub.icon || this.iconMap()[type] || this.fallbackIcon();\n }\n\n subItemStyle(sub: TimelineSubItem): { [key: string]: string } | undefined {\n const palette = this.iconColors()[sub.type || ''];\n if (palette) return { 'background-color': palette.bg, color: palette.text };\n return {\n 'background-color': sub.color || '#6b7280',\n color: sub.colorText || '#ffffff',\n };\n }\n\n // ---------- Header actions ----------\n isHeaderActionVisible(action: TimelineAction): boolean {\n return action.isVisible ? action.isVisible() : true;\n }\n\n isHeaderActionDisabled(action: TimelineAction): boolean {\n return action.isDisabled ? action.isDisabled() : false;\n }\n\n // ---------- Item actions ----------\n getItemActionLabel(action: TimelineItemAction, item: TimelineItem): string {\n return typeof action.label === 'function' ? action.label(item) : action.label;\n }\n\n getItemActionIconName(action: TimelineItemAction, item: TimelineItem): any {\n const icon = action.icon;\n if (typeof icon === 'function') {\n if (icon.prototype === undefined) {\n return icon(item);\n }\n return icon;\n }\n return icon;\n }\n\n getItemActionClass(action: TimelineItemAction, item: TimelineItem): string {\n if (!action.class) return '';\n return typeof action.class === 'function' ? action.class(item) : action.class;\n }\n\n isItemActionVisible(action: TimelineItemAction, item: TimelineItem): boolean {\n return action.isVisible ? action.isVisible(item) : true;\n }\n\n isItemActionDisabled(action: TimelineItemAction, item: TimelineItem): boolean {\n return action.isDisabled ? action.isDisabled(item) : false;\n }\n\n // ---------- Sub-item actions ----------\n getSubItemActionLabel(action: TimelineSubItemAction, item: TimelineItem, sub: TimelineSubItem): string {\n return typeof action.label === 'function' ? action.label(item, sub) : action.label;\n }\n\n getSubItemActionIconName(action: TimelineSubItemAction, item: TimelineItem, sub: TimelineSubItem): any {\n const icon = action.icon;\n if (typeof icon === 'function') {\n if (icon.prototype === undefined) {\n return icon(item, sub);\n }\n return icon;\n }\n return icon;\n }\n\n isSubItemActionVisible(action: TimelineSubItemAction, item: TimelineItem, sub: TimelineSubItem): boolean {\n return action.isVisible ? action.isVisible(item, sub) : true;\n }\n\n isSubItemActionDisabled(action: TimelineSubItemAction, item: TimelineItem, sub: TimelineSubItem): boolean {\n return action.isDisabled ? action.isDisabled(item, sub) : false;\n }\n}\n","<div class=\"space-y-4\">\n\n <!-- ============ Header ============ -->\n @if (showHeader() && (headerTitle() || showAddItem() || headerActions().length > 0)) {\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n @if (headerTitle()) {\n <div class=\"text-sm font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ headerTitle() }}\n </div>\n }\n <div class=\"flex items-center gap-1.5 ml-auto\">\n @if (showAddItem()) {\n <button\n type=\"button\"\n (click)=\"addItem.emit()\"\n [attr.aria-label]=\"addItemTooltip()\"\n class=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md _shk-bg-primary text-white hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon(addItemIcon())\" class=\"w-3.5 h-3.5\"></svg>\n {{ addItemLabel() }}\n </button>\n }\n @for (action of headerActions(); track $index) {\n @if (isHeaderActionVisible(action)) {\n <button\n type=\"button\"\n [class]=\"action.class || 'inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md _shk-bg-primary text-white hover:[background-color:var(--shk-primary-700)] transition-colors disabled:opacity-50 disabled:cursor-not-allowed'\"\n [disabled]=\"isHeaderActionDisabled(action)\"\n (click)=\"action.onClick()\"\n >\n @if (action.icon) {\n <svg [lucideIcon]=\"getIcon(action.icon)\" class=\"w-3.5 h-3.5\"></svg>\n }\n {{ action.label }}\n </button>\n }\n }\n </div>\n </div>\n }\n\n <!-- ============ Timeline ============ -->\n @if (items().length > 0) {\n <div class=\"relative\">\n @if (showLine()) {\n <div [class]=\"lineClass()\" aria-hidden=\"true\"></div>\n }\n\n @for (item of items(); track item.id; let i = $index) {\n @if (alignment() === 'alternate') {\n <div class=\"relative flex items-start gap-4 lg:grid lg:grid-cols-2 lg:gap-0\">\n <!-- Marker (centered on desktop) -->\n <div [class]=\"alternateMarkerColumnClass()\">\n <span [class]=\"markerClass(item, i)\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['marker'] || defaultMarker; context: { $implicit: item, index: i }\"\n ></ng-container>\n </span>\n </div>\n\n <!-- Content card -->\n <div\n class=\"flex-1 min-w-0\"\n [class.lg:order-1]=\"$even\"\n [class.lg:order-2]=\"!$even\"\n [class.lg:pr-12]=\"$even\"\n [class.lg:pl-12]=\"!$even\"\n >\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['content'] || card; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n\n <!-- Opposite info -->\n @if (showOpposite()) {\n <div\n class=\"hidden lg:flex lg:items-center\"\n [class.lg:order-2]=\"$even\"\n [class.lg:order-1]=\"!$even\"\n [class.lg:pl-12]=\"$even\"\n [class.lg:justify-end]=\"!$even\"\n [class.lg:pr-12]=\"!$even\"\n >\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['opposite'] || itemInfo; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n }\n </div>\n } @else {\n <!-- Left alignment -->\n <div class=\"relative flex items-start gap-4\">\n <div [class]=\"markerColumnClass()\">\n <span [class]=\"markerClass(item, i)\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['marker'] || defaultMarker; context: { $implicit: item, index: i }\"\n ></ng-container>\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['content'] || card; context: { $implicit: item, index: i }\"\n ></ng-container>\n </div>\n </div>\n }\n }\n </div>\n } @else if (showEmptyState()) {\n <!-- ============ Empty state ============ -->\n <div class=\"text-center py-12\">\n @if (customTemplates()['empty']) {\n <ng-container *ngTemplateOutlet=\"customTemplates()['empty']\"></ng-container>\n } @else {\n <div class=\"w-16 h-16 mx-auto mb-4 _shk-bg-surface-100 dark:[background-color:var(--shk-surface-100)] rounded-full flex items-center justify-center\">\n <svg [lucideIcon]=\"getIcon(emptyIcon())\" class=\"w-8 h-8 _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\"></svg>\n </div>\n <p class=\"text-sm _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\">{{ emptyMessage() }}</p>\n }\n </div>\n }\n\n <!-- ============ Templates ============ -->\n\n <ng-template #defaultMarker let-item let-index=\"index\">\n <span class=\"font-bold\">{{ markerText(item, index) }}</span>\n </ng-template>\n\n <ng-template #itemInfo let-item>\n <div>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <div class=\"mb-2\">\n <span class=\"inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-semibold _shk-bg-surface-100 dark:[background-color:var(--shk-surface-200)] _shk-text-surface-600 dark:[color:var(--shk-surface-600)]\">\n @if (item.badgeIcon) {\n <svg [lucideIcon]=\"getIcon(item.badgeIcon)\" class=\"w-3 h-3\"></svg>\n }\n {{ item.badge }}\n </span>\n </div>\n }\n @if (item.title) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">{{ item.title }}</div>\n }\n @let subCount = (item.subItems?.length || 0);\n @if (item.subtitle || (showSubItemCount() && subCount > 0)) {\n <div class=\"text-xs _shk-text-surface-400 dark:[color:var(--shk-surface-500)] mt-1\">\n {{ item.subtitle || (subCount + ' ' + subItemCountLabel()) }}\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #card let-item>\n @let subItems = item.subItems || [];\n <div class=\"shk-timeline-card mb-4 bg-white dark:[background-color:var(--shk-surface-50)] rounded-xl border _shk-border dark:[border-color:var(--shk-surface-200)] shadow-sm overflow-hidden\">\n <!-- Header (mobile in alternate, always in left) -->\n <div class=\"flex items-center gap-2 px-4 pt-4 pb-2\" [class.lg:hidden]=\"alignment() === 'alternate'\">\n <ng-container *ngTemplateOutlet=\"itemInfo; context: { $implicit: item }\"></ng-container>\n </div>\n\n <!-- Description -->\n @if (showDescription() && item.description) {\n <div class=\"px-4 pt-3\">\n @if (customTemplates()['description']) {\n <ng-container *ngTemplateOutlet=\"customTemplates()['description']; context: { $implicit: item }\"></ng-container>\n } @else {\n <p class=\"text-sm _shk-text-surface-600 dark:[color:var(--shk-surface-600)] leading-relaxed\">{{ item.description }}</p>\n }\n </div>\n }\n\n <!-- Sub items -->\n @if (subItems.length > 0) {\n <div class=\"mt-2\">\n @for (sub of subItems; track sub.id) {\n <ng-container\n *ngTemplateOutlet=\"customTemplates()['subItem'] || defaultSubItem; context: { $implicit: item, subItem: sub }\"\n ></ng-container>\n }\n </div>\n } @else if (noSubItemsMessage()) {\n <div class=\"px-4 py-6 text-center\">\n <div class=\"inline-flex items-center gap-2 text-sm _shk-text-surface-400 dark:[color:var(--shk-surface-500)]\">\n <svg [lucideIcon]=\"getIcon('info')\" class=\"w-4 h-4\"></svg>\n <span class=\"italic\">{{ noSubItemsMessage() }}</span>\n </div>\n </div>\n }\n\n <!-- Footer actions -->\n @if (showAddSubItem() || itemActions().length > 0) {\n <div class=\"flex items-center gap-1 px-4 py-2 _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] border-t _shk-border dark:[border-color:var(--shk-surface-100)]\">\n @if (showAddSubItem()) {\n <button\n type=\"button\"\n (click)=\"addSubItem.emit(item)\"\n class=\"relative group inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium _shk-text-primary hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] rounded-lg transition-colors\"\n >\n <svg [lucideIcon]=\"getIcon('circle-plus')\" class=\"w-3.5 h-3.5\"></svg>\n {{ addSubItemLabel() }}\n <span class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ addSubItemTooltip() }}\n </span>\n </button>\n }\n <div class=\"flex-1\"></div>\n @for (action of itemActions(); track $index) {\n @if (isItemActionVisible(action, item)) {\n <div class=\"relative group\">\n <button\n type=\"button\"\n (click)=\"action.onClick(item)\"\n [class]=\"'timeline-icon-btn ' + getItemActionClass(action, item)\"\n [disabled]=\"isItemActionDisabled(action, item)\"\n [attr.aria-label]=\"getItemActionLabel(action, item)\"\n >\n <svg [lucideIcon]=\"getIcon(getItemActionIconName(action, item))\" class=\"w-3.5 h-3.5\"></svg>\n </button>\n <span class=\"absolute bottom-full left-1/2 -translate-x-1/2 mb-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ getItemActionLabel(action, item) }}\n </span>\n </div>\n }\n }\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template #defaultSubItem let-item let-sub=\"subItem\">\n <div class=\"px-4 py-3 border-t [border-color:var(--shk-surface-100)] dark:[border-color:var(--shk-surface-700)] hover:[background-color:color-mix(in srgb,var(--shk-primary-50)30%,transparent)] dark:hover:[background-color:color-mix(in srgb,var(--shk-primary-900)10%,transparent)] transition-colors duration-200 group\">\n <div class=\"flex items-start gap-3\">\n <span\n [class]=\"sub.iconClass || 'flex items-center justify-center w-9 h-9 rounded-lg shrink-0 mt-0.5'\"\n [style]=\"sub.iconClass ? undefined : subItemStyle(sub)\"\n >\n <svg [lucideIcon]=\"getIcon(subItemIconName(sub))\" class=\"w-4 h-4\"></svg>\n </span>\n\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex items-center gap-2 flex-wrap\">\n @if (sub.optional) {\n <span class=\"text-[10px] font-semibold uppercase tracking-wide px-1.5 py-0.5 rounded _shk-bg-amber-soft _shk-text-amber-600 dark:[color:var(--shk-amber-400)]\">\n {{ sub.optionalLabel || optionalLabel() }}\n </span>\n }\n <span class=\"font-medium _shk-text-surface-800 dark:[color:var(--shk-surface-800)] text-sm truncate\">{{ sub.title }}</span>\n @if (sub.subtitle) {\n <span class=\"text-xs _shk-text-surface-400 dark:[color:var(--shk-surface-500)] truncate\">· {{ sub.subtitle }}</span>\n }\n </div>\n\n @if (showSubItemMeta() && (sub.meta?.length || 0) > 0) {\n <div class=\"flex flex-wrap items-center gap-x-3 gap-y-1 mt-1.5 text-xs _shk-text-surface-500 dark:[color:var(--shk-surface-500)]\">\n @for (m of sub.meta!; track $index) {\n <span class=\"flex items-center gap-1\">\n <svg [lucideIcon]=\"getIcon(m.icon)\" class=\"w-3 h-3\"></svg>\n @if (m.label) {\n <span class=\"font-medium\">{{ m.label }}:</span>\n }\n {{ m.value }}\n </span>\n }\n </div>\n }\n </div>\n\n <div class=\"flex items-center gap-0.5 shrink-0\">\n @if (showSubItemPrice() && sub.price !== undefined && sub.price !== null && sub.price !== '') {\n <span class=\"font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)] text-xs mr-1\">{{ sub.price }}</span>\n }\n @for (action of subItemActions(); track $index) {\n @if (isSubItemActionVisible(action, item, sub)) {\n <div class=\"relative group\">\n <button\n type=\"button\"\n (click)=\"action.onClick(item, sub)\"\n class=\"timeline-icon-btn opacity-100 lg:opacity-0 lg:group-hover:opacity-100 transition-opacity\"\n [disabled]=\"isSubItemActionDisabled(action, item, sub)\"\n [attr.aria-label]=\"getSubItemActionLabel(action, item, sub)\"\n >\n <svg [lucideIcon]=\"getIcon(getSubItemActionIconName(action, item, sub))\" class=\"w-3.5 h-3.5\"></svg>\n </button>\n <span class=\"absolute top-full left-1/2 -translate-x-1/2 mt-1 px-2 py-1 text-xs _shk-bg-tooltip _shk-text-tooltip rounded whitespace-nowrap opacity-0 group-hover:opacity-100 transition pointer-events-none z-[9999] shadow-lg\">\n {{ getSubItemActionLabel(action, item, sub) }}\n </span>\n </div>\n }\n }\n </div>\n </div>\n </div>\n </ng-template>\n\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["getIconFromCentral"],"mappings":"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"}
@@ -0,0 +1,186 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, signal, effect, forwardRef, Component } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import { CommonModule } from '@angular/common';
5
+
6
+ /**
7
+ * Shirkasoft UI Components.
8
+ * Authors: Roberto Valladares Martin (Ansem13), Julio César García García (Sanjuli14).
9
+ * Belongs to Shirkasoft.
10
+ */
11
+ /**
12
+ * Switch / checkbox component that implements ControlValueAccessor so it can
13
+ * be used with reactive and template-driven forms.
14
+ */
15
+ class ToggleComponent {
16
+ constructor() {
17
+ /** Text displayed next to the control. */
18
+ this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
19
+ /** Visual style: 'toggle' (switch) or 'checkbox'. Defaults to 'toggle'. */
20
+ this.mode = input('toggle', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
21
+ /** Manually controlled checked state (supports one-way binding). */
22
+ this.checked = input(undefined, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
23
+ /** Emitted with the new value when the user toggles the control. */
24
+ this.checkedChange = output();
25
+ /** Internal controlled/reactive value. */
26
+ this._value = signal(false, ...(ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []));
27
+ /** Reactive disabled state. */
28
+ this._disabled = signal(false, ...(ngDevMode ? [{ debugName: "_disabled" }] : /* istanbul ignore next */ []));
29
+ /** Callback notified with the new value on change (ControlValueAccessor). */
30
+ this.onChange = () => { };
31
+ /** Callback notified when the control loses focus or is touched. */
32
+ this.onTouched = () => { };
33
+ effect(() => {
34
+ const manual = this.checked();
35
+ if (manual !== undefined) {
36
+ this._value.set(manual);
37
+ }
38
+ });
39
+ }
40
+ /** Sets the value from the form control. */
41
+ writeValue(value) {
42
+ this._value.set(!!value);
43
+ }
44
+ /** Registers the callback invoked on value changes (ControlValueAccessor). */
45
+ registerOnChange(fn) {
46
+ this.onChange = fn;
47
+ }
48
+ /** Registers the callback invoked when the control is touched. */
49
+ registerOnTouched(fn) {
50
+ this.onTouched = fn;
51
+ }
52
+ /** Reflects the disabled state of the form control. */
53
+ setDisabledState(isDisabled) {
54
+ this._disabled.set(isDisabled);
55
+ }
56
+ /**
57
+ * Inverts the current value (unless disabled), notifies the form control,
58
+ * marks the control as touched and emits `checkedChange`.
59
+ */
60
+ toggle() {
61
+ if (this._disabled())
62
+ return;
63
+ const newValue = !this._value();
64
+ this._value.set(newValue);
65
+ this.onChange(newValue);
66
+ this.onTouched();
67
+ this.checkedChange.emit(newValue);
68
+ }
69
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
70
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: ToggleComponent, isStandalone: true, selector: "shk-toggle", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checkedChange: "checkedChange" }, providers: [
71
+ {
72
+ provide: NG_VALUE_ACCESSOR,
73
+ useExisting: forwardRef(() => ToggleComponent),
74
+ multi: true,
75
+ },
76
+ ], ngImport: i0, template: `
77
+ <div class="relative">
78
+ <label
79
+ class="inline-flex items-center gap-3 cursor-pointer select-none"
80
+ [class.opacity-50]="_disabled()"
81
+ [class.cursor-not-allowed]="_disabled()"
82
+ >
83
+ @if (mode() === 'toggle') {
84
+ <div class="relative flex-shrink-0" (click)="toggle()">
85
+ <div
86
+ class="w-10 h-6 rounded-full transition-colors duration-200"
87
+ [class._shk-bg-primary]="_value()"
88
+ [class._shk-bg-surface-300]="!_value()"
89
+ [class._shk-dark-bg-surface-600]="!_value()"
90
+ ></div>
91
+ <div
92
+ class="absolute top-0.5 left-0.5 w-5 h-5 _shk-bg-white rounded-full shadow transition-transform duration-200"
93
+ [class.translate-x-4]="_value()"
94
+ ></div>
95
+ </div>
96
+ } @else {
97
+ <div
98
+ class="flex-shrink-0 w-4 h-4 rounded border-2 transition-colors duration-200 flex items-center justify-center"
99
+ [class._shk-bg-primary]="_value()"
100
+ [class._shk-border-primary]="_value()"
101
+ [class._shk-border-surface-300]="!_value()"
102
+ [class._shk-dark-border-surface-600]="!_value()"
103
+ (click)="toggle()"
104
+ >
105
+ @if (_value()) {
106
+ <svg class="w-3 h-3 text-white" viewBox="0 0 12 12" fill="none">
107
+ <path d="M2 6l3 3 5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
108
+ </svg>
109
+ }
110
+ </div>
111
+ }
112
+ @if (label()) {
113
+ <span class="text-sm _shk-text-surface-700 _shk-dark-text-surface-300">
114
+ {{ label() }}
115
+ </span>
116
+ }
117
+ </label>
118
+ </div>
119
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
120
+ }
121
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: ToggleComponent, decorators: [{
122
+ type: Component,
123
+ args: [{
124
+ selector: 'shk-toggle',
125
+ standalone: true,
126
+ imports: [CommonModule],
127
+ template: `
128
+ <div class="relative">
129
+ <label
130
+ class="inline-flex items-center gap-3 cursor-pointer select-none"
131
+ [class.opacity-50]="_disabled()"
132
+ [class.cursor-not-allowed]="_disabled()"
133
+ >
134
+ @if (mode() === 'toggle') {
135
+ <div class="relative flex-shrink-0" (click)="toggle()">
136
+ <div
137
+ class="w-10 h-6 rounded-full transition-colors duration-200"
138
+ [class._shk-bg-primary]="_value()"
139
+ [class._shk-bg-surface-300]="!_value()"
140
+ [class._shk-dark-bg-surface-600]="!_value()"
141
+ ></div>
142
+ <div
143
+ class="absolute top-0.5 left-0.5 w-5 h-5 _shk-bg-white rounded-full shadow transition-transform duration-200"
144
+ [class.translate-x-4]="_value()"
145
+ ></div>
146
+ </div>
147
+ } @else {
148
+ <div
149
+ class="flex-shrink-0 w-4 h-4 rounded border-2 transition-colors duration-200 flex items-center justify-center"
150
+ [class._shk-bg-primary]="_value()"
151
+ [class._shk-border-primary]="_value()"
152
+ [class._shk-border-surface-300]="!_value()"
153
+ [class._shk-dark-border-surface-600]="!_value()"
154
+ (click)="toggle()"
155
+ >
156
+ @if (_value()) {
157
+ <svg class="w-3 h-3 text-white" viewBox="0 0 12 12" fill="none">
158
+ <path d="M2 6l3 3 5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
159
+ </svg>
160
+ }
161
+ </div>
162
+ }
163
+ @if (label()) {
164
+ <span class="text-sm _shk-text-surface-700 _shk-dark-text-surface-300">
165
+ {{ label() }}
166
+ </span>
167
+ }
168
+ </label>
169
+ </div>
170
+ `,
171
+ providers: [
172
+ {
173
+ provide: NG_VALUE_ACCESSOR,
174
+ useExisting: forwardRef(() => ToggleComponent),
175
+ multi: true,
176
+ },
177
+ ],
178
+ }]
179
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], checkedChange: [{ type: i0.Output, args: ["checkedChange"] }] } });
180
+
181
+ /**
182
+ * Generated bundle index. Do not edit.
183
+ */
184
+
185
+ export { ToggleComponent };
186
+ //# sourceMappingURL=shirkasoft-ui-components-toggle.mjs.map