@weeehaoooz/talos-ui 0.1.0 → 0.1.2

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 (187) hide show
  1. package/README.md +2 -0
  2. package/fesm2022/{weeehaoooz-talos-ui-button-button-group.mjs → weeehaoooz-talos-ui-button.mjs} +115 -18
  3. package/fesm2022/weeehaoooz-talos-ui-button.mjs.map +1 -0
  4. package/fesm2022/weeehaoooz-talos-ui-data-display.mjs +3110 -0
  5. package/fesm2022/weeehaoooz-talos-ui-data-display.mjs.map +1 -0
  6. package/fesm2022/weeehaoooz-talos-ui-data-viz.mjs +2414 -0
  7. package/fesm2022/weeehaoooz-talos-ui-data-viz.mjs.map +1 -0
  8. package/fesm2022/weeehaoooz-talos-ui-dropdown.mjs +1039 -0
  9. package/fesm2022/weeehaoooz-talos-ui-dropdown.mjs.map +1 -0
  10. package/fesm2022/weeehaoooz-talos-ui-feedback.mjs +2885 -0
  11. package/fesm2022/weeehaoooz-talos-ui-feedback.mjs.map +1 -0
  12. package/fesm2022/weeehaoooz-talos-ui-form.mjs +10799 -0
  13. package/fesm2022/weeehaoooz-talos-ui-form.mjs.map +1 -0
  14. package/fesm2022/weeehaoooz-talos-ui-layout.mjs +1320 -11
  15. package/fesm2022/weeehaoooz-talos-ui-layout.mjs.map +1 -1
  16. package/fesm2022/weeehaoooz-talos-ui-nav.mjs +119 -72
  17. package/fesm2022/weeehaoooz-talos-ui-nav.mjs.map +1 -1
  18. package/fesm2022/weeehaoooz-talos-ui.mjs +22190 -15213
  19. package/fesm2022/weeehaoooz-talos-ui.mjs.map +1 -1
  20. package/package.json +20 -135
  21. package/styles/_breadcrumb.scss +16 -0
  22. package/styles/_button-group.scss +156 -7
  23. package/styles/_buttons.scss +156 -8
  24. package/styles/_dropdown.scss +438 -0
  25. package/styles/_form-controls.scss +13 -0
  26. package/styles/_progress-bar.scss +43 -0
  27. package/styles/_skeleton.scss +176 -0
  28. package/styles/_spinner.scss +58 -0
  29. package/styles/_variables.scss +37 -0
  30. package/styles/index.scss +6 -1
  31. package/types/weeehaoooz-talos-ui-button.d.ts +92 -0
  32. package/types/weeehaoooz-talos-ui-button.d.ts.map +1 -0
  33. package/types/weeehaoooz-talos-ui-data-display.d.ts +1018 -0
  34. package/types/weeehaoooz-talos-ui-data-display.d.ts.map +1 -0
  35. package/types/weeehaoooz-talos-ui-data-viz.d.ts +839 -0
  36. package/types/weeehaoooz-talos-ui-data-viz.d.ts.map +1 -0
  37. package/types/weeehaoooz-talos-ui-dropdown.d.ts +187 -0
  38. package/types/weeehaoooz-talos-ui-dropdown.d.ts.map +1 -0
  39. package/types/weeehaoooz-talos-ui-feedback.d.ts +1495 -0
  40. package/types/weeehaoooz-talos-ui-feedback.d.ts.map +1 -0
  41. package/types/weeehaoooz-talos-ui-form.d.ts +2639 -0
  42. package/types/weeehaoooz-talos-ui-form.d.ts.map +1 -0
  43. package/types/weeehaoooz-talos-ui-layout.d.ts +851 -3
  44. package/types/weeehaoooz-talos-ui-layout.d.ts.map +1 -1
  45. package/types/weeehaoooz-talos-ui-nav.d.ts +36 -10
  46. package/types/weeehaoooz-talos-ui-nav.d.ts.map +1 -1
  47. package/types/weeehaoooz-talos-ui.d.ts +6949 -4137
  48. package/types/weeehaoooz-talos-ui.d.ts.map +1 -1
  49. package/fesm2022/weeehaoooz-talos-ui-button-button-group.mjs.map +0 -1
  50. package/fesm2022/weeehaoooz-talos-ui-button-button.mjs +0 -93
  51. package/fesm2022/weeehaoooz-talos-ui-button-button.mjs.map +0 -1
  52. package/fesm2022/weeehaoooz-talos-ui-data-display-badge.mjs +0 -233
  53. package/fesm2022/weeehaoooz-talos-ui-data-display-badge.mjs.map +0 -1
  54. package/fesm2022/weeehaoooz-talos-ui-data-display-status-tag.mjs +0 -361
  55. package/fesm2022/weeehaoooz-talos-ui-data-display-status-tag.mjs.map +0 -1
  56. package/fesm2022/weeehaoooz-talos-ui-data-display-timeline.mjs +0 -312
  57. package/fesm2022/weeehaoooz-talos-ui-data-display-timeline.mjs.map +0 -1
  58. package/fesm2022/weeehaoooz-talos-ui-data-display-trend-indicator.mjs +0 -235
  59. package/fesm2022/weeehaoooz-talos-ui-data-display-trend-indicator.mjs.map +0 -1
  60. package/fesm2022/weeehaoooz-talos-ui-data-viz-category-bar.mjs +0 -462
  61. package/fesm2022/weeehaoooz-talos-ui-data-viz-category-bar.mjs.map +0 -1
  62. package/fesm2022/weeehaoooz-talos-ui-data-viz-heatmap.mjs +0 -805
  63. package/fesm2022/weeehaoooz-talos-ui-data-viz-heatmap.mjs.map +0 -1
  64. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-donut.mjs +0 -267
  65. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-donut.mjs.map +0 -1
  66. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-gauge.mjs +0 -351
  67. package/fesm2022/weeehaoooz-talos-ui-data-viz-mini-gauge.mjs.map +0 -1
  68. package/fesm2022/weeehaoooz-talos-ui-data-viz-sparkline.mjs +0 -566
  69. package/fesm2022/weeehaoooz-talos-ui-data-viz-sparkline.mjs.map +0 -1
  70. package/fesm2022/weeehaoooz-talos-ui-feedback-alert.mjs +0 -534
  71. package/fesm2022/weeehaoooz-talos-ui-feedback-alert.mjs.map +0 -1
  72. package/fesm2022/weeehaoooz-talos-ui-feedback-dialog.mjs +0 -446
  73. package/fesm2022/weeehaoooz-talos-ui-feedback-dialog.mjs.map +0 -1
  74. package/fesm2022/weeehaoooz-talos-ui-feedback-snackbar.mjs +0 -376
  75. package/fesm2022/weeehaoooz-talos-ui-feedback-snackbar.mjs.map +0 -1
  76. package/fesm2022/weeehaoooz-talos-ui-feedback-tooltip.mjs +0 -147
  77. package/fesm2022/weeehaoooz-talos-ui-feedback-tooltip.mjs.map +0 -1
  78. package/fesm2022/weeehaoooz-talos-ui-form-affix.mjs +0 -242
  79. package/fesm2022/weeehaoooz-talos-ui-form-affix.mjs.map +0 -1
  80. package/fesm2022/weeehaoooz-talos-ui-form-autocomplete.mjs +0 -514
  81. package/fesm2022/weeehaoooz-talos-ui-form-autocomplete.mjs.map +0 -1
  82. package/fesm2022/weeehaoooz-talos-ui-form-checkbox.mjs +0 -548
  83. package/fesm2022/weeehaoooz-talos-ui-form-checkbox.mjs.map +0 -1
  84. package/fesm2022/weeehaoooz-talos-ui-form-chips.mjs +0 -692
  85. package/fesm2022/weeehaoooz-talos-ui-form-chips.mjs.map +0 -1
  86. package/fesm2022/weeehaoooz-talos-ui-form-color-picker.mjs +0 -761
  87. package/fesm2022/weeehaoooz-talos-ui-form-color-picker.mjs.map +0 -1
  88. package/fesm2022/weeehaoooz-talos-ui-form-date-picker.mjs +0 -896
  89. package/fesm2022/weeehaoooz-talos-ui-form-date-picker.mjs.map +0 -1
  90. package/fesm2022/weeehaoooz-talos-ui-form-date-range-picker.mjs +0 -872
  91. package/fesm2022/weeehaoooz-talos-ui-form-date-range-picker.mjs.map +0 -1
  92. package/fesm2022/weeehaoooz-talos-ui-form-date-time-picker.mjs +0 -119
  93. package/fesm2022/weeehaoooz-talos-ui-form-date-time-picker.mjs.map +0 -1
  94. package/fesm2022/weeehaoooz-talos-ui-form-date-time-range-picker.mjs +0 -135
  95. package/fesm2022/weeehaoooz-talos-ui-form-date-time-range-picker.mjs.map +0 -1
  96. package/fesm2022/weeehaoooz-talos-ui-form-drop-zone.mjs +0 -666
  97. package/fesm2022/weeehaoooz-talos-ui-form-drop-zone.mjs.map +0 -1
  98. package/fesm2022/weeehaoooz-talos-ui-form-form-field.mjs +0 -147
  99. package/fesm2022/weeehaoooz-talos-ui-form-form-field.mjs.map +0 -1
  100. package/fesm2022/weeehaoooz-talos-ui-form-input.mjs +0 -33
  101. package/fesm2022/weeehaoooz-talos-ui-form-input.mjs.map +0 -1
  102. package/fesm2022/weeehaoooz-talos-ui-form-otp.mjs +0 -455
  103. package/fesm2022/weeehaoooz-talos-ui-form-otp.mjs.map +0 -1
  104. package/fesm2022/weeehaoooz-talos-ui-form-password-input.mjs +0 -379
  105. package/fesm2022/weeehaoooz-talos-ui-form-password-input.mjs.map +0 -1
  106. package/fesm2022/weeehaoooz-talos-ui-form-radio.mjs +0 -297
  107. package/fesm2022/weeehaoooz-talos-ui-form-radio.mjs.map +0 -1
  108. package/fesm2022/weeehaoooz-talos-ui-form-range-input.mjs +0 -661
  109. package/fesm2022/weeehaoooz-talos-ui-form-range-input.mjs.map +0 -1
  110. package/fesm2022/weeehaoooz-talos-ui-form-rating.mjs +0 -346
  111. package/fesm2022/weeehaoooz-talos-ui-form-rating.mjs.map +0 -1
  112. package/fesm2022/weeehaoooz-talos-ui-form-select-input.mjs +0 -896
  113. package/fesm2022/weeehaoooz-talos-ui-form-select-input.mjs.map +0 -1
  114. package/fesm2022/weeehaoooz-talos-ui-form-slide-toggle.mjs +0 -252
  115. package/fesm2022/weeehaoooz-talos-ui-form-slide-toggle.mjs.map +0 -1
  116. package/fesm2022/weeehaoooz-talos-ui-form-transfer-list.mjs +0 -916
  117. package/fesm2022/weeehaoooz-talos-ui-form-transfer-list.mjs.map +0 -1
  118. package/types/weeehaoooz-talos-ui-button-button-group.d.ts +0 -59
  119. package/types/weeehaoooz-talos-ui-button-button-group.d.ts.map +0 -1
  120. package/types/weeehaoooz-talos-ui-button-button.d.ts +0 -38
  121. package/types/weeehaoooz-talos-ui-button-button.d.ts.map +0 -1
  122. package/types/weeehaoooz-talos-ui-data-display-badge.d.ts +0 -119
  123. package/types/weeehaoooz-talos-ui-data-display-badge.d.ts.map +0 -1
  124. package/types/weeehaoooz-talos-ui-data-display-status-tag.d.ts +0 -135
  125. package/types/weeehaoooz-talos-ui-data-display-status-tag.d.ts.map +0 -1
  126. package/types/weeehaoooz-talos-ui-data-display-timeline.d.ts +0 -144
  127. package/types/weeehaoooz-talos-ui-data-display-timeline.d.ts.map +0 -1
  128. package/types/weeehaoooz-talos-ui-data-display-trend-indicator.d.ts +0 -83
  129. package/types/weeehaoooz-talos-ui-data-display-trend-indicator.d.ts.map +0 -1
  130. package/types/weeehaoooz-talos-ui-data-viz-category-bar.d.ts +0 -255
  131. package/types/weeehaoooz-talos-ui-data-viz-category-bar.d.ts.map +0 -1
  132. package/types/weeehaoooz-talos-ui-data-viz-heatmap.d.ts +0 -204
  133. package/types/weeehaoooz-talos-ui-data-viz-heatmap.d.ts.map +0 -1
  134. package/types/weeehaoooz-talos-ui-data-viz-mini-donut.d.ts +0 -101
  135. package/types/weeehaoooz-talos-ui-data-viz-mini-donut.d.ts.map +0 -1
  136. package/types/weeehaoooz-talos-ui-data-viz-mini-gauge.d.ts +0 -138
  137. package/types/weeehaoooz-talos-ui-data-viz-mini-gauge.d.ts.map +0 -1
  138. package/types/weeehaoooz-talos-ui-data-viz-sparkline.d.ts +0 -161
  139. package/types/weeehaoooz-talos-ui-data-viz-sparkline.d.ts.map +0 -1
  140. package/types/weeehaoooz-talos-ui-feedback-alert.d.ts +0 -212
  141. package/types/weeehaoooz-talos-ui-feedback-alert.d.ts.map +0 -1
  142. package/types/weeehaoooz-talos-ui-feedback-dialog.d.ts +0 -259
  143. package/types/weeehaoooz-talos-ui-feedback-dialog.d.ts.map +0 -1
  144. package/types/weeehaoooz-talos-ui-feedback-snackbar.d.ts +0 -147
  145. package/types/weeehaoooz-talos-ui-feedback-snackbar.d.ts.map +0 -1
  146. package/types/weeehaoooz-talos-ui-feedback-tooltip.d.ts +0 -32
  147. package/types/weeehaoooz-talos-ui-feedback-tooltip.d.ts.map +0 -1
  148. package/types/weeehaoooz-talos-ui-form-affix.d.ts +0 -88
  149. package/types/weeehaoooz-talos-ui-form-affix.d.ts.map +0 -1
  150. package/types/weeehaoooz-talos-ui-form-autocomplete.d.ts +0 -113
  151. package/types/weeehaoooz-talos-ui-form-autocomplete.d.ts.map +0 -1
  152. package/types/weeehaoooz-talos-ui-form-checkbox.d.ts +0 -165
  153. package/types/weeehaoooz-talos-ui-form-checkbox.d.ts.map +0 -1
  154. package/types/weeehaoooz-talos-ui-form-chips.d.ts +0 -152
  155. package/types/weeehaoooz-talos-ui-form-chips.d.ts.map +0 -1
  156. package/types/weeehaoooz-talos-ui-form-color-picker.d.ts +0 -144
  157. package/types/weeehaoooz-talos-ui-form-color-picker.d.ts.map +0 -1
  158. package/types/weeehaoooz-talos-ui-form-date-picker.d.ts +0 -138
  159. package/types/weeehaoooz-talos-ui-form-date-picker.d.ts.map +0 -1
  160. package/types/weeehaoooz-talos-ui-form-date-range-picker.d.ts +0 -148
  161. package/types/weeehaoooz-talos-ui-form-date-range-picker.d.ts.map +0 -1
  162. package/types/weeehaoooz-talos-ui-form-date-time-picker.d.ts +0 -44
  163. package/types/weeehaoooz-talos-ui-form-date-time-picker.d.ts.map +0 -1
  164. package/types/weeehaoooz-talos-ui-form-date-time-range-picker.d.ts +0 -48
  165. package/types/weeehaoooz-talos-ui-form-date-time-range-picker.d.ts.map +0 -1
  166. package/types/weeehaoooz-talos-ui-form-drop-zone.d.ts +0 -227
  167. package/types/weeehaoooz-talos-ui-form-drop-zone.d.ts.map +0 -1
  168. package/types/weeehaoooz-talos-ui-form-form-field.d.ts +0 -42
  169. package/types/weeehaoooz-talos-ui-form-form-field.d.ts.map +0 -1
  170. package/types/weeehaoooz-talos-ui-form-input.d.ts +0 -15
  171. package/types/weeehaoooz-talos-ui-form-input.d.ts.map +0 -1
  172. package/types/weeehaoooz-talos-ui-form-otp.d.ts +0 -111
  173. package/types/weeehaoooz-talos-ui-form-otp.d.ts.map +0 -1
  174. package/types/weeehaoooz-talos-ui-form-password-input.d.ts +0 -145
  175. package/types/weeehaoooz-talos-ui-form-password-input.d.ts.map +0 -1
  176. package/types/weeehaoooz-talos-ui-form-radio.d.ts +0 -84
  177. package/types/weeehaoooz-talos-ui-form-radio.d.ts.map +0 -1
  178. package/types/weeehaoooz-talos-ui-form-range-input.d.ts +0 -181
  179. package/types/weeehaoooz-talos-ui-form-range-input.d.ts.map +0 -1
  180. package/types/weeehaoooz-talos-ui-form-rating.d.ts +0 -110
  181. package/types/weeehaoooz-talos-ui-form-rating.d.ts.map +0 -1
  182. package/types/weeehaoooz-talos-ui-form-select-input.d.ts +0 -195
  183. package/types/weeehaoooz-talos-ui-form-select-input.d.ts.map +0 -1
  184. package/types/weeehaoooz-talos-ui-form-slide-toggle.d.ts +0 -79
  185. package/types/weeehaoooz-talos-ui-form-slide-toggle.d.ts.map +0 -1
  186. package/types/weeehaoooz-talos-ui-form-transfer-list.d.ts +0 -192
  187. package/types/weeehaoooz-talos-ui-form-transfer-list.d.ts.map +0 -1
@@ -0,0 +1,1039 @@
1
+ import { Overlay } from '@angular/cdk/overlay';
2
+ import { TemplatePortal } from '@angular/cdk/portal';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, ElementRef, ViewContainerRef, DestroyRef, input, output, signal, effect, Directive, computed, Component, contentChildren, ViewChild, NgModule } from '@angular/core';
5
+ import { filter } from 'rxjs/operators';
6
+ import * as i1 from '@angular/common';
7
+ import { CommonModule } from '@angular/common';
8
+ import { LucideChevronRight, LucideCheck } from '@lucide/angular';
9
+
10
+ class TalosDropdownTriggerDirective {
11
+ elementRef = inject(ElementRef);
12
+ overlay = inject(Overlay);
13
+ vcr = inject(ViewContainerRef);
14
+ destroyRef = inject(DestroyRef);
15
+ /** Menu component instance to trigger */
16
+ menu = input(null, { ...(ngDevMode ? { debugName: "menu" } : /* istanbul ignore next */ {}), alias: 'talosDropdownTrigger' });
17
+ /** Secondary alias for menu */
18
+ menuAlt = input(null, { ...(ngDevMode ? { debugName: "menuAlt" } : /* istanbul ignore next */ {}), alias: 'talosDropdown' });
19
+ /** Trigger activation mechanism: 'click', 'hover', or 'both' */
20
+ triggerOn = input('click', /* @ts-ignore */
21
+ ...(ngDevMode ? [{ debugName: "triggerOn" }] : /* istanbul ignore next */ []));
22
+ /** Desired placement around the trigger */
23
+ placement = input('bottom-start', /* @ts-ignore */
24
+ ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
25
+ /** Element, ElementRef, or Component instance to which the dropdown overlay is anchored/attached */
26
+ connectedTo = input(null, /* @ts-ignore */
27
+ ...(ngDevMode ? [{ debugName: "connectedTo" }] : /* istanbul ignore next */ []));
28
+ /** Secondary alias for connectedTo */
29
+ origin = input(null, /* @ts-ignore */
30
+ ...(ngDevMode ? [{ debugName: "origin" }] : /* istanbul ignore next */ []));
31
+ /** Whether the dropdown overlay should match the width of the connected element */
32
+ matchWidth = input(false, /* @ts-ignore */
33
+ ...(ngDevMode ? [{ debugName: "matchWidth" }] : /* istanbul ignore next */ []));
34
+ /** Whether the dropdown trigger is disabled */
35
+ disabled = input(false, /* @ts-ignore */
36
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
37
+ /** Delay in milliseconds before closing on hover leave */
38
+ hoverDelay = input(150, /* @ts-ignore */
39
+ ...(ngDevMode ? [{ debugName: "hoverDelay" }] : /* istanbul ignore next */ []));
40
+ /** Vertical offset in pixels from the trigger */
41
+ offsetY = input(4, /* @ts-ignore */
42
+ ...(ngDevMode ? [{ debugName: "offsetY" }] : /* istanbul ignore next */ []));
43
+ /** Horizontal offset in pixels from the trigger */
44
+ offsetX = input(0, /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "offsetX" }] : /* istanbul ignore next */ []));
46
+ /** Whether clicking any menu item automatically closes the menu */
47
+ closeOnItemClick = input(true, /* @ts-ignore */
48
+ ...(ngDevMode ? [{ debugName: "closeOnItemClick" }] : /* istanbul ignore next */ []));
49
+ /** Emitted when the dropdown opens */
50
+ opened = output();
51
+ /** Emitted when the dropdown closes */
52
+ closed = output();
53
+ /** Current open state signal */
54
+ isOpen = signal(false, /* @ts-ignore */
55
+ ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
56
+ overlayRef = null;
57
+ portal = null;
58
+ hoverTimer = null;
59
+ constructor() {
60
+ // Listen to menu panel mouse events for hover bridging
61
+ effect(() => {
62
+ const activeMenu = this.activeMenu;
63
+ if (!activeMenu)
64
+ return;
65
+ activeMenu.panelMouseEnter.subscribe(() => {
66
+ if (this.triggerOn() === 'hover' || this.triggerOn() === 'both') {
67
+ this.cancelHoverClose();
68
+ }
69
+ });
70
+ activeMenu.panelMouseLeave.subscribe(() => {
71
+ if (this.triggerOn() === 'hover' || this.triggerOn() === 'both') {
72
+ this.scheduleHoverClose();
73
+ }
74
+ });
75
+ activeMenu.itemActivated.subscribe(() => {
76
+ if (this.closeOnItemClick()) {
77
+ this.close();
78
+ }
79
+ });
80
+ });
81
+ // Listen to origin element mouse events for hover bridging when anchor differs from trigger
82
+ effect((onCleanup) => {
83
+ const originEl = this.targetOriginElement;
84
+ if (originEl && originEl !== this.elementRef.nativeElement) {
85
+ const onOriginEnter = () => {
86
+ if (this.isOpen() && (this.triggerOn() === 'hover' || this.triggerOn() === 'both')) {
87
+ this.cancelHoverClose();
88
+ }
89
+ };
90
+ const onOriginLeave = () => {
91
+ if (this.isOpen() && (this.triggerOn() === 'hover' || this.triggerOn() === 'both')) {
92
+ this.scheduleHoverClose();
93
+ }
94
+ };
95
+ originEl.addEventListener('mouseenter', onOriginEnter);
96
+ originEl.addEventListener('mouseleave', onOriginLeave);
97
+ onCleanup(() => {
98
+ originEl.removeEventListener('mouseenter', onOriginEnter);
99
+ originEl.removeEventListener('mouseleave', onOriginLeave);
100
+ });
101
+ }
102
+ });
103
+ this.destroyRef.onDestroy(() => {
104
+ this.clearHoverTimer();
105
+ this.disposeOverlay();
106
+ });
107
+ }
108
+ get activeMenu() {
109
+ return this.menu() || this.menuAlt();
110
+ }
111
+ get targetOrigin() {
112
+ const custom = this.connectedTo() || this.origin();
113
+ if (!custom) {
114
+ return this.elementRef;
115
+ }
116
+ if (custom instanceof ElementRef) {
117
+ return custom;
118
+ }
119
+ if (typeof HTMLElement !== 'undefined' && custom instanceof HTMLElement) {
120
+ return custom;
121
+ }
122
+ if (typeof custom === 'object' && custom !== null) {
123
+ if ('elementRef' in custom && custom.elementRef instanceof ElementRef) {
124
+ return custom.elementRef;
125
+ }
126
+ if ('nativeElement' in custom && custom.nativeElement instanceof HTMLElement) {
127
+ return custom.nativeElement;
128
+ }
129
+ }
130
+ return this.elementRef;
131
+ }
132
+ get targetOriginElement() {
133
+ const origin = this.targetOrigin;
134
+ if (origin instanceof ElementRef) {
135
+ return origin.nativeElement;
136
+ }
137
+ return origin;
138
+ }
139
+ handleClick(event) {
140
+ if (this.disabled())
141
+ return;
142
+ if (this.triggerOn() === 'click' || this.triggerOn() === 'both') {
143
+ event.preventDefault();
144
+ this.toggle();
145
+ }
146
+ }
147
+ handleMouseEnter() {
148
+ if (this.disabled())
149
+ return;
150
+ if (this.triggerOn() === 'hover' || this.triggerOn() === 'both') {
151
+ this.cancelHoverClose();
152
+ this.open();
153
+ }
154
+ }
155
+ handleMouseLeave() {
156
+ if (this.disabled())
157
+ return;
158
+ if (this.triggerOn() === 'hover' || this.triggerOn() === 'both') {
159
+ this.scheduleHoverClose();
160
+ }
161
+ }
162
+ handleKeyDownArrowDown(event) {
163
+ if (this.disabled())
164
+ return;
165
+ event.preventDefault();
166
+ if (!this.isOpen()) {
167
+ this.open();
168
+ }
169
+ setTimeout(() => {
170
+ this.activeMenu?.focusFirstItem();
171
+ }, 10);
172
+ }
173
+ handleKeyDownEscape(event) {
174
+ if (this.isOpen()) {
175
+ event.preventDefault();
176
+ this.close();
177
+ this.elementRef.nativeElement.focus();
178
+ }
179
+ }
180
+ open() {
181
+ if (this.disabled() || this.isOpen() || !this.activeMenu) {
182
+ return;
183
+ }
184
+ const overlayRef = this.getOrCreateOverlay();
185
+ if (!this.portal) {
186
+ this.portal = new TemplatePortal(this.activeMenu.templateRef, this.vcr);
187
+ }
188
+ if (this.matchWidth()) {
189
+ const width = this.targetOriginElement.offsetWidth;
190
+ if (width > 0) {
191
+ overlayRef.updateSize({ minWidth: width });
192
+ }
193
+ }
194
+ if (!overlayRef.hasAttached()) {
195
+ overlayRef.attach(this.portal);
196
+ }
197
+ this.isOpen.set(true);
198
+ this.opened.emit();
199
+ }
200
+ close() {
201
+ if (!this.isOpen())
202
+ return;
203
+ this.clearHoverTimer();
204
+ if (this.overlayRef?.hasAttached()) {
205
+ this.overlayRef.detach();
206
+ }
207
+ this.activeMenu?.resetFocus();
208
+ this.isOpen.set(false);
209
+ this.closed.emit();
210
+ }
211
+ toggle() {
212
+ if (this.isOpen()) {
213
+ this.close();
214
+ }
215
+ else {
216
+ this.open();
217
+ }
218
+ }
219
+ scheduleHoverClose() {
220
+ this.clearHoverTimer();
221
+ this.hoverTimer = setTimeout(() => {
222
+ this.close();
223
+ }, this.hoverDelay());
224
+ }
225
+ cancelHoverClose() {
226
+ this.clearHoverTimer();
227
+ }
228
+ clearHoverTimer() {
229
+ if (this.hoverTimer) {
230
+ clearTimeout(this.hoverTimer);
231
+ this.hoverTimer = null;
232
+ }
233
+ }
234
+ getOrCreateOverlay() {
235
+ if (this.overlayRef) {
236
+ return this.overlayRef;
237
+ }
238
+ const positionStrategy = this.createPositionStrategy();
239
+ this.overlayRef = this.overlay.create({
240
+ positionStrategy,
241
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
242
+ hasBackdrop: false,
243
+ minWidth: this.matchWidth() ? this.targetOriginElement.offsetWidth : undefined
244
+ });
245
+ // Close when clicking outside of both the trigger element and the overlay
246
+ this.overlayRef
247
+ .outsidePointerEvents()
248
+ .pipe(filter(event => !this.elementRef.nativeElement.contains(event.target)))
249
+ .subscribe(() => {
250
+ this.close();
251
+ });
252
+ return this.overlayRef;
253
+ }
254
+ createPositionStrategy() {
255
+ const chosenPlacement = this.placement() || this.activeMenu?.placement() || 'bottom-start';
256
+ const offsetY = this.offsetY();
257
+ const offsetX = this.offsetX();
258
+ const positions = this.getPositionsForPlacement(chosenPlacement, offsetX, offsetY);
259
+ return this.overlay
260
+ .position()
261
+ .flexibleConnectedTo(this.targetOrigin)
262
+ .withPositions(positions)
263
+ .withPush(true)
264
+ .withFlexibleDimensions(false);
265
+ }
266
+ getPositionsForPlacement(placement, offsetX, offsetY) {
267
+ const bottomStart = {
268
+ originX: 'start',
269
+ originY: 'bottom',
270
+ overlayX: 'start',
271
+ overlayY: 'top',
272
+ offsetX,
273
+ offsetY
274
+ };
275
+ const bottomEnd = {
276
+ originX: 'end',
277
+ originY: 'bottom',
278
+ overlayX: 'end',
279
+ overlayY: 'top',
280
+ offsetX,
281
+ offsetY
282
+ };
283
+ const bottomCenter = {
284
+ originX: 'center',
285
+ originY: 'bottom',
286
+ overlayX: 'center',
287
+ overlayY: 'top',
288
+ offsetX,
289
+ offsetY
290
+ };
291
+ const topStart = {
292
+ originX: 'start',
293
+ originY: 'top',
294
+ overlayX: 'start',
295
+ overlayY: 'bottom',
296
+ offsetX,
297
+ offsetY: -offsetY
298
+ };
299
+ const topEnd = {
300
+ originX: 'end',
301
+ originY: 'top',
302
+ overlayX: 'end',
303
+ overlayY: 'bottom',
304
+ offsetX,
305
+ offsetY: -offsetY
306
+ };
307
+ const topCenter = {
308
+ originX: 'center',
309
+ originY: 'top',
310
+ overlayX: 'center',
311
+ overlayY: 'bottom',
312
+ offsetX,
313
+ offsetY: -offsetY
314
+ };
315
+ const rightStart = {
316
+ originX: 'end',
317
+ originY: 'top',
318
+ overlayX: 'start',
319
+ overlayY: 'top',
320
+ offsetX: offsetY,
321
+ offsetY: offsetX
322
+ };
323
+ const leftStart = {
324
+ originX: 'start',
325
+ originY: 'top',
326
+ overlayX: 'end',
327
+ overlayY: 'top',
328
+ offsetX: -offsetY,
329
+ offsetY: offsetX
330
+ };
331
+ switch (placement) {
332
+ case 'bottom-end':
333
+ return [bottomEnd, topEnd, bottomStart, topStart];
334
+ case 'bottom':
335
+ return [bottomCenter, topCenter, bottomStart, bottomEnd];
336
+ case 'top-start':
337
+ return [topStart, bottomStart, topEnd, bottomEnd];
338
+ case 'top-end':
339
+ return [topEnd, bottomEnd, topStart, bottomStart];
340
+ case 'top':
341
+ return [topCenter, bottomCenter, topStart, topEnd];
342
+ case 'right-start':
343
+ case 'right':
344
+ return [rightStart, leftStart, bottomStart, topStart];
345
+ case 'left-start':
346
+ case 'left':
347
+ return [leftStart, rightStart, bottomStart, topStart];
348
+ case 'bottom-start':
349
+ default:
350
+ return [bottomStart, topStart, bottomEnd, topEnd];
351
+ }
352
+ }
353
+ disposeOverlay() {
354
+ if (this.overlayRef) {
355
+ this.overlayRef.dispose();
356
+ this.overlayRef = null;
357
+ this.portal = null;
358
+ }
359
+ }
360
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
361
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.1", type: TalosDropdownTriggerDirective, isStandalone: true, selector: "[talosDropdownTrigger], [talosDropdown]", inputs: { menu: { classPropertyName: "menu", publicName: "talosDropdownTrigger", isSignal: true, isRequired: false, transformFunction: null }, menuAlt: { classPropertyName: "menuAlt", publicName: "talosDropdown", isSignal: true, isRequired: false, transformFunction: null }, triggerOn: { classPropertyName: "triggerOn", publicName: "triggerOn", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, connectedTo: { classPropertyName: "connectedTo", publicName: "connectedTo", isSignal: true, isRequired: false, transformFunction: null }, origin: { classPropertyName: "origin", publicName: "origin", isSignal: true, isRequired: false, transformFunction: null }, matchWidth: { classPropertyName: "matchWidth", publicName: "matchWidth", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hoverDelay: { classPropertyName: "hoverDelay", publicName: "hoverDelay", isSignal: true, isRequired: false, transformFunction: null }, offsetY: { classPropertyName: "offsetY", publicName: "offsetY", isSignal: true, isRequired: false, transformFunction: null }, offsetX: { classPropertyName: "offsetX", publicName: "offsetX", isSignal: true, isRequired: false, transformFunction: null }, closeOnItemClick: { classPropertyName: "closeOnItemClick", publicName: "closeOnItemClick", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed" }, host: { listeners: { "click": "handleClick($event)", "mouseenter": "handleMouseEnter()", "mouseleave": "handleMouseLeave()", "keydown.arrowdown": "handleKeyDownArrowDown($event)", "keydown.escape": "handleKeyDownEscape($event)" }, properties: { "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "isOpen()", "class.talos-dropdown-open": "isOpen()" } }, exportAs: ["talosDropdownTrigger"], ngImport: i0 });
362
+ }
363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownTriggerDirective, decorators: [{
364
+ type: Directive,
365
+ args: [{
366
+ selector: '[talosDropdownTrigger], [talosDropdown]',
367
+ exportAs: 'talosDropdownTrigger',
368
+ host: {
369
+ '[attr.aria-haspopup]': '"menu"',
370
+ '[attr.aria-expanded]': 'isOpen()',
371
+ '[class.talos-dropdown-open]': 'isOpen()',
372
+ '(click)': 'handleClick($event)',
373
+ '(mouseenter)': 'handleMouseEnter()',
374
+ '(mouseleave)': 'handleMouseLeave()',
375
+ '(keydown.arrowdown)': 'handleKeyDownArrowDown($event)',
376
+ '(keydown.escape)': 'handleKeyDownEscape($event)'
377
+ }
378
+ }]
379
+ }], ctorParameters: () => [], propDecorators: { menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "talosDropdownTrigger", required: false }] }], menuAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "talosDropdown", required: false }] }], triggerOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerOn", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], connectedTo: [{ type: i0.Input, args: [{ isSignal: true, alias: "connectedTo", required: false }] }], origin: [{ type: i0.Input, args: [{ isSignal: true, alias: "origin", required: false }] }], matchWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "matchWidth", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hoverDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverDelay", required: false }] }], offsetY: [{ type: i0.Input, args: [{ isSignal: true, alias: "offsetY", required: false }] }], offsetX: [{ type: i0.Input, args: [{ isSignal: true, alias: "offsetX", required: false }] }], closeOnItemClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnItemClick", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
380
+
381
+ class TalosDropdownItemComponent {
382
+ elementRef = inject(ElementRef);
383
+ overlay = inject(Overlay);
384
+ vcr = inject(ViewContainerRef);
385
+ destroyRef = inject(DestroyRef);
386
+ /** Optional plain text label (if not using content projection) */
387
+ label = input('', /* @ts-ignore */
388
+ ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
389
+ /** Optional icon component type */
390
+ icon = input(null, /* @ts-ignore */
391
+ ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
392
+ /** Optional external link URL */
393
+ href = input('', /* @ts-ignore */
394
+ ...(ngDevMode ? [{ debugName: "href" }] : /* istanbul ignore next */ []));
395
+ /** Target for external link (default '_blank' when href is present) */
396
+ target = input('_blank', /* @ts-ignore */
397
+ ...(ngDevMode ? [{ debugName: "target" }] : /* istanbul ignore next */ []));
398
+ /** Visual variant: default, danger, primary, success, warning */
399
+ variant = input('default', /* @ts-ignore */
400
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
401
+ /** Quick flag for destructive danger styling */
402
+ danger = input(false, /* @ts-ignore */
403
+ ...(ngDevMode ? [{ debugName: "danger" }] : /* istanbul ignore next */ []));
404
+ /** Disabled state */
405
+ disabled = input(false, /* @ts-ignore */
406
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
407
+ /** Keyboard shortcut hint text (e.g. '⌘K', 'Ctrl+S') */
408
+ shortcut = input('', /* @ts-ignore */
409
+ ...(ngDevMode ? [{ debugName: "shortcut" }] : /* istanbul ignore next */ []));
410
+ /** Checkable / selectable state */
411
+ checked = input(undefined, /* @ts-ignore */
412
+ ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
413
+ /** Optional badge text or number */
414
+ badge = input(null, /* @ts-ignore */
415
+ ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
416
+ /** Badge visual variant */
417
+ badgeVariant = input('primary', /* @ts-ignore */
418
+ ...(ngDevMode ? [{ debugName: "badgeVariant" }] : /* istanbul ignore next */ []));
419
+ /** Child Sub-menu to fly out when hovering/clicking */
420
+ subMenu = input(null, /* @ts-ignore */
421
+ ...(ngDevMode ? [{ debugName: "subMenu" }] : /* istanbul ignore next */ []));
422
+ /** Emitted when the item is activated */
423
+ itemClick = output();
424
+ /** Whether this item has an attached sub-menu */
425
+ hasSubMenu = computed(() => !!this.subMenu(), /* @ts-ignore */
426
+ ...(ngDevMode ? [{ debugName: "hasSubMenu" }] : /* istanbul ignore next */ []));
427
+ /** Whether the sub-menu is currently opened */
428
+ isSubMenuOpen = signal(false, /* @ts-ignore */
429
+ ...(ngDevMode ? [{ debugName: "isSubMenuOpen" }] : /* istanbul ignore next */ []));
430
+ /** Internal callback set by parent menu container to notify on click */
431
+ _onActivate;
432
+ /** Internal callback set by parent menu container to notify on item hover */
433
+ _onHover;
434
+ overlayRef = null;
435
+ portal = null;
436
+ hoverTimer = null;
437
+ constructor() {
438
+ // Listen to sub-menu mouse & item activation events
439
+ effect(() => {
440
+ const childMenu = this.subMenu();
441
+ if (!childMenu)
442
+ return;
443
+ childMenu.panelMouseEnter.subscribe(() => {
444
+ this.cancelHoverClose();
445
+ });
446
+ childMenu.panelMouseLeave.subscribe(() => {
447
+ this.scheduleHoverClose();
448
+ });
449
+ childMenu.itemActivated.subscribe((e) => {
450
+ if (this._onActivate) {
451
+ this._onActivate(e);
452
+ }
453
+ });
454
+ });
455
+ this.destroyRef.onDestroy(() => {
456
+ this.clearHoverTimer();
457
+ this.disposeOverlay();
458
+ });
459
+ }
460
+ handleClick(event) {
461
+ if (this.disabled()) {
462
+ event.preventDefault();
463
+ event.stopPropagation();
464
+ return;
465
+ }
466
+ if (this.hasSubMenu()) {
467
+ event.preventDefault();
468
+ event.stopPropagation();
469
+ this.toggleSubMenu();
470
+ return;
471
+ }
472
+ this.itemClick.emit(event);
473
+ if (this._onActivate) {
474
+ this._onActivate(event);
475
+ }
476
+ }
477
+ handleMouseEnter() {
478
+ if (this.disabled())
479
+ return;
480
+ if (this._onHover) {
481
+ this._onHover(this);
482
+ }
483
+ if (this.hasSubMenu()) {
484
+ this.cancelHoverClose();
485
+ this.hoverTimer = setTimeout(() => {
486
+ this.openSubMenu();
487
+ }, 60);
488
+ }
489
+ }
490
+ handleMouseLeave() {
491
+ if (this.disabled())
492
+ return;
493
+ if (this.hasSubMenu()) {
494
+ this.scheduleHoverClose();
495
+ }
496
+ }
497
+ openSubMenu() {
498
+ if (this.disabled() || this.isSubMenuOpen() || !this.subMenu()) {
499
+ return;
500
+ }
501
+ const overlayRef = this.getOrCreateOverlay();
502
+ if (!this.portal && this.subMenu()) {
503
+ this.portal = new TemplatePortal(this.subMenu().templateRef, this.vcr);
504
+ }
505
+ if (!overlayRef.hasAttached() && this.portal) {
506
+ overlayRef.attach(this.portal);
507
+ }
508
+ this.isSubMenuOpen.set(true);
509
+ }
510
+ closeSubMenu() {
511
+ if (!this.isSubMenuOpen())
512
+ return;
513
+ this.clearHoverTimer();
514
+ if (this.overlayRef?.hasAttached()) {
515
+ this.overlayRef.detach();
516
+ }
517
+ this.subMenu()?.resetFocus();
518
+ this.isSubMenuOpen.set(false);
519
+ }
520
+ toggleSubMenu() {
521
+ if (this.isSubMenuOpen()) {
522
+ this.closeSubMenu();
523
+ }
524
+ else {
525
+ this.openSubMenu();
526
+ }
527
+ }
528
+ scheduleHoverClose() {
529
+ this.clearHoverTimer();
530
+ this.hoverTimer = setTimeout(() => {
531
+ this.closeSubMenu();
532
+ }, 180);
533
+ }
534
+ cancelHoverClose() {
535
+ this.clearHoverTimer();
536
+ }
537
+ clearHoverTimer() {
538
+ if (this.hoverTimer) {
539
+ clearTimeout(this.hoverTimer);
540
+ this.hoverTimer = null;
541
+ }
542
+ }
543
+ getOrCreateOverlay() {
544
+ if (this.overlayRef) {
545
+ return this.overlayRef;
546
+ }
547
+ const positionStrategy = this.createSubMenuPositionStrategy();
548
+ this.overlayRef = this.overlay.create({
549
+ positionStrategy,
550
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
551
+ hasBackdrop: false
552
+ });
553
+ return this.overlayRef;
554
+ }
555
+ createSubMenuPositionStrategy() {
556
+ const positions = [
557
+ // Standard right-start flyout (offset by 4px)
558
+ {
559
+ originX: 'end',
560
+ originY: 'top',
561
+ overlayX: 'start',
562
+ overlayY: 'top',
563
+ offsetX: 4,
564
+ offsetY: -4
565
+ },
566
+ // Flip left-start if right edge of viewport is reached
567
+ {
568
+ originX: 'start',
569
+ originY: 'top',
570
+ overlayX: 'end',
571
+ overlayY: 'top',
572
+ offsetX: -4,
573
+ offsetY: -4
574
+ },
575
+ // Flip bottom aligned if bottom edge is reached
576
+ {
577
+ originX: 'end',
578
+ originY: 'bottom',
579
+ overlayX: 'start',
580
+ overlayY: 'bottom',
581
+ offsetX: 4,
582
+ offsetY: 4
583
+ },
584
+ {
585
+ originX: 'start',
586
+ originY: 'bottom',
587
+ overlayX: 'end',
588
+ overlayY: 'bottom',
589
+ offsetX: -4,
590
+ offsetY: 4
591
+ }
592
+ ];
593
+ return this.overlay
594
+ .position()
595
+ .flexibleConnectedTo(this.elementRef)
596
+ .withPositions(positions)
597
+ .withPush(true)
598
+ .withFlexibleDimensions(false);
599
+ }
600
+ disposeOverlay() {
601
+ if (this.overlayRef) {
602
+ this.overlayRef.dispose();
603
+ this.overlayRef = null;
604
+ this.portal = null;
605
+ }
606
+ }
607
+ focus() {
608
+ const focusable = this.elementRef.nativeElement.querySelector('button, a');
609
+ focusable?.focus();
610
+ }
611
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
612
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: TalosDropdownItemComponent, isStandalone: true, selector: "talos-dropdown-item, button[talosDropdownItem], a[talosDropdownItem]", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, danger: { classPropertyName: "danger", publicName: "danger", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, shortcut: { classPropertyName: "shortcut", publicName: "shortcut", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgeVariant: { classPropertyName: "badgeVariant", publicName: "badgeVariant", isSignal: true, isRequired: false, transformFunction: null }, subMenu: { classPropertyName: "subMenu", publicName: "subMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick" }, host: { attributes: { "role": "none" }, listeners: { "mouseenter": "handleMouseEnter()", "mouseleave": "handleMouseLeave()" }, properties: { "class.is-disabled": "disabled()", "class.is-danger": "danger() || variant() === \"danger\"", "class.is-primary": "variant() === \"primary\"", "class.is-success": "variant() === \"success\"", "class.has-submenu": "hasSubMenu()", "class.is-submenu-open": "isSubMenuOpen()", "class.is-checked": "checked() === true" }, classAttribute: "talos-dropdown-item-host" }, ngImport: i0, template: `
613
+ @if (href()) {
614
+ <a
615
+ class="talos-dropdown-item-link"
616
+ [href]="href()"
617
+ [target]="target()"
618
+ [rel]="target() === '_blank' ? 'noopener noreferrer' : null"
619
+ [attr.tabindex]="disabled() ? -1 : 0"
620
+ (click)="handleClick($event)"
621
+ >
622
+ <ng-container *ngTemplateOutlet="itemBody"></ng-container>
623
+ </a>
624
+ } @else {
625
+ <button
626
+ type="button"
627
+ class="talos-dropdown-item-btn"
628
+ [disabled]="disabled()"
629
+ [attr.tabindex]="disabled() ? -1 : 0"
630
+ [attr.aria-haspopup]="hasSubMenu() ? 'menu' : null"
631
+ [attr.aria-expanded]="hasSubMenu() ? isSubMenuOpen() : null"
632
+ (click)="handleClick($event)"
633
+ >
634
+ <ng-container *ngTemplateOutlet="itemBody"></ng-container>
635
+ </button>
636
+ }
637
+
638
+ <ng-template #itemBody>
639
+ <!-- Checkmark for checkable items -->
640
+ @if (checked() !== null && checked() !== undefined) {
641
+ <span class="talos-dropdown-item-check" [class.is-checked]="checked()">
642
+ @if (checked()) {
643
+ <svg lucideCheck [size]="13"></svg>
644
+ }
645
+ </span>
646
+ }
647
+
648
+ <!-- Custom Prefix Icon -->
649
+ @if (icon(); as itemIcon) {
650
+ <span class="talos-dropdown-item-icon">
651
+ <ng-container *ngComponentOutlet="itemIcon" />
652
+ </span>
653
+ }
654
+
655
+ <!-- Item Label / Content -->
656
+ <span class="talos-dropdown-item-label">
657
+ @if (label()) {
658
+ {{ label() }}
659
+ } @else {
660
+ <ng-content />
661
+ }
662
+ </span>
663
+
664
+ <!-- Optional Status Badge -->
665
+ @if (badge() !== null && badge() !== undefined && badge() !== '') {
666
+ <span class="talos-dropdown-item-badge" [class]="'badge-' + (badgeVariant() || 'primary')">
667
+ {{ badge() }}
668
+ </span>
669
+ }
670
+
671
+ <!-- Keyboard Shortcut Key Hint -->
672
+ @if (shortcut()) {
673
+ <kbd class="talos-dropdown-item-shortcut">{{ shortcut() }}</kbd>
674
+ }
675
+
676
+ <!-- Right Chevron for Sub-menus -->
677
+ @if (hasSubMenu()) {
678
+ <span class="talos-dropdown-item-submenu-arrow">
679
+ <svg lucideChevronRight [size]="13"></svg>
680
+ </span>
681
+ }
682
+ </ng-template>
683
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "component", type: LucideCheck, selector: "svg[lucideCheck]" }] });
684
+ }
685
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownItemComponent, decorators: [{
686
+ type: Component,
687
+ args: [{
688
+ selector: 'talos-dropdown-item, button[talosDropdownItem], a[talosDropdownItem]',
689
+ imports: [CommonModule, LucideChevronRight, LucideCheck],
690
+ template: `
691
+ @if (href()) {
692
+ <a
693
+ class="talos-dropdown-item-link"
694
+ [href]="href()"
695
+ [target]="target()"
696
+ [rel]="target() === '_blank' ? 'noopener noreferrer' : null"
697
+ [attr.tabindex]="disabled() ? -1 : 0"
698
+ (click)="handleClick($event)"
699
+ >
700
+ <ng-container *ngTemplateOutlet="itemBody"></ng-container>
701
+ </a>
702
+ } @else {
703
+ <button
704
+ type="button"
705
+ class="talos-dropdown-item-btn"
706
+ [disabled]="disabled()"
707
+ [attr.tabindex]="disabled() ? -1 : 0"
708
+ [attr.aria-haspopup]="hasSubMenu() ? 'menu' : null"
709
+ [attr.aria-expanded]="hasSubMenu() ? isSubMenuOpen() : null"
710
+ (click)="handleClick($event)"
711
+ >
712
+ <ng-container *ngTemplateOutlet="itemBody"></ng-container>
713
+ </button>
714
+ }
715
+
716
+ <ng-template #itemBody>
717
+ <!-- Checkmark for checkable items -->
718
+ @if (checked() !== null && checked() !== undefined) {
719
+ <span class="talos-dropdown-item-check" [class.is-checked]="checked()">
720
+ @if (checked()) {
721
+ <svg lucideCheck [size]="13"></svg>
722
+ }
723
+ </span>
724
+ }
725
+
726
+ <!-- Custom Prefix Icon -->
727
+ @if (icon(); as itemIcon) {
728
+ <span class="talos-dropdown-item-icon">
729
+ <ng-container *ngComponentOutlet="itemIcon" />
730
+ </span>
731
+ }
732
+
733
+ <!-- Item Label / Content -->
734
+ <span class="talos-dropdown-item-label">
735
+ @if (label()) {
736
+ {{ label() }}
737
+ } @else {
738
+ <ng-content />
739
+ }
740
+ </span>
741
+
742
+ <!-- Optional Status Badge -->
743
+ @if (badge() !== null && badge() !== undefined && badge() !== '') {
744
+ <span class="talos-dropdown-item-badge" [class]="'badge-' + (badgeVariant() || 'primary')">
745
+ {{ badge() }}
746
+ </span>
747
+ }
748
+
749
+ <!-- Keyboard Shortcut Key Hint -->
750
+ @if (shortcut()) {
751
+ <kbd class="talos-dropdown-item-shortcut">{{ shortcut() }}</kbd>
752
+ }
753
+
754
+ <!-- Right Chevron for Sub-menus -->
755
+ @if (hasSubMenu()) {
756
+ <span class="talos-dropdown-item-submenu-arrow">
757
+ <svg lucideChevronRight [size]="13"></svg>
758
+ </span>
759
+ }
760
+ </ng-template>
761
+ `,
762
+ host: {
763
+ 'class': 'talos-dropdown-item-host',
764
+ 'role': 'none',
765
+ '[class.is-disabled]': 'disabled()',
766
+ '[class.is-danger]': 'danger() || variant() === "danger"',
767
+ '[class.is-primary]': 'variant() === "primary"',
768
+ '[class.is-success]': 'variant() === "success"',
769
+ '[class.has-submenu]': 'hasSubMenu()',
770
+ '[class.is-submenu-open]': 'isSubMenuOpen()',
771
+ '[class.is-checked]': 'checked() === true',
772
+ '(mouseenter)': 'handleMouseEnter()',
773
+ '(mouseleave)': 'handleMouseLeave()'
774
+ }
775
+ }]
776
+ }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], danger: [{ type: i0.Input, args: [{ isSignal: true, alias: "danger", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], shortcut: [{ type: i0.Input, args: [{ isSignal: true, alias: "shortcut", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], badgeVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgeVariant", required: false }] }], subMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "subMenu", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
777
+
778
+ class TalosDropdownMenuComponent {
779
+ templateRef;
780
+ panelEl;
781
+ /** Optional custom CSS class applied to the dropdown panel */
782
+ customClass = input('', /* @ts-ignore */
783
+ ...(ngDevMode ? [{ debugName: "customClass" }] : /* istanbul ignore next */ []));
784
+ /** Minimum width of the dropdown menu */
785
+ minWidth = input('180px', /* @ts-ignore */
786
+ ...(ngDevMode ? [{ debugName: "minWidth" }] : /* istanbul ignore next */ []));
787
+ /** Maximum width of the dropdown menu */
788
+ maxWidth = input('360px', /* @ts-ignore */
789
+ ...(ngDevMode ? [{ debugName: "maxWidth" }] : /* istanbul ignore next */ []));
790
+ /** Preferred placement of the dropdown menu */
791
+ placement = input('bottom-start', /* @ts-ignore */
792
+ ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
793
+ /** Whether clicking an item should automatically close the dropdown */
794
+ autoClose = input(true, /* @ts-ignore */
795
+ ...(ngDevMode ? [{ debugName: "autoClose" }] : /* istanbul ignore next */ []));
796
+ /** Emitted when mouse enters the floating menu panel */
797
+ panelMouseEnter = output();
798
+ /** Emitted when mouse leaves the floating menu panel */
799
+ panelMouseLeave = output();
800
+ /** Emitted when an item inside this menu is activated */
801
+ itemActivated = output();
802
+ /** Query all menu items inside */
803
+ items = contentChildren(TalosDropdownItemComponent, { ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), descendants: true });
804
+ focusedItemIndex = signal(-1, /* @ts-ignore */
805
+ ...(ngDevMode ? [{ debugName: "focusedItemIndex" }] : /* istanbul ignore next */ []));
806
+ constructor() {
807
+ // Coordinate items: activation & closing sibling submenus on hover
808
+ effect(() => {
809
+ const itemList = this.items();
810
+ for (const item of itemList) {
811
+ item._onActivate = (e) => {
812
+ this.closeAllSubMenus();
813
+ this.itemActivated.emit(e);
814
+ };
815
+ item._onHover = (hoveredItem) => {
816
+ // Close submenus on all other sibling items
817
+ for (const other of this.items()) {
818
+ if (other !== hoveredItem && other.hasSubMenu()) {
819
+ other.closeSubMenu();
820
+ }
821
+ }
822
+ };
823
+ }
824
+ });
825
+ }
826
+ handlePanelMouseEnter() {
827
+ this.panelMouseEnter.emit();
828
+ }
829
+ handlePanelMouseLeave() {
830
+ this.panelMouseLeave.emit();
831
+ }
832
+ closeAllSubMenus() {
833
+ for (const item of this.items()) {
834
+ if (item.hasSubMenu()) {
835
+ item.closeSubMenu();
836
+ }
837
+ }
838
+ }
839
+ handleKeyDown(event) {
840
+ const itemList = this.items().filter(item => !item.disabled());
841
+ if (itemList.length === 0)
842
+ return;
843
+ switch (event.key) {
844
+ case 'ArrowDown': {
845
+ event.preventDefault();
846
+ const nextIndex = (this.focusedItemIndex() + 1) % itemList.length;
847
+ this.focusedItemIndex.set(nextIndex);
848
+ itemList[nextIndex]?.focus();
849
+ break;
850
+ }
851
+ case 'ArrowUp': {
852
+ event.preventDefault();
853
+ const prevIndex = (this.focusedItemIndex() - 1 + itemList.length) % itemList.length;
854
+ this.focusedItemIndex.set(prevIndex);
855
+ itemList[prevIndex]?.focus();
856
+ break;
857
+ }
858
+ case 'ArrowRight': {
859
+ const currentItem = itemList[this.focusedItemIndex()];
860
+ if (currentItem && currentItem.hasSubMenu()) {
861
+ event.preventDefault();
862
+ currentItem.openSubMenu();
863
+ setTimeout(() => {
864
+ currentItem.subMenu()?.focusFirstItem();
865
+ }, 20);
866
+ }
867
+ break;
868
+ }
869
+ case 'Home': {
870
+ event.preventDefault();
871
+ this.focusedItemIndex.set(0);
872
+ itemList[0]?.focus();
873
+ break;
874
+ }
875
+ case 'End': {
876
+ event.preventDefault();
877
+ const lastIndex = itemList.length - 1;
878
+ this.focusedItemIndex.set(lastIndex);
879
+ itemList[lastIndex]?.focus();
880
+ break;
881
+ }
882
+ default:
883
+ break;
884
+ }
885
+ }
886
+ focusFirstItem() {
887
+ const availableItems = this.items().filter(item => !item.disabled());
888
+ if (availableItems.length > 0) {
889
+ this.focusedItemIndex.set(0);
890
+ availableItems[0]?.focus();
891
+ }
892
+ }
893
+ resetFocus() {
894
+ this.focusedItemIndex.set(-1);
895
+ this.closeAllSubMenus();
896
+ }
897
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
898
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.1", type: TalosDropdownMenuComponent, isStandalone: true, selector: "talos-dropdown-menu", inputs: { customClass: { classPropertyName: "customClass", publicName: "customClass", isSignal: true, isRequired: false, transformFunction: null }, minWidth: { classPropertyName: "minWidth", publicName: "minWidth", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, autoClose: { classPropertyName: "autoClose", publicName: "autoClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { panelMouseEnter: "panelMouseEnter", panelMouseLeave: "panelMouseLeave", itemActivated: "itemActivated" }, host: { styleAttribute: "display: none;" }, queries: [{ propertyName: "items", predicate: TalosDropdownItemComponent, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["templateRef"], descendants: true, static: true }, { propertyName: "panelEl", first: true, predicate: ["panelEl"], descendants: true }], exportAs: ["talosDropdownMenu"], ngImport: i0, template: `
899
+ <ng-template #templateRef>
900
+ <div
901
+ #panelEl
902
+ class="talos-dropdown-panel"
903
+ [class]="customClass()"
904
+ [style.min-width]="minWidth()"
905
+ [style.max-width]="maxWidth()"
906
+ role="menu"
907
+ tabindex="-1"
908
+ (mouseenter)="handlePanelMouseEnter()"
909
+ (mouseleave)="handlePanelMouseLeave()"
910
+ (keydown)="handleKeyDown($event)"
911
+ >
912
+ <ng-content />
913
+ </div>
914
+ </ng-template>
915
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
916
+ }
917
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownMenuComponent, decorators: [{
918
+ type: Component,
919
+ args: [{
920
+ selector: 'talos-dropdown-menu',
921
+ exportAs: 'talosDropdownMenu',
922
+ imports: [CommonModule],
923
+ template: `
924
+ <ng-template #templateRef>
925
+ <div
926
+ #panelEl
927
+ class="talos-dropdown-panel"
928
+ [class]="customClass()"
929
+ [style.min-width]="minWidth()"
930
+ [style.max-width]="maxWidth()"
931
+ role="menu"
932
+ tabindex="-1"
933
+ (mouseenter)="handlePanelMouseEnter()"
934
+ (mouseleave)="handlePanelMouseLeave()"
935
+ (keydown)="handleKeyDown($event)"
936
+ >
937
+ <ng-content />
938
+ </div>
939
+ </ng-template>
940
+ `,
941
+ host: {
942
+ 'style': 'display: none;'
943
+ }
944
+ }]
945
+ }], ctorParameters: () => [], propDecorators: { templateRef: [{
946
+ type: ViewChild,
947
+ args: ['templateRef', { static: true }]
948
+ }], panelEl: [{
949
+ type: ViewChild,
950
+ args: ['panelEl']
951
+ }], customClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "customClass", required: false }] }], minWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "minWidth", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], autoClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClose", required: false }] }], panelMouseEnter: [{ type: i0.Output, args: ["panelMouseEnter"] }], panelMouseLeave: [{ type: i0.Output, args: ["panelMouseLeave"] }], itemActivated: [{ type: i0.Output, args: ["itemActivated"] }], items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TalosDropdownItemComponent), { ...{ descendants: true }, isSignal: true }] }] } });
952
+
953
+ class TalosDropdownDividerComponent {
954
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownDividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
955
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.1", type: TalosDropdownDividerComponent, isStandalone: true, selector: "talos-dropdown-divider, [talosDropdownDivider]", host: { attributes: { "role": "separator", "aria-orientation": "horizontal" }, classAttribute: "talos-dropdown-divider" }, ngImport: i0, template: '', isInline: true });
956
+ }
957
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownDividerComponent, decorators: [{
958
+ type: Component,
959
+ args: [{
960
+ selector: 'talos-dropdown-divider, [talosDropdownDivider]',
961
+ template: '',
962
+ host: {
963
+ 'class': 'talos-dropdown-divider',
964
+ 'role': 'separator',
965
+ 'aria-orientation': 'horizontal'
966
+ }
967
+ }]
968
+ }] });
969
+
970
+ class TalosDropdownHeaderComponent {
971
+ /** Optional header title string */
972
+ title = input('', /* @ts-ignore */
973
+ ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
974
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
975
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.1", type: TalosDropdownHeaderComponent, isStandalone: true, selector: "talos-dropdown-header, [talosDropdownHeader]", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "presentation" }, classAttribute: "talos-dropdown-header" }, ngImport: i0, template: `
976
+ <span class="talos-dropdown-header-text">
977
+ @if (title()) {
978
+ {{ title() }}
979
+ } @else {
980
+ <ng-content />
981
+ }
982
+ </span>
983
+ `, isInline: true });
984
+ }
985
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownHeaderComponent, decorators: [{
986
+ type: Component,
987
+ args: [{
988
+ selector: 'talos-dropdown-header, [talosDropdownHeader]',
989
+ template: `
990
+ <span class="talos-dropdown-header-text">
991
+ @if (title()) {
992
+ {{ title() }}
993
+ } @else {
994
+ <ng-content />
995
+ }
996
+ </span>
997
+ `,
998
+ host: {
999
+ 'class': 'talos-dropdown-header',
1000
+ 'role': 'presentation'
1001
+ }
1002
+ }]
1003
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }] } });
1004
+
1005
+ const DROPDOWN_DECLARATIONS = [
1006
+ TalosDropdownTriggerDirective,
1007
+ TalosDropdownMenuComponent,
1008
+ TalosDropdownItemComponent,
1009
+ TalosDropdownDividerComponent,
1010
+ TalosDropdownHeaderComponent
1011
+ ];
1012
+ class TalosDropdownModule {
1013
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1014
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownModule, imports: [TalosDropdownTriggerDirective,
1015
+ TalosDropdownMenuComponent,
1016
+ TalosDropdownItemComponent,
1017
+ TalosDropdownDividerComponent,
1018
+ TalosDropdownHeaderComponent], exports: [TalosDropdownTriggerDirective,
1019
+ TalosDropdownMenuComponent,
1020
+ TalosDropdownItemComponent,
1021
+ TalosDropdownDividerComponent,
1022
+ TalosDropdownHeaderComponent] });
1023
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownModule, imports: [TalosDropdownMenuComponent,
1024
+ TalosDropdownItemComponent] });
1025
+ }
1026
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: TalosDropdownModule, decorators: [{
1027
+ type: NgModule,
1028
+ args: [{
1029
+ imports: [...DROPDOWN_DECLARATIONS],
1030
+ exports: [...DROPDOWN_DECLARATIONS]
1031
+ }]
1032
+ }] });
1033
+
1034
+ /**
1035
+ * Generated bundle index. Do not edit.
1036
+ */
1037
+
1038
+ export { TalosDropdownDividerComponent, TalosDropdownHeaderComponent, TalosDropdownItemComponent, TalosDropdownMenuComponent, TalosDropdownModule, TalosDropdownTriggerDirective };
1039
+ //# sourceMappingURL=weeehaoooz-talos-ui-dropdown.mjs.map