angular-tailwind-components 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/README.md +168 -0
  2. package/fesm2022/angular-tailwind-components.mjs +3144 -0
  3. package/fesm2022/angular-tailwind-components.mjs.map +1 -0
  4. package/package.json +29 -0
  5. package/tailwind-icons/academic-cap.svg +3 -0
  6. package/tailwind-icons/adjustments-horizontal.svg +3 -0
  7. package/tailwind-icons/adjustments-vertical.svg +3 -0
  8. package/tailwind-icons/archive-box-arrow-down.svg +3 -0
  9. package/tailwind-icons/archive-box-x-mark.svg +3 -0
  10. package/tailwind-icons/archive-box.svg +3 -0
  11. package/tailwind-icons/arrow-down-circle.svg +3 -0
  12. package/tailwind-icons/arrow-down-left.svg +3 -0
  13. package/tailwind-icons/arrow-down-on-square-stack.svg +3 -0
  14. package/tailwind-icons/arrow-down-on-square.svg +3 -0
  15. package/tailwind-icons/arrow-down-right.svg +3 -0
  16. package/tailwind-icons/arrow-down-tray.svg +3 -0
  17. package/tailwind-icons/arrow-down.svg +3 -0
  18. package/tailwind-icons/arrow-left-circle.svg +3 -0
  19. package/tailwind-icons/arrow-left-end-on-rectangle.svg +3 -0
  20. package/tailwind-icons/arrow-left-on-rectangle.svg +3 -0
  21. package/tailwind-icons/arrow-left-start-on-rectangle.svg +3 -0
  22. package/tailwind-icons/arrow-left.svg +3 -0
  23. package/tailwind-icons/arrow-long-down.svg +3 -0
  24. package/tailwind-icons/arrow-long-left.svg +3 -0
  25. package/tailwind-icons/arrow-long-right.svg +3 -0
  26. package/tailwind-icons/arrow-long-up.svg +3 -0
  27. package/tailwind-icons/arrow-path-rounded-square.svg +3 -0
  28. package/tailwind-icons/arrow-path.svg +3 -0
  29. package/tailwind-icons/arrow-right-circle.svg +3 -0
  30. package/tailwind-icons/arrow-right-end-on-rectangle.svg +3 -0
  31. package/tailwind-icons/arrow-right-on-rectangle.svg +3 -0
  32. package/tailwind-icons/arrow-right-start-on-rectangle.svg +3 -0
  33. package/tailwind-icons/arrow-right.svg +3 -0
  34. package/tailwind-icons/arrow-small-down.svg +3 -0
  35. package/tailwind-icons/arrow-small-left.svg +3 -0
  36. package/tailwind-icons/arrow-small-right.svg +3 -0
  37. package/tailwind-icons/arrow-small-up.svg +3 -0
  38. package/tailwind-icons/arrow-top-right-on-square.svg +3 -0
  39. package/tailwind-icons/arrow-trending-down.svg +3 -0
  40. package/tailwind-icons/arrow-trending-up.svg +3 -0
  41. package/tailwind-icons/arrow-turn-down-left.svg +3 -0
  42. package/tailwind-icons/arrow-turn-down-right.svg +3 -0
  43. package/tailwind-icons/arrow-turn-left-down.svg +3 -0
  44. package/tailwind-icons/arrow-turn-left-up.svg +3 -0
  45. package/tailwind-icons/arrow-turn-right-down.svg +3 -0
  46. package/tailwind-icons/arrow-turn-right-up.svg +3 -0
  47. package/tailwind-icons/arrow-turn-up-left.svg +3 -0
  48. package/tailwind-icons/arrow-turn-up-right.svg +3 -0
  49. package/tailwind-icons/arrow-up-circle.svg +3 -0
  50. package/tailwind-icons/arrow-up-left.svg +3 -0
  51. package/tailwind-icons/arrow-up-on-square-stack.svg +3 -0
  52. package/tailwind-icons/arrow-up-on-square.svg +3 -0
  53. package/tailwind-icons/arrow-up-right.svg +3 -0
  54. package/tailwind-icons/arrow-up-tray.svg +3 -0
  55. package/tailwind-icons/arrow-up.svg +3 -0
  56. package/tailwind-icons/arrow-uturn-down.svg +3 -0
  57. package/tailwind-icons/arrow-uturn-left.svg +3 -0
  58. package/tailwind-icons/arrow-uturn-right.svg +3 -0
  59. package/tailwind-icons/arrow-uturn-up.svg +3 -0
  60. package/tailwind-icons/arrows-pointing-in.svg +3 -0
  61. package/tailwind-icons/arrows-pointing-out.svg +3 -0
  62. package/tailwind-icons/arrows-right-left.svg +3 -0
  63. package/tailwind-icons/arrows-up-down.svg +3 -0
  64. package/tailwind-icons/at-symbol.svg +3 -0
  65. package/tailwind-icons/backspace.svg +3 -0
  66. package/tailwind-icons/backward.svg +3 -0
  67. package/tailwind-icons/banknotes.svg +3 -0
  68. package/tailwind-icons/bars-2.svg +3 -0
  69. package/tailwind-icons/bars-3-bottom-left.svg +3 -0
  70. package/tailwind-icons/bars-3-bottom-right.svg +3 -0
  71. package/tailwind-icons/bars-3-center-left.svg +3 -0
  72. package/tailwind-icons/bars-3.svg +3 -0
  73. package/tailwind-icons/bars-4.svg +3 -0
  74. package/tailwind-icons/bars-arrow-down.svg +3 -0
  75. package/tailwind-icons/bars-arrow-up.svg +3 -0
  76. package/tailwind-icons/battery-0.svg +3 -0
  77. package/tailwind-icons/battery-100.svg +3 -0
  78. package/tailwind-icons/battery-50.svg +3 -0
  79. package/tailwind-icons/beaker.svg +3 -0
  80. package/tailwind-icons/bell-alert.svg +3 -0
  81. package/tailwind-icons/bell-slash.svg +3 -0
  82. package/tailwind-icons/bell-snooze.svg +3 -0
  83. package/tailwind-icons/bell.svg +3 -0
  84. package/tailwind-icons/bold.svg +3 -0
  85. package/tailwind-icons/bolt-slash.svg +3 -0
  86. package/tailwind-icons/bolt.svg +3 -0
  87. package/tailwind-icons/book-open.svg +3 -0
  88. package/tailwind-icons/bookmark-slash.svg +3 -0
  89. package/tailwind-icons/bookmark-square.svg +3 -0
  90. package/tailwind-icons/bookmark.svg +3 -0
  91. package/tailwind-icons/briefcase.svg +3 -0
  92. package/tailwind-icons/bug-ant.svg +3 -0
  93. package/tailwind-icons/building-library.svg +3 -0
  94. package/tailwind-icons/building-office-2.svg +3 -0
  95. package/tailwind-icons/building-office.svg +3 -0
  96. package/tailwind-icons/building-storefront.svg +3 -0
  97. package/tailwind-icons/cake.svg +3 -0
  98. package/tailwind-icons/calculator.svg +3 -0
  99. package/tailwind-icons/calendar-date-range.svg +3 -0
  100. package/tailwind-icons/calendar-days.svg +3 -0
  101. package/tailwind-icons/calendar.svg +3 -0
  102. package/tailwind-icons/camera.svg +4 -0
  103. package/tailwind-icons/chart-bar-square.svg +3 -0
  104. package/tailwind-icons/chart-bar.svg +3 -0
  105. package/tailwind-icons/chart-pie.svg +4 -0
  106. package/tailwind-icons/chat-bubble-bottom-center-text.svg +3 -0
  107. package/tailwind-icons/chat-bubble-bottom-center.svg +3 -0
  108. package/tailwind-icons/chat-bubble-left-ellipsis.svg +3 -0
  109. package/tailwind-icons/chat-bubble-left-right.svg +3 -0
  110. package/tailwind-icons/chat-bubble-left.svg +3 -0
  111. package/tailwind-icons/chat-bubble-oval-left-ellipsis.svg +3 -0
  112. package/tailwind-icons/chat-bubble-oval-left.svg +3 -0
  113. package/tailwind-icons/check-badge.svg +3 -0
  114. package/tailwind-icons/check-circle.svg +3 -0
  115. package/tailwind-icons/check.svg +3 -0
  116. package/tailwind-icons/chevron-double-down.svg +3 -0
  117. package/tailwind-icons/chevron-double-left.svg +3 -0
  118. package/tailwind-icons/chevron-double-right.svg +3 -0
  119. package/tailwind-icons/chevron-double-up.svg +4 -0
  120. package/tailwind-icons/chevron-down.svg +3 -0
  121. package/tailwind-icons/chevron-left.svg +3 -0
  122. package/tailwind-icons/chevron-right.svg +3 -0
  123. package/tailwind-icons/chevron-up-down.svg +3 -0
  124. package/tailwind-icons/chevron-up.svg +3 -0
  125. package/tailwind-icons/circle-stack.svg +3 -0
  126. package/tailwind-icons/clipboard-document-check.svg +3 -0
  127. package/tailwind-icons/clipboard-document-list.svg +3 -0
  128. package/tailwind-icons/clipboard-document.svg +3 -0
  129. package/tailwind-icons/clipboard.svg +3 -0
  130. package/tailwind-icons/clock.svg +3 -0
  131. package/tailwind-icons/cloud-arrow-down.svg +3 -0
  132. package/tailwind-icons/cloud-arrow-up.svg +3 -0
  133. package/tailwind-icons/cloud.svg +3 -0
  134. package/tailwind-icons/code-bracket-square.svg +3 -0
  135. package/tailwind-icons/code-bracket.svg +3 -0
  136. package/tailwind-icons/cog-6-tooth.svg +4 -0
  137. package/tailwind-icons/cog-8-tooth.svg +4 -0
  138. package/tailwind-icons/cog.svg +3 -0
  139. package/tailwind-icons/command-line.svg +3 -0
  140. package/tailwind-icons/computer-desktop.svg +3 -0
  141. package/tailwind-icons/cpu-chip.svg +3 -0
  142. package/tailwind-icons/credit-card.svg +3 -0
  143. package/tailwind-icons/cube-transparent.svg +3 -0
  144. package/tailwind-icons/cube.svg +3 -0
  145. package/tailwind-icons/currency-bangladeshi.svg +3 -0
  146. package/tailwind-icons/currency-dollar.svg +3 -0
  147. package/tailwind-icons/currency-euro.svg +3 -0
  148. package/tailwind-icons/currency-pound.svg +3 -0
  149. package/tailwind-icons/currency-rupee.svg +3 -0
  150. package/tailwind-icons/currency-yen.svg +3 -0
  151. package/tailwind-icons/cursor-arrow-rays.svg +3 -0
  152. package/tailwind-icons/cursor-arrow-ripple.svg +3 -0
  153. package/tailwind-icons/device-phone-mobile.svg +3 -0
  154. package/tailwind-icons/device-tablet.svg +3 -0
  155. package/tailwind-icons/divide.svg +3 -0
  156. package/tailwind-icons/document-arrow-down.svg +3 -0
  157. package/tailwind-icons/document-arrow-up.svg +3 -0
  158. package/tailwind-icons/document-chart-bar.svg +3 -0
  159. package/tailwind-icons/document-check.svg +3 -0
  160. package/tailwind-icons/document-currency-bangladeshi.svg +3 -0
  161. package/tailwind-icons/document-currency-dollar.svg +3 -0
  162. package/tailwind-icons/document-currency-euro.svg +3 -0
  163. package/tailwind-icons/document-currency-pound.svg +3 -0
  164. package/tailwind-icons/document-currency-rupee.svg +3 -0
  165. package/tailwind-icons/document-currency-yen.svg +3 -0
  166. package/tailwind-icons/document-duplicate.svg +3 -0
  167. package/tailwind-icons/document-magnifying-glass.svg +3 -0
  168. package/tailwind-icons/document-minus.svg +3 -0
  169. package/tailwind-icons/document-plus.svg +3 -0
  170. package/tailwind-icons/document-text.svg +3 -0
  171. package/tailwind-icons/document.svg +3 -0
  172. package/tailwind-icons/ellipsis-horizontal-circle.svg +3 -0
  173. package/tailwind-icons/ellipsis-horizontal.svg +3 -0
  174. package/tailwind-icons/ellipsis-vertical.svg +3 -0
  175. package/tailwind-icons/envelope-open.svg +3 -0
  176. package/tailwind-icons/envelope.svg +3 -0
  177. package/tailwind-icons/equals.svg +3 -0
  178. package/tailwind-icons/exclamation-circle.svg +3 -0
  179. package/tailwind-icons/exclamation-triangle.svg +3 -0
  180. package/tailwind-icons/eye-dropper.svg +3 -0
  181. package/tailwind-icons/eye-slash.svg +3 -0
  182. package/tailwind-icons/eye.svg +4 -0
  183. package/tailwind-icons/face-frown.svg +3 -0
  184. package/tailwind-icons/face-smile.svg +3 -0
  185. package/tailwind-icons/film.svg +3 -0
  186. package/tailwind-icons/finger-print.svg +3 -0
  187. package/tailwind-icons/fire.svg +4 -0
  188. package/tailwind-icons/flag.svg +3 -0
  189. package/tailwind-icons/folder-arrow-down.svg +3 -0
  190. package/tailwind-icons/folder-minus.svg +3 -0
  191. package/tailwind-icons/folder-open.svg +3 -0
  192. package/tailwind-icons/folder-plus.svg +3 -0
  193. package/tailwind-icons/folder.svg +3 -0
  194. package/tailwind-icons/forward.svg +3 -0
  195. package/tailwind-icons/funnel.svg +3 -0
  196. package/tailwind-icons/gif.svg +3 -0
  197. package/tailwind-icons/gift-top.svg +3 -0
  198. package/tailwind-icons/gift.svg +3 -0
  199. package/tailwind-icons/globe-alt.svg +3 -0
  200. package/tailwind-icons/globe-americas.svg +3 -0
  201. package/tailwind-icons/globe-asia-australia.svg +3 -0
  202. package/tailwind-icons/globe-europe-africa.svg +3 -0
  203. package/tailwind-icons/h1.svg +3 -0
  204. package/tailwind-icons/h2.svg +3 -0
  205. package/tailwind-icons/h3.svg +3 -0
  206. package/tailwind-icons/hand-raised.svg +3 -0
  207. package/tailwind-icons/hand-thumb-down.svg +3 -0
  208. package/tailwind-icons/hand-thumb-up.svg +3 -0
  209. package/tailwind-icons/hashtag.svg +3 -0
  210. package/tailwind-icons/heart.svg +3 -0
  211. package/tailwind-icons/home-modern.svg +3 -0
  212. package/tailwind-icons/home.svg +3 -0
  213. package/tailwind-icons/identification.svg +3 -0
  214. package/tailwind-icons/inbox-arrow-down.svg +3 -0
  215. package/tailwind-icons/inbox-stack.svg +3 -0
  216. package/tailwind-icons/inbox.svg +3 -0
  217. package/tailwind-icons/information-circle.svg +3 -0
  218. package/tailwind-icons/italic.svg +3 -0
  219. package/tailwind-icons/key.svg +3 -0
  220. package/tailwind-icons/language.svg +3 -0
  221. package/tailwind-icons/lifebuoy.svg +3 -0
  222. package/tailwind-icons/light-bulb.svg +3 -0
  223. package/tailwind-icons/link-slash.svg +3 -0
  224. package/tailwind-icons/link.svg +3 -0
  225. package/tailwind-icons/list-bullet.svg +3 -0
  226. package/tailwind-icons/lock-closed.svg +3 -0
  227. package/tailwind-icons/lock-open.svg +3 -0
  228. package/tailwind-icons/magnifying-glass-circle.svg +3 -0
  229. package/tailwind-icons/magnifying-glass-minus.svg +3 -0
  230. package/tailwind-icons/magnifying-glass-plus.svg +3 -0
  231. package/tailwind-icons/magnifying-glass.svg +3 -0
  232. package/tailwind-icons/map-pin.svg +4 -0
  233. package/tailwind-icons/map.svg +3 -0
  234. package/tailwind-icons/megaphone.svg +3 -0
  235. package/tailwind-icons/microphone.svg +3 -0
  236. package/tailwind-icons/minus-circle.svg +3 -0
  237. package/tailwind-icons/minus-small.svg +3 -0
  238. package/tailwind-icons/minus.svg +3 -0
  239. package/tailwind-icons/moon.svg +3 -0
  240. package/tailwind-icons/musical-note.svg +3 -0
  241. package/tailwind-icons/newspaper.svg +3 -0
  242. package/tailwind-icons/no-symbol.svg +3 -0
  243. package/tailwind-icons/numbered-list.svg +3 -0
  244. package/tailwind-icons/paint-brush.svg +3 -0
  245. package/tailwind-icons/paper-airplane.svg +3 -0
  246. package/tailwind-icons/paper-clip.svg +3 -0
  247. package/tailwind-icons/pause-circle.svg +3 -0
  248. package/tailwind-icons/pause.svg +3 -0
  249. package/tailwind-icons/pencil-square.svg +3 -0
  250. package/tailwind-icons/pencil.svg +3 -0
  251. package/tailwind-icons/percent-badge.svg +3 -0
  252. package/tailwind-icons/phone-arrow-down-left.svg +3 -0
  253. package/tailwind-icons/phone-arrow-up-right.svg +3 -0
  254. package/tailwind-icons/phone-x-mark.svg +3 -0
  255. package/tailwind-icons/phone.svg +3 -0
  256. package/tailwind-icons/photo.svg +3 -0
  257. package/tailwind-icons/play-circle.svg +4 -0
  258. package/tailwind-icons/play-pause.svg +3 -0
  259. package/tailwind-icons/play.svg +3 -0
  260. package/tailwind-icons/plus-circle.svg +3 -0
  261. package/tailwind-icons/plus-small.svg +3 -0
  262. package/tailwind-icons/plus.svg +3 -0
  263. package/tailwind-icons/power.svg +3 -0
  264. package/tailwind-icons/presentation-chart-bar.svg +3 -0
  265. package/tailwind-icons/presentation-chart-line.svg +3 -0
  266. package/tailwind-icons/printer.svg +3 -0
  267. package/tailwind-icons/puzzle-piece.svg +3 -0
  268. package/tailwind-icons/qr-code.svg +4 -0
  269. package/tailwind-icons/question-mark-circle.svg +3 -0
  270. package/tailwind-icons/queue-list.svg +3 -0
  271. package/tailwind-icons/radio.svg +3 -0
  272. package/tailwind-icons/receipt-percent.svg +3 -0
  273. package/tailwind-icons/receipt-refund.svg +3 -0
  274. package/tailwind-icons/rectangle-group.svg +3 -0
  275. package/tailwind-icons/rectangle-stack.svg +3 -0
  276. package/tailwind-icons/rocket-launch.svg +3 -0
  277. package/tailwind-icons/rss.svg +3 -0
  278. package/tailwind-icons/scale.svg +3 -0
  279. package/tailwind-icons/scissors.svg +3 -0
  280. package/tailwind-icons/server-stack.svg +3 -0
  281. package/tailwind-icons/server.svg +3 -0
  282. package/tailwind-icons/share.svg +3 -0
  283. package/tailwind-icons/shield-check.svg +3 -0
  284. package/tailwind-icons/shield-exclamation.svg +3 -0
  285. package/tailwind-icons/shopping-bag.svg +3 -0
  286. package/tailwind-icons/shopping-cart.svg +3 -0
  287. package/tailwind-icons/signal-slash.svg +3 -0
  288. package/tailwind-icons/signal.svg +3 -0
  289. package/tailwind-icons/slash.svg +3 -0
  290. package/tailwind-icons/sparkles.svg +3 -0
  291. package/tailwind-icons/speaker-wave.svg +3 -0
  292. package/tailwind-icons/speaker-x-mark.svg +3 -0
  293. package/tailwind-icons/square-2-stack.svg +3 -0
  294. package/tailwind-icons/square-3-stack-3d.svg +3 -0
  295. package/tailwind-icons/squares-2x2.svg +3 -0
  296. package/tailwind-icons/squares-plus.svg +3 -0
  297. package/tailwind-icons/star.svg +3 -0
  298. package/tailwind-icons/stop-circle.svg +4 -0
  299. package/tailwind-icons/stop.svg +3 -0
  300. package/tailwind-icons/strikethrough.svg +3 -0
  301. package/tailwind-icons/sun.svg +3 -0
  302. package/tailwind-icons/swatch.svg +3 -0
  303. package/tailwind-icons/table-cells.svg +3 -0
  304. package/tailwind-icons/tag.svg +4 -0
  305. package/tailwind-icons/ticket.svg +3 -0
  306. package/tailwind-icons/trash.svg +3 -0
  307. package/tailwind-icons/trophy.svg +3 -0
  308. package/tailwind-icons/truck.svg +3 -0
  309. package/tailwind-icons/tv.svg +3 -0
  310. package/tailwind-icons/underline.svg +3 -0
  311. package/tailwind-icons/user-circle.svg +3 -0
  312. package/tailwind-icons/user-group.svg +3 -0
  313. package/tailwind-icons/user-minus.svg +3 -0
  314. package/tailwind-icons/user-plus.svg +3 -0
  315. package/tailwind-icons/user.svg +3 -0
  316. package/tailwind-icons/users.svg +3 -0
  317. package/tailwind-icons/variable.svg +3 -0
  318. package/tailwind-icons/video-camera-slash.svg +3 -0
  319. package/tailwind-icons/video-camera.svg +3 -0
  320. package/tailwind-icons/view-columns.svg +3 -0
  321. package/tailwind-icons/viewfinder-circle.svg +3 -0
  322. package/tailwind-icons/wallet.svg +3 -0
  323. package/tailwind-icons/wifi.svg +3 -0
  324. package/tailwind-icons/window.svg +3 -0
  325. package/tailwind-icons/wrench-screwdriver.svg +3 -0
  326. package/tailwind-icons/wrench.svg +4 -0
  327. package/tailwind-icons/x-circle.svg +3 -0
  328. package/tailwind-icons/x-mark.svg +3 -0
  329. package/types/angular-tailwind-components.d.ts +1022 -0
@@ -0,0 +1,3144 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, Directive, signal, inject, NgZone, ElementRef, viewChild, computed, Component, ViewContainerRef, HostListener, Input, output, InjectionToken, model, forwardRef, effect, contentChildren, ApplicationRef, EnvironmentInjector, Injector, createComponent, Injectable, booleanAttribute } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { DOCUMENT, NgClass, formatDate, CommonModule } from '@angular/common';
5
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
6
+ import { Overlay } from '@angular/cdk/overlay';
7
+ import { TemplatePortal } from '@angular/cdk/portal';
8
+ import { Subscription, fromEvent } from 'rxjs';
9
+
10
+ /** Common types used across all components */
11
+
12
+ /** Heroicons icon name (kebab-case). SVG assets live in `public/icons/` (outline 24×24). */
13
+ const TAILWIND_HERO_ICON_NAMES = [
14
+ 'academic-cap',
15
+ 'adjustments-horizontal',
16
+ 'adjustments-vertical',
17
+ 'archive-box',
18
+ 'archive-box-arrow-down',
19
+ 'archive-box-x-mark',
20
+ 'arrow-down',
21
+ 'arrow-down-circle',
22
+ 'arrow-down-left',
23
+ 'arrow-down-on-square',
24
+ 'arrow-down-on-square-stack',
25
+ 'arrow-down-right',
26
+ 'arrow-down-tray',
27
+ 'arrow-left',
28
+ 'arrow-left-circle',
29
+ 'arrow-left-end-on-rectangle',
30
+ 'arrow-left-on-rectangle',
31
+ 'arrow-left-start-on-rectangle',
32
+ 'arrow-long-down',
33
+ 'arrow-long-left',
34
+ 'arrow-long-right',
35
+ 'arrow-long-up',
36
+ 'arrow-path',
37
+ 'arrow-path-rounded-square',
38
+ 'arrow-right',
39
+ 'arrow-right-circle',
40
+ 'arrow-right-end-on-rectangle',
41
+ 'arrow-right-on-rectangle',
42
+ 'arrow-right-start-on-rectangle',
43
+ 'arrow-small-down',
44
+ 'arrow-small-left',
45
+ 'arrow-small-right',
46
+ 'arrow-small-up',
47
+ 'arrows-pointing-in',
48
+ 'arrows-pointing-out',
49
+ 'arrows-right-left',
50
+ 'arrows-up-down',
51
+ 'arrow-top-right-on-square',
52
+ 'arrow-trending-down',
53
+ 'arrow-trending-up',
54
+ 'arrow-turn-down-left',
55
+ 'arrow-turn-down-right',
56
+ 'arrow-turn-left-down',
57
+ 'arrow-turn-left-up',
58
+ 'arrow-turn-right-down',
59
+ 'arrow-turn-right-up',
60
+ 'arrow-turn-up-left',
61
+ 'arrow-turn-up-right',
62
+ 'arrow-up',
63
+ 'arrow-up-circle',
64
+ 'arrow-up-left',
65
+ 'arrow-up-on-square',
66
+ 'arrow-up-on-square-stack',
67
+ 'arrow-up-right',
68
+ 'arrow-up-tray',
69
+ 'arrow-uturn-down',
70
+ 'arrow-uturn-left',
71
+ 'arrow-uturn-right',
72
+ 'arrow-uturn-up',
73
+ 'at-symbol',
74
+ 'backspace',
75
+ 'backward',
76
+ 'banknotes',
77
+ 'bars-2',
78
+ 'bars-3',
79
+ 'bars-3-bottom-left',
80
+ 'bars-3-bottom-right',
81
+ 'bars-3-center-left',
82
+ 'bars-4',
83
+ 'bars-arrow-down',
84
+ 'bars-arrow-up',
85
+ 'battery-0',
86
+ 'battery-100',
87
+ 'battery-50',
88
+ 'beaker',
89
+ 'bell',
90
+ 'bell-alert',
91
+ 'bell-slash',
92
+ 'bell-snooze',
93
+ 'bold',
94
+ 'bolt',
95
+ 'bolt-slash',
96
+ 'bookmark',
97
+ 'bookmark-slash',
98
+ 'bookmark-square',
99
+ 'book-open',
100
+ 'briefcase',
101
+ 'bug-ant',
102
+ 'building-library',
103
+ 'building-office',
104
+ 'building-office-2',
105
+ 'building-storefront',
106
+ 'cake',
107
+ 'calculator',
108
+ 'calendar',
109
+ 'calendar-date-range',
110
+ 'calendar-days',
111
+ 'camera',
112
+ 'chart-bar',
113
+ 'chart-bar-square',
114
+ 'chart-pie',
115
+ 'chat-bubble-bottom-center',
116
+ 'chat-bubble-bottom-center-text',
117
+ 'chat-bubble-left',
118
+ 'chat-bubble-left-ellipsis',
119
+ 'chat-bubble-left-right',
120
+ 'chat-bubble-oval-left',
121
+ 'chat-bubble-oval-left-ellipsis',
122
+ 'check',
123
+ 'check-badge',
124
+ 'check-circle',
125
+ 'chevron-double-down',
126
+ 'chevron-double-left',
127
+ 'chevron-double-right',
128
+ 'chevron-double-up',
129
+ 'chevron-down',
130
+ 'chevron-left',
131
+ 'chevron-right',
132
+ 'chevron-up',
133
+ 'chevron-up-down',
134
+ 'circle-stack',
135
+ 'clipboard',
136
+ 'clipboard-document',
137
+ 'clipboard-document-check',
138
+ 'clipboard-document-list',
139
+ 'clock',
140
+ 'cloud',
141
+ 'cloud-arrow-down',
142
+ 'cloud-arrow-up',
143
+ 'code-bracket',
144
+ 'code-bracket-square',
145
+ 'cog',
146
+ 'cog-6-tooth',
147
+ 'cog-8-tooth',
148
+ 'command-line',
149
+ 'computer-desktop',
150
+ 'cpu-chip',
151
+ 'credit-card',
152
+ 'cube',
153
+ 'cube-transparent',
154
+ 'currency-bangladeshi',
155
+ 'currency-dollar',
156
+ 'currency-euro',
157
+ 'currency-pound',
158
+ 'currency-rupee',
159
+ 'currency-yen',
160
+ 'cursor-arrow-rays',
161
+ 'cursor-arrow-ripple',
162
+ 'device-phone-mobile',
163
+ 'device-tablet',
164
+ 'divide',
165
+ 'document',
166
+ 'document-arrow-down',
167
+ 'document-arrow-up',
168
+ 'document-chart-bar',
169
+ 'document-check',
170
+ 'document-currency-bangladeshi',
171
+ 'document-currency-dollar',
172
+ 'document-currency-euro',
173
+ 'document-currency-pound',
174
+ 'document-currency-rupee',
175
+ 'document-currency-yen',
176
+ 'document-duplicate',
177
+ 'document-magnifying-glass',
178
+ 'document-minus',
179
+ 'document-plus',
180
+ 'document-text',
181
+ 'ellipsis-horizontal',
182
+ 'ellipsis-horizontal-circle',
183
+ 'ellipsis-vertical',
184
+ 'envelope',
185
+ 'envelope-open',
186
+ 'equals',
187
+ 'exclamation-circle',
188
+ 'exclamation-triangle',
189
+ 'eye',
190
+ 'eye-dropper',
191
+ 'eye-slash',
192
+ 'face-frown',
193
+ 'face-smile',
194
+ 'film',
195
+ 'finger-print',
196
+ 'fire',
197
+ 'flag',
198
+ 'folder',
199
+ 'folder-arrow-down',
200
+ 'folder-minus',
201
+ 'folder-open',
202
+ 'folder-plus',
203
+ 'forward',
204
+ 'funnel',
205
+ 'gif',
206
+ 'gift',
207
+ 'gift-top',
208
+ 'globe-alt',
209
+ 'globe-americas',
210
+ 'globe-asia-australia',
211
+ 'globe-europe-africa',
212
+ 'h1',
213
+ 'h2',
214
+ 'h3',
215
+ 'hand-raised',
216
+ 'hand-thumb-down',
217
+ 'hand-thumb-up',
218
+ 'hashtag',
219
+ 'heart',
220
+ 'home',
221
+ 'home-modern',
222
+ 'identification',
223
+ 'inbox',
224
+ 'inbox-arrow-down',
225
+ 'inbox-stack',
226
+ 'information-circle',
227
+ 'italic',
228
+ 'key',
229
+ 'language',
230
+ 'lifebuoy',
231
+ 'light-bulb',
232
+ 'link',
233
+ 'link-slash',
234
+ 'list-bullet',
235
+ 'lock-closed',
236
+ 'lock-open',
237
+ 'magnifying-glass',
238
+ 'magnifying-glass-circle',
239
+ 'magnifying-glass-minus',
240
+ 'magnifying-glass-plus',
241
+ 'map',
242
+ 'map-pin',
243
+ 'megaphone',
244
+ 'microphone',
245
+ 'minus',
246
+ 'minus-circle',
247
+ 'minus-small',
248
+ 'moon',
249
+ 'musical-note',
250
+ 'newspaper',
251
+ 'no-symbol',
252
+ 'numbered-list',
253
+ 'paint-brush',
254
+ 'paper-airplane',
255
+ 'paper-clip',
256
+ 'pause',
257
+ 'pause-circle',
258
+ 'pencil',
259
+ 'pencil-square',
260
+ 'percent-badge',
261
+ 'phone',
262
+ 'phone-arrow-down-left',
263
+ 'phone-arrow-up-right',
264
+ 'phone-x-mark',
265
+ 'photo',
266
+ 'play',
267
+ 'play-circle',
268
+ 'play-pause',
269
+ 'plus',
270
+ 'plus-circle',
271
+ 'plus-small',
272
+ 'power',
273
+ 'presentation-chart-bar',
274
+ 'presentation-chart-line',
275
+ 'printer',
276
+ 'puzzle-piece',
277
+ 'qr-code',
278
+ 'question-mark-circle',
279
+ 'queue-list',
280
+ 'radio',
281
+ 'receipt-percent',
282
+ 'receipt-refund',
283
+ 'rectangle-group',
284
+ 'rectangle-stack',
285
+ 'rocket-launch',
286
+ 'rss',
287
+ 'scale',
288
+ 'scissors',
289
+ 'server',
290
+ 'server-stack',
291
+ 'share',
292
+ 'shield-check',
293
+ 'shield-exclamation',
294
+ 'shopping-bag',
295
+ 'shopping-cart',
296
+ 'signal',
297
+ 'signal-slash',
298
+ 'slash',
299
+ 'sparkles',
300
+ 'speaker-wave',
301
+ 'speaker-x-mark',
302
+ 'square-2-stack',
303
+ 'square-3-stack-3d',
304
+ 'squares-2x2',
305
+ 'squares-plus',
306
+ 'star',
307
+ 'stop',
308
+ 'stop-circle',
309
+ 'strikethrough',
310
+ 'sun',
311
+ 'swatch',
312
+ 'table-cells',
313
+ 'tag',
314
+ 'ticket',
315
+ 'trash',
316
+ 'trophy',
317
+ 'truck',
318
+ 'tv',
319
+ 'underline',
320
+ 'user',
321
+ 'user-circle',
322
+ 'user-group',
323
+ 'user-minus',
324
+ 'user-plus',
325
+ 'users',
326
+ 'variable',
327
+ 'video-camera',
328
+ 'video-camera-slash',
329
+ 'view-columns',
330
+ 'viewfinder-circle',
331
+ 'wallet',
332
+ 'wifi',
333
+ 'window',
334
+ 'wrench',
335
+ 'wrench-screwdriver',
336
+ 'x-circle',
337
+ 'x-mark',
338
+ ];
339
+
340
+ class TailwindComponent {
341
+ /** Optional ID for the component */
342
+ id = input(...(ngDevMode ? [undefined, { debugName: "id" }] : /* istanbul ignore next */ []));
343
+ /** Custom CSS classes to append */
344
+ class = input(undefined, { ...(ngDevMode ? { debugName: "class" } : /* istanbul ignore next */ {}), alias: 'class' });
345
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
346
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.12", type: TailwindComponent, isStandalone: true, inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "id() || null", "class": "class() || null" } }, ngImport: i0 });
347
+ }
348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindComponent, decorators: [{
349
+ type: Directive,
350
+ args: [{
351
+ host: {
352
+ '[attr.id]': 'id() || null',
353
+ '[class]': 'class() || null'
354
+ }
355
+ }]
356
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
357
+
358
+ class TailwindTooltip extends TailwindComponent {
359
+ /** Tooltip text */
360
+ text = input.required(...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
361
+ /** Position relative to trigger */
362
+ position = input('top', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
363
+ isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
364
+ topPos = signal(0, ...(ngDevMode ? [{ debugName: "topPos" }] : /* istanbul ignore next */ []));
365
+ leftPos = signal(0, ...(ngDevMode ? [{ debugName: "leftPos" }] : /* istanbul ignore next */ []));
366
+ targetElement = null;
367
+ document = inject(DOCUMENT);
368
+ ngZone = inject(NgZone);
369
+ el = inject(ElementRef);
370
+ tooltipEl = viewChild.required('tooltipEl');
371
+ scrollListener = () => this.updatePosition();
372
+ tooltipClasses = computed(() => {
373
+ const base = [
374
+ 'fixed z-[1070] px-3 py-1.5',
375
+ 'text-xs font-medium text-white bg-surface-900 rounded-lg',
376
+ 'shadow-lg whitespace-nowrap pointer-events-none',
377
+ 'transition-opacity duration-150',
378
+ this.isVisible() ? 'opacity-100' : 'opacity-0'
379
+ ];
380
+ return base.join(' ');
381
+ }, ...(ngDevMode ? [{ debugName: "tooltipClasses" }] : /* istanbul ignore next */ []));
382
+ arrowClasses = computed(() => {
383
+ const base = 'absolute w-2 h-2 bg-surface-900 rotate-45';
384
+ const posMap = {
385
+ top: 'top-full left-1/2 -translate-x-1/2 -mt-1',
386
+ bottom: 'bottom-full left-1/2 -translate-x-1/2 -mb-1',
387
+ left: 'left-full top-1/2 -translate-y-1/2 -ml-1',
388
+ right: 'right-full top-1/2 -translate-y-1/2 -mr-1'
389
+ };
390
+ return `${base} ${posMap[this.position()]}`;
391
+ }, ...(ngDevMode ? [{ debugName: "arrowClasses" }] : /* istanbul ignore next */ []));
392
+ ngAfterViewInit() {
393
+ this.updatePosition();
394
+ }
395
+ ngOnDestroy() {
396
+ this.hide();
397
+ }
398
+ setTarget(el) {
399
+ this.targetElement = el;
400
+ this.updatePosition();
401
+ }
402
+ getFixedOrigin() {
403
+ const dummy = this.document.createElement('div');
404
+ dummy.style.position = 'fixed';
405
+ dummy.style.top = '0';
406
+ dummy.style.left = '0';
407
+ this.el.nativeElement.appendChild(dummy);
408
+ const rect = dummy.getBoundingClientRect();
409
+ this.el.nativeElement.removeChild(dummy);
410
+ return { top: rect.top, left: rect.left };
411
+ }
412
+ updatePosition() {
413
+ if (!this.targetElement)
414
+ return;
415
+ const origin = this.getFixedOrigin();
416
+ const targetRect = this.targetElement.getBoundingClientRect();
417
+ const tooltipRect = this.tooltipEl().nativeElement.getBoundingClientRect();
418
+ let top = 0;
419
+ let left = 0;
420
+ switch (this.position()) {
421
+ case 'top':
422
+ top = targetRect.top - tooltipRect.height - 8;
423
+ left = targetRect.left + (targetRect.width - tooltipRect.width) / 2;
424
+ break;
425
+ case 'bottom':
426
+ top = targetRect.bottom + 8;
427
+ left = targetRect.left + (targetRect.width - tooltipRect.width) / 2;
428
+ break;
429
+ case 'left':
430
+ top = targetRect.top + (targetRect.height - tooltipRect.height) / 2;
431
+ left = targetRect.left - tooltipRect.width - 8;
432
+ break;
433
+ case 'right':
434
+ top = targetRect.top + (targetRect.height - tooltipRect.height) / 2;
435
+ left = targetRect.right + 8;
436
+ break;
437
+ }
438
+ this.ngZone.run(() => {
439
+ this.topPos.set(top - origin.top);
440
+ this.leftPos.set(left - origin.left);
441
+ });
442
+ }
443
+ show() {
444
+ this.updatePosition();
445
+ this.ngZone.run(() => {
446
+ this.isVisible.set(true);
447
+ });
448
+ this.ngZone.runOutsideAngular(() => {
449
+ window.addEventListener('scroll', this.scrollListener, true);
450
+ window.addEventListener('resize', this.scrollListener, true);
451
+ });
452
+ }
453
+ hide() {
454
+ this.ngZone.run(() => {
455
+ this.isVisible.set(false);
456
+ });
457
+ window.removeEventListener('scroll', this.scrollListener, true);
458
+ window.removeEventListener('resize', this.scrollListener, true);
459
+ }
460
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTooltip, deps: null, target: i0.ɵɵFactoryTarget.Component });
461
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.12", type: TailwindTooltip, isStandalone: true, selector: "tailwind-tooltip", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "tooltipEl", first: true, predicate: ["tooltipEl"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div #tooltipEl role=\"tooltip\" [class]=\"tooltipClasses()\" \n [style.top.px]=\"topPos()\" \n [style.left.px]=\"leftPos()\">\n {{ text() }}\n <!-- Arrow -->\n <div [class]=\"arrowClasses()\"></div>\n</div>\n", styles: [":host{display:inline-flex}\n"] });
462
+ }
463
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTooltip, decorators: [{
464
+ type: Component,
465
+ args: [{ selector: 'tailwind-tooltip', template: "<div #tooltipEl role=\"tooltip\" [class]=\"tooltipClasses()\" \n [style.top.px]=\"topPos()\" \n [style.left.px]=\"leftPos()\">\n {{ text() }}\n <!-- Arrow -->\n <div [class]=\"arrowClasses()\"></div>\n</div>\n", styles: [":host{display:inline-flex}\n"] }]
466
+ }], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], tooltipEl: [{ type: i0.ViewChild, args: ['tooltipEl', { isSignal: true }] }] } });
467
+
468
+ class TailwindTooltipDirective {
469
+ text;
470
+ tooltipPosition = 'top';
471
+ showTimeout = null;
472
+ hideTimeout = null;
473
+ componentRef = null;
474
+ viewContainerRef = inject(ViewContainerRef);
475
+ el = inject(ElementRef);
476
+ show() {
477
+ if (this.hideTimeout) {
478
+ clearTimeout(this.hideTimeout);
479
+ this.hideTimeout = null;
480
+ }
481
+ if (this.componentRef) {
482
+ return;
483
+ }
484
+ this.showTimeout = setTimeout(() => {
485
+ this.createComponent();
486
+ }, 200);
487
+ }
488
+ hide() {
489
+ if (this.showTimeout) {
490
+ clearTimeout(this.showTimeout);
491
+ this.showTimeout = null;
492
+ }
493
+ if (!this.componentRef) {
494
+ return;
495
+ }
496
+ this.componentRef.instance.hide();
497
+ this.hideTimeout = setTimeout(() => {
498
+ this.destroyComponent();
499
+ }, 150);
500
+ }
501
+ createComponent() {
502
+ this.componentRef = this.viewContainerRef.createComponent(TailwindTooltip);
503
+ this.componentRef.setInput('text', this.text);
504
+ this.componentRef.setInput('position', this.tooltipPosition);
505
+ this.componentRef.instance.setTarget(this.el.nativeElement);
506
+ setTimeout(() => {
507
+ if (this.componentRef) {
508
+ this.componentRef.instance.show();
509
+ }
510
+ });
511
+ }
512
+ destroyComponent() {
513
+ if (this.componentRef) {
514
+ this.componentRef.destroy();
515
+ this.componentRef = null;
516
+ }
517
+ }
518
+ ngOnDestroy() {
519
+ if (this.showTimeout)
520
+ clearTimeout(this.showTimeout);
521
+ if (this.hideTimeout)
522
+ clearTimeout(this.hideTimeout);
523
+ this.destroyComponent();
524
+ }
525
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
526
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.12", type: TailwindTooltipDirective, isStandalone: true, selector: "[tooltip]", inputs: { text: ["tooltip", "text"], tooltipPosition: "tooltipPosition" }, host: { listeners: { "mouseenter": "show()", "focusin": "show()", "mouseleave": "hide()", "focusout": "hide()" } }, ngImport: i0 });
527
+ }
528
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTooltipDirective, decorators: [{
529
+ type: Directive,
530
+ args: [{
531
+ selector: '[tooltip]'
532
+ }]
533
+ }], propDecorators: { text: [{
534
+ type: Input,
535
+ args: ['tooltip']
536
+ }], tooltipPosition: [{
537
+ type: Input
538
+ }], show: [{
539
+ type: HostListener,
540
+ args: ['mouseenter']
541
+ }, {
542
+ type: HostListener,
543
+ args: ['focusin']
544
+ }], hide: [{
545
+ type: HostListener,
546
+ args: ['mouseleave']
547
+ }, {
548
+ type: HostListener,
549
+ args: ['focusout']
550
+ }] } });
551
+
552
+ class TailwindButton extends TailwindComponent {
553
+ /** Visual color */
554
+ color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
555
+ /** Visual kind: `ghost` = transparent with hover tint; `text` = text color only, no hover background */
556
+ kind = input('solid', ...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
557
+ /** Size of the button */
558
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
559
+ /** Whether the button is disabled */
560
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
561
+ /** HTML button type attribute */
562
+ type = input('button', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
563
+ /** Emitted when the button is clicked (not disabled/loading) */
564
+ onClick = output();
565
+ /** Computed Tailwind classes based on color, kind, size, and state */
566
+ computedClasses = computed(() => {
567
+ const base = [
568
+ 'inline-flex items-center justify-center gap-2',
569
+ 'font-medium',
570
+ 'transition-all duration-150 ease-in-out',
571
+ 'focus-visible:outline-2 focus-visible:outline-offset-2',
572
+ 'disabled:cursor-not-allowed disabled:opacity-50',
573
+ 'cursor-pointer',
574
+ 'border'
575
+ ];
576
+ const solidMap = {
577
+ primary: 'bg-primary-600 text-white hover:bg-primary-700 active:bg-primary-800 border-transparent focus-visible:outline-primary-600 shadow-sm',
578
+ secondary: 'bg-surface-100 text-surface-800 hover:bg-surface-200 active:bg-surface-300 border-surface-300 focus-visible:outline-surface-500 shadow-sm',
579
+ danger: 'bg-danger-600 text-white hover:bg-danger-700 active:bg-danger-800 border-transparent focus-visible:outline-danger-600 shadow-sm',
580
+ success: 'bg-success-600 text-white hover:bg-success-700 active:bg-success-800 border-transparent focus-visible:outline-success-600 shadow-sm',
581
+ warning: 'bg-warning-500 text-surface-900 hover:bg-warning-600 active:bg-warning-700 border-transparent focus-visible:outline-warning-500 shadow-sm',
582
+ info: 'bg-info-600 text-white hover:bg-info-700 active:bg-info-800 border-transparent focus-visible:outline-info-600 shadow-sm'
583
+ };
584
+ const outlinedMap = {
585
+ primary: 'bg-transparent text-primary-600 border-primary-600 hover:bg-primary-50 active:bg-primary-100 focus-visible:outline-primary-600',
586
+ secondary: 'bg-transparent text-surface-700 border-surface-300 hover:bg-surface-50 active:bg-surface-100 focus-visible:outline-surface-500',
587
+ danger: 'bg-transparent text-danger-600 border-danger-600 hover:bg-danger-50 active:bg-danger-100 focus-visible:outline-danger-600',
588
+ success: 'bg-transparent text-success-600 border-success-600 hover:bg-success-50 active:bg-success-100 focus-visible:outline-success-600',
589
+ warning: 'bg-transparent text-warning-600 border-warning-500 hover:bg-warning-50 active:bg-warning-100 focus-visible:outline-warning-500',
590
+ info: 'bg-transparent text-info-600 border-info-600 hover:bg-info-50 active:bg-info-100 focus-visible:outline-info-600'
591
+ };
592
+ /** Transparent + hover/active background tint (former `text` look). */
593
+ const ghostMap = {
594
+ primary: 'bg-transparent text-primary-600 border-transparent hover:bg-primary-50 active:bg-primary-100 focus-visible:outline-primary-600',
595
+ secondary: 'bg-transparent text-surface-700 border-transparent hover:bg-surface-100 active:bg-surface-200 focus-visible:outline-surface-500',
596
+ danger: 'bg-transparent text-danger-600 border-transparent hover:bg-danger-50 active:bg-danger-100 focus-visible:outline-danger-600',
597
+ success: 'bg-transparent text-success-600 border-transparent hover:bg-success-50 active:bg-success-100 focus-visible:outline-success-600',
598
+ warning: 'bg-transparent text-warning-600 border-transparent hover:bg-warning-50 active:bg-warning-100 focus-visible:outline-warning-500',
599
+ info: 'bg-transparent text-info-600 border-transparent hover:bg-info-50 active:bg-info-100 focus-visible:outline-info-600'
600
+ };
601
+ /** Text color from severity only; background stays transparent on hover/active. */
602
+ const textMap = {
603
+ primary: 'bg-transparent text-primary-600 border-transparent focus-visible:outline-primary-600',
604
+ secondary: 'bg-transparent text-surface-700 border-transparent focus-visible:outline-surface-500',
605
+ danger: 'bg-transparent text-danger-600 border-transparent focus-visible:outline-danger-600',
606
+ success: 'bg-transparent text-success-600 border-transparent focus-visible:outline-success-600',
607
+ warning: 'bg-transparent text-warning-600 border-transparent focus-visible:outline-warning-500',
608
+ info: 'bg-transparent text-info-600 border-transparent focus-visible:outline-info-600'
609
+ };
610
+ const styleMap = {
611
+ solid: solidMap,
612
+ outlined: outlinedMap,
613
+ ghost: ghostMap,
614
+ text: textMap
615
+ };
616
+ const sizeMap = {
617
+ xs: 'text-xs px-2 py-1 rounded-sm',
618
+ sm: 'text-sm px-3 py-1.5 rounded-md',
619
+ md: 'text-sm px-4 py-2 rounded-md',
620
+ lg: 'text-base px-5 py-2.5 rounded-lg',
621
+ xl: 'text-base px-6 py-3 rounded-lg'
622
+ };
623
+ const iconSizeMap = {
624
+ xs: 'p-1 rounded-sm',
625
+ sm: 'p-1.5 rounded-md',
626
+ md: 'p-2 rounded-md',
627
+ lg: 'p-2.5 rounded-lg',
628
+ xl: 'p-3 rounded-lg'
629
+ };
630
+ return [...base, styleMap[this.kind()][this.color()] || styleMap['solid']['primary'], sizeMap[this.size()]].join(' ');
631
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
632
+ handleClick(event) {
633
+ if (!this.disabled()) {
634
+ this.onClick.emit(event);
635
+ }
636
+ }
637
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindButton, deps: null, target: i0.ɵɵFactoryTarget.Component });
638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: TailwindButton, isStandalone: true, selector: "tailwind-button", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClick: "onClick" }, usesInheritance: true, ngImport: i0, template: "<button\n [ngClass]=\"computedClasses()\"\n [disabled]=\"disabled()\"\n [type]=\"type()\"\n [attr.aria-disabled]=\"disabled() || null\"\n (click)=\"handleClick($event)\">\n <ng-content />\n</button>\n", styles: [":host{display:inline-block}.tailwind-btn-spinner{animation:tailwind-spin 1s linear infinite;width:1em;height:1em}@keyframes tailwind-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
639
+ }
640
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindButton, decorators: [{
641
+ type: Component,
642
+ args: [{ selector: 'tailwind-button', imports: [NgClass], template: "<button\n [ngClass]=\"computedClasses()\"\n [disabled]=\"disabled()\"\n [type]=\"type()\"\n [attr.aria-disabled]=\"disabled() || null\"\n (click)=\"handleClick($event)\">\n <ng-content />\n</button>\n", styles: [":host{display:inline-block}.tailwind-btn-spinner{animation:tailwind-spin 1s linear infinite;width:1em;height:1em}@keyframes tailwind-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
643
+ }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], onClick: [{ type: i0.Output, args: ["onClick"] }] } });
644
+
645
+ const TAILWIND_MODAL_DATA = new InjectionToken('TAILWIND_MODAL_DATA');
646
+ const TAILWIND_ICON_SIZE = new InjectionToken('TAILWIND_ICON_SIZE');
647
+ const TAILWIND_DATETIME_LANGUAGE = new InjectionToken('TAILWIND_DATETIME_LANGUAGE');
648
+ const TAILWIND_COMPONENTS_SIZE = new InjectionToken('TAILWIND_COMPONENTS_SIZE');
649
+
650
+ class TailwindIcon extends TailwindComponent {
651
+ iconSize = inject(TAILWIND_ICON_SIZE, { optional: true });
652
+ /** Heroicon name; SVG path `public/icons/<name>.svg` */
653
+ icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
654
+ /** `normal` = 24×24, `small` = 16×16; default dalla DI (`TAILWIND_ICON_SIZE`) se presente */
655
+ size = input(this.iconSize ?? 'normal', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
656
+ src = computed(() => `/tailwind-icons/${this.icon()}.svg`, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
657
+ pixelSize = computed(() => (this.size() === 'small' ? 16 : 24), ...(ngDevMode ? [{ debugName: "pixelSize" }] : /* istanbul ignore next */ []));
658
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindIcon, deps: null, target: i0.ɵɵFactoryTarget.Component });
659
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: TailwindIcon, isStandalone: true, selector: "tailwind-icon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "inline-flex shrink-0 items-center justify-center" }, usesInheritance: true, ngImport: i0, template: "<img\r\n class=\"block shrink-0\"\r\n [src]=\"src()\"\r\n [attr.width]=\"pixelSize()\"\r\n [attr.height]=\"pixelSize()\"\r\n [attr.alt]=\"icon()\"\r\n [attr.aria-hidden]=\"true\"\r\n decoding=\"async\" />\r\n" });
660
+ }
661
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindIcon, decorators: [{
662
+ type: Component,
663
+ args: [{ selector: 'tailwind-icon', host: {
664
+ class: 'inline-flex shrink-0 items-center justify-center'
665
+ }, template: "<img\r\n class=\"block shrink-0\"\r\n [src]=\"src()\"\r\n [attr.width]=\"pixelSize()\"\r\n [attr.height]=\"pixelSize()\"\r\n [attr.alt]=\"icon()\"\r\n [attr.aria-hidden]=\"true\"\r\n decoding=\"async\" />\r\n" }]
666
+ }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
667
+
668
+ class TailwindInput extends TailwindComponent {
669
+ /** Label text */
670
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
671
+ /** Placeholder text */
672
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
673
+ /** Input type */
674
+ type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
675
+ /** Size variant */
676
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
677
+ /** Whether the input is readonly */
678
+ readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
679
+ /** Helper text shown below input */
680
+ helperText = input('', ...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
681
+ /** Error text shown when hasError is true */
682
+ errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
683
+ /** Whether the input is in error state */
684
+ hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
685
+ /** Two-way bound value */
686
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
687
+ /** Internal disabled state */
688
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
689
+ /** Computed input classes */
690
+ inputClasses = computed(() => {
691
+ const base = [
692
+ 'block w-full bg-white',
693
+ 'border transition-colors duration-150',
694
+ 'placeholder:text-surface-400',
695
+ 'outline-none focus:outline focus:outline-2 focus:outline-offset-2',
696
+ 'disabled:bg-surface-50 disabled:text-surface-400 disabled:cursor-not-allowed'
697
+ ];
698
+ const sizeMap = {
699
+ xs: 'text-xs px-2 py-1 rounded-sm',
700
+ sm: 'text-sm px-2.5 py-1.5 rounded-md',
701
+ md: 'text-sm px-3 py-2 rounded-md',
702
+ lg: 'text-base px-3.5 py-2.5 rounded-lg',
703
+ xl: 'text-base px-4 py-3 rounded-lg'
704
+ };
705
+ const stateClass = this.hasError()
706
+ ? 'border-danger-400 focus:outline-danger-500 text-danger-900'
707
+ : 'border-surface-300 focus:outline-primary-500 text-surface-900';
708
+ return [...base, sizeMap[this.size()], stateClass].join(' ');
709
+ }, ...(ngDevMode ? [{ debugName: "inputClasses" }] : /* istanbul ignore next */ []));
710
+ // CVA
711
+ onChange = () => { };
712
+ onTouched = () => { };
713
+ writeValue(value) {
714
+ this.value.set(value ?? '');
715
+ }
716
+ registerOnChange(fn) {
717
+ this.onChange = fn;
718
+ }
719
+ registerOnTouched(fn) {
720
+ this.onTouched = fn;
721
+ }
722
+ setDisabledState(disabled) {
723
+ this.isDisabled.set(disabled);
724
+ }
725
+ onInputChange(event) {
726
+ const val = event.target.value;
727
+ this.value.set(val);
728
+ this.onChange(val);
729
+ }
730
+ onBlur() {
731
+ this.onTouched();
732
+ }
733
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindInput, deps: null, target: i0.ɵɵFactoryTarget.Component });
734
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindInput, isStandalone: true, selector: "tailwind-input", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
735
+ {
736
+ provide: NG_VALUE_ACCESSOR,
737
+ useExisting: forwardRef(() => TailwindInput),
738
+ multi: true
739
+ }
740
+ ], usesInheritance: true, ngImport: i0, template: "<div class=\"tailwind-input-wrapper flex flex-col gap-1.5\">\n @if (label()) {\n <label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"text-sm font-medium text-surface-700\"\n [class.text-danger-600]=\"hasError()\">\n {{ label() }}\n </label>\n }\n\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\n [value]=\"value()\"\n [class]=\"inputClasses()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\" />\n\n @if (helperText() && !hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\n {{ helperText() }}\n </p>\n }\n @if (errorText() && hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\n {{ errorText() }}\n </p>\n }\n</div>\n", styles: [":host{display:block}\n"] });
741
+ }
742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindInput, decorators: [{
743
+ type: Component,
744
+ args: [{ selector: 'tailwind-input', providers: [
745
+ {
746
+ provide: NG_VALUE_ACCESSOR,
747
+ useExisting: forwardRef(() => TailwindInput),
748
+ multi: true
749
+ }
750
+ ], template: "<div class=\"tailwind-input-wrapper flex flex-col gap-1.5\">\n @if (label()) {\n <label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"text-sm font-medium text-surface-700\"\n [class.text-danger-600]=\"hasError()\">\n {{ label() }}\n </label>\n }\n\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\n [value]=\"value()\"\n [class]=\"inputClasses()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\" />\n\n @if (helperText() && !hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">\n {{ helperText() }}\n </p>\n }\n @if (errorText() && hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">\n {{ errorText() }}\n </p>\n }\n</div>\n", styles: [":host{display:block}\n"] }]
751
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
752
+
753
+ class TailwindCheckbox extends TailwindComponent {
754
+ /** Label text */
755
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
756
+ /** Description text */
757
+ description = input('', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
758
+ /** Size variant */
759
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
760
+ /** Unique ID */
761
+ /** Two-way bound checked state */
762
+ checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
763
+ /** Internal disabled state */
764
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
765
+ /** Box size class based on size input */
766
+ boxSizeClass = computed(() => {
767
+ const sizeMap = {
768
+ xs: 'w-3.5 h-3.5',
769
+ sm: 'w-4 h-4',
770
+ md: 'w-5 h-5',
771
+ lg: 'w-6 h-6',
772
+ xl: 'w-7 h-7'
773
+ };
774
+ return sizeMap[this.size()];
775
+ }, ...(ngDevMode ? [{ debugName: "boxSizeClass" }] : /* istanbul ignore next */ []));
776
+ // CVA
777
+ onChange = () => { };
778
+ onTouched = () => { };
779
+ writeValue(value) {
780
+ this.checked.set(!!value);
781
+ }
782
+ registerOnChange(fn) {
783
+ this.onChange = fn;
784
+ }
785
+ registerOnTouched(fn) {
786
+ this.onTouched = fn;
787
+ }
788
+ setDisabledState(disabled) {
789
+ this.isDisabled.set(disabled);
790
+ }
791
+ onCheckboxChange(event) {
792
+ const val = event.target.checked;
793
+ this.checked.set(val);
794
+ this.onChange(val);
795
+ this.onTouched();
796
+ }
797
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindCheckbox, deps: null, target: i0.ɵɵFactoryTarget.Component });
798
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindCheckbox, isStandalone: true, selector: "tailwind-checkbox", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, providers: [
799
+ {
800
+ provide: NG_VALUE_ACCESSOR,
801
+ useExisting: forwardRef(() => TailwindCheckbox),
802
+ multi: true
803
+ }
804
+ ], usesInheritance: true, ngImport: i0, template: "<label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"inline-flex items-center gap-2.5 cursor-pointer select-none\"\n [class.cursor-not-allowed]=\"isDisabled()\"\n [class.opacity-50]=\"isDisabled()\">\n <div class=\"relative flex items-center justify-center shrink-0\" [class]=\"boxSizeClass()\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"checkbox\"\n class=\"peer sr-only\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-describedby]=\"description() && id() ? id() + '-desc' : null\"\n (change)=\"onCheckboxChange($event)\" />\n <div\n class=\"w-full h-full border-2 transition-all duration-150 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-500/30 peer-focus-visible:ring-offset-1\"\n [class.rounded-sm]=\"size() === 'xs' || size() === 'sm'\"\n [class.rounded-md]=\"size() !== 'xs' && size() !== 'sm'\"\n [class.border-surface-300]=\"!checked()\"\n [class.bg-white]=\"!checked()\"\n [class.border-primary-600]=\"checked()\"\n [class.bg-primary-600]=\"checked()\">\n @if (checked()) {\n <svg class=\"w-full h-full text-white p-0.5\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M13.5 4.5L6.5 11.5L3 8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-0.5 pt-0.5\">\n @if (label()) {\n <span class=\"text-sm font-medium text-surface-800 leading-tight\">{{ label() }}</span>\n }\n @if (description()) {\n <span [attr.id]=\"id() ? id() + '-desc' : null\" class=\"text-xs text-surface-500 leading-snug\">\n {{ description() }}\n </span>\n }\n </div>\n</label>\n", styles: [":host{display:inline-block}\n"] });
805
+ }
806
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindCheckbox, decorators: [{
807
+ type: Component,
808
+ args: [{ selector: 'tailwind-checkbox', providers: [
809
+ {
810
+ provide: NG_VALUE_ACCESSOR,
811
+ useExisting: forwardRef(() => TailwindCheckbox),
812
+ multi: true
813
+ }
814
+ ], template: "<label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"inline-flex items-center gap-2.5 cursor-pointer select-none\"\n [class.cursor-not-allowed]=\"isDisabled()\"\n [class.opacity-50]=\"isDisabled()\">\n <div class=\"relative flex items-center justify-center shrink-0\" [class]=\"boxSizeClass()\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"checkbox\"\n class=\"peer sr-only\"\n [checked]=\"checked()\"\n [disabled]=\"isDisabled()\"\n [attr.aria-describedby]=\"description() && id() ? id() + '-desc' : null\"\n (change)=\"onCheckboxChange($event)\" />\n <div\n class=\"w-full h-full border-2 transition-all duration-150 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-500/30 peer-focus-visible:ring-offset-1\"\n [class.rounded-sm]=\"size() === 'xs' || size() === 'sm'\"\n [class.rounded-md]=\"size() !== 'xs' && size() !== 'sm'\"\n [class.border-surface-300]=\"!checked()\"\n [class.bg-white]=\"!checked()\"\n [class.border-primary-600]=\"checked()\"\n [class.bg-primary-600]=\"checked()\">\n @if (checked()) {\n <svg class=\"w-full h-full text-white p-0.5\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path\n d=\"M13.5 4.5L6.5 11.5L3 8\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-0.5 pt-0.5\">\n @if (label()) {\n <span class=\"text-sm font-medium text-surface-800 leading-tight\">{{ label() }}</span>\n }\n @if (description()) {\n <span [attr.id]=\"id() ? id() + '-desc' : null\" class=\"text-xs text-surface-500 leading-snug\">\n {{ description() }}\n </span>\n }\n </div>\n</label>\n", styles: [":host{display:inline-block}\n"] }]
815
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }] } });
816
+
817
+ class TailwindRadioGroup extends TailwindComponent {
818
+ /** Label for the radio group */
819
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
820
+ /** Aria label for accessibility */
821
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
822
+ /** Name for the radio group (used for native radio grouping) */
823
+ name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : /* istanbul ignore next */ []));
824
+ /** Available options */
825
+ options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
826
+ /** Size variant */
827
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
828
+ /** Layout orientation */
829
+ orientation = input('vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
830
+ /** Currently selected value */
831
+ value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
832
+ /** Internal disabled state */
833
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
834
+ /** Radio button outer ring size */
835
+ radioSizeClass = computed(() => {
836
+ const sizeMap = {
837
+ xs: 'w-3.5 h-3.5',
838
+ sm: 'w-4 h-4',
839
+ md: 'w-5 h-5',
840
+ lg: 'w-6 h-6',
841
+ xl: 'w-7 h-7'
842
+ };
843
+ return sizeMap[this.size()];
844
+ }, ...(ngDevMode ? [{ debugName: "radioSizeClass" }] : /* istanbul ignore next */ []));
845
+ /** Inner dot size */
846
+ dotSizeClass = computed(() => {
847
+ const sizeMap = {
848
+ xs: 'w-1.5 h-1.5',
849
+ sm: 'w-2 h-2',
850
+ md: 'w-2.5 h-2.5',
851
+ lg: 'w-3 h-3',
852
+ xl: 'w-3.5 h-3.5'
853
+ };
854
+ return sizeMap[this.size()];
855
+ }, ...(ngDevMode ? [{ debugName: "dotSizeClass" }] : /* istanbul ignore next */ []));
856
+ // CVA
857
+ onChange = () => { };
858
+ onTouched = () => { };
859
+ writeValue(value) {
860
+ this.value.set(value ?? null);
861
+ }
862
+ registerOnChange(fn) {
863
+ this.onChange = fn;
864
+ }
865
+ registerOnTouched(fn) {
866
+ this.onTouched = fn;
867
+ }
868
+ setDisabledState(disabled) {
869
+ this.isDisabled.set(disabled);
870
+ }
871
+ onRadioChange(optionValue) {
872
+ this.value.set(optionValue);
873
+ this.onChange(optionValue);
874
+ this.onTouched();
875
+ }
876
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindRadioGroup, deps: null, target: i0.ɵɵFactoryTarget.Component });
877
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindRadioGroup, isStandalone: true, selector: "tailwind-radio-group", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
878
+ {
879
+ provide: NG_VALUE_ACCESSOR,
880
+ useExisting: forwardRef(() => TailwindRadioGroup),
881
+ multi: true
882
+ }
883
+ ], usesInheritance: true, ngImport: i0, template: "<fieldset\n class=\"flex gap-3\"\n [class.flex-col]=\"orientation() === 'vertical'\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"radiogroup\">\n @if (label()) {\n <legend class=\"text-sm font-medium text-surface-700 mb-2\">{{ label() }}</legend>\n }\n\n @for (option of options(); track option.value) {\n <label\n class=\"inline-flex items-start gap-2.5 cursor-pointer select-none\"\n [class.cursor-not-allowed]=\"isDisabled() || option.disabled\"\n [class.opacity-50]=\"isDisabled() || option.disabled\">\n <div class=\"relative flex items-center justify-center shrink-0\" [class]=\"radioSizeClass()\">\n <input\n type=\"radio\"\n class=\"peer sr-only\"\n [name]=\"name()\"\n [value]=\"option.value\"\n [checked]=\"value() === option.value\"\n [disabled]=\"isDisabled() || !!option.disabled\"\n (change)=\"onRadioChange(option.value)\" />\n <div\n class=\"w-full h-full rounded-full border-2 transition-all duration-150 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-500/30 peer-focus-visible:ring-offset-1 flex items-center justify-center\"\n [class.border-surface-300]=\"value() !== option.value\"\n [class.border-primary-600]=\"value() === option.value\">\n @if (value() === option.value) {\n <div\n class=\"rounded-full bg-primary-600 transition-transform duration-150 scale-100\"\n [class]=\"dotSizeClass()\"></div>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-0.5 pt-0.5\">\n <span class=\"text-sm font-medium text-surface-800 leading-tight\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"text-xs text-surface-500 leading-snug\">{{ option.description }}</span>\n }\n </div>\n </label>\n }\n</fieldset>\n", styles: [":host{display:block}\n"] });
884
+ }
885
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindRadioGroup, decorators: [{
886
+ type: Component,
887
+ args: [{ selector: 'tailwind-radio-group', providers: [
888
+ {
889
+ provide: NG_VALUE_ACCESSOR,
890
+ useExisting: forwardRef(() => TailwindRadioGroup),
891
+ multi: true
892
+ }
893
+ ], template: "<fieldset\n class=\"flex gap-3\"\n [class.flex-col]=\"orientation() === 'vertical'\"\n [attr.aria-label]=\"ariaLabel()\"\n role=\"radiogroup\">\n @if (label()) {\n <legend class=\"text-sm font-medium text-surface-700 mb-2\">{{ label() }}</legend>\n }\n\n @for (option of options(); track option.value) {\n <label\n class=\"inline-flex items-start gap-2.5 cursor-pointer select-none\"\n [class.cursor-not-allowed]=\"isDisabled() || option.disabled\"\n [class.opacity-50]=\"isDisabled() || option.disabled\">\n <div class=\"relative flex items-center justify-center shrink-0\" [class]=\"radioSizeClass()\">\n <input\n type=\"radio\"\n class=\"peer sr-only\"\n [name]=\"name()\"\n [value]=\"option.value\"\n [checked]=\"value() === option.value\"\n [disabled]=\"isDisabled() || !!option.disabled\"\n (change)=\"onRadioChange(option.value)\" />\n <div\n class=\"w-full h-full rounded-full border-2 transition-all duration-150 peer-focus-visible:ring-2 peer-focus-visible:ring-primary-500/30 peer-focus-visible:ring-offset-1 flex items-center justify-center\"\n [class.border-surface-300]=\"value() !== option.value\"\n [class.border-primary-600]=\"value() === option.value\">\n @if (value() === option.value) {\n <div\n class=\"rounded-full bg-primary-600 transition-transform duration-150 scale-100\"\n [class]=\"dotSizeClass()\"></div>\n }\n </div>\n </div>\n\n <div class=\"flex flex-col gap-0.5 pt-0.5\">\n <span class=\"text-sm font-medium text-surface-800 leading-tight\">{{ option.label }}</span>\n @if (option.description) {\n <span class=\"text-xs text-surface-500 leading-snug\">{{ option.description }}</span>\n }\n </div>\n </label>\n }\n</fieldset>\n", styles: [":host{display:block}\n"] }]
894
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
895
+
896
+ class TailwindSelect extends TailwindComponent {
897
+ overlay = inject(Overlay);
898
+ vcr = inject(ViewContainerRef);
899
+ elRef = inject((ElementRef));
900
+ panelTemplate = viewChild.required('panelTemplate');
901
+ overlayRef = null;
902
+ outsideSub = null;
903
+ /** Label text */
904
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
905
+ /** Placeholder text */
906
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
907
+ /** Available options */
908
+ options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
909
+ /** Size variant */
910
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
911
+ /** Helper text */
912
+ helperText = input('', ...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
913
+ /** Error text */
914
+ errorText = input('', ...(ngDevMode ? [{ debugName: "errorText" }] : /* istanbul ignore next */ []));
915
+ /** Whether in error state */
916
+ hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
917
+ /** When true, value is `T[]` and several options can be selected */
918
+ multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
919
+ /** Selected value: `T | null` when single, `T[]` when `multiple` */
920
+ value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
921
+ /** Internal disabled state */
922
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
923
+ /** Whether the dropdown panel is open */
924
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
925
+ /** Keyboard-highlighted option index (-1 = none) */
926
+ activeIndex = signal(-1, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
927
+ /** The currently selected option object (single mode only) */
928
+ selectedOption = computed(() => {
929
+ if (this.multiple())
930
+ return null;
931
+ const v = this.value();
932
+ if (v == null || Array.isArray(v))
933
+ return null;
934
+ return this.options().find(o => this.optionValueEquals(o.value, v)) ?? null;
935
+ }, ...(ngDevMode ? [{ debugName: "selectedOption" }] : /* istanbul ignore next */ []));
936
+ /** Selected option objects in `options()` order (multiple mode only) */
937
+ selectedOptions = computed(() => {
938
+ if (!this.multiple())
939
+ return [];
940
+ const v = this.value();
941
+ const arr = Array.isArray(v) ? v : [];
942
+ return this.options().filter(o => arr.some(sv => this.optionValueEquals(o.value, sv)));
943
+ }, ...(ngDevMode ? [{ debugName: "selectedOptions" }] : /* istanbul ignore next */ []));
944
+ /** Classes for the trigger button */
945
+ triggerClasses = computed(() => {
946
+ const sizeMap = {
947
+ xs: 'text-xs px-2 py-1 rounded-sm',
948
+ sm: 'text-sm px-2.5 py-1.5 rounded-md',
949
+ md: 'text-sm px-3 py-2 rounded-md',
950
+ lg: 'text-base px-3.5 py-2.5 rounded-lg',
951
+ xl: 'text-base px-4 py-3 rounded-lg'
952
+ };
953
+ const stateClass = this.hasError()
954
+ ? 'border-danger-400 focus:outline-danger-500 text-danger-900'
955
+ : 'border-surface-300 focus:outline-primary-500';
956
+ const layout = this.multiple() ? 'items-start' : 'items-center';
957
+ return [
958
+ 'flex justify-between w-full bg-white border transition-colors duration-150',
959
+ layout,
960
+ 'pr-3 cursor-pointer text-left',
961
+ 'outline-none focus:outline focus:outline-2 focus:outline-offset-2',
962
+ 'disabled:bg-surface-50 disabled:text-surface-400 disabled:cursor-not-allowed',
963
+ sizeMap[this.size()],
964
+ stateClass
965
+ ].join(' ');
966
+ }, ...(ngDevMode ? [{ debugName: "triggerClasses" }] : /* istanbul ignore next */ []));
967
+ optionValueEquals(a, b) {
968
+ return Object.is(a, b);
969
+ }
970
+ /** Used in the template to compare option values */
971
+ isOptionSelected(option) {
972
+ if (this.multiple()) {
973
+ const v = this.value();
974
+ const arr = Array.isArray(v) ? v : [];
975
+ return arr.some(sv => this.optionValueEquals(option.value, sv));
976
+ }
977
+ const v = this.value();
978
+ if (v == null || Array.isArray(v))
979
+ return false;
980
+ return this.optionValueEquals(option.value, v);
981
+ }
982
+ /** Classes for a single option row */
983
+ optionClasses(index, option) {
984
+ const isSelected = this.isOptionSelected(option);
985
+ const isActive = this.activeIndex() === index;
986
+ const isDisabled = !!option.disabled;
987
+ return [
988
+ 'flex items-center justify-between px-3 py-2 text-sm cursor-pointer select-none',
989
+ isDisabled
990
+ ? 'text-surface-400 cursor-not-allowed'
991
+ : isSelected
992
+ ? 'bg-primary-50 text-primary-700 font-medium'
993
+ : isActive
994
+ ? 'bg-surface-100 text-surface-900'
995
+ : 'text-surface-800 hover:bg-surface-50'
996
+ ].join(' ');
997
+ }
998
+ // CVA
999
+ onChange = () => { };
1000
+ onTouched = () => { };
1001
+ writeValue(value) {
1002
+ if (this.multiple()) {
1003
+ if (value == null)
1004
+ this.value.set([]);
1005
+ else
1006
+ this.value.set(Array.isArray(value) ? [...value] : []);
1007
+ }
1008
+ else {
1009
+ if (Array.isArray(value))
1010
+ this.value.set(null);
1011
+ else
1012
+ this.value.set(value ?? null);
1013
+ }
1014
+ }
1015
+ registerOnChange(fn) {
1016
+ this.onChange = fn;
1017
+ }
1018
+ registerOnTouched(fn) {
1019
+ this.onTouched = fn;
1020
+ }
1021
+ setDisabledState(disabled) {
1022
+ this.isDisabled.set(disabled);
1023
+ }
1024
+ ngOnDestroy() {
1025
+ this.closeDropdown();
1026
+ }
1027
+ openDropdown() {
1028
+ if (this.overlayRef)
1029
+ return;
1030
+ const trigger = this.elRef.nativeElement.querySelector('button[role="combobox"]') ?? this.elRef.nativeElement;
1031
+ const positionStrategy = this.overlay
1032
+ .position()
1033
+ .flexibleConnectedTo(trigger)
1034
+ .withPositions([
1035
+ // Preferred: open downward
1036
+ { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },
1037
+ // Fallback: open upward
1038
+ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' }
1039
+ ])
1040
+ .withFlexibleDimensions(false)
1041
+ .withPush(false);
1042
+ this.overlayRef = this.overlay.create({
1043
+ positionStrategy,
1044
+ scrollStrategy: this.overlay.scrollStrategies.close(),
1045
+ width: trigger.offsetWidth,
1046
+ minWidth: 'w-full'
1047
+ });
1048
+ const portal = new TemplatePortal(this.panelTemplate(), this.vcr);
1049
+ this.overlayRef.attach(portal);
1050
+ const pane = this.overlayRef.overlayElement;
1051
+ this.outsideSub = new Subscription();
1052
+ // Close on outside click (capture: trigger + panel are excluded; avoids CDK edge cases)
1053
+ this.outsideSub.add(fromEvent(document, 'pointerdown', { capture: true }).subscribe(ev => {
1054
+ const t = ev.target;
1055
+ if (this.elRef.nativeElement.contains(t) || pane.contains(t))
1056
+ return;
1057
+ this.closeDropdown();
1058
+ }));
1059
+ this.outsideSub.add(fromEvent(document, 'keydown').subscribe(ev => {
1060
+ if (ev.key === 'Escape') {
1061
+ ev.preventDefault();
1062
+ this.closeDropdown();
1063
+ }
1064
+ }));
1065
+ this.isOpen.set(true);
1066
+ const opts = this.options();
1067
+ let initial = -1;
1068
+ if (this.multiple()) {
1069
+ const v = this.value();
1070
+ const arr = Array.isArray(v) ? v : [];
1071
+ initial = opts.findIndex(o => arr.some(sv => this.optionValueEquals(o.value, sv)));
1072
+ }
1073
+ else {
1074
+ const v = this.value();
1075
+ if (v != null && !Array.isArray(v)) {
1076
+ initial = opts.findIndex(o => this.optionValueEquals(o.value, v));
1077
+ }
1078
+ }
1079
+ this.activeIndex.set(initial >= 0 ? initial : -1);
1080
+ }
1081
+ closeDropdown() {
1082
+ this.overlayRef?.detach();
1083
+ this.overlayRef?.dispose();
1084
+ this.overlayRef = null;
1085
+ this.outsideSub?.unsubscribe();
1086
+ this.outsideSub = null;
1087
+ this.isOpen.set(false);
1088
+ this.activeIndex.set(-1);
1089
+ }
1090
+ toggleDropdown() {
1091
+ if (this.isDisabled())
1092
+ return;
1093
+ if (this.isOpen()) {
1094
+ this.closeDropdown();
1095
+ }
1096
+ else {
1097
+ this.openDropdown();
1098
+ }
1099
+ }
1100
+ selectOption(option) {
1101
+ if (option.disabled)
1102
+ return;
1103
+ if (this.multiple()) {
1104
+ const v = this.value();
1105
+ const current = Array.isArray(v) ? [...v] : [];
1106
+ const idx = current.findIndex(sv => this.optionValueEquals(sv, option.value));
1107
+ if (idx >= 0)
1108
+ current.splice(idx, 1);
1109
+ else
1110
+ current.push(option.value);
1111
+ this.value.set(current);
1112
+ this.onChange(current);
1113
+ this.onTouched();
1114
+ return;
1115
+ }
1116
+ const val = option.value;
1117
+ this.value.set(val);
1118
+ this.onChange(val);
1119
+ this.onTouched();
1120
+ this.closeDropdown();
1121
+ }
1122
+ onKeydown(event) {
1123
+ if (this.isDisabled())
1124
+ return;
1125
+ const opts = this.options();
1126
+ switch (event.key) {
1127
+ case 'ArrowDown': {
1128
+ event.preventDefault();
1129
+ if (!this.isOpen()) {
1130
+ this.openDropdown();
1131
+ return;
1132
+ }
1133
+ let next = this.activeIndex() + 1;
1134
+ while (next < opts.length && opts[next].disabled)
1135
+ next++;
1136
+ if (next < opts.length)
1137
+ this.activeIndex.set(next);
1138
+ break;
1139
+ }
1140
+ case 'ArrowUp': {
1141
+ event.preventDefault();
1142
+ if (!this.isOpen()) {
1143
+ this.openDropdown();
1144
+ return;
1145
+ }
1146
+ let prev = this.activeIndex() - 1;
1147
+ while (prev >= 0 && opts[prev].disabled)
1148
+ prev--;
1149
+ if (prev >= 0)
1150
+ this.activeIndex.set(prev);
1151
+ break;
1152
+ }
1153
+ case 'Enter':
1154
+ case ' ': {
1155
+ event.preventDefault();
1156
+ if (!this.isOpen()) {
1157
+ this.openDropdown();
1158
+ return;
1159
+ }
1160
+ const active = this.activeIndex();
1161
+ if (active >= 0 && active < opts.length) {
1162
+ this.selectOption(opts[active]);
1163
+ }
1164
+ break;
1165
+ }
1166
+ case 'Escape':
1167
+ case 'Tab': {
1168
+ this.closeDropdown();
1169
+ break;
1170
+ }
1171
+ }
1172
+ }
1173
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSelect, deps: null, target: i0.ɵɵFactoryTarget.Component });
1174
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindSelect, isStandalone: true, selector: "tailwind-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
1175
+ {
1176
+ provide: NG_VALUE_ACCESSOR,
1177
+ useExisting: forwardRef(() => TailwindSelect),
1178
+ multi: true
1179
+ }
1180
+ ], viewQueries: [{ propertyName: "panelTemplate", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"text-sm font-medium text-surface-700\"\n [class.text-danger-600]=\"hasError()\">\n {{ label() }}\n </label>\n }\n\n <!-- Trigger button -->\n <button\n type=\"button\"\n [attr.id]=\"id() ? id() + '-inner' : null\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\n [disabled]=\"isDisabled()\"\n [class]=\"triggerClasses()\"\n (click)=\"toggleDropdown()\"\n (keydown)=\"onKeydown($event)\">\n @if (multiple()) {\n <span class=\"flex flex-wrap gap-1 flex-1 min-w-0 mr-2\" [class.text-surface-400]=\"selectedOptions().length === 0\">\n @if (selectedOptions().length === 0) {\n {{ placeholder() }}\n } @else {\n @for (opt of selectedOptions(); track opt) {\n <span class=\"rounded-md bg-surface-100 px-2 py-0.5 text-sm text-surface-800\">{{ opt.label }}</span>\n }\n }\n </span>\n } @else {\n <span [class.text-surface-400]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\n }\n\n <svg\n class=\"shrink-0 ml-2 w-4 h-4 text-surface-400 transition-transform duration-150\"\n [class.rotate-180]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n\n @if (helperText() && !hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">{{ helperText() }}</p>\n }\n @if (errorText() && hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">{{ errorText() }}</p>\n }\n</div>\n\n<!-- Dropdown panel \u2014 rendered via CDK Overlay outside the component DOM -->\n<ng-template #panelTemplate>\n <ul\n role=\"listbox\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n class=\"w-full bg-white border border-surface-200 rounded-md shadow-lg py-1 max-h-60 overflow-auto\">\n @if (placeholder()) {\n <li role=\"option\" aria-disabled=\"true\" class=\"px-3 py-2 text-sm text-surface-400 cursor-default select-none\">\n {{ placeholder() }}\n </li>\n }\n @for (option of options(); track option.value; let i = $index) {\n <li\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled || null\"\n [class]=\"optionClasses(i, option)\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"!option.disabled && activeIndex.set(i)\">\n <span>{{ option.label }}</span>\n\n @if (isOptionSelected(option)) {\n <svg\n class=\"w-4 h-4 text-primary-600 shrink-0\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n </li>\n }\n </ul>\n</ng-template>\n", styles: [":host{display:block}\n"] });
1181
+ }
1182
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSelect, decorators: [{
1183
+ type: Component,
1184
+ args: [{ selector: 'tailwind-select', providers: [
1185
+ {
1186
+ provide: NG_VALUE_ACCESSOR,
1187
+ useExisting: forwardRef(() => TailwindSelect),
1188
+ multi: true
1189
+ }
1190
+ ], template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label\n [attr.for]=\"id() ? id() + '-inner' : null\"\n class=\"text-sm font-medium text-surface-700\"\n [class.text-danger-600]=\"hasError()\">\n {{ label() }}\n </label>\n }\n\n <!-- Trigger button -->\n <button\n type=\"button\"\n [attr.id]=\"id() ? id() + '-inner' : null\"\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-invalid]=\"hasError() || null\"\n [attr.aria-describedby]=\"(helperText() || errorText()) && id() ? id() + '-helper' : null\"\n [disabled]=\"isDisabled()\"\n [class]=\"triggerClasses()\"\n (click)=\"toggleDropdown()\"\n (keydown)=\"onKeydown($event)\">\n @if (multiple()) {\n <span class=\"flex flex-wrap gap-1 flex-1 min-w-0 mr-2\" [class.text-surface-400]=\"selectedOptions().length === 0\">\n @if (selectedOptions().length === 0) {\n {{ placeholder() }}\n } @else {\n @for (opt of selectedOptions(); track opt) {\n <span class=\"rounded-md bg-surface-100 px-2 py-0.5 text-sm text-surface-800\">{{ opt.label }}</span>\n }\n }\n </span>\n } @else {\n <span [class.text-surface-400]=\"!selectedOption()\">\n {{ selectedOption()?.label ?? placeholder() }}\n </span>\n }\n\n <svg\n class=\"shrink-0 ml-2 w-4 h-4 text-surface-400 transition-transform duration-150\"\n [class.rotate-180]=\"isOpen()\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n\n @if (helperText() && !hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-surface-500\">{{ helperText() }}</p>\n }\n @if (errorText() && hasError()) {\n <p [attr.id]=\"id() ? id() + '-helper' : null\" class=\"text-xs text-danger-600\">{{ errorText() }}</p>\n }\n</div>\n\n<!-- Dropdown panel \u2014 rendered via CDK Overlay outside the component DOM -->\n<ng-template #panelTemplate>\n <ul\n role=\"listbox\"\n [attr.aria-multiselectable]=\"multiple() ? true : null\"\n class=\"w-full bg-white border border-surface-200 rounded-md shadow-lg py-1 max-h-60 overflow-auto\">\n @if (placeholder()) {\n <li role=\"option\" aria-disabled=\"true\" class=\"px-3 py-2 text-sm text-surface-400 cursor-default select-none\">\n {{ placeholder() }}\n </li>\n }\n @for (option of options(); track option.value; let i = $index) {\n <li\n role=\"option\"\n [attr.aria-selected]=\"isOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled || null\"\n [class]=\"optionClasses(i, option)\"\n (click)=\"selectOption(option)\"\n (mouseenter)=\"!option.disabled && activeIndex.set(i)\">\n <span>{{ option.label }}</span>\n\n @if (isOptionSelected(option)) {\n <svg\n class=\"w-4 h-4 text-primary-600 shrink-0\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\">\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n </li>\n }\n </ul>\n</ng-template>\n", styles: [":host{display:block}\n"] }]
1191
+ }], propDecorators: { panelTemplate: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], errorText: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorText", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
1192
+
1193
+ class TailwindToggle extends TailwindComponent {
1194
+ /** Label text */
1195
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1196
+ /** Aria label for accessibility */
1197
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1198
+ /** Size variant */
1199
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1200
+ /** Two-way bound checked state */
1201
+ checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
1202
+ /** Internal disabled state */
1203
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
1204
+ /** Track (background) classes */
1205
+ trackClasses = computed(() => {
1206
+ const sizeMap = {
1207
+ xs: 'w-7 h-4',
1208
+ sm: 'w-8 h-5',
1209
+ md: 'w-11 h-6',
1210
+ lg: 'w-14 h-7',
1211
+ xl: 'w-16 h-8'
1212
+ };
1213
+ const base = [
1214
+ 'relative inline-flex shrink-0 rounded-full',
1215
+ 'border-2 border-transparent',
1216
+ 'transition-colors duration-200 ease-in-out',
1217
+ 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600',
1218
+ 'cursor-pointer disabled:cursor-not-allowed'
1219
+ ];
1220
+ const stateClass = this.checked() ? 'bg-primary-600' : 'bg-surface-300';
1221
+ return [...base, sizeMap[this.size()], stateClass].join(' ');
1222
+ }, ...(ngDevMode ? [{ debugName: "trackClasses" }] : /* istanbul ignore next */ []));
1223
+ /** Thumb (knob) classes */
1224
+ thumbClasses = computed(() => {
1225
+ const sizeMap = {
1226
+ xs: { thumb: 'w-3 h-3', translateOn: 'translate-x-3' },
1227
+ sm: { thumb: 'w-4 h-4', translateOn: 'translate-x-3' },
1228
+ md: { thumb: 'w-5 h-5', translateOn: 'translate-x-5' },
1229
+ lg: { thumb: 'w-6 h-6', translateOn: 'translate-x-7' },
1230
+ xl: { thumb: 'w-7 h-7', translateOn: 'translate-x-8' }
1231
+ };
1232
+ const config = sizeMap[this.size()];
1233
+ const base = [
1234
+ 'pointer-events-none inline-block rounded-full',
1235
+ 'bg-white shadow-md',
1236
+ 'transform transition-transform duration-200 ease-in-out'
1237
+ ];
1238
+ const translateClass = this.checked() ? config.translateOn : 'translate-x-0';
1239
+ return [...base, config.thumb, translateClass].join(' ');
1240
+ }, ...(ngDevMode ? [{ debugName: "thumbClasses" }] : /* istanbul ignore next */ []));
1241
+ // CVA
1242
+ onChange = () => { };
1243
+ onTouched = () => { };
1244
+ writeValue(value) {
1245
+ this.checked.set(!!value);
1246
+ }
1247
+ registerOnChange(fn) {
1248
+ this.onChange = fn;
1249
+ }
1250
+ registerOnTouched(fn) {
1251
+ this.onTouched = fn;
1252
+ }
1253
+ setDisabledState(disabled) {
1254
+ this.isDisabled.set(disabled);
1255
+ }
1256
+ toggle() {
1257
+ if (this.isDisabled())
1258
+ return;
1259
+ const newValue = !this.checked();
1260
+ this.checked.set(newValue);
1261
+ this.onChange(newValue);
1262
+ this.onTouched();
1263
+ }
1264
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToggle, deps: null, target: i0.ɵɵFactoryTarget.Component });
1265
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindToggle, isStandalone: true, selector: "tailwind-toggle", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, providers: [
1266
+ {
1267
+ provide: NG_VALUE_ACCESSOR,
1268
+ useExisting: forwardRef(() => TailwindToggle),
1269
+ multi: true
1270
+ }
1271
+ ], usesInheritance: true, ngImport: i0, template: "<label\n class=\"inline-flex items-center gap-3 cursor-pointer select-none\"\n [class.cursor-not-allowed]=\"isDisabled()\"\n [class.opacity-50]=\"isDisabled()\">\n <button\n type=\"button\"\n role=\"switch\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [disabled]=\"isDisabled()\"\n [class]=\"trackClasses()\"\n (click)=\"toggle()\">\n <span [class]=\"thumbClasses()\" aria-hidden=\"true\"></span>\n </button>\n\n @if (label()) {\n <span class=\"text-sm font-medium text-surface-800\">{{ label() }}</span>\n }\n</label>\n", styles: [":host{display:inline-block}\n"] });
1272
+ }
1273
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToggle, decorators: [{
1274
+ type: Component,
1275
+ args: [{ selector: 'tailwind-toggle', providers: [
1276
+ {
1277
+ provide: NG_VALUE_ACCESSOR,
1278
+ useExisting: forwardRef(() => TailwindToggle),
1279
+ multi: true
1280
+ }
1281
+ ], template: "<label\n class=\"inline-flex items-center gap-3 cursor-pointer select-none\"\n [class.cursor-not-allowed]=\"isDisabled()\"\n [class.opacity-50]=\"isDisabled()\">\n <button\n type=\"button\"\n role=\"switch\"\n [attr.aria-checked]=\"checked()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n [disabled]=\"isDisabled()\"\n [class]=\"trackClasses()\"\n (click)=\"toggle()\">\n <span [class]=\"thumbClasses()\" aria-hidden=\"true\"></span>\n </button>\n\n @if (label()) {\n <span class=\"text-sm font-medium text-surface-800\">{{ label() }}</span>\n }\n</label>\n", styles: [":host{display:inline-block}\n"] }]
1282
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }] } });
1283
+
1284
+ class TailwindBadge extends TailwindComponent {
1285
+ /** Color variant */
1286
+ variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1287
+ /** Size variant */
1288
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1289
+ /** Show a dot indicator */
1290
+ dot = input(false, ...(ngDevMode ? [{ debugName: "dot" }] : /* istanbul ignore next */ []));
1291
+ /** Shape variant */
1292
+ rounded = input(false, ...(ngDevMode ? [{ debugName: "rounded" }] : /* istanbul ignore next */ []));
1293
+ /** Accessible label */
1294
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1295
+ computedClasses = computed(() => {
1296
+ const base = ['inline-flex items-center gap-1 font-medium', 'leading-none'];
1297
+ const variantMap = {
1298
+ primary: 'bg-primary-100 text-primary-700',
1299
+ neutral: 'bg-surface-100 text-surface-700',
1300
+ success: 'bg-success-100 text-success-700',
1301
+ warning: 'bg-warning-100 text-warning-800',
1302
+ danger: 'bg-danger-100 text-danger-700',
1303
+ info: 'bg-info-100 text-info-700'
1304
+ };
1305
+ const sizeMap = {
1306
+ xs: 'text-[10px] px-1.5 py-0.5',
1307
+ sm: 'text-xs px-2 py-0.5',
1308
+ md: 'text-xs px-2.5 py-1',
1309
+ lg: 'text-sm px-3 py-1',
1310
+ xl: 'text-sm px-3.5 py-1.5'
1311
+ };
1312
+ const shape = this.rounded() ? 'rounded-full' : 'rounded-md';
1313
+ return [...base, variantMap[this.variant()] ?? variantMap['primary'], sizeMap[this.size()], shape].join(' ');
1314
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
1315
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindBadge, deps: null, target: i0.ɵɵFactoryTarget.Component });
1316
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindBadge, isStandalone: true, selector: "tailwind-badge", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, dot: { classPropertyName: "dot", publicName: "dot", isSignal: true, isRequired: false, transformFunction: null }, rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<span [class]=\"computedClasses()\" [attr.aria-label]=\"ariaLabel()\">\n @if (dot()) {\n <span class=\"w-1.5 h-1.5 rounded-full bg-current\"></span>\n }\n <ng-content />\n</span>\n", styles: [":host{display:inline-block}\n"] });
1317
+ }
1318
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindBadge, decorators: [{
1319
+ type: Component,
1320
+ args: [{ selector: 'tailwind-badge', template: "<span [class]=\"computedClasses()\" [attr.aria-label]=\"ariaLabel()\">\n @if (dot()) {\n <span class=\"w-1.5 h-1.5 rounded-full bg-current\"></span>\n }\n <ng-content />\n</span>\n", styles: [":host{display:inline-block}\n"] }]
1321
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], dot: [{ type: i0.Input, args: [{ isSignal: true, alias: "dot", required: false }] }], rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
1322
+
1323
+ class TailwindCard extends TailwindComponent {
1324
+ /** Whether the card has elevated shadow */
1325
+ elevated = input(false, ...(ngDevMode ? [{ debugName: "elevated" }] : /* istanbul ignore next */ []));
1326
+ /** Whether to show hover shadow effect */
1327
+ hoverable = input(false, ...(ngDevMode ? [{ debugName: "hoverable" }] : /* istanbul ignore next */ []));
1328
+ /** Whether to show header background */
1329
+ headerBg = input(false, ...(ngDevMode ? [{ debugName: "headerBg" }] : /* istanbul ignore next */ []));
1330
+ /** Whether the card has a header */
1331
+ hasHeader = input(true, ...(ngDevMode ? [{ debugName: "hasHeader" }] : /* istanbul ignore next */ []));
1332
+ /** Whether the card has a footer */
1333
+ hasFooter = input(true, ...(ngDevMode ? [{ debugName: "hasFooter" }] : /* istanbul ignore next */ []));
1334
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindCard, deps: null, target: i0.ɵɵFactoryTarget.Component });
1335
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindCard, isStandalone: true, selector: "tailwind-card", inputs: { elevated: { classPropertyName: "elevated", publicName: "elevated", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, headerBg: { classPropertyName: "headerBg", publicName: "headerBg", isSignal: true, isRequired: false, transformFunction: null }, hasHeader: { classPropertyName: "hasHeader", publicName: "hasHeader", isSignal: true, isRequired: false, transformFunction: null }, hasFooter: { classPropertyName: "hasFooter", publicName: "hasFooter", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div\n class=\"bg-white rounded-xl border border-surface-200 overflow-hidden transition-shadow duration-200\"\n [class.shadow-sm]=\"!elevated()\"\n [class.shadow-lg]=\"elevated()\"\n [class.hover:shadow-md]=\"hoverable() && !elevated()\"\n [class.hover:shadow-xl]=\"hoverable() && elevated()\">\n @if (hasHeader()) {\n <!-- Header slot (always rendered; only visible when content is projected) -->\n <div class=\"px-6 py-4 border-b border-surface-100\" [class.bg-surface-50]=\"headerBg()\">\n <ng-content select=\"tailwind-card-header\" />\n </div>\n }\n\n <!-- Image slot -->\n <ng-content select=\"tailwind-card-image\" />\n\n <!-- Body -->\n <div class=\"p-6\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <!-- Footer slot -->\n <div class=\"px-6 py-4 border-t border-surface-100 bg-surface-50/50\">\n <ng-content select=\"tailwind-card-footer\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}\n"] });
1336
+ }
1337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindCard, decorators: [{
1338
+ type: Component,
1339
+ args: [{ selector: 'tailwind-card', template: "<div\n class=\"bg-white rounded-xl border border-surface-200 overflow-hidden transition-shadow duration-200\"\n [class.shadow-sm]=\"!elevated()\"\n [class.shadow-lg]=\"elevated()\"\n [class.hover:shadow-md]=\"hoverable() && !elevated()\"\n [class.hover:shadow-xl]=\"hoverable() && elevated()\">\n @if (hasHeader()) {\n <!-- Header slot (always rendered; only visible when content is projected) -->\n <div class=\"px-6 py-4 border-b border-surface-100\" [class.bg-surface-50]=\"headerBg()\">\n <ng-content select=\"tailwind-card-header\" />\n </div>\n }\n\n <!-- Image slot -->\n <ng-content select=\"tailwind-card-image\" />\n\n <!-- Body -->\n <div class=\"p-6\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <!-- Footer slot -->\n <div class=\"px-6 py-4 border-t border-surface-100 bg-surface-50/50\">\n <ng-content select=\"tailwind-card-footer\" />\n </div>\n }\n</div>\n", styles: [":host{display:block}\n"] }]
1340
+ }], propDecorators: { elevated: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevated", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], headerBg: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerBg", required: false }] }], hasHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasHeader", required: false }] }], hasFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasFooter", required: false }] }] } });
1341
+
1342
+ class TailwindAlert extends TailwindComponent {
1343
+ /** Severity / color variant */
1344
+ severity = input('info', ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
1345
+ /** Alert title */
1346
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
1347
+ /** Alert message */
1348
+ message = input('', ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
1349
+ /** Whether the alert can be dismissed */
1350
+ dismissible = input(false, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
1351
+ /** Whether to show a border on the left */
1352
+ bordered = input(true, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
1353
+ /** Emitted when the alert is dismissed */
1354
+ onDismiss = output();
1355
+ /** Internal dismissed state */
1356
+ dismissed = signal(false, ...(ngDevMode ? [{ debugName: "dismissed" }] : /* istanbul ignore next */ []));
1357
+ computedClasses = computed(() => {
1358
+ const base = 'flex gap-3 p-4 rounded-lg';
1359
+ const variantMap = {
1360
+ success: 'bg-success-50 text-success-800 border-success-200',
1361
+ warning: 'bg-warning-50 text-warning-800 border-warning-200',
1362
+ danger: 'bg-danger-50 text-danger-800 border-danger-200',
1363
+ info: 'bg-info-50 text-info-800 border-info-200'
1364
+ };
1365
+ const borderClass = this.bordered() ? 'border-l-4' : 'border';
1366
+ return `${base} ${variantMap[this.severity()]} ${borderClass}`;
1367
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
1368
+ dismiss() {
1369
+ this.dismissed.set(true);
1370
+ this.onDismiss.emit();
1371
+ }
1372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindAlert, deps: null, target: i0.ɵɵFactoryTarget.Component });
1373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindAlert, isStandalone: true, selector: "tailwind-alert", inputs: { severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onDismiss: "onDismiss" }, usesInheritance: true, ngImport: i0, template: "@if (!dismissed()) {\n <div [class]=\"computedClasses()\" role=\"alert\" [attr.aria-live]=\"severity() === 'danger' ? 'assertive' : 'polite'\">\n <!-- Icon -->\n <div class=\"shrink-0 mt-0.5\">\n @switch (severity()) {\n @case ('success') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('warning') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 6a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 6zm0 9a1 1 0 100-2 1 1 0 000 2z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('danger') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('info') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n }\n </div>\n\n <!-- Content -->\n <div class=\"flex-1 min-w-0\">\n @if (title()) {\n <h3 class=\"text-sm font-semibold mb-0.5\">{{ title() }}</h3>\n }\n <div class=\"text-sm\">\n {{ message() }}\n </div>\n </div>\n\n <!-- Dismiss button -->\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"shrink-0 -m-1 p-1 rounded-md opacity-70 hover:opacity-100 transition-opacity focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 cursor-pointer\"\n [attr.aria-label]=\"'Dismiss alert'\"\n (click)=\"dismiss()\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\n </svg>\n </button>\n }\n </div>\n}\n", styles: [":host{display:block}\n"] });
1374
+ }
1375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindAlert, decorators: [{
1376
+ type: Component,
1377
+ args: [{ selector: 'tailwind-alert', template: "@if (!dismissed()) {\n <div [class]=\"computedClasses()\" role=\"alert\" [attr.aria-live]=\"severity() === 'danger' ? 'assertive' : 'polite'\">\n <!-- Icon -->\n <div class=\"shrink-0 mt-0.5\">\n @switch (severity()) {\n @case ('success') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('warning') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 6a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 6zm0 9a1 1 0 100-2 1 1 0 000 2z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('danger') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n @case ('info') {\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z\"\n clip-rule=\"evenodd\" />\n </svg>\n }\n }\n </div>\n\n <!-- Content -->\n <div class=\"flex-1 min-w-0\">\n @if (title()) {\n <h3 class=\"text-sm font-semibold mb-0.5\">{{ title() }}</h3>\n }\n <div class=\"text-sm\">\n {{ message() }}\n </div>\n </div>\n\n <!-- Dismiss button -->\n @if (dismissible()) {\n <button\n type=\"button\"\n class=\"shrink-0 -m-1 p-1 rounded-md opacity-70 hover:opacity-100 transition-opacity focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 cursor-pointer\"\n [attr.aria-label]=\"'Dismiss alert'\"\n (click)=\"dismiss()\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\n </svg>\n </button>\n }\n </div>\n}\n", styles: [":host{display:block}\n"] }]
1378
+ }], propDecorators: { severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], onDismiss: [{ type: i0.Output, args: ["onDismiss"] }] } });
1379
+
1380
+ class TailwindSpinner extends TailwindComponent {
1381
+ /** Size variant */
1382
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1383
+ /** Color uses Tailwind text color class */
1384
+ color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
1385
+ /** Optional label text */
1386
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1387
+ /** Aria label for accessibility */
1388
+ ariaLabel = input('Loading', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1389
+ /** Layout orientation */
1390
+ orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
1391
+ containerClasses = computed(() => {
1392
+ const base = 'inline-flex items-center gap-2';
1393
+ const orient = this.orientation() === 'vertical' ? 'flex-col' : '';
1394
+ return `${base} ${orient}`;
1395
+ }, ...(ngDevMode ? [{ debugName: "containerClasses" }] : /* istanbul ignore next */ []));
1396
+ spinnerClasses = computed(() => {
1397
+ const sizeMap = {
1398
+ xs: 'w-3 h-3',
1399
+ sm: 'w-4 h-4',
1400
+ md: 'w-6 h-6',
1401
+ lg: 'w-8 h-8',
1402
+ xl: 'w-12 h-12'
1403
+ };
1404
+ const colorMap = {
1405
+ primary: 'text-primary-600',
1406
+ secondary: 'text-secondary-600',
1407
+ success: 'text-success-600',
1408
+ warning: 'text-warning-600',
1409
+ danger: 'text-danger-600',
1410
+ info: 'text-info-600'
1411
+ };
1412
+ return `tailwind-spinner-svg ${sizeMap[this.size()]} ${colorMap[this.color()]}`;
1413
+ }, ...(ngDevMode ? [{ debugName: "spinnerClasses" }] : /* istanbul ignore next */ []));
1414
+ labelClasses = computed(() => {
1415
+ const sizeMap = {
1416
+ xs: 'text-xs',
1417
+ sm: 'text-xs',
1418
+ md: 'text-sm',
1419
+ lg: 'text-base',
1420
+ xl: 'text-lg'
1421
+ };
1422
+ return `${sizeMap[this.size()]} ${this.color()} font-medium`;
1423
+ }, ...(ngDevMode ? [{ debugName: "labelClasses" }] : /* istanbul ignore next */ []));
1424
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSpinner, deps: null, target: i0.ɵɵFactoryTarget.Component });
1425
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindSpinner, isStandalone: true, selector: "tailwind-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div [class]=\"containerClasses()\" role=\"status\" [attr.aria-label]=\"ariaLabel()\">\n <svg [class]=\"spinnerClasses()\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-20\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\" />\n <path\n class=\"opacity-80\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n\n @if (label()) {\n <span [class]=\"labelClasses()\">{{ label() }}</span>\n }\n</div>\n", styles: [":host{display:inline-flex}@keyframes tailwind-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.tailwind-spinner-svg{animation:tailwind-spin .75s linear infinite}\n"] });
1426
+ }
1427
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSpinner, decorators: [{
1428
+ type: Component,
1429
+ args: [{ selector: 'tailwind-spinner', template: "<div [class]=\"containerClasses()\" role=\"status\" [attr.aria-label]=\"ariaLabel()\">\n <svg [class]=\"spinnerClasses()\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-20\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\" />\n <path\n class=\"opacity-80\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\" />\n </svg>\n\n @if (label()) {\n <span [class]=\"labelClasses()\">{{ label() }}</span>\n }\n</div>\n", styles: [":host{display:inline-flex}@keyframes tailwind-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.tailwind-spinner-svg{animation:tailwind-spin .75s linear infinite}\n"] }]
1430
+ }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
1431
+
1432
+ class TailwindModal extends TailwindComponent {
1433
+ /** Size variant */
1434
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1435
+ /** Whether to show close button in header */
1436
+ showCloseButton = input(true, ...(ngDevMode ? [{ debugName: "showCloseButton" }] : /* istanbul ignore next */ []));
1437
+ /** Whether clicking backdrop closes the modal */
1438
+ closeOnBackdrop = input(true, ...(ngDevMode ? [{ debugName: "closeOnBackdrop" }] : /* istanbul ignore next */ []));
1439
+ /** Whether pressing Escape closes the modal */
1440
+ closeOnEscape = input(true, ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : /* istanbul ignore next */ []));
1441
+ /** Open/close state */
1442
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1443
+ /** Visibility for animation */
1444
+ isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
1445
+ /** Emitted when the modal is fully closed (after exit animation) */
1446
+ onClose = output();
1447
+ modalPanel = viewChild('modalPanel', ...(ngDevMode ? [{ debugName: "modalPanel" }] : /* istanbul ignore next */ []));
1448
+ panelClasses = computed(() => {
1449
+ const base = ['relative bg-white rounded-xl shadow-2xl', 'w-full transform transition-all duration-200'];
1450
+ const sizeMap = {
1451
+ xs: 'max-w-sm',
1452
+ sm: 'max-w-md',
1453
+ md: 'max-w-lg',
1454
+ lg: 'max-w-2xl',
1455
+ xl: 'max-w-4xl'
1456
+ };
1457
+ const animation = this.isVisible() ? 'opacity-100 scale-100' : 'opacity-0 scale-95';
1458
+ return [...base, sizeMap[this.size()], animation].join(' ');
1459
+ }, ...(ngDevMode ? [{ debugName: "panelClasses" }] : /* istanbul ignore next */ []));
1460
+ constructor() {
1461
+ super();
1462
+ effect(() => {
1463
+ if (this.isOpen()) {
1464
+ requestAnimationFrame(() => {
1465
+ this.isVisible.set(true);
1466
+ this.modalPanel()?.nativeElement?.focus();
1467
+ });
1468
+ }
1469
+ });
1470
+ }
1471
+ /** Open the modal */
1472
+ open() {
1473
+ this.isOpen.set(true);
1474
+ }
1475
+ /** Close the modal (plays exit animation then emits onClose) */
1476
+ close() {
1477
+ this.isVisible.set(false);
1478
+ setTimeout(() => {
1479
+ this.isOpen.set(false);
1480
+ this.onClose.emit();
1481
+ }, 200);
1482
+ }
1483
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
1484
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindModal, isStandalone: true, selector: "tailwind-modal", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showCloseButton: { classPropertyName: "showCloseButton", publicName: "showCloseButton", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClose: "onClose" }, viewQueries: [{ propertyName: "modalPanel", first: true, predicate: ["modalPanel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (isOpen()) {\r\n <!-- Backdrop -->\r\n <div\r\n class=\"fixed inset-0 bg-black/50 backdrop-blur-sm z-1040 transition-opacity duration-200\"\r\n [class.opacity-100]=\"isVisible()\"\r\n [class.opacity-0]=\"!isVisible()\"\r\n (click)=\"closeOnBackdrop() && close()\"\r\n aria-hidden=\"true\"></div>\r\n\r\n <!-- Modal -->\r\n <div\r\n class=\"fixed inset-0 z-1050 overflow-y-auto\"\r\n role=\"dialog\"\r\n [attr.aria-modal]=\"true\"\r\n (keydown.escape)=\"closeOnEscape() && close()\">\r\n <div class=\"flex min-h-full items-center justify-center p-4\">\r\n <div #modalPanel [class]=\"panelClasses()\" tabindex=\"-1\">\r\n\r\n <!-- Header -->\r\n <div class=\"flex items-center justify-between px-6 py-4 border-b border-surface-200\">\r\n <h2 class=\"text-lg font-semibold text-surface-900 pr-2\">\r\n <ng-content />\r\n </h2>\r\n @if (showCloseButton()) {\r\n <button\r\n type=\"button\"\r\n class=\"p-1.5 -m-1.5 shrink-0 rounded-lg text-surface-400 hover:text-surface-600 hover:bg-surface-100 transition-colors cursor-pointer\"\r\n aria-label=\"Close\"\r\n (click)=\"close()\">\r\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- Body -->\r\n <ng-content select=\"tailwind-modal-content\" />\r\n\r\n <!-- Footer -->\r\n <ng-content select=\"tailwind-modal-footer\" />\r\n\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}\n"] });
1485
+ }
1486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModal, decorators: [{
1487
+ type: Component,
1488
+ args: [{ selector: 'tailwind-modal', template: "@if (isOpen()) {\r\n <!-- Backdrop -->\r\n <div\r\n class=\"fixed inset-0 bg-black/50 backdrop-blur-sm z-1040 transition-opacity duration-200\"\r\n [class.opacity-100]=\"isVisible()\"\r\n [class.opacity-0]=\"!isVisible()\"\r\n (click)=\"closeOnBackdrop() && close()\"\r\n aria-hidden=\"true\"></div>\r\n\r\n <!-- Modal -->\r\n <div\r\n class=\"fixed inset-0 z-1050 overflow-y-auto\"\r\n role=\"dialog\"\r\n [attr.aria-modal]=\"true\"\r\n (keydown.escape)=\"closeOnEscape() && close()\">\r\n <div class=\"flex min-h-full items-center justify-center p-4\">\r\n <div #modalPanel [class]=\"panelClasses()\" tabindex=\"-1\">\r\n\r\n <!-- Header -->\r\n <div class=\"flex items-center justify-between px-6 py-4 border-b border-surface-200\">\r\n <h2 class=\"text-lg font-semibold text-surface-900 pr-2\">\r\n <ng-content />\r\n </h2>\r\n @if (showCloseButton()) {\r\n <button\r\n type=\"button\"\r\n class=\"p-1.5 -m-1.5 shrink-0 rounded-lg text-surface-400 hover:text-surface-600 hover:bg-surface-100 transition-colors cursor-pointer\"\r\n aria-label=\"Close\"\r\n (click)=\"close()\">\r\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n\r\n <!-- Body -->\r\n <ng-content select=\"tailwind-modal-content\" />\r\n\r\n <!-- Footer -->\r\n <ng-content select=\"tailwind-modal-footer\" />\r\n\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}\n"] }]
1489
+ }], ctorParameters: () => [], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], onClose: [{ type: i0.Output, args: ["onClose"] }], modalPanel: [{ type: i0.ViewChild, args: ['modalPanel', { isSignal: true }] }] } });
1490
+
1491
+ /**
1492
+ * Transparent wrapper — the visual header structure is provided by TailwindModal.
1493
+ * Use inside a programmatically-opened component to supply the modal title.
1494
+ */
1495
+ class TailwindModalTitle {
1496
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalTitle, deps: [], target: i0.ɵɵFactoryTarget.Component });
1497
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: TailwindModalTitle, isStandalone: true, selector: "tailwind-modal-title", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:contents}\n"] });
1498
+ }
1499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalTitle, decorators: [{
1500
+ type: Component,
1501
+ args: [{ selector: 'tailwind-modal-title', template: `<ng-content />`, styles: [":host{display:contents}\n"] }]
1502
+ }] });
1503
+
1504
+ class TailwindModalContent {
1505
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalContent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1506
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: TailwindModalContent, isStandalone: true, selector: "tailwind-modal-content", ngImport: i0, template: `
1507
+ <div class="px-6 py-5">
1508
+ <ng-content />
1509
+ </div>
1510
+ `, isInline: true });
1511
+ }
1512
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalContent, decorators: [{
1513
+ type: Component,
1514
+ args: [{
1515
+ selector: 'tailwind-modal-content',
1516
+ template: `
1517
+ <div class="px-6 py-5">
1518
+ <ng-content />
1519
+ </div>
1520
+ `
1521
+ }]
1522
+ }] });
1523
+
1524
+ class TailwindModalFooter {
1525
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalFooter, deps: [], target: i0.ɵɵFactoryTarget.Component });
1526
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.12", type: TailwindModalFooter, isStandalone: true, selector: "tailwind-modal-footer", ngImport: i0, template: `
1527
+ <div class="px-6 py-4 border-t border-surface-100 bg-surface-50/50 rounded-b-xl">
1528
+ <ng-content />
1529
+ </div>
1530
+ `, isInline: true });
1531
+ }
1532
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalFooter, decorators: [{
1533
+ type: Component,
1534
+ args: [{
1535
+ selector: 'tailwind-modal-footer',
1536
+ template: `
1537
+ <div class="px-6 py-4 border-t border-surface-100 bg-surface-50/50 rounded-b-xl">
1538
+ <ng-content />
1539
+ </div>
1540
+ `
1541
+ }]
1542
+ }] });
1543
+
1544
+ class TailwindTab extends TailwindComponent {
1545
+ /** Tab label */
1546
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1547
+ /** Tab icon (optional, CSS class or content) */
1548
+ icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
1549
+ /** Whether the tab is disabled */
1550
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
1551
+ /** Whether this tab is the currently active one (set by parent) */
1552
+ isActive = signal(false, ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
1553
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTab, deps: null, target: i0.ɵɵFactoryTarget.Component });
1554
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindTab, isStandalone: true, selector: "tailwind-tab", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (isActive()) {\n <div role=\"tabpanel\" [attr.aria-labelledby]=\"id() ? 'tab-' + id() : null\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}\n"] });
1555
+ }
1556
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTab, decorators: [{
1557
+ type: Component,
1558
+ args: [{ selector: 'tailwind-tab', template: "@if (isActive()) {\n <div role=\"tabpanel\" [attr.aria-labelledby]=\"id() ? 'tab-' + id() : null\">\n <ng-content />\n </div>\n}\n", styles: [":host{display:block}\n"] }]
1559
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
1560
+
1561
+ class TailwindTabGroup extends TailwindComponent {
1562
+ /** Accessible label for the tab list */
1563
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1564
+ /** Whether tabs can scroll horizontally */
1565
+ scrollable = input(false, ...(ngDevMode ? [{ debugName: "scrollable" }] : /* istanbul ignore next */ []));
1566
+ /** Currently active tab index (two-way) */
1567
+ activeIndex = model(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
1568
+ /** Query all child TailwindTab components */
1569
+ tabs = contentChildren(TailwindTab, ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
1570
+ constructor() {
1571
+ super();
1572
+ effect(() => {
1573
+ const allTabs = this.tabs();
1574
+ const idx = this.activeIndex();
1575
+ allTabs.forEach((tab, i) => tab.isActive.set(i === idx));
1576
+ });
1577
+ }
1578
+ selectTab(index) {
1579
+ this.activeIndex.set(index);
1580
+ }
1581
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTabGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
1582
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindTabGroup, isStandalone: true, selector: "tailwind-tab-group", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, scrollable: { classPropertyName: "scrollable", publicName: "scrollable", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, queries: [{ propertyName: "tabs", predicate: TailwindTab, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Tab Headers -->\n<div class=\"border-b border-surface-200\" role=\"tablist\" [attr.aria-label]=\"ariaLabel()\">\n <nav class=\"flex -mb-px gap-1\" [class.overflow-x-auto]=\"scrollable()\">\n @for (tab of tabs(); track $index; let i = $index) {\n <button\n type=\"button\"\n role=\"tab\"\n [attr.id]=\"tab.id() ? 'tab-' + tab.id() : null\"\n [attr.aria-selected]=\"activeIndex() === i\"\n [attr.aria-controls]=\"tab.id() ? tab.id() : null\"\n [disabled]=\"tab.disabled()\"\n class=\"group relative px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-colors duration-150 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/30 focus-visible:rounded-t-lg\"\n [class.text-primary-600]=\"activeIndex() === i\"\n [class.text-surface-500]=\"activeIndex() !== i\"\n [class.hover:text-surface-700]=\"activeIndex() !== i && !tab.disabled()\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.cursor-not-allowed]=\"tab.disabled()\"\n (click)=\"!tab.disabled() && selectTab(i)\">\n {{ tab.label() }}\n <!-- Active indicator -->\n <span\n class=\"absolute bottom-0 left-0 right-0 h-0.5 rounded-full transition-all duration-200\"\n [class.bg-primary-600]=\"activeIndex() === i\"\n [class.scale-x-100]=\"activeIndex() === i\"\n [class.scale-x-0]=\"activeIndex() !== i\"></span>\n </button>\n }\n </nav>\n</div>\n\n<!-- Tab Content -->\n<div class=\"pt-4\">\n <ng-content />\n</div>\n", styles: [":host{display:block}\n"] });
1583
+ }
1584
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTabGroup, decorators: [{
1585
+ type: Component,
1586
+ args: [{ selector: 'tailwind-tab-group', template: "<!-- Tab Headers -->\n<div class=\"border-b border-surface-200\" role=\"tablist\" [attr.aria-label]=\"ariaLabel()\">\n <nav class=\"flex -mb-px gap-1\" [class.overflow-x-auto]=\"scrollable()\">\n @for (tab of tabs(); track $index; let i = $index) {\n <button\n type=\"button\"\n role=\"tab\"\n [attr.id]=\"tab.id() ? 'tab-' + tab.id() : null\"\n [attr.aria-selected]=\"activeIndex() === i\"\n [attr.aria-controls]=\"tab.id() ? tab.id() : null\"\n [disabled]=\"tab.disabled()\"\n class=\"group relative px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-colors duration-150 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/30 focus-visible:rounded-t-lg\"\n [class.text-primary-600]=\"activeIndex() === i\"\n [class.text-surface-500]=\"activeIndex() !== i\"\n [class.hover:text-surface-700]=\"activeIndex() !== i && !tab.disabled()\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.cursor-not-allowed]=\"tab.disabled()\"\n (click)=\"!tab.disabled() && selectTab(i)\">\n {{ tab.label() }}\n <!-- Active indicator -->\n <span\n class=\"absolute bottom-0 left-0 right-0 h-0.5 rounded-full transition-all duration-200\"\n [class.bg-primary-600]=\"activeIndex() === i\"\n [class.scale-x-100]=\"activeIndex() === i\"\n [class.scale-x-0]=\"activeIndex() !== i\"></span>\n </button>\n }\n </nav>\n</div>\n\n<!-- Tab Content -->\n<div class=\"pt-4\">\n <ng-content />\n</div>\n", styles: [":host{display:block}\n"] }]
1587
+ }], ctorParameters: () => [], propDecorators: { ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], scrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollable", required: false }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TailwindTab), { isSignal: true }] }] } });
1588
+
1589
+ class TailwindProgressBar extends TailwindComponent {
1590
+ /** Current value (0-100) */
1591
+ value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1592
+ /** Label text */
1593
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1594
+ /** Show the label row */
1595
+ showLabel = input(true, ...(ngDevMode ? [{ debugName: "showLabel" }] : /* istanbul ignore next */ []));
1596
+ /** Show percentage value */
1597
+ showValue = input(true, ...(ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []));
1598
+ /** Color variant */
1599
+ variant = input('primary', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1600
+ /** Size variant */
1601
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1602
+ /** Indeterminate mode (animated) */
1603
+ indeterminate = input(false, ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
1604
+ /** Whether to use striped pattern */
1605
+ striped = input(false, ...(ngDevMode ? [{ debugName: "striped" }] : /* istanbul ignore next */ []));
1606
+ clampedValue = computed(() => Math.max(0, Math.min(100, this.value())), ...(ngDevMode ? [{ debugName: "clampedValue" }] : /* istanbul ignore next */ []));
1607
+ trackClasses = computed(() => {
1608
+ const sizeMap = {
1609
+ xs: 'h-1',
1610
+ sm: 'h-1.5',
1611
+ md: 'h-2.5',
1612
+ lg: 'h-4',
1613
+ xl: 'h-5'
1614
+ };
1615
+ return `w-full bg-surface-200 rounded-full overflow-hidden ${sizeMap[this.size()]}`;
1616
+ }, ...(ngDevMode ? [{ debugName: "trackClasses" }] : /* istanbul ignore next */ []));
1617
+ barClasses = computed(() => {
1618
+ const variantMap = {
1619
+ primary: 'bg-primary-600',
1620
+ success: 'bg-success-600',
1621
+ warning: 'bg-warning-500',
1622
+ danger: 'bg-danger-600',
1623
+ info: 'bg-info-600'
1624
+ };
1625
+ const base = [
1626
+ 'h-full rounded-full transition-all duration-300 ease-out',
1627
+ variantMap[this.variant()] ?? variantMap['primary']
1628
+ ];
1629
+ if (this.indeterminate()) {
1630
+ base.push('tailwind-progress-indeterminate');
1631
+ }
1632
+ if (this.striped()) {
1633
+ base.push('bg-gradient-to-r from-transparent via-white/20 to-transparent bg-[length:1rem_100%]');
1634
+ }
1635
+ return base.join(' ');
1636
+ }, ...(ngDevMode ? [{ debugName: "barClasses" }] : /* istanbul ignore next */ []));
1637
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindProgressBar, deps: null, target: i0.ɵɵFactoryTarget.Component });
1638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindProgressBar, isStandalone: true, selector: "tailwind-progress-bar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showLabel: { classPropertyName: "showLabel", publicName: "showLabel", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, indeterminate: { classPropertyName: "indeterminate", publicName: "indeterminate", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"w-full\">\n @if (showLabel()) {\n <div class=\"flex justify-between items-center mb-1.5\">\n @if (label()) {\n <span class=\"text-sm font-medium text-surface-700\">{{ label() }}</span>\n }\n @if (showValue()) {\n <span class=\"text-sm font-medium text-surface-600\">{{ clampedValue() }}%</span>\n }\n </div>\n }\n\n <div\n [class]=\"trackClasses()\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"clampedValue()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"100\"\n [attr.aria-label]=\"label() || 'Progress'\">\n <div [class]=\"barClasses()\" [style.width.%]=\"indeterminate() ? 100 : clampedValue()\"></div>\n </div>\n</div>\n", styles: [":host{display:block}@keyframes tailwind-indeterminate{0%{transform:translate(-100%)}to{transform:translate(200%)}}.tailwind-progress-indeterminate{animation:tailwind-indeterminate 1.5s ease-in-out infinite;width:40%!important}\n"] });
1639
+ }
1640
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindProgressBar, decorators: [{
1641
+ type: Component,
1642
+ args: [{ selector: 'tailwind-progress-bar', template: "<div class=\"w-full\">\n @if (showLabel()) {\n <div class=\"flex justify-between items-center mb-1.5\">\n @if (label()) {\n <span class=\"text-sm font-medium text-surface-700\">{{ label() }}</span>\n }\n @if (showValue()) {\n <span class=\"text-sm font-medium text-surface-600\">{{ clampedValue() }}%</span>\n }\n </div>\n }\n\n <div\n [class]=\"trackClasses()\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"clampedValue()\"\n [attr.aria-valuemin]=\"0\"\n [attr.aria-valuemax]=\"100\"\n [attr.aria-label]=\"label() || 'Progress'\">\n <div [class]=\"barClasses()\" [style.width.%]=\"indeterminate() ? 100 : clampedValue()\"></div>\n </div>\n</div>\n", styles: [":host{display:block}@keyframes tailwind-indeterminate{0%{transform:translate(-100%)}to{transform:translate(200%)}}.tailwind-progress-indeterminate{animation:tailwind-indeterminate 1.5s ease-in-out infinite;width:40%!important}\n"] }]
1643
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }] } });
1644
+
1645
+ /** Matches previous `min-w-48` floor when the anchor is narrower. */
1646
+ const MIN_PANEL_WIDTH_PX = 192;
1647
+ class TailwindMenu extends TailwindComponent {
1648
+ openScheduleId;
1649
+ anchorEl = null;
1650
+ onScrollReposition = () => {
1651
+ if (this.isOpen()) {
1652
+ this.updatePanelPosition();
1653
+ }
1654
+ };
1655
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
1656
+ align = input('left', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
1657
+ onSelect = output();
1658
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1659
+ /** Popover box in coordinates relative to the `position: fixed` containing block (often viewport, not under transformed Docs wrappers). */
1660
+ panelLayout = signal(null, ...(ngDevMode ? [{ debugName: "panelLayout" }] : /* istanbul ignore next */ []));
1661
+ panelRef = viewChild('panel', ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
1662
+ ngOnInit() {
1663
+ document.addEventListener('scroll', this.onScrollReposition, true);
1664
+ }
1665
+ ngOnDestroy() {
1666
+ document.removeEventListener('scroll', this.onScrollReposition, true);
1667
+ if (this.openScheduleId != null) {
1668
+ clearTimeout(this.openScheduleId);
1669
+ }
1670
+ }
1671
+ /**
1672
+ * Opens the menu under `anchor` (toggle element).
1673
+ * Pass the click event from the button, e.g. `(click)="menu.open($event)"`, or an `HTMLElement`.
1674
+ * After the first open with an anchor, `open()` without arguments reuses the last anchor.
1675
+ *
1676
+ * Opening is deferred one macrotask so the same `click` is not closed immediately by `document:click`.
1677
+ */
1678
+ open(anchor) {
1679
+ if (anchor !== undefined) {
1680
+ this.storeAnchor(anchor);
1681
+ }
1682
+ if (!this.anchorEl) {
1683
+ return;
1684
+ }
1685
+ if (this.isOpen()) {
1686
+ return;
1687
+ }
1688
+ this.scheduleOpen();
1689
+ }
1690
+ close() {
1691
+ this.isOpen.set(false);
1692
+ this.panelLayout.set(null);
1693
+ }
1694
+ toggle(anchor) {
1695
+ if (this.isOpen()) {
1696
+ this.close();
1697
+ return;
1698
+ }
1699
+ if (anchor !== undefined) {
1700
+ this.storeAnchor(anchor);
1701
+ }
1702
+ if (!this.anchorEl) {
1703
+ return;
1704
+ }
1705
+ this.scheduleOpen();
1706
+ }
1707
+ storeAnchor(anchor) {
1708
+ if (anchor instanceof HTMLElement) {
1709
+ this.anchorEl = anchor;
1710
+ return;
1711
+ }
1712
+ const target = anchor.currentTarget;
1713
+ if (target instanceof HTMLElement) {
1714
+ this.anchorEl = target;
1715
+ }
1716
+ }
1717
+ scheduleOpen() {
1718
+ if (this.openScheduleId != null) {
1719
+ clearTimeout(this.openScheduleId);
1720
+ }
1721
+ this.openScheduleId = setTimeout(() => {
1722
+ this.openScheduleId = undefined;
1723
+ this.isOpen.set(true);
1724
+ this.updatePanelPosition();
1725
+ requestAnimationFrame(() => this.updatePanelPosition());
1726
+ }, 0);
1727
+ }
1728
+ updatePanelPosition() {
1729
+ const anchor = this.anchorEl;
1730
+ if (!anchor) {
1731
+ this.panelLayout.set(null);
1732
+ return;
1733
+ }
1734
+ const panelEl = this.panelRef()?.nativeElement;
1735
+ const cbRoot = panelEl
1736
+ ? this.getFixedPositioningContainingBlock(panelEl)
1737
+ : this.getFixedPositioningContainingBlock(anchor);
1738
+ const cbRect = cbRoot.getBoundingClientRect();
1739
+ const rect = anchor.getBoundingClientRect();
1740
+ const minWidth = Math.max(rect.width, MIN_PANEL_WIDTH_PX);
1741
+ const top = rect.bottom - cbRect.top;
1742
+ if (this.align() === 'right') {
1743
+ this.panelLayout.set({
1744
+ top,
1745
+ right: cbRect.right - rect.right,
1746
+ minWidth
1747
+ });
1748
+ }
1749
+ else {
1750
+ this.panelLayout.set({
1751
+ top,
1752
+ left: rect.left - cbRect.left,
1753
+ minWidth
1754
+ });
1755
+ }
1756
+ }
1757
+ selectItem(item) {
1758
+ if (!item.disabled) {
1759
+ this.onSelect.emit(item);
1760
+ this.close();
1761
+ }
1762
+ }
1763
+ onDocumentEscape() {
1764
+ if (!this.isOpen()) {
1765
+ return;
1766
+ }
1767
+ this.close();
1768
+ }
1769
+ onDocumentClick(event) {
1770
+ if (!this.isOpen()) {
1771
+ return;
1772
+ }
1773
+ const target = event.target;
1774
+ if (!target) {
1775
+ return;
1776
+ }
1777
+ const panelEl = this.panelRef()?.nativeElement;
1778
+ const inPanel = panelEl?.contains(target) ?? false;
1779
+ const inAnchor = this.anchorEl?.contains(target) ?? false;
1780
+ if (!inPanel && !inAnchor) {
1781
+ this.close();
1782
+ }
1783
+ }
1784
+ onWindowResize() {
1785
+ if (this.isOpen()) {
1786
+ this.updatePanelPosition();
1787
+ }
1788
+ }
1789
+ /** Ancestor that becomes the containing block for `position: fixed` (e.g. Storybook Docs wrappers with `transform`). */
1790
+ createsFixedContainingBlock(el) {
1791
+ const s = getComputedStyle(el);
1792
+ if (s.transform && s.transform !== 'none') {
1793
+ return true;
1794
+ }
1795
+ if (s.perspective && s.perspective !== 'none') {
1796
+ return true;
1797
+ }
1798
+ if (s.filter && s.filter !== 'none') {
1799
+ return true;
1800
+ }
1801
+ const contain = s.contain;
1802
+ if (contain && contain !== 'none' && contain.split(/\s+/).includes('paint')) {
1803
+ return true;
1804
+ }
1805
+ return false;
1806
+ }
1807
+ getFixedPositioningContainingBlock(from) {
1808
+ for (let p = from.parentElement; p; p = p.parentElement) {
1809
+ if (this.createsFixedContainingBlock(p)) {
1810
+ return p;
1811
+ }
1812
+ }
1813
+ return document.documentElement;
1814
+ }
1815
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindMenu, deps: null, target: i0.ɵɵFactoryTarget.Component });
1816
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindMenu, isStandalone: true, selector: "tailwind-menu", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { listeners: { "document:keydown.escape": "onDocumentEscape()", "document:click": "onDocumentClick($event)", "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (isOpen() && panelLayout(); as layout) {\n <div\n #panel\n role=\"menu\"\n class=\"fixed z-1000 bg-white rounded-xl border border-surface-200 shadow-lg py-1 animate-in fade-in slide-in-from-top-1\"\n [style.top.px]=\"layout.top\"\n [style.left.px]=\"layout.left ?? null\"\n [style.right.px]=\"layout.right ?? null\"\n [style.minWidth.px]=\"layout.minWidth\">\n @for (item of items(); track $index) {\n @if (item.divider) {\n <hr class=\"my-1 border-surface-100\" />\n } @else {\n <button\n type=\"button\"\n role=\"menuitem\"\n [disabled]=\"!!item.disabled\"\n class=\"w-full text-left px-4 py-2 text-sm text-surface-700 hover:bg-surface-50 hover:text-surface-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors cursor-pointer\"\n (click)=\"selectItem(item)\">\n {{ item.label }}\n </button>\n }\n }\n </div>\n}\n", styles: [":host{display:contents}\n"] });
1817
+ }
1818
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindMenu, decorators: [{
1819
+ type: Component,
1820
+ args: [{ selector: 'tailwind-menu', template: "@if (isOpen() && panelLayout(); as layout) {\n <div\n #panel\n role=\"menu\"\n class=\"fixed z-1000 bg-white rounded-xl border border-surface-200 shadow-lg py-1 animate-in fade-in slide-in-from-top-1\"\n [style.top.px]=\"layout.top\"\n [style.left.px]=\"layout.left ?? null\"\n [style.right.px]=\"layout.right ?? null\"\n [style.minWidth.px]=\"layout.minWidth\">\n @for (item of items(); track $index) {\n @if (item.divider) {\n <hr class=\"my-1 border-surface-100\" />\n } @else {\n <button\n type=\"button\"\n role=\"menuitem\"\n [disabled]=\"!!item.disabled\"\n class=\"w-full text-left px-4 py-2 text-sm text-surface-700 hover:bg-surface-50 hover:text-surface-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors cursor-pointer\"\n (click)=\"selectItem(item)\">\n {{ item.label }}\n </button>\n }\n }\n </div>\n}\n", styles: [":host{display:contents}\n"] }]
1821
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], onDocumentEscape: [{
1822
+ type: HostListener,
1823
+ args: ['document:keydown.escape']
1824
+ }], onDocumentClick: [{
1825
+ type: HostListener,
1826
+ args: ['document:click', ['$event']]
1827
+ }], onWindowResize: [{
1828
+ type: HostListener,
1829
+ args: ['window:resize']
1830
+ }] } });
1831
+
1832
+ class TailwindDrawer extends TailwindComponent {
1833
+ /** Drawer title */
1834
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
1835
+ /** Position (left or right) */
1836
+ position = input('right', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
1837
+ /** Width class */
1838
+ width = input('max-w-md', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
1839
+ /** Whether clicking backdrop closes */
1840
+ closeOnBackdrop = input(true, ...(ngDevMode ? [{ debugName: "closeOnBackdrop" }] : /* istanbul ignore next */ []));
1841
+ /** Open/close state */
1842
+ isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
1843
+ /** Visibility for animation */
1844
+ isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
1845
+ /** Emitted when closed */
1846
+ onClose = output();
1847
+ panelClasses = computed(() => {
1848
+ const base = [
1849
+ 'fixed top-0 bottom-0 z-[1050]',
1850
+ 'flex flex-col w-full bg-white shadow-2xl',
1851
+ 'transition-transform duration-300 ease-in-out',
1852
+ this.width()
1853
+ ];
1854
+ const pos = this.position();
1855
+ if (pos === 'right') {
1856
+ base.push('right-0');
1857
+ base.push(this.isVisible() ? 'translate-x-0' : 'translate-x-full');
1858
+ }
1859
+ else {
1860
+ base.push('left-0');
1861
+ base.push(this.isVisible() ? 'translate-x-0' : '-translate-x-full');
1862
+ }
1863
+ return base.join(' ');
1864
+ }, ...(ngDevMode ? [{ debugName: "panelClasses" }] : /* istanbul ignore next */ []));
1865
+ open() {
1866
+ this.isOpen.set(true);
1867
+ requestAnimationFrame(() => {
1868
+ this.isVisible.set(true);
1869
+ });
1870
+ }
1871
+ close() {
1872
+ this.isVisible.set(false);
1873
+ setTimeout(() => {
1874
+ this.isOpen.set(false);
1875
+ this.onClose.emit();
1876
+ }, 300);
1877
+ }
1878
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDrawer, deps: null, target: i0.ɵɵFactoryTarget.Component });
1879
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindDrawer, isStandalone: true, selector: "tailwind-drawer", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClose: "onClose" }, usesInheritance: true, ngImport: i0, template: "@if (isOpen()) {\n <!-- Backdrop -->\n <div\n class=\"fixed inset-0 bg-black/40 backdrop-blur-sm z-1040 transition-opacity duration-300\"\n [class.opacity-100]=\"isVisible()\"\n [class.opacity-0]=\"!isVisible()\"\n (click)=\"closeOnBackdrop() && close()\"\n aria-hidden=\"true\"></div>\n\n <!-- Drawer Panel -->\n <div [class]=\"panelClasses()\" role=\"dialog\" [attr.aria-modal]=\"true\" [attr.aria-label]=\"title()\">\n <!-- Header -->\n <div class=\"flex items-center justify-between px-6 py-4 border-b border-surface-200\">\n @if (title()) {\n <h2 class=\"text-lg font-semibold text-surface-900\">{{ title() }}</h2>\n }\n <button\n type=\"button\"\n class=\"p-1.5 -m-1.5 rounded-lg text-surface-400 hover:text-surface-600 hover:bg-surface-100 transition-colors ml-auto cursor-pointer\"\n aria-label=\"Close\"\n (click)=\"close()\">\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\n </svg>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"flex-1 overflow-y-auto px-6 py-5\">\n <ng-content />\n </div>\n\n <!-- Footer -->\n <ng-content select=\"tailwind-drawer-footer\" />\n </div>\n}\n", styles: [":host{display:contents}\n"] });
1880
+ }
1881
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDrawer, decorators: [{
1882
+ type: Component,
1883
+ args: [{ selector: 'tailwind-drawer', template: "@if (isOpen()) {\n <!-- Backdrop -->\n <div\n class=\"fixed inset-0 bg-black/40 backdrop-blur-sm z-1040 transition-opacity duration-300\"\n [class.opacity-100]=\"isVisible()\"\n [class.opacity-0]=\"!isVisible()\"\n (click)=\"closeOnBackdrop() && close()\"\n aria-hidden=\"true\"></div>\n\n <!-- Drawer Panel -->\n <div [class]=\"panelClasses()\" role=\"dialog\" [attr.aria-modal]=\"true\" [attr.aria-label]=\"title()\">\n <!-- Header -->\n <div class=\"flex items-center justify-between px-6 py-4 border-b border-surface-200\">\n @if (title()) {\n <h2 class=\"text-lg font-semibold text-surface-900\">{{ title() }}</h2>\n }\n <button\n type=\"button\"\n class=\"p-1.5 -m-1.5 rounded-lg text-surface-400 hover:text-surface-600 hover:bg-surface-100 transition-colors ml-auto cursor-pointer\"\n aria-label=\"Close\"\n (click)=\"close()\">\n <svg class=\"w-5 h-5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\n </svg>\n </button>\n </div>\n\n <!-- Body -->\n <div class=\"flex-1 overflow-y-auto px-6 py-5\">\n <ng-content />\n </div>\n\n <!-- Footer -->\n <ng-content select=\"tailwind-drawer-footer\" />\n </div>\n}\n", styles: [":host{display:contents}\n"] }]
1884
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], onClose: [{ type: i0.Output, args: ["onClose"] }] } });
1885
+
1886
+ class TailwindBreadcrumb extends TailwindComponent {
1887
+ items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
1888
+ ariaLabel = input('Breadcrumb', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1889
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindBreadcrumb, deps: null, target: i0.ɵɵFactoryTarget.Component });
1890
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindBreadcrumb, isStandalone: true, selector: "tailwind-breadcrumb", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"flex\">\n <ol class=\"inline-flex items-center gap-1.5 text-sm\">\n @for (item of items(); track item.label; let last = $last; let first = $first) {\n <li class=\"inline-flex items-center\">\n @if (!first) {\n <span class=\"mx-1.5 text-surface-400\" aria-hidden=\"true\">\n <svg class=\"w-3.5 h-3.5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @if (item.href && !last) {\n <a [href]=\"item.href\" class=\"text-surface-500 hover:text-primary-600 transition-colors font-medium\">{{\n item.label\n }}</a>\n } @else {\n <span\n class=\"font-medium\"\n [class.text-surface-900]=\"last\"\n [class.text-surface-500]=\"!last\"\n [attr.aria-current]=\"last ? 'page' : null\"\n >{{ item.label }}</span\n >\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block}\n"] });
1891
+ }
1892
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindBreadcrumb, decorators: [{
1893
+ type: Component,
1894
+ args: [{ selector: 'tailwind-breadcrumb', template: "<nav [attr.aria-label]=\"ariaLabel()\" class=\"flex\">\n <ol class=\"inline-flex items-center gap-1.5 text-sm\">\n @for (item of items(); track item.label; let last = $last; let first = $first) {\n <li class=\"inline-flex items-center\">\n @if (!first) {\n <span class=\"mx-1.5 text-surface-400\" aria-hidden=\"true\">\n <svg class=\"w-3.5 h-3.5\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @if (item.href && !last) {\n <a [href]=\"item.href\" class=\"text-surface-500 hover:text-primary-600 transition-colors font-medium\">{{\n item.label\n }}</a>\n } @else {\n <span\n class=\"font-medium\"\n [class.text-surface-900]=\"last\"\n [class.text-surface-500]=\"!last\"\n [attr.aria-current]=\"last ? 'page' : null\"\n >{{ item.label }}</span\n >\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [":host{display:block}\n"] }]
1895
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
1896
+
1897
+ class TailwindPagination extends TailwindComponent {
1898
+ totalItems = input.required(...(ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []));
1899
+ pageSize = input(10, ...(ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []));
1900
+ currentPage = model(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
1901
+ ariaLabel = input('Pagination', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
1902
+ summary = input('Showing {start}-{end} of {total}', ...(ngDevMode ? [{ debugName: "summary" }] : /* istanbul ignore next */ []));
1903
+ onPageChange = output();
1904
+ totalPages = computed(() => Math.ceil(this.totalItems() / this.pageSize()), ...(ngDevMode ? [{ debugName: "totalPages" }] : /* istanbul ignore next */ []));
1905
+ visiblePages = computed(() => {
1906
+ const total = this.totalPages();
1907
+ return Array.from({ length: total }, (_, i) => i + 1);
1908
+ }, ...(ngDevMode ? [{ debugName: "visiblePages" }] : /* istanbul ignore next */ []));
1909
+ summaryText = computed(() => {
1910
+ const total = this.totalItems();
1911
+ if (total === 0)
1912
+ return this.summary().replace('{start}', '0').replace('{end}', '0').replace('{total}', '0');
1913
+ const start = (this.currentPage() - 1) * this.pageSize() + 1;
1914
+ const end = Math.min(this.currentPage() * this.pageSize(), total);
1915
+ return this.summary()
1916
+ .replace('{start}', start.toString())
1917
+ .replace('{end}', end.toString())
1918
+ .replace('{total}', total.toString());
1919
+ }, ...(ngDevMode ? [{ debugName: "summaryText" }] : /* istanbul ignore next */ []));
1920
+ goToPage(page) {
1921
+ if (page >= 1 && page <= this.totalPages()) {
1922
+ this.currentPage.set(page);
1923
+ this.onPageChange.emit(page);
1924
+ }
1925
+ }
1926
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindPagination, deps: null, target: i0.ɵɵFactoryTarget.Component });
1927
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindPagination, isStandalone: true, selector: "tailwind-pagination", inputs: { totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: true, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, currentPage: { classPropertyName: "currentPage", publicName: "currentPage", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, summary: { classPropertyName: "summary", publicName: "summary", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { currentPage: "currentPageChange", onPageChange: "onPageChange" }, usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-wrap items-center justify-between gap-4 w-full\">\n @if (summary()) {\n <span class=\"text-sm text-surface-700 dark:text-surface-300\">\n {{ summaryText() }}\n </span>\n }\n\n <nav [attr.aria-label]=\"ariaLabel()\" class=\"flex items-center gap-1\">\n <!-- Previous -->\n <button\n type=\"button\"\n [disabled]=\"currentPage() <= 1\"\n (click)=\"goToPage(currentPage() - 1)\"\n class=\"p-2 rounded-lg text-surface-500 hover:bg-surface-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n\n @for (page of visiblePages(); track page) {\n <button\n type=\"button\"\n (click)=\"goToPage(page)\"\n class=\"min-w-8 h-8 px-2 rounded-lg text-sm font-medium transition-colors cursor-pointer\"\n [class.bg-primary-600]=\"page === currentPage()\"\n [class.text-white]=\"page === currentPage()\"\n [class.text-surface-600]=\"page !== currentPage()\"\n [class.hover:bg-surface-100]=\"page !== currentPage()\">\n {{ page }}\n </button>\n }\n\n <!-- Next -->\n <button\n type=\"button\"\n [disabled]=\"currentPage() >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n class=\"p-2 rounded-lg text-surface-500 hover:bg-surface-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n </nav>\n</div>\n", styles: [":host{display:block}\n"] });
1928
+ }
1929
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindPagination, decorators: [{
1930
+ type: Component,
1931
+ args: [{ selector: 'tailwind-pagination', template: "<div class=\"flex flex-wrap items-center justify-between gap-4 w-full\">\n @if (summary()) {\n <span class=\"text-sm text-surface-700 dark:text-surface-300\">\n {{ summaryText() }}\n </span>\n }\n\n <nav [attr.aria-label]=\"ariaLabel()\" class=\"flex items-center gap-1\">\n <!-- Previous -->\n <button\n type=\"button\"\n [disabled]=\"currentPage() <= 1\"\n (click)=\"goToPage(currentPage() - 1)\"\n class=\"p-2 rounded-lg text-surface-500 hover:bg-surface-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n\n @for (page of visiblePages(); track page) {\n <button\n type=\"button\"\n (click)=\"goToPage(page)\"\n class=\"min-w-8 h-8 px-2 rounded-lg text-sm font-medium transition-colors cursor-pointer\"\n [class.bg-primary-600]=\"page === currentPage()\"\n [class.text-white]=\"page === currentPage()\"\n [class.text-surface-600]=\"page !== currentPage()\"\n [class.hover:bg-surface-100]=\"page !== currentPage()\">\n {{ page }}\n </button>\n }\n\n <!-- Next -->\n <button\n type=\"button\"\n [disabled]=\"currentPage() >= totalPages()\"\n (click)=\"goToPage(currentPage() + 1)\"\n class=\"p-2 rounded-lg text-surface-500 hover:bg-surface-100 disabled:opacity-40 disabled:cursor-not-allowed transition-colors cursor-pointer\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n </nav>\n</div>\n", styles: [":host{display:block}\n"] }]
1932
+ }], propDecorators: { totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], summary: [{ type: i0.Input, args: [{ isSignal: true, alias: "summary", required: false }] }], onPageChange: [{ type: i0.Output, args: ["onPageChange"] }] } });
1933
+
1934
+ class TailwindTag extends TailwindComponent {
1935
+ variant = input('neutral', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
1936
+ computedClasses = computed(() => {
1937
+ const variantMap = {
1938
+ primary: 'bg-primary-600 text-white',
1939
+ neutral: 'bg-surface-600 text-white',
1940
+ success: 'bg-success-600 text-white',
1941
+ warning: 'bg-warning-500 text-surface-900',
1942
+ danger: 'bg-danger-600 text-white',
1943
+ info: 'bg-info-600 text-white'
1944
+ };
1945
+ return `inline-flex items-center text-[11px] font-semibold uppercase tracking-wider px-2 py-0.5 rounded ${variantMap[this.variant()]}`;
1946
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
1947
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTag, deps: null, target: i0.ɵɵFactoryTarget.Component });
1948
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: TailwindTag, isStandalone: true, selector: "tailwind-tag", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<span [class]=\"computedClasses()\"><ng-content /></span>\n", styles: [":host{display:inline-block}\n"] });
1949
+ }
1950
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTag, decorators: [{
1951
+ type: Component,
1952
+ args: [{ selector: 'tailwind-tag', template: "<span [class]=\"computedClasses()\"><ng-content /></span>\n", styles: [":host{display:inline-block}\n"] }]
1953
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }] } });
1954
+
1955
+ class TailwindTable extends TailwindComponent {
1956
+ columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
1957
+ data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
1958
+ selectable = input(false, ...(ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []));
1959
+ striped = input(false, ...(ngDevMode ? [{ debugName: "striped" }] : /* istanbul ignore next */ []));
1960
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
1961
+ emptyMessage = input('No data available', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
1962
+ // --- Pagination Inputs ---
1963
+ paginated = input(true, ...(ngDevMode ? [{ debugName: "paginated" }] : /* istanbul ignore next */ []));
1964
+ pagination = input(...(ngDevMode ? [undefined, { debugName: "pagination" }] : /* istanbul ignore next */ []));
1965
+ // --- Outputs ---
1966
+ onSortChange = output();
1967
+ onSelectionChange = output();
1968
+ // --- Internal State ---
1969
+ sortKey = signal('', ...(ngDevMode ? [{ debugName: "sortKey" }] : /* istanbul ignore next */ []));
1970
+ sortDir = signal('asc', ...(ngDevMode ? [{ debugName: "sortDir" }] : /* istanbul ignore next */ []));
1971
+ selectedRows = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedRows" }] : /* istanbul ignore next */ []));
1972
+ currentPage = signal(1, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
1973
+ constructor() {
1974
+ super();
1975
+ effect(() => {
1976
+ const fromInput = this.pagination()?.currentPage;
1977
+ if (fromInput != null && fromInput >= 1) {
1978
+ this.currentPage.set(fromInput);
1979
+ }
1980
+ });
1981
+ }
1982
+ // --- Computed ---
1983
+ sortedData = computed(() => {
1984
+ let rows = [...this.data()];
1985
+ const key = this.sortKey();
1986
+ if (key) {
1987
+ const dir = this.sortDir() === 'asc' ? 1 : -1;
1988
+ rows.sort((a, b) => {
1989
+ const va = a[key], vb = b[key];
1990
+ if (va < vb)
1991
+ return -dir;
1992
+ if (va > vb)
1993
+ return dir;
1994
+ return 0;
1995
+ });
1996
+ }
1997
+ return rows;
1998
+ }, ...(ngDevMode ? [{ debugName: "sortedData" }] : /* istanbul ignore next */ []));
1999
+ displayedData = computed(() => {
2000
+ const rows = this.sortedData();
2001
+ if (!this.paginated())
2002
+ return rows;
2003
+ const size = this.pagination()?.pageSize ?? 10;
2004
+ const page = this.currentPage();
2005
+ return rows.slice((page - 1) * size, page * size);
2006
+ }, ...(ngDevMode ? [{ debugName: "displayedData" }] : /* istanbul ignore next */ []));
2007
+ // --- Methods ---
2008
+ sort(key) {
2009
+ if (this.sortKey() === key) {
2010
+ this.sortDir.update(d => (d === 'asc' ? 'desc' : 'asc'));
2011
+ }
2012
+ else {
2013
+ this.sortKey.set(key);
2014
+ this.sortDir.set('asc');
2015
+ }
2016
+ this.currentPage.set(1); // Reset to first page on sort
2017
+ this.onSortChange.emit({ key: this.sortKey(), direction: this.sortDir() });
2018
+ }
2019
+ toggleSelection(index) {
2020
+ this.selectedRows.update(s => {
2021
+ const next = new Set(s);
2022
+ if (next.has(index))
2023
+ next.delete(index);
2024
+ else
2025
+ next.add(index);
2026
+ return next;
2027
+ });
2028
+ this.onSelectionChange.emit(this.selectedRows());
2029
+ }
2030
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
2031
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindTable, isStandalone: true, selector: "tailwind-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, striped: { classPropertyName: "striped", publicName: "striped", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, paginated: { classPropertyName: "paginated", publicName: "paginated", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSortChange: "onSortChange", onSelectionChange: "onSelectionChange" }, usesInheritance: true, ngImport: i0, template: "<div class=\"w-full overflow-x-auto rounded-xl border border-surface-200\">\n <!-- Loading overlay -->\n @if (loading()) {\n <div class=\"flex items-center justify-center py-16 text-surface-400\">\n <svg class=\"animate-spin w-6 h-6 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\" />\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v8z\" />\n </svg>\n Loading...\n </div>\n } @else {\n <table class=\"w-full text-sm text-left\">\n <thead class=\"bg-surface-50 border-b border-surface-200\">\n <tr>\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n class=\"px-4 py-3 font-semibold text-surface-700 whitespace-nowrap\"\n [class.text-center]=\"col.align === 'center'\"\n [class.text-right]=\"col.align === 'right'\"\n [style.width]=\"col.width || 'auto'\">\n @if (col.sortable) {\n <button\n type=\"button\"\n (click)=\"sort(col.key)\"\n class=\"inline-flex items-center gap-1 cursor-pointer hover:text-surface-900 transition-colors\">\n {{ col.label }}\n <svg\n class=\"w-3.5 h-3.5 text-surface-400\"\n [class.text-primary-600]=\"sortKey() === col.key\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n @if (sortKey() === col.key && sortDir() === 'asc') {\n <path\n fill-rule=\"evenodd\"\n d=\"M10 17a.75.75 0 01-.75-.75V5.612L5.29 9.77a.75.75 0 01-1.08-1.04l5.25-5.5a.75.75 0 011.08 0l5.25 5.5a.75.75 0 11-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0110 17z\"\n clip-rule=\"evenodd\" />\n } @else {\n <path\n fill-rule=\"evenodd\"\n d=\"M10 3a.75.75 0 01.75.75v10.638l3.96-4.158a.75.75 0 111.08 1.04l-5.25 5.5a.75.75 0 01-1.08 0l-5.25-5.5a.75.75 0 111.08-1.04l3.96 4.158V3.75A.75.75 0 0110 3z\"\n clip-rule=\"evenodd\" />\n }\n </svg>\n </button>\n } @else {\n {{ col.label }}\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"divide-y divide-surface-100\">\n @for (row of displayedData(); track $index) {\n <tr\n class=\"hover:bg-surface-50/50 transition-colors\"\n [class.bg-surface-50]=\"striped() && $index % 2 === 1\"\n [class.bg-primary-50/30]=\"selectedRows().has($index)\"\n [class.cursor-pointer]=\"selectable()\"\n (click)=\"selectable() && toggleSelection($index)\">\n @for (col of columns(); track col.key) {\n <td\n class=\"px-4 py-3 text-surface-700\"\n [class.text-center]=\"col.align === 'center'\"\n [class.text-right]=\"col.align === 'right'\">\n {{ row[col.key] }}\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"columns().length\" class=\"px-4 py-8 text-center text-surface-400\">\n {{ emptyMessage() }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n @if (paginated() && data().length > 0) {\n <div class=\"px-4 py-3 border-t border-surface-200 bg-white\">\n <tailwind-pagination\n [totalItems]=\"pagination()?.totalItems ?? data().length\"\n [pageSize]=\"pagination()?.pageSize ?? 10\"\n [currentPage]=\"currentPage()\"\n (onPageChange)=\"currentPage.set($event)\"\n [ariaLabel]=\"pagination()?.ariaLabel ?? 'Pagination'\"\n [summary]=\"pagination()?.summary ?? 'Showing {start}-{end} of {total}'\">\n </tailwind-pagination>\n </div>\n }\n }\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: TailwindPagination, selector: "tailwind-pagination", inputs: ["totalItems", "pageSize", "currentPage", "ariaLabel", "summary"], outputs: ["currentPageChange", "onPageChange"] }] });
2032
+ }
2033
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTable, decorators: [{
2034
+ type: Component,
2035
+ args: [{ selector: 'tailwind-table', imports: [TailwindPagination], template: "<div class=\"w-full overflow-x-auto rounded-xl border border-surface-200\">\n <!-- Loading overlay -->\n @if (loading()) {\n <div class=\"flex items-center justify-center py-16 text-surface-400\">\n <svg class=\"animate-spin w-6 h-6 mr-2\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\" />\n <path class=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8v8z\" />\n </svg>\n Loading...\n </div>\n } @else {\n <table class=\"w-full text-sm text-left\">\n <thead class=\"bg-surface-50 border-b border-surface-200\">\n <tr>\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n class=\"px-4 py-3 font-semibold text-surface-700 whitespace-nowrap\"\n [class.text-center]=\"col.align === 'center'\"\n [class.text-right]=\"col.align === 'right'\"\n [style.width]=\"col.width || 'auto'\">\n @if (col.sortable) {\n <button\n type=\"button\"\n (click)=\"sort(col.key)\"\n class=\"inline-flex items-center gap-1 cursor-pointer hover:text-surface-900 transition-colors\">\n {{ col.label }}\n <svg\n class=\"w-3.5 h-3.5 text-surface-400\"\n [class.text-primary-600]=\"sortKey() === col.key\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n @if (sortKey() === col.key && sortDir() === 'asc') {\n <path\n fill-rule=\"evenodd\"\n d=\"M10 17a.75.75 0 01-.75-.75V5.612L5.29 9.77a.75.75 0 01-1.08-1.04l5.25-5.5a.75.75 0 011.08 0l5.25 5.5a.75.75 0 11-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0110 17z\"\n clip-rule=\"evenodd\" />\n } @else {\n <path\n fill-rule=\"evenodd\"\n d=\"M10 3a.75.75 0 01.75.75v10.638l3.96-4.158a.75.75 0 111.08 1.04l-5.25 5.5a.75.75 0 01-1.08 0l-5.25-5.5a.75.75 0 111.08-1.04l3.96 4.158V3.75A.75.75 0 0110 3z\"\n clip-rule=\"evenodd\" />\n }\n </svg>\n </button>\n } @else {\n {{ col.label }}\n }\n </th>\n }\n </tr>\n </thead>\n <tbody class=\"divide-y divide-surface-100\">\n @for (row of displayedData(); track $index) {\n <tr\n class=\"hover:bg-surface-50/50 transition-colors\"\n [class.bg-surface-50]=\"striped() && $index % 2 === 1\"\n [class.bg-primary-50/30]=\"selectedRows().has($index)\"\n [class.cursor-pointer]=\"selectable()\"\n (click)=\"selectable() && toggleSelection($index)\">\n @for (col of columns(); track col.key) {\n <td\n class=\"px-4 py-3 text-surface-700\"\n [class.text-center]=\"col.align === 'center'\"\n [class.text-right]=\"col.align === 'right'\">\n {{ row[col.key] }}\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"columns().length\" class=\"px-4 py-8 text-center text-surface-400\">\n {{ emptyMessage() }}\n </td>\n </tr>\n }\n </tbody>\n </table>\n\n @if (paginated() && data().length > 0) {\n <div class=\"px-4 py-3 border-t border-surface-200 bg-white\">\n <tailwind-pagination\n [totalItems]=\"pagination()?.totalItems ?? data().length\"\n [pageSize]=\"pagination()?.pageSize ?? 10\"\n [currentPage]=\"currentPage()\"\n (onPageChange)=\"currentPage.set($event)\"\n [ariaLabel]=\"pagination()?.ariaLabel ?? 'Pagination'\"\n [summary]=\"pagination()?.summary ?? 'Showing {start}-{end} of {total}'\">\n </tailwind-pagination>\n </div>\n }\n }\n</div>\n", styles: [":host{display:block}\n"] }]
2036
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], striped: [{ type: i0.Input, args: [{ isSignal: true, alias: "striped", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], paginated: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginated", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], onSortChange: [{ type: i0.Output, args: ["onSortChange"] }], onSelectionChange: [{ type: i0.Output, args: ["onSelectionChange"] }] } });
2037
+
2038
+ const I18N$2 = {
2039
+ it: {
2040
+ months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
2041
+ weekDays: ['Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa', 'Do'],
2042
+ today: 'Oggi',
2043
+ confirm: 'Applica',
2044
+ placeholder: 'Seleziona data'
2045
+ },
2046
+ en: {
2047
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
2048
+ weekDays: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
2049
+ today: 'Today',
2050
+ confirm: 'Apply',
2051
+ placeholder: 'Select date'
2052
+ }
2053
+ };
2054
+ class TailwindDatePicker extends TailwindComponent {
2055
+ lang = inject(TAILWIND_DATETIME_LANGUAGE, { optional: true }) ?? 'it';
2056
+ i18n = I18N$2[this.lang];
2057
+ weekDays = this.i18n.weekDays;
2058
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2059
+ placeholder = input(undefined, ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
2060
+ format = input('dd/MM/yyyy', ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
2061
+ value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2062
+ /** Working selection while the panel is open; committed on Apply. */
2063
+ draft = signal(null, ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
2064
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2065
+ showCalendar = signal(false, ...(ngDevMode ? [{ debugName: "showCalendar" }] : /* istanbul ignore next */ []));
2066
+ viewMonth = signal(new Date().getMonth(), ...(ngDevMode ? [{ debugName: "viewMonth" }] : /* istanbul ignore next */ []));
2067
+ viewYear = signal(new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "viewYear" }] : /* istanbul ignore next */ []));
2068
+ effectivePlaceholder = computed(() => {
2069
+ const p = this.placeholder();
2070
+ return p?.trim() ? p : this.i18n.placeholder;
2071
+ }, ...(ngDevMode ? [{ debugName: "effectivePlaceholder" }] : /* istanbul ignore next */ []));
2072
+ displayValue = computed(() => {
2073
+ const d = this.value();
2074
+ if (!d)
2075
+ return '';
2076
+ const fmt = this.format();
2077
+ try {
2078
+ return formatDate(d, fmt, this.lang === 'it' ? 'it-IT' : 'en-US');
2079
+ }
2080
+ catch {
2081
+ return formatDate(d, fmt, 'en-US');
2082
+ }
2083
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
2084
+ monthYearLabel = computed(() => `${this.i18n.months[this.viewMonth()]} ${this.viewYear()}`, ...(ngDevMode ? [{ debugName: "monthYearLabel" }] : /* istanbul ignore next */ []));
2085
+ calendarDays = computed(() => {
2086
+ const y = this.viewYear(), m = this.viewMonth();
2087
+ const offset = (new Date(y, m, 1).getDay() + 6) % 7; // Mon = 0
2088
+ const total = new Date(y, m + 1, 0).getDate();
2089
+ const days = Array(offset).fill(0);
2090
+ for (let i = 1; i <= total; i++)
2091
+ days.push(i);
2092
+ return days;
2093
+ }, ...(ngDevMode ? [{ debugName: "calendarDays" }] : /* istanbul ignore next */ []));
2094
+ onChange = () => { };
2095
+ onTouched = () => { };
2096
+ writeValue(v) {
2097
+ this.value.set(v ?? null);
2098
+ if (v && !isNaN(v.getTime())) {
2099
+ this.viewMonth.set(v.getMonth());
2100
+ this.viewYear.set(v.getFullYear());
2101
+ }
2102
+ }
2103
+ registerOnChange(fn) { this.onChange = fn; }
2104
+ registerOnTouched(fn) { this.onTouched = fn; }
2105
+ setDisabledState(d) { this.isDisabled.set(d); }
2106
+ toggleCalendar() {
2107
+ if (this.isDisabled())
2108
+ return;
2109
+ if (!this.showCalendar()) {
2110
+ this.draft.set(this.value());
2111
+ const ref = this.value() ?? new Date();
2112
+ this.viewMonth.set(ref.getMonth());
2113
+ this.viewYear.set(ref.getFullYear());
2114
+ }
2115
+ this.showCalendar.update(v => !v);
2116
+ }
2117
+ apply() {
2118
+ const d = this.draft();
2119
+ this.value.set(d);
2120
+ this.onChange(d);
2121
+ this.onTouched();
2122
+ this.showCalendar.set(false);
2123
+ }
2124
+ prevMonth() {
2125
+ if (this.viewMonth() === 0) {
2126
+ this.viewMonth.set(11);
2127
+ this.viewYear.update(y => y - 1);
2128
+ }
2129
+ else {
2130
+ this.viewMonth.update(m => m - 1);
2131
+ }
2132
+ }
2133
+ nextMonth() {
2134
+ if (this.viewMonth() === 11) {
2135
+ this.viewMonth.set(0);
2136
+ this.viewYear.update(y => y + 1);
2137
+ }
2138
+ else {
2139
+ this.viewMonth.update(m => m + 1);
2140
+ }
2141
+ }
2142
+ selectDay(day) {
2143
+ this.draft.set(new Date(this.viewYear(), this.viewMonth(), day));
2144
+ }
2145
+ isSelected(day) {
2146
+ const d = this.draft();
2147
+ if (!d)
2148
+ return false;
2149
+ return d.getFullYear() === this.viewYear() && d.getMonth() === this.viewMonth() && d.getDate() === day;
2150
+ }
2151
+ isToday(day) {
2152
+ const t = new Date();
2153
+ return t.getFullYear() === this.viewYear() && t.getMonth() === this.viewMonth() && t.getDate() === day;
2154
+ }
2155
+ goToToday() {
2156
+ const t = new Date();
2157
+ this.viewMonth.set(t.getMonth());
2158
+ this.viewYear.set(t.getFullYear());
2159
+ this.selectDay(t.getDate());
2160
+ }
2161
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDatePicker, deps: null, target: i0.ɵɵFactoryTarget.Component });
2162
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindDatePicker, isStandalone: true, selector: "tailwind-date-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TailwindDatePicker), multi: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label [attr.for]=\"id() ? id() + '-inner' : null\" class=\"text-sm font-medium text-surface-700\">{{ label() }}</label>\n }\n <div class=\"relative\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"text\"\n readonly\n [value]=\"displayValue()\"\n [placeholder]=\"effectivePlaceholder()\"\n class=\"block w-full bg-white border border-surface-300 rounded-md px-3 py-2 text-sm text-surface-900 placeholder:text-surface-400 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 cursor-pointer disabled:bg-surface-50 disabled:cursor-not-allowed pr-10\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggleCalendar()\" />\n <svg\n class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400 pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\" />\n </svg>\n </div>\n\n @if (showCalendar()) {\n <div class=\"absolute z-popover mt-1 bg-white rounded-xl border border-surface-200 shadow-xl p-4 w-72\">\n <!-- Month/Year nav -->\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prevMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n <span class=\"text-sm font-semibold text-surface-800\">{{ monthYearLabel() }}</span>\n <button\n type=\"button\"\n (click)=\"nextMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n </div>\n <!-- Weekdays -->\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (day of weekDays; track $index) {\n <div class=\"text-center text-xs font-medium text-surface-400 py-1\">{{ day }}</div>\n }\n </div>\n <!-- Days -->\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day === 0) {\n <div></div>\n } @else {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"h-8 w-8 mx-auto rounded-lg text-sm transition-colors cursor-pointer hover:bg-surface-100\"\n [class.bg-primary-600]=\"isSelected(day)\"\n [class.text-white]=\"isSelected(day)\"\n [class.hover:bg-primary-700]=\"isSelected(day)\"\n [class.text-surface-700]=\"!isSelected(day) && !isToday(day)\"\n [class.font-semibold]=\"isToday(day)\"\n [class.text-primary-600]=\"isToday(day) && !isSelected(day)\">\n {{ day }}\n </button>\n }\n }\n </div>\n <div class=\"mt-2 pt-2 border-t border-surface-100 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n (click)=\"goToToday()\"\n [disabled]=\"isDisabled()\"\n class=\"text-xs text-primary-600 font-medium hover:underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:no-underline\">\n {{ i18n.today }}\n </button>\n <button\n type=\"button\"\n (click)=\"apply()\"\n [disabled]=\"isDisabled() || !draft()\"\n class=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 cursor-pointer disabled:bg-surface-200 disabled:text-surface-500 disabled:cursor-not-allowed\">\n {{ i18n.confirm }}\n </button>\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;position:relative}\n"] });
2163
+ }
2164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDatePicker, decorators: [{
2165
+ type: Component,
2166
+ args: [{ selector: 'tailwind-date-picker', providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TailwindDatePicker), multi: true }], template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label [attr.for]=\"id() ? id() + '-inner' : null\" class=\"text-sm font-medium text-surface-700\">{{ label() }}</label>\n }\n <div class=\"relative\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"text\"\n readonly\n [value]=\"displayValue()\"\n [placeholder]=\"effectivePlaceholder()\"\n class=\"block w-full bg-white border border-surface-300 rounded-md px-3 py-2 text-sm text-surface-900 placeholder:text-surface-400 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 cursor-pointer disabled:bg-surface-50 disabled:cursor-not-allowed pr-10\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggleCalendar()\" />\n <svg\n class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400 pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\" />\n </svg>\n </div>\n\n @if (showCalendar()) {\n <div class=\"absolute z-popover mt-1 bg-white rounded-xl border border-surface-200 shadow-xl p-4 w-72\">\n <!-- Month/Year nav -->\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prevMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n <span class=\"text-sm font-semibold text-surface-800\">{{ monthYearLabel() }}</span>\n <button\n type=\"button\"\n (click)=\"nextMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n </div>\n <!-- Weekdays -->\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (day of weekDays; track $index) {\n <div class=\"text-center text-xs font-medium text-surface-400 py-1\">{{ day }}</div>\n }\n </div>\n <!-- Days -->\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day === 0) {\n <div></div>\n } @else {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"h-8 w-8 mx-auto rounded-lg text-sm transition-colors cursor-pointer hover:bg-surface-100\"\n [class.bg-primary-600]=\"isSelected(day)\"\n [class.text-white]=\"isSelected(day)\"\n [class.hover:bg-primary-700]=\"isSelected(day)\"\n [class.text-surface-700]=\"!isSelected(day) && !isToday(day)\"\n [class.font-semibold]=\"isToday(day)\"\n [class.text-primary-600]=\"isToday(day) && !isSelected(day)\">\n {{ day }}\n </button>\n }\n }\n </div>\n <div class=\"mt-2 pt-2 border-t border-surface-100 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n (click)=\"goToToday()\"\n [disabled]=\"isDisabled()\"\n class=\"text-xs text-primary-600 font-medium hover:underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:no-underline\">\n {{ i18n.today }}\n </button>\n <button\n type=\"button\"\n (click)=\"apply()\"\n [disabled]=\"isDisabled() || !draft()\"\n class=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 cursor-pointer disabled:bg-surface-200 disabled:text-surface-500 disabled:cursor-not-allowed\">\n {{ i18n.confirm }}\n </button>\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;position:relative}\n"] }]
2167
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
2168
+
2169
+ const I18N$1 = {
2170
+ it: { placeholder: 'Seleziona ora', now: 'Adesso', apply: 'Applica' },
2171
+ en: { placeholder: 'Select time', now: 'Now', apply: 'Apply' }
2172
+ };
2173
+ class TailwindTimePicker extends TailwindComponent {
2174
+ lang = inject(TAILWIND_DATETIME_LANGUAGE, { optional: true }) ?? 'it';
2175
+ i18n = I18N$1[this.lang];
2176
+ hours = Array.from({ length: 24 }, (_, i) => i);
2177
+ minutes = Array.from({ length: 60 }, (_, i) => i);
2178
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2179
+ value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2180
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2181
+ showPanel = signal(false, ...(ngDevMode ? [{ debugName: "showPanel" }] : /* istanbul ignore next */ []));
2182
+ draft = signal(null, ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
2183
+ displayValue = computed(() => this.value(), ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
2184
+ onChange = () => { };
2185
+ onTouched = () => { };
2186
+ writeValue(v) {
2187
+ this.value.set(v ?? '');
2188
+ }
2189
+ registerOnChange(fn) {
2190
+ this.onChange = fn;
2191
+ }
2192
+ registerOnTouched(fn) {
2193
+ this.onTouched = fn;
2194
+ }
2195
+ setDisabledState(d) {
2196
+ this.isDisabled.set(d);
2197
+ }
2198
+ togglePanel() {
2199
+ if (this.isDisabled())
2200
+ return;
2201
+ const opening = !this.showPanel();
2202
+ if (opening) {
2203
+ const v = this.value();
2204
+ const parts = v ? v.split(':') : null;
2205
+ const now = new Date();
2206
+ this.draft.set({
2207
+ h: parts ? parseInt(parts[0], 10) || 0 : now.getHours(),
2208
+ m: parts ? parseInt(parts[1], 10) || 0 : now.getMinutes()
2209
+ });
2210
+ }
2211
+ this.showPanel.set(opening);
2212
+ }
2213
+ apply() {
2214
+ const d = this.draft();
2215
+ if (!d)
2216
+ return;
2217
+ const val = `${d.h.toString().padStart(2, '0')}:${d.m.toString().padStart(2, '0')}`;
2218
+ this.value.set(val);
2219
+ this.onChange(val);
2220
+ this.onTouched();
2221
+ this.showPanel.set(false);
2222
+ }
2223
+ goToNow() {
2224
+ const now = new Date();
2225
+ this.draft.set({ h: now.getHours(), m: now.getMinutes() });
2226
+ }
2227
+ onHourChange(e) {
2228
+ const cur = this.draft();
2229
+ if (!cur)
2230
+ return;
2231
+ this.draft.set({ ...cur, h: Number(e.target.value) });
2232
+ }
2233
+ onMinuteChange(e) {
2234
+ const cur = this.draft();
2235
+ if (!cur)
2236
+ return;
2237
+ this.draft.set({ ...cur, m: Number(e.target.value) });
2238
+ }
2239
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTimePicker, deps: null, target: i0.ɵɵFactoryTarget.Component });
2240
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindTimePicker, isStandalone: true, selector: "tailwind-time-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TailwindTimePicker), multi: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label [attr.for]=\"id() ? id() + '-inner' : null\" class=\"text-sm font-medium text-surface-700\">{{ label() }}</label>\n }\n <div class=\"relative\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"text\"\n readonly\n [value]=\"displayValue()\"\n [placeholder]=\"i18n.placeholder\"\n [disabled]=\"isDisabled()\"\n class=\"block w-full bg-white border border-surface-300 rounded-md px-3 py-2 text-sm text-surface-900 placeholder:text-surface-400 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 cursor-pointer disabled:bg-surface-50 disabled:cursor-not-allowed pr-10\"\n (click)=\"togglePanel()\" />\n <svg\n class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400 pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z\"\n clip-rule=\"evenodd\" />\n </svg>\n\n @if (showPanel()) {\n <div\n class=\"absolute left-0 top-full z-popover mt-1 w-52 rounded-xl border border-surface-200 bg-white p-4 shadow-xl\">\n <div class=\"flex items-center gap-2\">\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled()\"\n (change)=\"onHourChange($event)\">\n @for (h of hours; track h) {\n <option [value]=\"h\" [selected]=\"h === (draft()?.h ?? 0)\">\n {{ h.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n <span class=\"text-surface-400 text-sm shrink-0\">:</span>\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled()\"\n (change)=\"onMinuteChange($event)\">\n @for (m of minutes; track m) {\n <option [value]=\"m\" [selected]=\"m === (draft()?.m ?? 0)\">\n {{ m.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n </div>\n <div class=\"mt-2 pt-2 border-t border-surface-100 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n (click)=\"goToNow()\"\n [disabled]=\"isDisabled()\"\n class=\"text-xs text-primary-600 font-medium hover:underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:no-underline\">\n {{ i18n.now }}\n </button>\n <button\n type=\"button\"\n (click)=\"apply()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 cursor-pointer disabled:bg-surface-200 disabled:text-surface-500 disabled:cursor-not-allowed\">\n {{ i18n.apply }}\n </button>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block}\n"] });
2241
+ }
2242
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindTimePicker, decorators: [{
2243
+ type: Component,
2244
+ args: [{ selector: 'tailwind-time-picker', imports: [], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TailwindTimePicker), multi: true }], template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label [attr.for]=\"id() ? id() + '-inner' : null\" class=\"text-sm font-medium text-surface-700\">{{ label() }}</label>\n }\n <div class=\"relative\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"text\"\n readonly\n [value]=\"displayValue()\"\n [placeholder]=\"i18n.placeholder\"\n [disabled]=\"isDisabled()\"\n class=\"block w-full bg-white border border-surface-300 rounded-md px-3 py-2 text-sm text-surface-900 placeholder:text-surface-400 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 cursor-pointer disabled:bg-surface-50 disabled:cursor-not-allowed pr-10\"\n (click)=\"togglePanel()\" />\n <svg\n class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400 pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z\"\n clip-rule=\"evenodd\" />\n </svg>\n\n @if (showPanel()) {\n <div\n class=\"absolute left-0 top-full z-popover mt-1 w-52 rounded-xl border border-surface-200 bg-white p-4 shadow-xl\">\n <div class=\"flex items-center gap-2\">\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled()\"\n (change)=\"onHourChange($event)\">\n @for (h of hours; track h) {\n <option [value]=\"h\" [selected]=\"h === (draft()?.h ?? 0)\">\n {{ h.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n <span class=\"text-surface-400 text-sm shrink-0\">:</span>\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled()\"\n (change)=\"onMinuteChange($event)\">\n @for (m of minutes; track m) {\n <option [value]=\"m\" [selected]=\"m === (draft()?.m ?? 0)\">\n {{ m.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n </div>\n <div class=\"mt-2 pt-2 border-t border-surface-100 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n (click)=\"goToNow()\"\n [disabled]=\"isDisabled()\"\n class=\"text-xs text-primary-600 font-medium hover:underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:no-underline\">\n {{ i18n.now }}\n </button>\n <button\n type=\"button\"\n (click)=\"apply()\"\n [disabled]=\"isDisabled()\"\n class=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 cursor-pointer disabled:bg-surface-200 disabled:text-surface-500 disabled:cursor-not-allowed\">\n {{ i18n.apply }}\n </button>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
2245
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
2246
+
2247
+ const I18N = {
2248
+ it: {
2249
+ months: ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre'],
2250
+ weekDays: ['Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa', 'Do'],
2251
+ time: 'Ora',
2252
+ today: 'Oggi',
2253
+ confirm: 'Applica',
2254
+ placeholder: 'Seleziona data e ora'
2255
+ },
2256
+ en: {
2257
+ months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
2258
+ weekDays: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'],
2259
+ time: 'Time',
2260
+ today: 'Today',
2261
+ confirm: 'Apply',
2262
+ placeholder: 'Select date and time'
2263
+ }
2264
+ };
2265
+ class TailwindDateTimePicker extends TailwindComponent {
2266
+ lang = inject(TAILWIND_DATETIME_LANGUAGE, { optional: true }) ?? 'it';
2267
+ i18n = I18N[this.lang];
2268
+ weekDays = this.i18n.weekDays;
2269
+ hours = Array.from({ length: 24 }, (_, i) => i);
2270
+ minutes = Array.from({ length: 60 }, (_, i) => i);
2271
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2272
+ placeholder = input(undefined, ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
2273
+ /** Angular [DatePipe](https://angular.dev/api/common/DatePipe) format string. */
2274
+ format = input('dd/MM/yyyy HH:mm', ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
2275
+ selected = signal(null, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
2276
+ draft = signal(null, ...(ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []));
2277
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2278
+ showPanel = signal(false, ...(ngDevMode ? [{ debugName: "showPanel" }] : /* istanbul ignore next */ []));
2279
+ viewMonth = signal(new Date().getMonth(), ...(ngDevMode ? [{ debugName: "viewMonth" }] : /* istanbul ignore next */ []));
2280
+ viewYear = signal(new Date().getFullYear(), ...(ngDevMode ? [{ debugName: "viewYear" }] : /* istanbul ignore next */ []));
2281
+ effectivePlaceholder = computed(() => {
2282
+ const p = this.placeholder();
2283
+ return p?.trim() ? p : this.i18n.placeholder;
2284
+ }, ...(ngDevMode ? [{ debugName: "effectivePlaceholder" }] : /* istanbul ignore next */ []));
2285
+ displayValue = computed(() => {
2286
+ const d = this.selected();
2287
+ if (!d)
2288
+ return '';
2289
+ // formatDate richiede registerLocaleData per locale non-EN: leggiamo format fuori dal try
2290
+ // per non richiamare signal dentro il catch (contesto reattivo non garantito dopo un throw).
2291
+ // Per i formati numerici (default dd/MM/yyyy HH:mm) il risultato è identico in ogni locale.
2292
+ const fmt = this.format();
2293
+ try {
2294
+ return formatDate(d, fmt, this.lang === 'it' ? 'it-IT' : 'en-US');
2295
+ }
2296
+ catch {
2297
+ return formatDate(d, fmt, 'en-US');
2298
+ }
2299
+ }, ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
2300
+ monthYearLabel = computed(() => `${this.i18n.months[this.viewMonth()]} ${this.viewYear()}`, ...(ngDevMode ? [{ debugName: "monthYearLabel" }] : /* istanbul ignore next */ []));
2301
+ calendarDays = computed(() => {
2302
+ const y = this.viewYear(), m = this.viewMonth();
2303
+ const offset = (new Date(y, m, 1).getDay() + 6) % 7; // Mon = 0
2304
+ const total = new Date(y, m + 1, 0).getDate();
2305
+ const days = Array(offset).fill(0);
2306
+ for (let i = 1; i <= total; i++)
2307
+ days.push(i);
2308
+ return days;
2309
+ }, ...(ngDevMode ? [{ debugName: "calendarDays" }] : /* istanbul ignore next */ []));
2310
+ onChange = () => { };
2311
+ onTouched = () => { };
2312
+ writeValue(v) {
2313
+ const d = v ? new Date(v.getTime()) : null;
2314
+ this.selected.set(d);
2315
+ if (this.showPanel())
2316
+ this.draft.set(d ? new Date(d.getTime()) : null);
2317
+ const ref = d ?? new Date();
2318
+ this.viewMonth.set(ref.getMonth());
2319
+ this.viewYear.set(ref.getFullYear());
2320
+ }
2321
+ registerOnChange(fn) { this.onChange = fn; }
2322
+ registerOnTouched(fn) { this.onTouched = fn; }
2323
+ setDisabledState(disabled) { this.isDisabled.set(disabled); }
2324
+ togglePanel() {
2325
+ if (this.isDisabled())
2326
+ return;
2327
+ const opening = !this.showPanel();
2328
+ if (opening) {
2329
+ const s = this.selected();
2330
+ const ref = s ? new Date(s.getTime()) : this.todayNow();
2331
+ this.draft.set(ref);
2332
+ this.viewMonth.set(ref.getMonth());
2333
+ this.viewYear.set(ref.getFullYear());
2334
+ }
2335
+ this.showPanel.set(opening);
2336
+ }
2337
+ apply() {
2338
+ const d = this.draft();
2339
+ this.selected.set(d ? new Date(d.getTime()) : null);
2340
+ this.emitValue(this.selected());
2341
+ this.showPanel.set(false);
2342
+ }
2343
+ prevMonth() {
2344
+ if (this.viewMonth() === 0) {
2345
+ this.viewMonth.set(11);
2346
+ this.viewYear.update(y => y - 1);
2347
+ }
2348
+ else {
2349
+ this.viewMonth.update(m => m - 1);
2350
+ }
2351
+ }
2352
+ nextMonth() {
2353
+ if (this.viewMonth() === 11) {
2354
+ this.viewMonth.set(0);
2355
+ this.viewYear.update(y => y + 1);
2356
+ }
2357
+ else {
2358
+ this.viewMonth.update(m => m + 1);
2359
+ }
2360
+ }
2361
+ selectDay(day) {
2362
+ const cur = this.draft();
2363
+ this.draft.set(new Date(this.viewYear(), this.viewMonth(), day, cur?.getHours() ?? 0, cur?.getMinutes() ?? 0, 0, 0));
2364
+ }
2365
+ isSelected(day) {
2366
+ const v = this.draft();
2367
+ return !!v && v.getFullYear() === this.viewYear() && v.getMonth() === this.viewMonth() && v.getDate() === day;
2368
+ }
2369
+ isToday(day) {
2370
+ const t = new Date();
2371
+ return t.getFullYear() === this.viewYear() && t.getMonth() === this.viewMonth() && t.getDate() === day;
2372
+ }
2373
+ goToToday() {
2374
+ const t = this.todayNow();
2375
+ this.viewMonth.set(t.getMonth());
2376
+ this.viewYear.set(t.getFullYear());
2377
+ this.draft.set(t);
2378
+ }
2379
+ onHourChange(e) {
2380
+ const cur = this.draft();
2381
+ if (!cur)
2382
+ return;
2383
+ const h = Number(e.target.value);
2384
+ this.draft.set(new Date(cur.getFullYear(), cur.getMonth(), cur.getDate(), h, cur.getMinutes(), 0, 0));
2385
+ }
2386
+ onMinuteChange(e) {
2387
+ const cur = this.draft();
2388
+ if (!cur)
2389
+ return;
2390
+ const min = Number(e.target.value);
2391
+ this.draft.set(new Date(cur.getFullYear(), cur.getMonth(), cur.getDate(), cur.getHours(), min, 0, 0));
2392
+ }
2393
+ todayNow() {
2394
+ const t = new Date();
2395
+ return new Date(t.getFullYear(), t.getMonth(), t.getDate(), t.getHours(), t.getMinutes(), 0, 0);
2396
+ }
2397
+ emitValue(d) {
2398
+ this.onChange(d ? new Date(d.getTime()) : null);
2399
+ this.onTouched();
2400
+ }
2401
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDateTimePicker, deps: null, target: i0.ɵɵFactoryTarget.Component });
2402
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindDateTimePicker, isStandalone: true, selector: "tailwind-datetime-picker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TailwindDateTimePicker), multi: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label [attr.for]=\"id() ? id() + '-inner' : null\" class=\"text-sm font-medium text-surface-700\">{{ label() }}</label>\n }\n <div class=\"relative\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"text\"\n readonly\n [value]=\"displayValue()\"\n [placeholder]=\"effectivePlaceholder()\"\n class=\"block w-full bg-white border border-surface-300 rounded-md px-3 py-2 text-sm text-surface-900 placeholder:text-surface-400 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 cursor-pointer disabled:bg-surface-50 disabled:cursor-not-allowed pr-10\"\n [disabled]=\"isDisabled()\"\n (click)=\"togglePanel()\" />\n <svg\n class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400 pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\" />\n </svg>\n\n @if (showPanel()) {\n <div\n class=\"absolute left-0 top-full z-popover mt-1 w-80 max-w-full rounded-xl border border-surface-200 bg-white p-4 shadow-xl\">\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prevMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n <span class=\"text-sm font-semibold text-surface-800\">{{ monthYearLabel() }}</span>\n <button\n type=\"button\"\n (click)=\"nextMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n </div>\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (day of weekDays; track day) {\n <div class=\"text-center text-xs font-medium text-surface-400 py-1\">{{ day }}</div>\n }\n </div>\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day === 0) {\n <div></div>\n } @else {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"h-8 w-8 mx-auto rounded-lg text-sm transition-colors cursor-pointer hover:bg-surface-100\"\n [class.bg-primary-600]=\"isSelected(day)\"\n [class.text-white]=\"isSelected(day)\"\n [class.hover:bg-primary-700]=\"isSelected(day)\"\n [class.text-surface-700]=\"!isSelected(day) && !isToday(day)\"\n [class.font-semibold]=\"isToday(day)\"\n [class.text-primary-600]=\"isToday(day) && !isSelected(day)\">\n {{ day }}\n </button>\n }\n }\n </div>\n <div class=\"mt-3 pt-3 border-t border-surface-100 flex items-center gap-2\">\n <span class=\"text-xs font-medium text-surface-600 shrink-0\">{{ i18n.time }}</span>\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled() || !draft()\"\n (change)=\"onHourChange($event)\">\n @for (h of hours; track h) {\n <option [value]=\"h\" [selected]=\"h === (draft()?.getHours() ?? 0)\">\n {{ h.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n <span class=\"text-surface-400 text-sm\">:</span>\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled() || !draft()\"\n (change)=\"onMinuteChange($event)\">\n @for (m of minutes; track m) {\n <option [value]=\"m\" [selected]=\"m === (draft()?.getMinutes() ?? 0)\">\n {{ m.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n </div>\n <div class=\"mt-2 pt-2 border-t border-surface-100 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n (click)=\"goToToday()\"\n [disabled]=\"isDisabled()\"\n class=\"text-xs text-primary-600 font-medium hover:underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:no-underline\">\n {{ i18n.today }}\n </button>\n <button\n type=\"button\"\n (click)=\"apply()\"\n [disabled]=\"isDisabled() || !draft()\"\n class=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 cursor-pointer disabled:bg-surface-200 disabled:text-surface-500 disabled:cursor-not-allowed\">\n {{ i18n.confirm }}\n </button>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;position:relative;overflow:visible}\n"] });
2403
+ }
2404
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDateTimePicker, decorators: [{
2405
+ type: Component,
2406
+ args: [{ selector: 'tailwind-datetime-picker', imports: [], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TailwindDateTimePicker), multi: true }], template: "<div class=\"flex flex-col gap-1.5\">\n @if (label()) {\n <label [attr.for]=\"id() ? id() + '-inner' : null\" class=\"text-sm font-medium text-surface-700\">{{ label() }}</label>\n }\n <div class=\"relative\">\n <input\n [attr.id]=\"id() ? id() + '-inner' : null\"\n type=\"text\"\n readonly\n [value]=\"displayValue()\"\n [placeholder]=\"effectivePlaceholder()\"\n class=\"block w-full bg-white border border-surface-300 rounded-md px-3 py-2 text-sm text-surface-900 placeholder:text-surface-400 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 cursor-pointer disabled:bg-surface-50 disabled:cursor-not-allowed pr-10\"\n [disabled]=\"isDisabled()\"\n (click)=\"togglePanel()\" />\n <svg\n class=\"absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-surface-400 pointer-events-none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M5.75 2a.75.75 0 01.75.75V4h7V2.75a.75.75 0 011.5 0V4h.25A2.75 2.75 0 0118 6.75v8.5A2.75 2.75 0 0115.25 18H4.75A2.75 2.75 0 012 15.25v-8.5A2.75 2.75 0 014.75 4H5V2.75A.75.75 0 015.75 2zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75z\"\n clip-rule=\"evenodd\" />\n </svg>\n\n @if (showPanel()) {\n <div\n class=\"absolute left-0 top-full z-popover mt-1 w-80 max-w-full rounded-xl border border-surface-200 bg-white p-4 shadow-xl\">\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prevMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n <span class=\"text-sm font-semibold text-surface-800\">{{ monthYearLabel() }}</span>\n <button\n type=\"button\"\n (click)=\"nextMonth()\"\n class=\"p-1 rounded-lg hover:bg-surface-100 transition-colors cursor-pointer\">\n <svg\n class=\"w-4 h-4 text-surface-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z\"\n clip-rule=\"evenodd\" />\n </svg>\n </button>\n </div>\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (day of weekDays; track day) {\n <div class=\"text-center text-xs font-medium text-surface-400 py-1\">{{ day }}</div>\n }\n </div>\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day === 0) {\n <div></div>\n } @else {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"h-8 w-8 mx-auto rounded-lg text-sm transition-colors cursor-pointer hover:bg-surface-100\"\n [class.bg-primary-600]=\"isSelected(day)\"\n [class.text-white]=\"isSelected(day)\"\n [class.hover:bg-primary-700]=\"isSelected(day)\"\n [class.text-surface-700]=\"!isSelected(day) && !isToday(day)\"\n [class.font-semibold]=\"isToday(day)\"\n [class.text-primary-600]=\"isToday(day) && !isSelected(day)\">\n {{ day }}\n </button>\n }\n }\n </div>\n <div class=\"mt-3 pt-3 border-t border-surface-100 flex items-center gap-2\">\n <span class=\"text-xs font-medium text-surface-600 shrink-0\">{{ i18n.time }}</span>\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled() || !draft()\"\n (change)=\"onHourChange($event)\">\n @for (h of hours; track h) {\n <option [value]=\"h\" [selected]=\"h === (draft()?.getHours() ?? 0)\">\n {{ h.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n <span class=\"text-surface-400 text-sm\">:</span>\n <select\n class=\"flex-1 min-w-0 block bg-white border border-surface-300 rounded-md px-2 py-1.5 text-sm text-surface-900 outline-none focus:outline focus:outline-primary-500 focus:outline-offset-2 disabled:bg-surface-50 disabled:cursor-not-allowed\"\n [disabled]=\"isDisabled() || !draft()\"\n (change)=\"onMinuteChange($event)\">\n @for (m of minutes; track m) {\n <option [value]=\"m\" [selected]=\"m === (draft()?.getMinutes() ?? 0)\">\n {{ m.toString().padStart(2, '0') }}\n </option>\n }\n </select>\n </div>\n <div class=\"mt-2 pt-2 border-t border-surface-100 flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n (click)=\"goToToday()\"\n [disabled]=\"isDisabled()\"\n class=\"text-xs text-primary-600 font-medium hover:underline cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed disabled:no-underline\">\n {{ i18n.today }}\n </button>\n <button\n type=\"button\"\n (click)=\"apply()\"\n [disabled]=\"isDisabled() || !draft()\"\n class=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 cursor-pointer disabled:bg-surface-200 disabled:text-surface-500 disabled:cursor-not-allowed\">\n {{ i18n.confirm }}\n </button>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;position:relative;overflow:visible}\n"] }]
2407
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }] } });
2408
+
2409
+ class TailwindStep extends TailwindComponent {
2410
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2411
+ description = input('', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
2412
+ optional = input(false, ...(ngDevMode ? [{ debugName: "optional" }] : /* istanbul ignore next */ []));
2413
+ completed = signal(false, ...(ngDevMode ? [{ debugName: "completed" }] : /* istanbul ignore next */ []));
2414
+ isActive = signal(false, ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
2415
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindStep, deps: null, target: i0.ɵɵFactoryTarget.Component });
2416
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindStep, isStandalone: true, selector: "tailwind-step", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (isActive()) {\n <div class=\"py-4\"><ng-content /></div>\n}\n", styles: [":host{display:block}\n"] });
2417
+ }
2418
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindStep, decorators: [{
2419
+ type: Component,
2420
+ args: [{ selector: 'tailwind-step', template: "@if (isActive()) {\n <div class=\"py-4\"><ng-content /></div>\n}\n", styles: [":host{display:block}\n"] }]
2421
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }] } });
2422
+
2423
+ class TailwindStepper extends TailwindComponent {
2424
+ activeIndex = model(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
2425
+ linear = input(false, ...(ngDevMode ? [{ debugName: "linear" }] : /* istanbul ignore next */ []));
2426
+ steps = contentChildren(TailwindStep, ...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
2427
+ constructor() {
2428
+ super();
2429
+ effect(() => {
2430
+ const allSteps = this.steps();
2431
+ const idx = this.activeIndex();
2432
+ allSteps.forEach((s, i) => s.isActive.set(i === idx));
2433
+ });
2434
+ }
2435
+ goToStep(index) {
2436
+ if (!this.linear() || index <= this.activeIndex()) {
2437
+ this.activeIndex.set(index);
2438
+ }
2439
+ }
2440
+ next() {
2441
+ const s = this.steps();
2442
+ if (this.activeIndex() < s.length - 1) {
2443
+ s[this.activeIndex()].completed.set(true);
2444
+ this.activeIndex.update(v => v + 1);
2445
+ }
2446
+ }
2447
+ previous() {
2448
+ if (this.activeIndex() > 0)
2449
+ this.activeIndex.update(v => v - 1);
2450
+ }
2451
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
2452
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindStepper, isStandalone: true, selector: "tailwind-stepper", inputs: { activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, queries: [{ propertyName: "steps", predicate: TailwindStep, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Step indicators -->\n<div class=\"flex items-center mb-6\">\n @for (step of steps(); track step.label(); let i = $index; let last = $last) {\n <div class=\"flex items-center\" [class.flex-1]=\"!last\">\n <button\n type=\"button\"\n (click)=\"goToStep(i)\"\n class=\"flex items-center gap-2 cursor-pointer group\"\n [attr.aria-current]=\"activeIndex() === i ? 'step' : null\">\n <div\n class=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold border-2 transition-all duration-200\"\n [class.bg-primary-600]=\"i <= activeIndex()\"\n [class.border-primary-600]=\"i <= activeIndex()\"\n [class.text-white]=\"i <= activeIndex()\"\n [class.border-surface-300]=\"i > activeIndex()\"\n [class.text-surface-500]=\"i > activeIndex()\">\n @if (step.completed()) {\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\" />\n </svg>\n } @else {\n {{ i + 1 }}\n }\n </div>\n <div class=\"hidden sm:block\">\n <p\n class=\"text-sm font-medium\"\n [class.text-primary-600]=\"i <= activeIndex()\"\n [class.text-surface-500]=\"i > activeIndex()\">\n {{ step.label() }}\n </p>\n @if (step.description()) {\n <p class=\"text-xs text-surface-400\">{{ step.description() }}</p>\n }\n </div>\n </button>\n @if (!last) {\n <div\n class=\"flex-1 h-0.5 mx-3 rounded-full transition-colors duration-200\"\n [class.bg-primary-600]=\"i < activeIndex()\"\n [class.bg-surface-200]=\"i >= activeIndex()\"></div>\n }\n </div>\n }\n</div>\n<!-- Step content -->\n<ng-content />\n", styles: [":host{display:block}\n"] });
2453
+ }
2454
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindStepper, decorators: [{
2455
+ type: Component,
2456
+ args: [{ selector: 'tailwind-stepper', template: "<!-- Step indicators -->\n<div class=\"flex items-center mb-6\">\n @for (step of steps(); track step.label(); let i = $index; let last = $last) {\n <div class=\"flex items-center\" [class.flex-1]=\"!last\">\n <button\n type=\"button\"\n (click)=\"goToStep(i)\"\n class=\"flex items-center gap-2 cursor-pointer group\"\n [attr.aria-current]=\"activeIndex() === i ? 'step' : null\">\n <div\n class=\"w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold border-2 transition-all duration-200\"\n [class.bg-primary-600]=\"i <= activeIndex()\"\n [class.border-primary-600]=\"i <= activeIndex()\"\n [class.text-white]=\"i <= activeIndex()\"\n [class.border-surface-300]=\"i > activeIndex()\"\n [class.text-surface-500]=\"i > activeIndex()\">\n @if (step.completed()) {\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fill-rule=\"evenodd\"\n d=\"M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z\"\n clip-rule=\"evenodd\" />\n </svg>\n } @else {\n {{ i + 1 }}\n }\n </div>\n <div class=\"hidden sm:block\">\n <p\n class=\"text-sm font-medium\"\n [class.text-primary-600]=\"i <= activeIndex()\"\n [class.text-surface-500]=\"i > activeIndex()\">\n {{ step.label() }}\n </p>\n @if (step.description()) {\n <p class=\"text-xs text-surface-400\">{{ step.description() }}</p>\n }\n </div>\n </button>\n @if (!last) {\n <div\n class=\"flex-1 h-0.5 mx-3 rounded-full transition-colors duration-200\"\n [class.bg-primary-600]=\"i < activeIndex()\"\n [class.bg-surface-200]=\"i >= activeIndex()\"></div>\n }\n </div>\n }\n</div>\n<!-- Step content -->\n<ng-content />\n", styles: [":host{display:block}\n"] }]
2457
+ }], ctorParameters: () => [], propDecorators: { activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], steps: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TailwindStep), { isSignal: true }] }] } });
2458
+
2459
+ class TailwindAccordionItem extends TailwindComponent {
2460
+ title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
2461
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
2462
+ isExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
2463
+ onToggle = output();
2464
+ toggle() {
2465
+ if (!this.disabled()) {
2466
+ this.isExpanded.update(v => !v);
2467
+ this.onToggle.emit();
2468
+ }
2469
+ }
2470
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindAccordionItem, deps: null, target: i0.ɵɵFactoryTarget.Component });
2471
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindAccordionItem, isStandalone: true, selector: "tailwind-accordion-item", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onToggle: "onToggle" }, usesInheritance: true, ngImport: i0, template: "<div [id]=\"id()\" [ngClass]=\"class()\" class=\"border-b border-surface-200 last:border-b-0\">\r\n <button\r\n type=\"button\"\r\n (click)=\"toggle()\"\r\n class=\"flex items-center justify-between w-full px-5 py-4 text-left text-sm font-medium text-surface-800 hover:bg-surface-50 transition-colors cursor-pointer\"\r\n [attr.aria-expanded]=\"isExpanded()\">\r\n <span>{{ title() }}</span>\r\n <svg\r\n class=\"w-4 h-4 text-surface-400 transition-transform duration-200\"\r\n [class.rotate-180]=\"isExpanded()\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"currentColor\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\r\n clip-rule=\"evenodd\" />\r\n </svg>\r\n </button>\r\n @if (isExpanded()) {\r\n <div class=\"px-5 py-4 text-sm text-surface-600\">\r\n <ng-content />\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
2472
+ }
2473
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindAccordionItem, decorators: [{
2474
+ type: Component,
2475
+ args: [{ imports: [CommonModule], selector: 'tailwind-accordion-item', template: "<div [id]=\"id()\" [ngClass]=\"class()\" class=\"border-b border-surface-200 last:border-b-0\">\r\n <button\r\n type=\"button\"\r\n (click)=\"toggle()\"\r\n class=\"flex items-center justify-between w-full px-5 py-4 text-left text-sm font-medium text-surface-800 hover:bg-surface-50 transition-colors cursor-pointer\"\r\n [attr.aria-expanded]=\"isExpanded()\">\r\n <span>{{ title() }}</span>\r\n <svg\r\n class=\"w-4 h-4 text-surface-400 transition-transform duration-200\"\r\n [class.rotate-180]=\"isExpanded()\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 20 20\"\r\n fill=\"currentColor\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z\"\r\n clip-rule=\"evenodd\" />\r\n </svg>\r\n </button>\r\n @if (isExpanded()) {\r\n <div class=\"px-5 py-4 text-sm text-surface-600\">\r\n <ng-content />\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
2476
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], onToggle: [{ type: i0.Output, args: ["onToggle"] }] } });
2477
+
2478
+ class TailwindAccordion extends TailwindComponent {
2479
+ items = contentChildren(TailwindAccordionItem, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
2480
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindAccordion, deps: null, target: i0.ɵɵFactoryTarget.Component });
2481
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.12", type: TailwindAccordion, isStandalone: true, selector: "tailwind-accordion", queries: [{ propertyName: "items", predicate: TailwindAccordionItem, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\r\n [id]=\"id()\"\r\n [ngClass]=\"class()\"\r\n class=\"border border-surface-200 rounded-xl overflow-hidden divide-y divide-surface-200\">\r\n <ng-content />\r\n</div>\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
2482
+ }
2483
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindAccordion, decorators: [{
2484
+ type: Component,
2485
+ args: [{ imports: [CommonModule], selector: 'tailwind-accordion', template: "<div\r\n [id]=\"id()\"\r\n [ngClass]=\"class()\"\r\n class=\"border border-surface-200 rounded-xl overflow-hidden divide-y divide-surface-200\">\r\n <ng-content />\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
2486
+ }], propDecorators: { items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TailwindAccordionItem), { isSignal: true }] }] } });
2487
+
2488
+ class TailwindModalRef {
2489
+ _closeFn;
2490
+ _result;
2491
+ /** @internal called by the service after component creation */
2492
+ _init(closeFn) {
2493
+ this._closeFn = closeFn;
2494
+ }
2495
+ /** Close the modal resolving with the given result */
2496
+ close(result) {
2497
+ this._result = result;
2498
+ this._closeFn();
2499
+ }
2500
+ /** @internal read by the service after the close animation */
2501
+ _getResult() {
2502
+ return this._result;
2503
+ }
2504
+ }
2505
+
2506
+ class TailwindModalService {
2507
+ appRef = inject(ApplicationRef);
2508
+ environmentInjector = inject(EnvironmentInjector);
2509
+ /**
2510
+ * Open a modal programmatically.
2511
+ *
2512
+ * The `component` is instantiated and its slot elements are projected into
2513
+ * TailwindModal's ng-content slots:
2514
+ * - `<tailwind-modal-title>` → header title area
2515
+ * - `<tailwind-modal-content>` → body area
2516
+ * - `<tailwind-modal-footer>` → footer area
2517
+ *
2518
+ * The component can inject `TailwindModalRef<R>` to close with a typed result
2519
+ * and `TAILWIND_MODAL_DATA` to receive the `config.data` payload.
2520
+ *
2521
+ * @returns Promise that resolves with `R` on `close(result)` or `undefined` on dismiss.
2522
+ */
2523
+ open(component, config = {}) {
2524
+ return new Promise(resolve => {
2525
+ const modalRef = new TailwindModalRef();
2526
+ const injector = Injector.create({
2527
+ providers: [
2528
+ { provide: TailwindModalRef, useValue: modalRef },
2529
+ { provide: TAILWIND_MODAL_DATA, useValue: config.data ?? null }
2530
+ ],
2531
+ parent: this.environmentInjector
2532
+ });
2533
+ // ── Step 1: create and render the user component ─────────────────────
2534
+ const userComp = createComponent(component, {
2535
+ environmentInjector: this.environmentInjector,
2536
+ elementInjector: injector
2537
+ });
2538
+ this.appRef.attachView(userComp.hostView);
2539
+ userComp.changeDetectorRef.detectChanges();
2540
+ // ── Step 2: extract slot elements from the rendered host ──────────────
2541
+ const host = userComp.location.nativeElement;
2542
+ const nodes = (sel) => Array.from(host.querySelectorAll(`:scope > ${sel}`));
2543
+ // ── Step 3: create TailwindModal projecting the slot nodes ────────────
2544
+ // projectableNodes[0] → <ng-content /> (title / catch-all)
2545
+ // projectableNodes[1] → <ng-content select="tailwind-modal-content" />
2546
+ // projectableNodes[2] → <ng-content select="tailwind-modal-footer" />
2547
+ const modalComp = createComponent(TailwindModal, {
2548
+ environmentInjector: this.environmentInjector,
2549
+ elementInjector: injector,
2550
+ projectableNodes: [
2551
+ nodes('tailwind-modal-title'),
2552
+ nodes('tailwind-modal-content'),
2553
+ nodes('tailwind-modal-footer')
2554
+ ]
2555
+ });
2556
+ modalComp.setInput('size', config.size ?? 'md');
2557
+ modalComp.setInput('showCloseButton', config.showCloseButton ?? true);
2558
+ modalComp.setInput('closeOnBackdrop', config.closeOnBackdrop ?? true);
2559
+ modalComp.setInput('closeOnEscape', config.closeOnEscape ?? true);
2560
+ this.appRef.attachView(modalComp.hostView);
2561
+ document.body.appendChild(modalComp.location.nativeElement);
2562
+ // ── Step 4: wire close ────────────────────────────────────────────────
2563
+ modalRef._init(() => modalComp.instance.close());
2564
+ const sub = modalComp.instance.onClose.subscribe(() => {
2565
+ sub.unsubscribe();
2566
+ resolve(modalRef._getResult());
2567
+ modalComp.location.nativeElement.remove();
2568
+ this.appRef.detachView(modalComp.hostView);
2569
+ this.appRef.detachView(userComp.hostView);
2570
+ modalComp.destroy();
2571
+ userComp.destroy();
2572
+ });
2573
+ modalComp.instance.open();
2574
+ });
2575
+ }
2576
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2577
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalService, providedIn: 'root' });
2578
+ }
2579
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindModalService, decorators: [{
2580
+ type: Injectable,
2581
+ args: [{ providedIn: 'root' }]
2582
+ }] });
2583
+
2584
+ class TailwindToastService {
2585
+ nextId = 0;
2586
+ toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : /* istanbul ignore next */ []));
2587
+ show(config) {
2588
+ const id = this.nextId++;
2589
+ const toast = { id, severity: 'info', duration: 4000, dismissible: true, ...config };
2590
+ this.toasts.update(list => [...list, toast]);
2591
+ if (toast.duration && toast.duration > 0) {
2592
+ setTimeout(() => this.dismiss(id), toast.duration);
2593
+ }
2594
+ return id;
2595
+ }
2596
+ success(message, title) {
2597
+ return this.show({ message, title, severity: 'success' });
2598
+ }
2599
+ warning(message, title) {
2600
+ return this.show({ message, title, severity: 'warning' });
2601
+ }
2602
+ danger(message, title) {
2603
+ return this.show({ message, title, severity: 'danger' });
2604
+ }
2605
+ info(message, title) {
2606
+ return this.show({ message, title, severity: 'info' });
2607
+ }
2608
+ dismiss(id) {
2609
+ this.toasts.update(list => list.filter(t => t.id !== id));
2610
+ }
2611
+ clear() {
2612
+ this.toasts.set([]);
2613
+ }
2614
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2615
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToastService, providedIn: 'root' });
2616
+ }
2617
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToastService, decorators: [{
2618
+ type: Injectable,
2619
+ args: [{ providedIn: 'root' }]
2620
+ }] });
2621
+
2622
+ class TailwindToast extends TailwindComponent {
2623
+ toastService = inject(TailwindToastService);
2624
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToast, deps: null, target: i0.ɵɵFactoryTarget.Component });
2625
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindToast, isStandalone: true, selector: "tailwind-toast", usesInheritance: true, ngImport: i0, template: "<div class=\"fixed bottom-4 right-4 z-1080 flex flex-col gap-2 max-w-sm w-full pointer-events-none\">\r\n @for (toast of toastService.toasts(); track toast.id) {\r\n <div\r\n class=\"pointer-events-auto rounded-xl border shadow-lg p-4 flex gap-3 animate-in slide-in-from-right-full duration-300\"\r\n [class.bg-success-50]=\"toast.severity === 'success'\"\r\n [class.border-success-200]=\"toast.severity === 'success'\"\r\n [class.bg-warning-50]=\"toast.severity === 'warning'\"\r\n [class.border-warning-200]=\"toast.severity === 'warning'\"\r\n [class.bg-danger-50]=\"toast.severity === 'danger'\"\r\n [class.border-danger-200]=\"toast.severity === 'danger'\"\r\n [class.bg-info-50]=\"toast.severity === 'info'\"\r\n [class.border-info-200]=\"toast.severity === 'info'\"\r\n role=\"alert\">\r\n <div class=\"flex-1 min-w-0\">\r\n @if (toast.title) {\r\n <p class=\"text-sm font-semibold mb-0.5\">{{ toast.title }}</p>\r\n }\r\n <p class=\"text-sm\">{{ toast.message }}</p>\r\n </div>\r\n @if (toast.dismissible) {\r\n <button\r\n type=\"button\"\r\n (click)=\"toastService.dismiss(toast.id)\"\r\n class=\"shrink-0 p-1 rounded-lg opacity-60 hover:opacity-100 transition-opacity cursor-pointer\"\r\n aria-label=\"Dismiss\">\r\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:contents}\n"] });
2626
+ }
2627
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToast, decorators: [{
2628
+ type: Component,
2629
+ args: [{ selector: 'tailwind-toast', template: "<div class=\"fixed bottom-4 right-4 z-1080 flex flex-col gap-2 max-w-sm w-full pointer-events-none\">\r\n @for (toast of toastService.toasts(); track toast.id) {\r\n <div\r\n class=\"pointer-events-auto rounded-xl border shadow-lg p-4 flex gap-3 animate-in slide-in-from-right-full duration-300\"\r\n [class.bg-success-50]=\"toast.severity === 'success'\"\r\n [class.border-success-200]=\"toast.severity === 'success'\"\r\n [class.bg-warning-50]=\"toast.severity === 'warning'\"\r\n [class.border-warning-200]=\"toast.severity === 'warning'\"\r\n [class.bg-danger-50]=\"toast.severity === 'danger'\"\r\n [class.border-danger-200]=\"toast.severity === 'danger'\"\r\n [class.bg-info-50]=\"toast.severity === 'info'\"\r\n [class.border-info-200]=\"toast.severity === 'info'\"\r\n role=\"alert\">\r\n <div class=\"flex-1 min-w-0\">\r\n @if (toast.title) {\r\n <p class=\"text-sm font-semibold mb-0.5\">{{ toast.title }}</p>\r\n }\r\n <p class=\"text-sm\">{{ toast.message }}</p>\r\n </div>\r\n @if (toast.dismissible) {\r\n <button\r\n type=\"button\"\r\n (click)=\"toastService.dismiss(toast.id)\"\r\n class=\"shrink-0 p-1 rounded-lg opacity-60 hover:opacity-100 transition-opacity cursor-pointer\"\r\n aria-label=\"Dismiss\">\r\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:contents}\n"] }]
2630
+ }] });
2631
+
2632
+ class TailwindNotification extends TailwindComponent {
2633
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
2634
+ severity = input('info', ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
2635
+ dismissible = input(true, ...(ngDevMode ? [{ debugName: "dismissible" }] : /* istanbul ignore next */ []));
2636
+ showActions = input(false, ...(ngDevMode ? [{ debugName: "showActions" }] : /* istanbul ignore next */ []));
2637
+ onDismiss = output();
2638
+ computedClasses = computed(() => {
2639
+ const variantMap = {
2640
+ success: 'bg-success-50 border-success-200 text-success-800',
2641
+ warning: 'bg-warning-50 border-warning-200 text-warning-800',
2642
+ danger: 'bg-danger-50 border-danger-200 text-danger-800',
2643
+ info: 'bg-info-50 border-info-200 text-info-800'
2644
+ };
2645
+ return `flex items-start rounded-xl border p-4 ${variantMap[this.severity()]}`;
2646
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
2647
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindNotification, deps: null, target: i0.ɵɵFactoryTarget.Component });
2648
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindNotification, isStandalone: true, selector: "tailwind-notification", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, showActions: { classPropertyName: "showActions", publicName: "showActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onDismiss: "onDismiss" }, usesInheritance: true, ngImport: i0, template: "<div [class]=\"computedClasses()\" role=\"alert\">\n <div class=\"flex-1 min-w-0\">\n @if (title()) {\n <p class=\"text-sm font-semibold mb-0.5\">{{ title() }}</p>\n }\n <p class=\"text-sm\"><ng-content /></p>\n @if (showActions()) {\n <div class=\"pt-3\">\n <ng-content select=\"tailwind-notification-actions\" />\n </div>\n }\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n (click)=\"onDismiss.emit()\"\n class=\"shrink-0 p-1 -m-1 rounded-lg opacity-60 hover:opacity-100 transition-opacity cursor-pointer\"\n aria-label=\"Dismiss\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\n </svg>\n </button>\n }\n</div>\n", styles: [":host{display:block}\n"] });
2649
+ }
2650
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindNotification, decorators: [{
2651
+ type: Component,
2652
+ args: [{ selector: 'tailwind-notification', template: "<div [class]=\"computedClasses()\" role=\"alert\">\n <div class=\"flex-1 min-w-0\">\n @if (title()) {\n <p class=\"text-sm font-semibold mb-0.5\">{{ title() }}</p>\n }\n <p class=\"text-sm\"><ng-content /></p>\n @if (showActions()) {\n <div class=\"pt-3\">\n <ng-content select=\"tailwind-notification-actions\" />\n </div>\n }\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n (click)=\"onDismiss.emit()\"\n class=\"shrink-0 p-1 -m-1 rounded-lg opacity-60 hover:opacity-100 transition-opacity cursor-pointer\"\n aria-label=\"Dismiss\">\n <svg class=\"w-4 h-4\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n d=\"M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z\" />\n </svg>\n </button>\n }\n</div>\n", styles: [":host{display:block}\n"] }]
2653
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], showActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActions", required: false }] }], onDismiss: [{ type: i0.Output, args: ["onDismiss"] }] } });
2654
+
2655
+ class TailwindMessage extends TailwindComponent {
2656
+ severity = input('info', ...(ngDevMode ? [{ debugName: "severity" }] : /* istanbul ignore next */ []));
2657
+ computedClasses = computed(() => {
2658
+ const variantMap = {
2659
+ success: 'bg-success-50 text-success-700 border-success-200',
2660
+ warning: 'bg-warning-50 text-warning-700 border-warning-200',
2661
+ danger: 'bg-danger-50 text-danger-700 border-danger-200',
2662
+ info: 'bg-info-50 text-info-700 border-info-200'
2663
+ };
2664
+ return `text-sm px-3 py-2 rounded-lg border ${variantMap[this.severity()]}`;
2665
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
2666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindMessage, deps: null, target: i0.ɵɵFactoryTarget.Component });
2667
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: TailwindMessage, isStandalone: true, selector: "tailwind-message", inputs: { severity: { classPropertyName: "severity", publicName: "severity", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div [class]=\"computedClasses()\" role=\"status\">\n <ng-content />\n</div>\n", styles: [":host{display:block}\n"] });
2668
+ }
2669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindMessage, decorators: [{
2670
+ type: Component,
2671
+ args: [{ selector: 'tailwind-message', template: "<div [class]=\"computedClasses()\" role=\"status\">\n <ng-content />\n</div>\n", styles: [":host{display:block}\n"] }]
2672
+ }], propDecorators: { severity: [{ type: i0.Input, args: [{ isSignal: true, alias: "severity", required: false }] }] } });
2673
+
2674
+ class TailwindSkeleton extends TailwindComponent {
2675
+ variant = input('text', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2676
+ width = input('100%', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
2677
+ height = input('', ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
2678
+ computedClasses = computed(() => {
2679
+ const base = 'tailwind-skeleton-pulse';
2680
+ const variantMap = {
2681
+ text: 'h-4 rounded',
2682
+ circle: 'rounded-full',
2683
+ rect: 'rounded-none',
2684
+ rounded: 'rounded-xl'
2685
+ };
2686
+ return `${base} ${variantMap[this.variant()]}`;
2687
+ }, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
2688
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSkeleton, deps: null, target: i0.ɵɵFactoryTarget.Component });
2689
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: TailwindSkeleton, isStandalone: true, selector: "tailwind-skeleton", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div\n [style.width]=\"width()\"\n [style.height]=\"height() || (variant() === 'circle' ? width() : '1.5rem')\"\n [class]=\"computedClasses()\"\n aria-hidden=\"true\"></div>\n", styles: [":host{display:block}@keyframes tailwind-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.tailwind-skeleton-pulse{animation:tailwind-shimmer 1.5s ease-in-out infinite;background:linear-gradient(90deg,var(--color-surface-200) 25%,var(--color-surface-100) 50%,var(--color-surface-200) 75%);background-size:200% 100%}\n"] });
2690
+ }
2691
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSkeleton, decorators: [{
2692
+ type: Component,
2693
+ args: [{ selector: 'tailwind-skeleton', template: "<div\n [style.width]=\"width()\"\n [style.height]=\"height() || (variant() === 'circle' ? width() : '1.5rem')\"\n [class]=\"computedClasses()\"\n aria-hidden=\"true\"></div>\n", styles: [":host{display:block}@keyframes tailwind-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.tailwind-skeleton-pulse{animation:tailwind-shimmer 1.5s ease-in-out infinite;background:linear-gradient(90deg,var(--color-surface-200) 25%,var(--color-surface-100) 50%,var(--color-surface-200) 75%);background-size:200% 100%}\n"] }]
2694
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }] } });
2695
+
2696
+ class TailwindToolbar extends TailwindComponent {
2697
+ /** When true, uses rounded corners (`rounded-xl`). */
2698
+ rounded = input(true, ...(ngDevMode ? [{ debugName: "rounded" }] : /* istanbul ignore next */ []));
2699
+ /**
2700
+ * Orizzontale: `full` = `w-full`; `container` = larghezza responsiva (95% / 85% / 75%) centrata.
2701
+ * Verticale: ignorato per l’altezza — il rail è sempre `h-full w-full` nella colonna.
2702
+ */
2703
+ width = input('full', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
2704
+ /** Applies a stronger drop shadow. */
2705
+ elevated = input(false, ...(ngDevMode ? [{ debugName: "elevated" }] : /* istanbul ignore next */ []));
2706
+ /** `horizontal` for a top app bar; `vertical` for a side rail (logo → menu → end). */
2707
+ orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
2708
+ /** Navigation / actions rendered between logo and end slots. */
2709
+ menu = input([], ...(ngDevMode ? [{ debugName: "menu" }] : /* istanbul ignore next */ []));
2710
+ /** Emitted when a non-disabled, non-divider menu entry is activated. */
2711
+ onMenuSelect = output();
2712
+ menuContainerClasses = computed(() => this.orientation() === 'horizontal'
2713
+ ? 'min-w-0 flex-1 flex flex-row flex-wrap items-center gap-1'
2714
+ : 'min-w-0 flex-1 flex flex-col gap-1 overflow-y-auto min-h-0', ...(ngDevMode ? [{ debugName: "menuContainerClasses" }] : /* istanbul ignore next */ []));
2715
+ menuItemButtonClasses = computed(() => this.orientation() === 'horizontal'
2716
+ ? 'shrink-0 rounded-md px-3 py-1.5 text-sm font-medium text-surface-700 hover:bg-surface-100 hover:text-surface-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors cursor-pointer border-0 bg-transparent'
2717
+ : 'w-full text-left rounded-md px-2 py-2 text-sm font-medium text-surface-700 hover:bg-surface-100 hover:text-surface-900 disabled:opacity-50 disabled:cursor-not-allowed transition-colors cursor-pointer border-0 bg-transparent', ...(ngDevMode ? [{ debugName: "menuItemButtonClasses" }] : /* istanbul ignore next */ []));
2718
+ rootClasses = computed(() => {
2719
+ const horizontal = this.orientation() === 'horizontal';
2720
+ const sizeClasses = horizontal
2721
+ ? this.width() === 'full'
2722
+ ? 'w-full'
2723
+ : 'w-[95%] md:w-[85%] lg:w-[75%] mx-auto'
2724
+ : 'h-full w-full';
2725
+ const base = [
2726
+ 'bg-white border border-surface-200',
2727
+ 'flex',
2728
+ sizeClasses,
2729
+ this.rounded() ? 'rounded-xl' : 'rounded-none',
2730
+ this.elevated() ? 'shadow-lg' : 'shadow-sm'
2731
+ ];
2732
+ if (horizontal) {
2733
+ base.push('flex-row items-center gap-3 px-4 py-3');
2734
+ }
2735
+ else {
2736
+ base.push('flex-col items-stretch gap-3 px-3 py-4 min-h-0');
2737
+ }
2738
+ return base.join(' ');
2739
+ }, ...(ngDevMode ? [{ debugName: "rootClasses" }] : /* istanbul ignore next */ []));
2740
+ selectMenuItem(item) {
2741
+ if (item.divider || item.disabled) {
2742
+ return;
2743
+ }
2744
+ this.onMenuSelect.emit(item);
2745
+ }
2746
+ menuTrackKey(index, item) {
2747
+ return item.value ?? item.label ?? String(index);
2748
+ }
2749
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToolbar, deps: null, target: i0.ɵɵFactoryTarget.Component });
2750
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindToolbar, isStandalone: true, selector: "tailwind-toolbar", inputs: { rounded: { classPropertyName: "rounded", publicName: "rounded", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, elevated: { classPropertyName: "elevated", publicName: "elevated", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, menu: { classPropertyName: "menu", publicName: "menu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onMenuSelect: "onMenuSelect" }, usesInheritance: true, ngImport: i0, template: "<div [class]=\"rootClasses()\">\r\n <div class=\"shrink-0\">\r\n <ng-content select=\"tailwind-toolbar-logo\" />\r\n </div>\r\n <nav [class]=\"menuContainerClasses()\" [attr.aria-label]=\"'Toolbar menu'\">\r\n @for (item of menu(); track menuTrackKey($index, item)) {\r\n @if (item.divider) {\r\n @if (orientation() === 'horizontal') {\r\n <span class=\"mx-0.5 h-5 w-px shrink-0 self-center bg-surface-200\" aria-hidden=\"true\"></span>\r\n } @else {\r\n <hr class=\"my-1 w-full border-0 border-t border-surface-100\" />\r\n }\r\n } @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"!!item.disabled\"\r\n [class]=\"menuItemButtonClasses()\"\r\n (click)=\"selectMenuItem(item)\">\r\n {{ item.label }}\r\n </button>\r\n }\r\n }\r\n </nav>\r\n <div\r\n class=\"flex flex-wrap items-center gap-2 shrink-0\"\r\n [class.justify-end]=\"orientation() === 'horizontal'\"\r\n [class.mt-auto]=\"orientation() === 'vertical'\">\r\n <ng-content select=\"tailwind-toolbar-end\" />\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}\n"] });
2751
+ }
2752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindToolbar, decorators: [{
2753
+ type: Component,
2754
+ args: [{ selector: 'tailwind-toolbar', template: "<div [class]=\"rootClasses()\">\r\n <div class=\"shrink-0\">\r\n <ng-content select=\"tailwind-toolbar-logo\" />\r\n </div>\r\n <nav [class]=\"menuContainerClasses()\" [attr.aria-label]=\"'Toolbar menu'\">\r\n @for (item of menu(); track menuTrackKey($index, item)) {\r\n @if (item.divider) {\r\n @if (orientation() === 'horizontal') {\r\n <span class=\"mx-0.5 h-5 w-px shrink-0 self-center bg-surface-200\" aria-hidden=\"true\"></span>\r\n } @else {\r\n <hr class=\"my-1 w-full border-0 border-t border-surface-100\" />\r\n }\r\n } @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"!!item.disabled\"\r\n [class]=\"menuItemButtonClasses()\"\r\n (click)=\"selectMenuItem(item)\">\r\n {{ item.label }}\r\n </button>\r\n }\r\n }\r\n </nav>\r\n <div\r\n class=\"flex flex-wrap items-center gap-2 shrink-0\"\r\n [class.justify-end]=\"orientation() === 'horizontal'\"\r\n [class.mt-auto]=\"orientation() === 'vertical'\">\r\n <ng-content select=\"tailwind-toolbar-end\" />\r\n </div>\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
2755
+ }], propDecorators: { rounded: [{ type: i0.Input, args: [{ isSignal: true, alias: "rounded", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], elevated: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevated", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], menu: [{ type: i0.Input, args: [{ isSignal: true, alias: "menu", required: false }] }], onMenuSelect: [{ type: i0.Output, args: ["onMenuSelect"] }] } });
2756
+
2757
+ class TailwindDivider extends TailwindComponent {
2758
+ /** Rule direction */
2759
+ orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
2760
+ /** Adds horizontal margin to the rule (horizontal orientation only). */
2761
+ inset = input(false, ...(ngDevMode ? [{ debugName: "inset" }] : /* istanbul ignore next */ []));
2762
+ /** Border style for the rule */
2763
+ variant = input('solid', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
2764
+ /** Centered text between two lines (horizontal only; ignored when empty). */
2765
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
2766
+ isLabeledHorizontal = computed(() => this.orientation() === 'horizontal' && !!this.label()?.trim(), ...(ngDevMode ? [{ debugName: "isLabeledHorizontal" }] : /* istanbul ignore next */ []));
2767
+ ruleClasses = computed(() => {
2768
+ const inset = this.inset() && this.orientation() === 'horizontal' ? 'mx-4' : '';
2769
+ const variant = this.variant() === 'dashed' ? 'border-dashed' : 'border-solid';
2770
+ if (this.orientation() === 'vertical') {
2771
+ return ['self-stretch shrink-0 w-px min-h-full border-0 border-l', variant, 'border-surface-200']
2772
+ .join(' ');
2773
+ }
2774
+ return ['w-full border-0 border-t', variant, 'border-surface-200', inset].filter(Boolean).join(' ');
2775
+ }, ...(ngDevMode ? [{ debugName: "ruleClasses" }] : /* istanbul ignore next */ []));
2776
+ /** Top rule for labeled horizontal layout */
2777
+ ruleLineClass = computed(() => {
2778
+ const variant = this.variant() === 'dashed' ? 'border-dashed' : 'border-solid';
2779
+ return ['border-surface-200', variant].join(' ');
2780
+ }, ...(ngDevMode ? [{ debugName: "ruleLineClass" }] : /* istanbul ignore next */ []));
2781
+ labeledRowClass = computed(() => this.inset() ? 'flex items-center gap-3 w-full mx-4' : 'flex items-center gap-3 w-full', ...(ngDevMode ? [{ debugName: "labeledRowClass" }] : /* istanbul ignore next */ []));
2782
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDivider, deps: null, target: i0.ɵɵFactoryTarget.Component });
2783
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindDivider, isStandalone: true, selector: "tailwind-divider", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, inset: { classPropertyName: "inset", publicName: "inset", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@if (isLabeledHorizontal()) {\r\n <div [class]=\"labeledRowClass()\" role=\"separator\" [attr.aria-label]=\"label()\">\r\n <div class=\"flex-1 border-0 border-t\" [class]=\"ruleLineClass()\"></div>\r\n <span class=\"text-xs font-medium text-surface-500 shrink-0\">{{ label() }}</span>\r\n <div class=\"flex-1 border-0 border-t\" [class]=\"ruleLineClass()\"></div>\r\n </div>\r\n} @else {\r\n <div [class]=\"ruleClasses()\" role=\"separator\"></div>\r\n}\r\n", styles: [":host{display:block}\n"] });
2784
+ }
2785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindDivider, decorators: [{
2786
+ type: Component,
2787
+ args: [{ selector: 'tailwind-divider', template: "@if (isLabeledHorizontal()) {\r\n <div [class]=\"labeledRowClass()\" role=\"separator\" [attr.aria-label]=\"label()\">\r\n <div class=\"flex-1 border-0 border-t\" [class]=\"ruleLineClass()\"></div>\r\n <span class=\"text-xs font-medium text-surface-500 shrink-0\">{{ label() }}</span>\r\n <div class=\"flex-1 border-0 border-t\" [class]=\"ruleLineClass()\"></div>\r\n </div>\r\n} @else {\r\n <div [class]=\"ruleClasses()\" role=\"separator\"></div>\r\n}\r\n", styles: [":host{display:block}\n"] }]
2788
+ }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], inset: [{ type: i0.Input, args: [{ isSignal: true, alias: "inset", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
2789
+
2790
+ class TailwindMeter extends TailwindComponent {
2791
+ /** Segments rendered as proportional blocks in the bar. */
2792
+ segments = input([], ...(ngDevMode ? [{ debugName: "segments" }] : /* istanbul ignore next */ []));
2793
+ /**
2794
+ * Scale maximum. Each segment `value` is shown as `value / max` of the bar width.
2795
+ * Default 100 (percent-style values).
2796
+ */
2797
+ max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
2798
+ /** Show a simple legend under the bar */
2799
+ showLabels = input(true, ...(ngDevMode ? [{ debugName: "showLabels" }] : /* istanbul ignore next */ []));
2800
+ /** Track height */
2801
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2802
+ trackHeightClass = computed(() => {
2803
+ const map = {
2804
+ xs: 'h-1.5',
2805
+ sm: 'h-2',
2806
+ md: 'h-2.5',
2807
+ lg: 'h-3.5',
2808
+ xl: 'h-4'
2809
+ };
2810
+ return map[this.size()];
2811
+ }, ...(ngDevMode ? [{ debugName: "trackHeightClass" }] : /* istanbul ignore next */ []));
2812
+ totalValue = computed(() => this.segments().reduce((s, x) => s + Math.max(0, x.value), 0), ...(ngDevMode ? [{ debugName: "totalValue" }] : /* istanbul ignore next */ []));
2813
+ scaleMax = computed(() => {
2814
+ const m = this.max();
2815
+ if (m > 0) {
2816
+ return m;
2817
+ }
2818
+ const t = this.totalValue();
2819
+ return t > 0 ? t : 1;
2820
+ }, ...(ngDevMode ? [{ debugName: "scaleMax" }] : /* istanbul ignore next */ []));
2821
+ segmentLayouts = computed(() => {
2822
+ const cap = this.scaleMax();
2823
+ return this.segments().map(seg => {
2824
+ const pct = cap > 0 ? (Math.max(0, seg.value) / cap) * 100 : 0;
2825
+ const variant = seg.variant ?? 'primary';
2826
+ return { ...seg, widthPct: pct, barClass: this.variantToBarClass(variant) };
2827
+ });
2828
+ }, ...(ngDevMode ? [{ debugName: "segmentLayouts" }] : /* istanbul ignore next */ []));
2829
+ trackContainerClasses = computed(() => `flex w-full overflow-hidden rounded-full bg-surface-200 ${this.trackHeightClass()}`, ...(ngDevMode ? [{ debugName: "trackContainerClasses" }] : /* istanbul ignore next */ []));
2830
+ legendSwatchClass(variant) {
2831
+ return this.variantToBarClass(variant ?? 'primary');
2832
+ }
2833
+ variantToBarClass(variant) {
2834
+ const map = {
2835
+ primary: 'bg-primary-600',
2836
+ success: 'bg-success-600',
2837
+ warning: 'bg-warning-500',
2838
+ danger: 'bg-danger-600',
2839
+ info: 'bg-info-600'
2840
+ };
2841
+ return map[variant] ?? map['primary'];
2842
+ }
2843
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindMeter, deps: null, target: i0.ɵɵFactoryTarget.Component });
2844
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindMeter, isStandalone: true, selector: "tailwind-meter", inputs: { segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, showLabels: { classPropertyName: "showLabels", publicName: "showLabels", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"w-full space-y-2\">\r\n <div\r\n [class]=\"trackContainerClasses()\"\r\n role=\"meter\"\r\n [attr.aria-valuemin]=\"0\"\r\n [attr.aria-valuemax]=\"scaleMax()\"\r\n [attr.aria-valuenow]=\"totalValue()\"\r\n [attr.aria-label]=\"'Meter'\">\r\n @for (seg of segmentLayouts(); track $index) {\r\n @if (seg.widthPct > 0) {\r\n <div\r\n class=\"h-full min-w-0 transition-all duration-300 ease-out\"\r\n [class]=\"seg.barClass\"\r\n [style.width.%]=\"seg.widthPct\"\r\n [attr.title]=\"seg.label + ': ' + seg.value\"></div>\r\n }\r\n }\r\n </div>\r\n\r\n @if (showLabels()) {\r\n <div class=\"flex flex-wrap gap-x-4 gap-y-1 text-xs text-surface-600\">\r\n @for (seg of segments(); track $index) {\r\n <span class=\"inline-flex items-center gap-1.5\">\r\n <span class=\"inline-block size-2 rounded-sm shrink-0\" [class]=\"legendSwatchClass(seg.variant)\"></span>\r\n <span>{{ seg.label }}</span>\r\n <span class=\"text-surface-400\">({{ seg.value }})</span>\r\n </span>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] });
2845
+ }
2846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindMeter, decorators: [{
2847
+ type: Component,
2848
+ args: [{ selector: 'tailwind-meter', template: "<div class=\"w-full space-y-2\">\r\n <div\r\n [class]=\"trackContainerClasses()\"\r\n role=\"meter\"\r\n [attr.aria-valuemin]=\"0\"\r\n [attr.aria-valuemax]=\"scaleMax()\"\r\n [attr.aria-valuenow]=\"totalValue()\"\r\n [attr.aria-label]=\"'Meter'\">\r\n @for (seg of segmentLayouts(); track $index) {\r\n @if (seg.widthPct > 0) {\r\n <div\r\n class=\"h-full min-w-0 transition-all duration-300 ease-out\"\r\n [class]=\"seg.barClass\"\r\n [style.width.%]=\"seg.widthPct\"\r\n [attr.title]=\"seg.label + ': ' + seg.value\"></div>\r\n }\r\n }\r\n </div>\r\n\r\n @if (showLabels()) {\r\n <div class=\"flex flex-wrap gap-x-4 gap-y-1 text-xs text-surface-600\">\r\n @for (seg of segments(); track $index) {\r\n <span class=\"inline-flex items-center gap-1.5\">\r\n <span class=\"inline-block size-2 rounded-sm shrink-0\" [class]=\"legendSwatchClass(seg.variant)\"></span>\r\n <span>{{ seg.label }}</span>\r\n <span class=\"text-surface-400\">({{ seg.value }})</span>\r\n </span>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}\n"] }]
2849
+ }], propDecorators: { segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], showLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabels", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
2850
+
2851
+ class TailwindSlider extends TailwindComponent {
2852
+ /** Minimum bound */
2853
+ min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
2854
+ /** Maximum bound */
2855
+ max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
2856
+ /** Step increment */
2857
+ step = input(1, ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
2858
+ /** Two-thumb range mode */
2859
+ range = input(false, ...(ngDevMode ? [{ debugName: "range" }] : /* istanbul ignore next */ []));
2860
+ /** Layout */
2861
+ orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
2862
+ /** Tick marks at each step */
2863
+ showTicks = input(false, ...(ngDevMode ? [{ debugName: "showTicks" }] : /* istanbul ignore next */ []));
2864
+ /** Control size */
2865
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2866
+ trackRef = viewChild('track', ...(ngDevMode ? [{ debugName: "trackRef" }] : /* istanbul ignore next */ []));
2867
+ /** Single-thumb value */
2868
+ singleValue = signal(0, ...(ngDevMode ? [{ debugName: "singleValue" }] : /* istanbul ignore next */ []));
2869
+ /** Range: lower value */
2870
+ rangeLow = signal(0, ...(ngDevMode ? [{ debugName: "rangeLow" }] : /* istanbul ignore next */ []));
2871
+ /** Range: upper value */
2872
+ rangeHigh = signal(100, ...(ngDevMode ? [{ debugName: "rangeHigh" }] : /* istanbul ignore next */ []));
2873
+ /** Disabled via template (combined with form `setDisabledState`) */
2874
+ hostDisabled = input(false, { ...(ngDevMode ? { debugName: "hostDisabled" } : /* istanbul ignore next */ {}), alias: 'disabled', transform: booleanAttribute });
2875
+ isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
2876
+ isEffectivelyDisabled = computed(() => this.isDisabled() || this.hostDisabled(), ...(ngDevMode ? [{ debugName: "isEffectivelyDisabled" }] : /* istanbul ignore next */ []));
2877
+ onChange = () => { };
2878
+ onTouched = () => { };
2879
+ activeThumb = signal(null, ...(ngDevMode ? [{ debugName: "activeThumb" }] : /* istanbul ignore next */ []));
2880
+ thumbSizeClass = computed(() => {
2881
+ const map = {
2882
+ xs: 'size-3',
2883
+ sm: 'size-3.5',
2884
+ md: 'size-4',
2885
+ lg: 'size-5',
2886
+ xl: 'size-6'
2887
+ };
2888
+ return map[this.size()];
2889
+ }, ...(ngDevMode ? [{ debugName: "thumbSizeClass" }] : /* istanbul ignore next */ []));
2890
+ trackThickness = computed(() => {
2891
+ const map = {
2892
+ xs: 'h-1',
2893
+ sm: 'h-1.5',
2894
+ md: 'h-2',
2895
+ lg: 'h-2.5',
2896
+ xl: 'h-3'
2897
+ };
2898
+ return map[this.size()];
2899
+ }, ...(ngDevMode ? [{ debugName: "trackThickness" }] : /* istanbul ignore next */ []));
2900
+ verticalTrackThickness = computed(() => {
2901
+ const map = {
2902
+ xs: 'w-1',
2903
+ sm: 'w-1.5',
2904
+ md: 'w-2',
2905
+ lg: 'w-2.5',
2906
+ xl: 'w-3'
2907
+ };
2908
+ return map[this.size()];
2909
+ }, ...(ngDevMode ? [{ debugName: "verticalTrackThickness" }] : /* istanbul ignore next */ []));
2910
+ singlePct = computed(() => this.valueToPct(this.singleValue()), ...(ngDevMode ? [{ debugName: "singlePct" }] : /* istanbul ignore next */ []));
2911
+ lowPct = computed(() => this.valueToPct(this.rangeLow()), ...(ngDevMode ? [{ debugName: "lowPct" }] : /* istanbul ignore next */ []));
2912
+ highPct = computed(() => this.valueToPct(this.rangeHigh()), ...(ngDevMode ? [{ debugName: "highPct" }] : /* istanbul ignore next */ []));
2913
+ fillStartPct = computed(() => (this.range() ? Math.min(this.lowPct(), this.highPct()) : 0), ...(ngDevMode ? [{ debugName: "fillStartPct" }] : /* istanbul ignore next */ []));
2914
+ fillWidthPct = computed(() => this.range() ? Math.abs(this.highPct() - this.lowPct()) : this.singlePct(), ...(ngDevMode ? [{ debugName: "fillWidthPct" }] : /* istanbul ignore next */ []));
2915
+ tickPositions = computed(() => {
2916
+ if (!this.showTicks()) {
2917
+ return [];
2918
+ }
2919
+ const lo = this.min();
2920
+ const hi = this.max();
2921
+ const st = this.step();
2922
+ if (st <= 0 || hi < lo) {
2923
+ return [];
2924
+ }
2925
+ const steps = Math.round((hi - lo) / st);
2926
+ const out = [];
2927
+ for (let i = 0; i <= steps; i++) {
2928
+ out.push(this.valueToPct(lo + i * st));
2929
+ }
2930
+ return out;
2931
+ }, ...(ngDevMode ? [{ debugName: "tickPositions" }] : /* istanbul ignore next */ []));
2932
+ writeValue(value) {
2933
+ const lo = this.min();
2934
+ const hi = this.max();
2935
+ if (this.range()) {
2936
+ const pair = Array.isArray(value) ? value : [lo, hi];
2937
+ const a = this.snap(Math.min(pair[0] ?? lo, pair[1] ?? hi));
2938
+ const b = this.snap(Math.max(pair[0] ?? lo, pair[1] ?? hi));
2939
+ this.rangeLow.set(Math.min(a, b));
2940
+ this.rangeHigh.set(Math.max(a, b));
2941
+ }
2942
+ else {
2943
+ const n = Array.isArray(value) ? value[0] : value;
2944
+ const num = typeof n === 'number' && !Number.isNaN(n) ? n : lo;
2945
+ this.singleValue.set(this.snap(num));
2946
+ }
2947
+ }
2948
+ registerOnChange(fn) {
2949
+ this.onChange = fn;
2950
+ }
2951
+ registerOnTouched(fn) {
2952
+ this.onTouched = fn;
2953
+ }
2954
+ setDisabledState(disabled) {
2955
+ this.isDisabled.set(disabled);
2956
+ }
2957
+ valueToPct(v) {
2958
+ const lo = this.min();
2959
+ const hi = this.max();
2960
+ if (hi === lo) {
2961
+ return 0;
2962
+ }
2963
+ return ((this.snap(v) - lo) / (hi - lo)) * 100;
2964
+ }
2965
+ snap(raw) {
2966
+ const lo = this.min();
2967
+ const hi = this.max();
2968
+ const st = this.step();
2969
+ if (st <= 0) {
2970
+ return Math.min(hi, Math.max(lo, raw));
2971
+ }
2972
+ const stepped = Math.round((raw - lo) / st) * st + lo;
2973
+ const rounded = Math.round(stepped * 1e6) / 1e6;
2974
+ return Math.min(hi, Math.max(lo, rounded));
2975
+ }
2976
+ pctToValue(pct) {
2977
+ const lo = this.min();
2978
+ const hi = this.max();
2979
+ const v = lo + (pct / 100) * (hi - lo);
2980
+ return this.snap(v);
2981
+ }
2982
+ onThumbPointerDown(event, thumbIndex) {
2983
+ event.stopPropagation();
2984
+ this.onTrackPointerDown(event, thumbIndex);
2985
+ }
2986
+ onTrackPointerDown(event, thumbIndex) {
2987
+ if (this.isEffectivelyDisabled()) {
2988
+ return;
2989
+ }
2990
+ event.preventDefault();
2991
+ const track = this.trackRef()?.nativeElement;
2992
+ if (!track) {
2993
+ return;
2994
+ }
2995
+ let thumb = thumbIndex;
2996
+ if (!this.range()) {
2997
+ thumb = null;
2998
+ }
2999
+ else if (thumb === null) {
3000
+ const v = this.readValueFromPointer(event, track);
3001
+ const low = this.rangeLow();
3002
+ const high = this.rangeHigh();
3003
+ const d0 = Math.abs(v - low);
3004
+ const d1 = Math.abs(v - high);
3005
+ thumb = d0 <= d1 ? 0 : 1;
3006
+ }
3007
+ this.activeThumb.set(thumb);
3008
+ this.applyPointer(event, track, thumb);
3009
+ if (typeof track.setPointerCapture === 'function') {
3010
+ track.setPointerCapture(event.pointerId);
3011
+ }
3012
+ const move = (ev) => this.applyPointer(ev, track, thumb);
3013
+ const up = (ev) => {
3014
+ document.removeEventListener('pointermove', move);
3015
+ document.removeEventListener('pointerup', up);
3016
+ document.removeEventListener('pointercancel', up);
3017
+ try {
3018
+ track.releasePointerCapture(ev.pointerId);
3019
+ }
3020
+ catch {
3021
+ /* ignore */
3022
+ }
3023
+ this.activeThumb.set(null);
3024
+ this.onTouched();
3025
+ };
3026
+ document.addEventListener('pointermove', move);
3027
+ document.addEventListener('pointerup', up);
3028
+ document.addEventListener('pointercancel', up);
3029
+ }
3030
+ readValueFromPointer(event, track) {
3031
+ const rect = track.getBoundingClientRect();
3032
+ const horizontal = this.orientation() === 'horizontal';
3033
+ let ratio;
3034
+ if (horizontal) {
3035
+ ratio = (event.clientX - rect.left) / rect.width;
3036
+ }
3037
+ else {
3038
+ ratio = 1 - (event.clientY - rect.top) / rect.height;
3039
+ }
3040
+ ratio = Math.min(1, Math.max(0, ratio));
3041
+ return this.pctToValue(ratio * 100);
3042
+ }
3043
+ applyPointer(event, track, thumbIndex) {
3044
+ const next = this.readValueFromPointer(event, track);
3045
+ if (this.range()) {
3046
+ const idx = thumbIndex ?? 0;
3047
+ if (idx === 0) {
3048
+ const hi = this.rangeHigh();
3049
+ this.rangeLow.set(this.snap(Math.min(next, hi)));
3050
+ }
3051
+ else {
3052
+ const lo = this.rangeLow();
3053
+ this.rangeHigh.set(this.snap(Math.max(next, lo)));
3054
+ }
3055
+ this.onChange([this.rangeLow(), this.rangeHigh()]);
3056
+ }
3057
+ else {
3058
+ this.singleValue.set(next);
3059
+ this.onChange(this.singleValue());
3060
+ }
3061
+ }
3062
+ onKeyDown(event, thumbIndex) {
3063
+ if (this.isEffectivelyDisabled()) {
3064
+ return;
3065
+ }
3066
+ const keys = ['ArrowLeft', 'ArrowRight', 'ArrowDown', 'ArrowUp', 'Home', 'End'];
3067
+ if (!keys.includes(event.key)) {
3068
+ return;
3069
+ }
3070
+ event.preventDefault();
3071
+ const lo = this.min();
3072
+ const hi = this.max();
3073
+ const st = this.step();
3074
+ const horizontal = this.orientation() === 'horizontal';
3075
+ const decKey = horizontal ? 'ArrowLeft' : 'ArrowDown';
3076
+ const incKey = horizontal ? 'ArrowRight' : 'ArrowUp';
3077
+ const delta = (key) => {
3078
+ if (key === 'Home') {
3079
+ return lo - (thumbIndex === 0 ? this.rangeLow() : this.rangeHigh());
3080
+ }
3081
+ if (key === 'End') {
3082
+ return hi - (thumbIndex === 0 ? this.rangeLow() : this.rangeHigh());
3083
+ }
3084
+ if (key === decKey) {
3085
+ return -st;
3086
+ }
3087
+ if (key === incKey) {
3088
+ return st;
3089
+ }
3090
+ return 0;
3091
+ };
3092
+ const d = delta(event.key);
3093
+ if (d === 0) {
3094
+ return;
3095
+ }
3096
+ if (this.range()) {
3097
+ if (thumbIndex === 0) {
3098
+ const next = this.snap(this.rangeLow() + d);
3099
+ this.rangeLow.set(Math.min(next, this.rangeHigh()));
3100
+ }
3101
+ else {
3102
+ const next = this.snap(this.rangeHigh() + d);
3103
+ this.rangeHigh.set(Math.max(next, this.rangeLow()));
3104
+ }
3105
+ this.onChange([this.rangeLow(), this.rangeHigh()]);
3106
+ }
3107
+ else {
3108
+ this.singleValue.set(this.snap(this.singleValue() + d));
3109
+ this.onChange(this.singleValue());
3110
+ }
3111
+ }
3112
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSlider, deps: null, target: i0.ɵɵFactoryTarget.Component });
3113
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TailwindSlider, isStandalone: true, selector: "tailwind-slider", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, showTicks: { classPropertyName: "showTicks", publicName: "showTicks", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hostDisabled: { classPropertyName: "hostDisabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
3114
+ {
3115
+ provide: NG_VALUE_ACCESSOR,
3116
+ useExisting: forwardRef(() => TailwindSlider),
3117
+ multi: true
3118
+ }
3119
+ ], viewQueries: [{ propertyName: "trackRef", first: true, predicate: ["track"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (orientation() === 'horizontal') {\r\n <div\r\n #track\r\n class=\"relative w-full touch-none select-none py-3\"\r\n [class.opacity-50]=\"isEffectivelyDisabled()\"\r\n [class.pointer-events-none]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onTrackPointerDown($event, range() ? null : null)\">\r\n <div class=\"relative h-6 w-full\">\r\n <!-- rail -->\r\n <div\r\n class=\"pointer-events-none absolute left-0 right-0 top-1/2 -translate-y-1/2 rounded-full bg-surface-200\"\r\n [class]=\"trackThickness()\"></div>\r\n\r\n @if (showTicks()) {\r\n @for (p of tickPositions(); track $index) {\r\n <div\r\n class=\"pointer-events-none absolute top-1/2 h-2 w-px -translate-x-1/2 -translate-y-1/2 bg-surface-300\"\r\n [style.left.%]=\"p\"></div>\r\n }\r\n }\r\n\r\n <!-- fill -->\r\n <div\r\n class=\"pointer-events-none absolute top-1/2 -translate-y-1/2 rounded-full bg-primary-500\"\r\n [class]=\"trackThickness()\"\r\n [style.left.%]=\"fillStartPct()\"\r\n [style.width.%]=\"fillWidthPct()\"></div>\r\n\r\n @if (range()) {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.left.%]=\"lowPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeLow()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.left.%]=\"highPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeHigh()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 1)\"\r\n (keydown)=\"onKeyDown($event, 1)\"></button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.left.%]=\"singlePct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"singleValue()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n }\r\n </div>\r\n </div>\r\n} @else {\r\n <div\r\n #track\r\n class=\"relative mx-auto h-52 w-10 touch-none select-none\"\r\n [class.opacity-50]=\"isEffectivelyDisabled()\"\r\n [class.pointer-events-none]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onTrackPointerDown($event, range() ? null : null)\">\r\n <div class=\"relative h-full w-full\">\r\n <div\r\n class=\"pointer-events-none absolute bottom-0 left-1/2 top-0 -translate-x-1/2 rounded-full bg-surface-200\"\r\n [class]=\"verticalTrackThickness()\"></div>\r\n\r\n @if (showTicks()) {\r\n @for (p of tickPositions(); track $index) {\r\n <div\r\n class=\"pointer-events-none absolute left-1/2 w-2 h-px -translate-x-1/2 translate-y-1/2 bg-surface-300\"\r\n [style.bottom.%]=\"p\"></div>\r\n }\r\n }\r\n\r\n <div\r\n class=\"pointer-events-none absolute bottom-0 left-1/2 -translate-x-1/2 rounded-full bg-primary-500\"\r\n [class]=\"verticalTrackThickness()\"\r\n [style.bottom.%]=\"fillStartPct()\"\r\n [style.height.%]=\"fillWidthPct()\"></div>\r\n\r\n @if (range()) {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute left-1/2 z-10 -translate-x-1/2 translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.bottom.%]=\"lowPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeLow()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute left-1/2 z-10 -translate-x-1/2 translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.bottom.%]=\"highPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeHigh()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 1)\"\r\n (keydown)=\"onKeyDown($event, 1)\"></button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute left-1/2 z-10 -translate-x-1/2 translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.bottom.%]=\"singlePct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"singleValue()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:block}.tailwind-slider-thumb{cursor:pointer}.tailwind-slider-thumb:disabled{cursor:not-allowed}\n"] });
3120
+ }
3121
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TailwindSlider, decorators: [{
3122
+ type: Component,
3123
+ args: [{ selector: 'tailwind-slider', providers: [
3124
+ {
3125
+ provide: NG_VALUE_ACCESSOR,
3126
+ useExisting: forwardRef(() => TailwindSlider),
3127
+ multi: true
3128
+ }
3129
+ ], template: "@if (orientation() === 'horizontal') {\r\n <div\r\n #track\r\n class=\"relative w-full touch-none select-none py-3\"\r\n [class.opacity-50]=\"isEffectivelyDisabled()\"\r\n [class.pointer-events-none]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onTrackPointerDown($event, range() ? null : null)\">\r\n <div class=\"relative h-6 w-full\">\r\n <!-- rail -->\r\n <div\r\n class=\"pointer-events-none absolute left-0 right-0 top-1/2 -translate-y-1/2 rounded-full bg-surface-200\"\r\n [class]=\"trackThickness()\"></div>\r\n\r\n @if (showTicks()) {\r\n @for (p of tickPositions(); track $index) {\r\n <div\r\n class=\"pointer-events-none absolute top-1/2 h-2 w-px -translate-x-1/2 -translate-y-1/2 bg-surface-300\"\r\n [style.left.%]=\"p\"></div>\r\n }\r\n }\r\n\r\n <!-- fill -->\r\n <div\r\n class=\"pointer-events-none absolute top-1/2 -translate-y-1/2 rounded-full bg-primary-500\"\r\n [class]=\"trackThickness()\"\r\n [style.left.%]=\"fillStartPct()\"\r\n [style.width.%]=\"fillWidthPct()\"></div>\r\n\r\n @if (range()) {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.left.%]=\"lowPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeLow()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.left.%]=\"highPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeHigh()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 1)\"\r\n (keydown)=\"onKeyDown($event, 1)\"></button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.left.%]=\"singlePct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"singleValue()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n }\r\n </div>\r\n </div>\r\n} @else {\r\n <div\r\n #track\r\n class=\"relative mx-auto h-52 w-10 touch-none select-none\"\r\n [class.opacity-50]=\"isEffectivelyDisabled()\"\r\n [class.pointer-events-none]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onTrackPointerDown($event, range() ? null : null)\">\r\n <div class=\"relative h-full w-full\">\r\n <div\r\n class=\"pointer-events-none absolute bottom-0 left-1/2 top-0 -translate-x-1/2 rounded-full bg-surface-200\"\r\n [class]=\"verticalTrackThickness()\"></div>\r\n\r\n @if (showTicks()) {\r\n @for (p of tickPositions(); track $index) {\r\n <div\r\n class=\"pointer-events-none absolute left-1/2 w-2 h-px -translate-x-1/2 translate-y-1/2 bg-surface-300\"\r\n [style.bottom.%]=\"p\"></div>\r\n }\r\n }\r\n\r\n <div\r\n class=\"pointer-events-none absolute bottom-0 left-1/2 -translate-x-1/2 rounded-full bg-primary-500\"\r\n [class]=\"verticalTrackThickness()\"\r\n [style.bottom.%]=\"fillStartPct()\"\r\n [style.height.%]=\"fillWidthPct()\"></div>\r\n\r\n @if (range()) {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute left-1/2 z-10 -translate-x-1/2 translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.bottom.%]=\"lowPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeLow()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute left-1/2 z-10 -translate-x-1/2 translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.bottom.%]=\"highPct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"rangeHigh()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 1)\"\r\n (keydown)=\"onKeyDown($event, 1)\"></button>\r\n } @else {\r\n <button\r\n type=\"button\"\r\n [disabled]=\"isEffectivelyDisabled()\"\r\n class=\"tailwind-slider-thumb absolute left-1/2 z-10 -translate-x-1/2 translate-y-1/2 rounded-full border-2 border-white bg-primary-600 shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2\"\r\n [class]=\"thumbSizeClass()\"\r\n [style.bottom.%]=\"singlePct()\"\r\n role=\"slider\"\r\n [attr.aria-valuemin]=\"min()\"\r\n [attr.aria-valuemax]=\"max()\"\r\n [attr.aria-valuenow]=\"singleValue()\"\r\n [attr.aria-disabled]=\"isEffectivelyDisabled()\"\r\n (pointerdown)=\"onThumbPointerDown($event, 0)\"\r\n (keydown)=\"onKeyDown($event, 0)\"></button>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [":host{display:block}.tailwind-slider-thumb{cursor:pointer}.tailwind-slider-thumb:disabled{cursor:not-allowed}\n"] }]
3130
+ }], propDecorators: { min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], range: [{ type: i0.Input, args: [{ isSignal: true, alias: "range", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], showTicks: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTicks", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], trackRef: [{ type: i0.ViewChild, args: ['track', { isSignal: true }] }], hostDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
3131
+
3132
+ // Batch 1 — Foundation
3133
+
3134
+ /*
3135
+ * Public API Surface of angular-tailwind-components
3136
+ */
3137
+ // Models & Types
3138
+
3139
+ /**
3140
+ * Generated bundle index. Do not edit.
3141
+ */
3142
+
3143
+ export { TAILWIND_COMPONENTS_SIZE, TAILWIND_DATETIME_LANGUAGE, TAILWIND_HERO_ICON_NAMES, TAILWIND_ICON_SIZE, TAILWIND_MODAL_DATA, TailwindAccordion, TailwindAccordionItem, TailwindAlert, TailwindBadge, TailwindBreadcrumb, TailwindButton, TailwindCard, TailwindCheckbox, TailwindDatePicker, TailwindDateTimePicker, TailwindDivider, TailwindDrawer, TailwindIcon, TailwindInput, TailwindMenu, TailwindMessage, TailwindMeter, TailwindModal, TailwindModalContent, TailwindModalFooter, TailwindModalRef, TailwindModalService, TailwindModalTitle, TailwindNotification, TailwindPagination, TailwindProgressBar, TailwindRadioGroup, TailwindSelect, TailwindSkeleton, TailwindSlider, TailwindSpinner, TailwindStep, TailwindStepper, TailwindTab, TailwindTabGroup, TailwindTable, TailwindTag, TailwindTimePicker, TailwindToast, TailwindToastService, TailwindToggle, TailwindToolbar, TailwindTooltip, TailwindTooltipDirective };
3144
+ //# sourceMappingURL=angular-tailwind-components.mjs.map