@cdevhub/ngx-tw 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +108 -0
  4. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -0
  5. package/fesm2022/cdevhub-ngx-tw-alert.mjs +240 -0
  6. package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -0
  7. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +287 -0
  8. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -0
  9. package/fesm2022/cdevhub-ngx-tw-badge.mjs +332 -0
  10. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -0
  11. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +452 -0
  12. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -0
  13. package/fesm2022/cdevhub-ngx-tw-button.mjs +227 -0
  14. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -0
  15. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +417 -0
  16. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -0
  17. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +232 -0
  18. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -0
  19. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +4482 -0
  20. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -0
  21. package/fesm2022/cdevhub-ngx-tw-card.mjs +157 -0
  22. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -0
  23. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +1454 -0
  24. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -0
  25. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +593 -0
  26. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -0
  27. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +228 -0
  28. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -0
  29. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +510 -0
  30. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -0
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +1721 -0
  32. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +721 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -0
  35. package/fesm2022/cdevhub-ngx-tw-core.mjs +861 -0
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -0
  37. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +1558 -0
  38. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +1833 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -0
  41. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +693 -0
  42. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -0
  43. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +331 -0
  44. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -0
  45. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +289 -0
  46. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -0
  47. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +572 -0
  48. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -0
  49. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +36 -0
  50. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -0
  51. package/fesm2022/cdevhub-ngx-tw-icon.mjs +278 -0
  52. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -0
  53. package/fesm2022/cdevhub-ngx-tw-input.mjs +355 -0
  54. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -0
  55. package/fesm2022/cdevhub-ngx-tw-item.mjs +241 -0
  56. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -0
  57. package/fesm2022/cdevhub-ngx-tw-menu.mjs +433 -0
  58. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -0
  59. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +691 -0
  60. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -0
  61. package/fesm2022/cdevhub-ngx-tw-popover.mjs +678 -0
  62. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -0
  63. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +335 -0
  64. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -0
  65. package/fesm2022/cdevhub-ngx-tw-radio.mjs +708 -0
  66. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -0
  67. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +319 -0
  68. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -0
  69. package/fesm2022/cdevhub-ngx-tw-select.mjs +1722 -0
  70. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -0
  71. package/fesm2022/cdevhub-ngx-tw-separator.mjs +115 -0
  72. package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -0
  73. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +768 -0
  74. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -0
  75. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +149 -0
  76. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -0
  77. package/fesm2022/cdevhub-ngx-tw-slider.mjs +1147 -0
  78. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -0
  79. package/fesm2022/cdevhub-ngx-tw-sort.mjs +346 -0
  80. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -0
  81. package/fesm2022/cdevhub-ngx-tw-spinner.mjs +186 -0
  82. package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -0
  83. package/fesm2022/cdevhub-ngx-tw-split.mjs +1082 -0
  84. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -0
  85. package/fesm2022/cdevhub-ngx-tw-stat.mjs +579 -0
  86. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -0
  87. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +443 -0
  88. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -0
  89. package/fesm2022/cdevhub-ngx-tw-switch.mjs +391 -0
  90. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -0
  91. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +315 -0
  92. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -0
  93. package/fesm2022/cdevhub-ngx-tw-table.mjs +994 -0
  94. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -0
  95. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +508 -0
  96. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -0
  97. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +147 -0
  98. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -0
  99. package/fesm2022/cdevhub-ngx-tw-theme.mjs +178 -0
  100. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -0
  101. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +1344 -0
  102. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -0
  103. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +1136 -0
  104. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -0
  105. package/fesm2022/cdevhub-ngx-tw-toast.mjs +1311 -0
  106. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -0
  107. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +533 -0
  108. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -0
  109. package/fesm2022/cdevhub-ngx-tw.mjs +61 -0
  110. package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -0
  111. package/package.json +265 -0
  112. package/theme/_base.css +394 -0
  113. package/theme/_dark.css +510 -0
  114. package/theme/_high-contrast.css +290 -0
  115. package/theme/_semantic.css +317 -0
  116. package/theme/_typography.css +9 -0
  117. package/theme/index.css +54 -0
  118. package/types/cdevhub-ngx-tw-accordion.d.ts +48 -0
  119. package/types/cdevhub-ngx-tw-alert.d.ts +67 -0
  120. package/types/cdevhub-ngx-tw-avatar.d.ts +79 -0
  121. package/types/cdevhub-ngx-tw-badge.d.ts +94 -0
  122. package/types/cdevhub-ngx-tw-breadcrumbs.d.ts +227 -0
  123. package/types/cdevhub-ngx-tw-button.d.ts +74 -0
  124. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +200 -0
  125. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +113 -0
  126. package/types/cdevhub-ngx-tw-calendar.d.ts +1704 -0
  127. package/types/cdevhub-ngx-tw-card.d.ts +48 -0
  128. package/types/cdevhub-ngx-tw-carousel.d.ts +406 -0
  129. package/types/cdevhub-ngx-tw-checkbox.d.ts +136 -0
  130. package/types/cdevhub-ngx-tw-code-block.d.ts +93 -0
  131. package/types/cdevhub-ngx-tw-collapsible.d.ts +151 -0
  132. package/types/cdevhub-ngx-tw-combobox.d.ts +389 -0
  133. package/types/cdevhub-ngx-tw-command-palette.d.ts +215 -0
  134. package/types/cdevhub-ngx-tw-core.d.ts +719 -0
  135. package/types/cdevhub-ngx-tw-date-picker.d.ts +317 -0
  136. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +313 -0
  137. package/types/cdevhub-ngx-tw-dialog.d.ts +303 -0
  138. package/types/cdevhub-ngx-tw-empty-state.d.ts +104 -0
  139. package/types/cdevhub-ngx-tw-flip-card.d.ts +95 -0
  140. package/types/cdevhub-ngx-tw-form-field.d.ts +210 -0
  141. package/types/cdevhub-ngx-tw-icon-lucide.d.ts +29 -0
  142. package/types/cdevhub-ngx-tw-icon.d.ts +134 -0
  143. package/types/cdevhub-ngx-tw-input.d.ts +110 -0
  144. package/types/cdevhub-ngx-tw-item.d.ts +70 -0
  145. package/types/cdevhub-ngx-tw-menu.d.ts +99 -0
  146. package/types/cdevhub-ngx-tw-paginator.d.ts +305 -0
  147. package/types/cdevhub-ngx-tw-popover.d.ts +157 -0
  148. package/types/cdevhub-ngx-tw-progress-bar.d.ts +100 -0
  149. package/types/cdevhub-ngx-tw-radio.d.ts +174 -0
  150. package/types/cdevhub-ngx-tw-segmented-control.d.ts +66 -0
  151. package/types/cdevhub-ngx-tw-select.d.ts +384 -0
  152. package/types/cdevhub-ngx-tw-separator.d.ts +28 -0
  153. package/types/cdevhub-ngx-tw-sheet.d.ts +335 -0
  154. package/types/cdevhub-ngx-tw-skeleton.d.ts +52 -0
  155. package/types/cdevhub-ngx-tw-slider.d.ts +258 -0
  156. package/types/cdevhub-ngx-tw-sort.d.ts +136 -0
  157. package/types/cdevhub-ngx-tw-spinner.d.ts +50 -0
  158. package/types/cdevhub-ngx-tw-split.d.ts +265 -0
  159. package/types/cdevhub-ngx-tw-stat.d.ts +140 -0
  160. package/types/cdevhub-ngx-tw-stepper.d.ts +127 -0
  161. package/types/cdevhub-ngx-tw-switch.d.ts +88 -0
  162. package/types/cdevhub-ngx-tw-tab-nav.d.ts +107 -0
  163. package/types/cdevhub-ngx-tw-table.d.ts +479 -0
  164. package/types/cdevhub-ngx-tw-tabs.d.ts +121 -0
  165. package/types/cdevhub-ngx-tw-textarea.d.ts +62 -0
  166. package/types/cdevhub-ngx-tw-theme.d.ts +106 -0
  167. package/types/cdevhub-ngx-tw-time-picker.d.ts +303 -0
  168. package/types/cdevhub-ngx-tw-timeline.d.ts +278 -0
  169. package/types/cdevhub-ngx-tw-toast.d.ts +388 -0
  170. package/types/cdevhub-ngx-tw-tooltip.d.ts +95 -0
  171. package/types/cdevhub-ngx-tw.d.ts +49 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Iuga Ciprian
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # ngx-tw
2
+
3
+ An Angular component library for applications built with **Tailwind CSS v4+**
4
+ and **Angular CDK**. The quality bar is [Angular Material](https://material.angular.io/)
5
+ — well-tested, accessible, composable — but styled with Tailwind utility classes
6
+ instead of Material Design tokens.
7
+
8
+ - **37 components** covering common UI needs (buttons, inputs, overlays,
9
+ navigation, data display, etc.)
10
+ - **Standalone, signal-based APIs** — Angular v21 idioms throughout (no
11
+ NgModules, `OnPush`, `input()`/`output()`/`model()`).
12
+ - **Accessible by default** — built on Angular CDK primitives (focus management,
13
+ overlays, a11y, collections). WCAG AA.
14
+ - **Tailwind v4 native** — no component CSS files; consumers control theming
15
+ through semantic tokens.
16
+ - **Tree-shakeable secondary entry points** — import only what you use.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @cdevhub/ngx-tw @angular/cdk tailwindcss tailwind-variants
22
+ ```
23
+
24
+ **Peer requirements**
25
+
26
+ - Angular `^21.2.0` (`@angular/core`, `@angular/common`)
27
+ - `@angular/cdk` `^21.0.0`
28
+ - `tailwindcss` `^4.0.0`
29
+ - `tailwind-variants` `^0.3.0`
30
+
31
+ ## Setup
32
+
33
+ ### 1. Import the default theme
34
+
35
+ Tailwind v4 has no JS config file — all customization happens in CSS. Add the
36
+ ngx-tw default theme to your global stylesheet so semantic tokens resolve:
37
+
38
+ ```css
39
+ /* src/styles.css */
40
+ @import 'tailwindcss';
41
+ @import '@cdevhub/ngx-tw/theme/index.css';
42
+ ```
43
+
44
+ The default theme maps semantic roles (`info`, `success`, `warning`, `error`,
45
+ `primary`, `secondary`, `accent`, `neutral`) and structural tokens (`surface`,
46
+ `fg`, `border`) to Tailwind's palette, with dark mode support out of the box.
47
+
48
+ ### 2. Use components
49
+
50
+ Import from the per-component entry points for best tree-shaking:
51
+
52
+ ```ts
53
+ import { Component } from '@angular/core';
54
+ import { ButtonDirective } from '@cdevhub/ngx-tw/button';
55
+ import { AlertComponent } from '@cdevhub/ngx-tw/alert';
56
+
57
+ @Component({
58
+ selector: 'app-root',
59
+ imports: [ButtonDirective, AlertComponent],
60
+ template: `
61
+ <button twButton color="primary">Save</button>
62
+ <tw-alert color="success">Changes saved.</tw-alert>
63
+ `,
64
+ })
65
+ export class AppComponent {}
66
+ ```
67
+
68
+ ## Customizing the theme
69
+
70
+ Override any semantic token in your own CSS using Tailwind v4's `@theme` block:
71
+
72
+ ```css
73
+ @import '@cdevhub/ngx-tw/theme/index.css';
74
+
75
+ @theme {
76
+ /* Re-brand primary to a custom indigo */
77
+ --color-primary-500: oklch(0.55 0.2 260);
78
+ --color-primary-600: oklch(0.48 0.2 260);
79
+
80
+ /* Remap "info" to the sky palette */
81
+ --color-info-50: var(--color-sky-50);
82
+ --color-info-500: var(--color-sky-500);
83
+ }
84
+ ```
85
+
86
+ Dark mode is handled entirely by the theme layer — swap in your own
87
+ `index.css` equivalent (or extend the ngx-tw one) if you need a different
88
+ dark palette. Components only reference semantic tokens, so they adapt
89
+ automatically.
90
+
91
+ ## Components
92
+
93
+ All components are exposed as independent secondary entry points:
94
+
95
+ ```
96
+ @cdevhub/ngx-tw/accordion @cdevhub/ngx-tw/input @cdevhub/ngx-tw/sort
97
+ @cdevhub/ngx-tw/alert @cdevhub/ngx-tw/item @cdevhub/ngx-tw/spinner
98
+ @cdevhub/ngx-tw/avatar @cdevhub/ngx-tw/menu @cdevhub/ngx-tw/stepper
99
+ @cdevhub/ngx-tw/badge @cdevhub/ngx-tw/paginator @cdevhub/ngx-tw/switch
100
+ @cdevhub/ngx-tw/button @cdevhub/ngx-tw/popover @cdevhub/ngx-tw/tab-nav
101
+ @cdevhub/ngx-tw/calendar @cdevhub/ngx-tw/progress-bar @cdevhub/ngx-tw/table
102
+ @cdevhub/ngx-tw/card @cdevhub/ngx-tw/radio @cdevhub/ngx-tw/tabs
103
+ @cdevhub/ngx-tw/checkbox @cdevhub/ngx-tw/segmented-control @cdevhub/ngx-tw/time-picker
104
+ @cdevhub/ngx-tw/code-block @cdevhub/ngx-tw/select @cdevhub/ngx-tw/toast
105
+ @cdevhub/ngx-tw/collapsible @cdevhub/ngx-tw/separator @cdevhub/ngx-tw/tooltip
106
+ @cdevhub/ngx-tw/command-palette @cdevhub/ngx-tw/skeleton
107
+ @cdevhub/ngx-tw/date-picker @cdevhub/ngx-tw/slider
108
+ @cdevhub/ngx-tw/dialog @cdevhub/ngx-tw/form-field
109
+ @cdevhub/ngx-tw/flip-card @cdevhub/ngx-tw/icon
110
+ ```
111
+
112
+ Shared types (`TwColor`, `TwSize`) live in `@cdevhub/ngx-tw/core`.
113
+
114
+ A catch-all entry (`@cdevhub/ngx-tw`) re-exports every public API for convenience, but
115
+ per-component imports are preferred for tree-shaking.
116
+
117
+ ## Form controls
118
+
119
+ Interactive controls (input, select, checkbox, radio, switch, slider,
120
+ date-picker, time-picker, etc.) implement `ControlValueAccessor` and work with
121
+ all three Angular form strategies — template-driven, reactive, and
122
+ signal-based forms.
123
+
124
+ ## Building locally
125
+
126
+ ```bash
127
+ ng build ngx-tw # build library to dist/ngx-tw
128
+ ng test ngx-tw --no-watch # run unit tests (Vitest)
129
+ ng serve demo # run the demo app
130
+ ```
131
+
132
+ ## License
133
+
134
+ [MIT](./LICENSE) © Iuga Ciprian
@@ -0,0 +1,108 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, booleanAttribute, computed, forwardRef, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { tv } from 'tailwind-variants';
4
+ import { CollapsibleGroupComponent } from '@cdevhub/ngx-tw/collapsible';
5
+
6
+ // ── tv() config ──
7
+ const accordionVariants = tv({
8
+ slots: {
9
+ root: 'block',
10
+ },
11
+ variants: {
12
+ variant: {
13
+ default: {
14
+ root: 'rounded-lg overflow-hidden divide-y divide-border',
15
+ },
16
+ bordered: {
17
+ root: 'rounded-lg overflow-hidden divide-y divide-border border border-border',
18
+ },
19
+ ghost: {
20
+ root: '',
21
+ },
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: 'default',
26
+ },
27
+ }, {
28
+ twMerge: true,
29
+ });
30
+ // ── AccordionComponent ──
31
+ /**
32
+ * Accordion — single- or multiple-open-panel group built on top of
33
+ * `<tw-collapsible>` children. Extends `CollapsibleGroupComponent` to inherit
34
+ * the keyboard navigation, value-sync, and toggle wiring; overrides the
35
+ * virtual `isAccordionMode()` / `canCollapseSingleMode()` hooks so the
36
+ * single-mode behaviour is driven from the local `type` + `collapsible`
37
+ * inputs instead of the parent's `accordion` input. The `hostRole` and
38
+ * `hostClasses` signals are also overridden so the accordion drops APG's
39
+ * `role="group"` and renders the variant-driven container classes.
40
+ *
41
+ * The `providers` block exposes the accordion instance to its descendant
42
+ * collapsibles via the `CollapsibleGroupComponent` DI token — Angular DI
43
+ * uses class identity rather than the prototype chain, so the explicit
44
+ * `useExisting` is required even though `AccordionComponent extends
45
+ * CollapsibleGroupComponent`.
46
+ */
47
+ class AccordionComponent extends CollapsibleGroupComponent {
48
+ /** Open mode. `'single'` allows one panel open at a time; `'multiple'` allows many. Defaults to `'single'`. */
49
+ type = input('single', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
50
+ /** Visual style of the accordion container. Defaults to `'default'`. */
51
+ variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
52
+ /** In `'single'` mode, whether re-clicking the open panel closes it. Defaults to `true` — accordions are collapsible by definition; opt-out only. */
53
+ collapsible = input(true, { ...(ngDevMode ? { debugName: "collapsible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
54
+ /** Accessible name for the accordion. Use when surrounding context doesn't make the purpose obvious. */
55
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
56
+ /** ID(s) of element(s) that label the accordion. Use instead of `aria-label` when a visible heading is available. */
57
+ ariaLabelledby = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabelledby" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
58
+ // ── Inherited-binding overrides ──
59
+ /** @internal APG: accordions don't carry `role="group"`. */
60
+ hostRole = computed(() => null, ...(ngDevMode ? [{ debugName: "hostRole" }] : /* istanbul ignore next */ []));
61
+ /** @internal Variant-driven container classes; replaces the parent's default group string. */
62
+ hostClasses = computed(() => accordionVariants({ variant: this.variant() }).root(), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
63
+ // ── Virtual-hook overrides ──
64
+ /** @internal Drive single-open-panel behaviour from `type`, ignoring the inherited `accordion` input. */
65
+ isAccordionMode() {
66
+ return this.type() === 'single';
67
+ }
68
+ /** @internal Honour the `collapsible` opt-out in single mode. */
69
+ canCollapseSingleMode() {
70
+ return this.collapsible();
71
+ }
72
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
73
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: AccordionComponent, isStandalone: true, selector: "tw-accordion", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.aria-multiselectable": "type() === 'multiple' ? 'true' : 'false'", "attr.aria-label": "ariaLabel() ?? null", "attr.aria-labelledby": "ariaLabelledby() ?? null" } }, providers: [
74
+ {
75
+ provide: CollapsibleGroupComponent,
76
+ useExisting: forwardRef(() => AccordionComponent),
77
+ },
78
+ ], usesInheritance: true, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
79
+ }
80
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionComponent, decorators: [{
81
+ type: Component,
82
+ args: [{
83
+ selector: 'tw-accordion',
84
+ changeDetection: ChangeDetectionStrategy.OnPush,
85
+ host: {
86
+ // `[class]` + `[attr.role]` are inherited from the parent's host metadata
87
+ // and read the overridden `hostClasses` / `hostRole` computeds below.
88
+ // We only need to add accordion-specific bindings here.
89
+ '[attr.aria-multiselectable]': "type() === 'multiple' ? 'true' : 'false'",
90
+ '[attr.aria-label]': 'ariaLabel() ?? null',
91
+ '[attr.aria-labelledby]': 'ariaLabelledby() ?? null',
92
+ },
93
+ template: `<ng-content />`,
94
+ providers: [
95
+ {
96
+ provide: CollapsibleGroupComponent,
97
+ useExisting: forwardRef(() => AccordionComponent),
98
+ },
99
+ ],
100
+ }]
101
+ }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }] } });
102
+
103
+ /**
104
+ * Generated bundle index. Do not edit.
105
+ */
106
+
107
+ export { AccordionComponent };
108
+ //# sourceMappingURL=cdevhub-ngx-tw-accordion.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-accordion.mjs","sources":["../../../projects/ngx-tw/accordion/accordion.ts","../../../projects/ngx-tw/accordion/cdevhub-ngx-tw-accordion.ts"],"sourcesContent":["import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n forwardRef,\n input,\n} from '@angular/core';\nimport { tv } from 'tailwind-variants';\nimport { CollapsibleGroupComponent } from '@cdevhub/ngx-tw/collapsible';\n\n/** Open mode of the accordion. */\nexport type AccordionType = 'single' | 'multiple';\n\n/** Visual style of the accordion container. */\nexport type AccordionVariant = 'default' | 'bordered' | 'ghost';\n\n// ── tv() config ──\n\nconst accordionVariants = tv(\n {\n slots: {\n root: 'block',\n },\n variants: {\n variant: {\n default: {\n root: 'rounded-lg overflow-hidden divide-y divide-border',\n },\n bordered: {\n root: 'rounded-lg overflow-hidden divide-y divide-border border border-border',\n },\n ghost: {\n root: '',\n },\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n {\n twMerge: true,\n },\n);\n\n// ── AccordionComponent ──\n\n/**\n * Accordion — single- or multiple-open-panel group built on top of\n * `<tw-collapsible>` children. Extends `CollapsibleGroupComponent` to inherit\n * the keyboard navigation, value-sync, and toggle wiring; overrides the\n * virtual `isAccordionMode()` / `canCollapseSingleMode()` hooks so the\n * single-mode behaviour is driven from the local `type` + `collapsible`\n * inputs instead of the parent's `accordion` input. The `hostRole` and\n * `hostClasses` signals are also overridden so the accordion drops APG's\n * `role=\"group\"` and renders the variant-driven container classes.\n *\n * The `providers` block exposes the accordion instance to its descendant\n * collapsibles via the `CollapsibleGroupComponent` DI token — Angular DI\n * uses class identity rather than the prototype chain, so the explicit\n * `useExisting` is required even though `AccordionComponent extends\n * CollapsibleGroupComponent`.\n */\n@Component({\n selector: 'tw-accordion',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n // `[class]` + `[attr.role]` are inherited from the parent's host metadata\n // and read the overridden `hostClasses` / `hostRole` computeds below.\n // We only need to add accordion-specific bindings here.\n '[attr.aria-multiselectable]': \"type() === 'multiple' ? 'true' : 'false'\",\n '[attr.aria-label]': 'ariaLabel() ?? null',\n '[attr.aria-labelledby]': 'ariaLabelledby() ?? null',\n },\n template: `<ng-content />`,\n providers: [\n {\n provide: CollapsibleGroupComponent,\n useExisting: forwardRef(() => AccordionComponent),\n },\n ],\n})\nexport class AccordionComponent extends CollapsibleGroupComponent {\n /** Open mode. `'single'` allows one panel open at a time; `'multiple'` allows many. Defaults to `'single'`. */\n readonly type = input<AccordionType>('single');\n\n /** Visual style of the accordion container. Defaults to `'default'`. */\n readonly variant = input<AccordionVariant>('default');\n\n /** In `'single'` mode, whether re-clicking the open panel closes it. Defaults to `true` — accordions are collapsible by definition; opt-out only. */\n readonly collapsible = input(true, { transform: booleanAttribute });\n\n /** Accessible name for the accordion. Use when surrounding context doesn't make the purpose obvious. */\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n /** ID(s) of element(s) that label the accordion. Use instead of `aria-label` when a visible heading is available. */\n readonly ariaLabelledby = input<string | undefined>(undefined, { alias: 'aria-labelledby' });\n\n // ── Inherited-binding overrides ──\n\n /** @internal APG: accordions don't carry `role=\"group\"`. */\n override readonly hostRole = computed<string | null>(() => null);\n\n /** @internal Variant-driven container classes; replaces the parent's default group string. */\n override readonly hostClasses = computed(() =>\n accordionVariants({ variant: this.variant() }).root(),\n );\n\n // ── Virtual-hook overrides ──\n\n /** @internal Drive single-open-panel behaviour from `type`, ignoring the inherited `accordion` input. */\n protected override isAccordionMode(): boolean {\n return this.type() === 'single';\n }\n\n /** @internal Honour the `collapsible` opt-out in single mode. */\n protected override canCollapseSingleMode(): boolean {\n return this.collapsible();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,240 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Directive, input, booleanAttribute, output, contentChild, computed, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { tv } from 'tailwind-variants';
4
+
5
+ function softSlots(role) {
6
+ return {
7
+ root: `bg-${role}-soft text-${role}-soft-fg-muted`,
8
+ icon: `text-${role}-icon`,
9
+ title: `text-${role}-soft-fg`,
10
+ content: `text-${role}-soft-fg-muted`,
11
+ dismiss: `text-${role}-icon hover:bg-${role}-soft-hover`,
12
+ };
13
+ }
14
+ function outlineSlots(role) {
15
+ return {
16
+ root: `border-${role}-border text-${role}-soft-fg-muted`,
17
+ icon: `text-${role}-icon`,
18
+ title: `text-${role}-soft-fg`,
19
+ content: `text-${role}-soft-fg-muted`,
20
+ dismiss: `text-${role}-icon hover:bg-${role}-soft`,
21
+ };
22
+ }
23
+ function solidSlots(role) {
24
+ return {
25
+ root: `bg-${role}-solid text-${role}-solid-fg`,
26
+ icon: `text-${role}-solid-fg`,
27
+ title: `text-${role}-solid-fg`,
28
+ content: `text-${role}-solid-fg`,
29
+ dismiss: `text-${role}-solid-fg/80 hover:bg-${role}-solid-hover`,
30
+ };
31
+ }
32
+ const ROLES = [
33
+ 'primary', 'secondary', 'accent', 'neutral',
34
+ 'info', 'success', 'warning', 'error',
35
+ ];
36
+ const alertVariants = tv({
37
+ slots: {
38
+ root: 'relative flex gap-3 rounded-lg p-4 text-sm',
39
+ icon: 'size-5 shrink-0 mt-0.5',
40
+ title: 'text-sm font-semibold',
41
+ content: 'text-sm',
42
+ actions: 'flex items-center gap-2 mt-2',
43
+ // size-3.5 inner glyph: half-step decorative — keeps the X visually centred
44
+ // in the size-6 square-interactive target without dominating the button.
45
+ dismiss: 'absolute top-2.5 right-2.5 inline-flex items-center justify-center size-6 rounded-md cursor-pointer transition-colors duration-normal motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',
46
+ },
47
+ variants: {
48
+ variant: {
49
+ solid: { root: '' },
50
+ outline: { root: 'border' },
51
+ soft: { root: '' },
52
+ },
53
+ color: Object.fromEntries(ROLES.map((r) => [r, {}])),
54
+ },
55
+ compoundVariants: ROLES.flatMap((role) => [
56
+ { variant: 'soft', color: role, class: softSlots(role) },
57
+ { variant: 'outline', color: role, class: outlineSlots(role) },
58
+ { variant: 'solid', color: role, class: solidSlots(role) },
59
+ ]),
60
+ defaultVariants: {
61
+ variant: 'soft',
62
+ color: 'info',
63
+ },
64
+ }, {
65
+ twMerge: true,
66
+ });
67
+ class AlertIconDirective {
68
+ alert = inject(AlertComponent);
69
+ classes = this.alert.iconClasses;
70
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
71
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: AlertIconDirective, isStandalone: true, selector: "[twAlertIcon]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
72
+ }
73
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertIconDirective, decorators: [{
74
+ type: Directive,
75
+ args: [{
76
+ selector: '[twAlertIcon]',
77
+ host: {
78
+ '[class]': 'classes()',
79
+ },
80
+ }]
81
+ }] });
82
+ class AlertTitleDirective {
83
+ alert = inject(AlertComponent);
84
+ classes = this.alert.titleClasses;
85
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
86
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: AlertTitleDirective, isStandalone: true, selector: "[twAlertTitle]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
87
+ }
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertTitleDirective, decorators: [{
89
+ type: Directive,
90
+ args: [{
91
+ selector: '[twAlertTitle]',
92
+ host: {
93
+ '[class]': 'classes()',
94
+ },
95
+ }]
96
+ }] });
97
+ class AlertContentDirective {
98
+ alert = inject(AlertComponent);
99
+ classes = this.alert.contentClasses;
100
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
101
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: AlertContentDirective, isStandalone: true, selector: "[twAlertContent]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
102
+ }
103
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertContentDirective, decorators: [{
104
+ type: Directive,
105
+ args: [{
106
+ selector: '[twAlertContent]',
107
+ host: {
108
+ '[class]': 'classes()',
109
+ },
110
+ }]
111
+ }] });
112
+ class AlertActionsDirective {
113
+ alert = inject(AlertComponent);
114
+ classes = this.alert.actionsClasses;
115
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertActionsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
116
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: AlertActionsDirective, isStandalone: true, selector: "[twAlertActions]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
117
+ }
118
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertActionsDirective, decorators: [{
119
+ type: Directive,
120
+ args: [{
121
+ selector: '[twAlertActions]',
122
+ host: {
123
+ '[class]': 'classes()',
124
+ },
125
+ }]
126
+ }] });
127
+ class AlertComponent {
128
+ /** Controls the visual style of the alert. Defaults to `'soft'`. */
129
+ variant = input('soft', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
130
+ /** Sets the semantic color palette. Defaults to `'info'`. */
131
+ color = input('info', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
132
+ /** When true, renders a dismiss button. Defaults to `false`. */
133
+ dismissible = input(false, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
134
+ /**
135
+ * Sets the ARIA live-region politeness. Maps to the host `role`:
136
+ * `'assertive'` → `role="alert"`, `'polite'` → `role="status"`,
137
+ * `'off'` → no role. Use `'off'` to suppress re-announcement when the
138
+ * alert content updates after initial render — assistive tech treats the
139
+ * alert as a static region rather than a live region. Defaults to `'polite'`.
140
+ */
141
+ politeness = input('polite', ...(ngDevMode ? [{ debugName: "politeness" }] : /* istanbul ignore next */ []));
142
+ /** Accessible label for the dismiss button. Override for localization. Defaults to `'Dismiss'`. */
143
+ dismissLabel = input('Dismiss', ...(ngDevMode ? [{ debugName: "dismissLabel" }] : /* istanbul ignore next */ []));
144
+ /** Fires when the dismiss button is clicked. */
145
+ dismissed = output();
146
+ /** @internal */
147
+ iconDirective = contentChild(AlertIconDirective, ...(ngDevMode ? [{ debugName: "iconDirective" }] : /* istanbul ignore next */ []));
148
+ hasIcon = computed(() => !!this.iconDirective(), ...(ngDevMode ? [{ debugName: "hasIcon" }] : /* istanbul ignore next */ []));
149
+ computedRole = computed(() => {
150
+ switch (this.politeness()) {
151
+ case 'assertive':
152
+ return 'alert';
153
+ case 'polite':
154
+ return 'status';
155
+ default:
156
+ return null;
157
+ }
158
+ }, ...(ngDevMode ? [{ debugName: "computedRole" }] : /* istanbul ignore next */ []));
159
+ variantResult = computed(() => alertVariants({
160
+ variant: this.variant(),
161
+ color: this.color(),
162
+ }), ...(ngDevMode ? [{ debugName: "variantResult" }] : /* istanbul ignore next */ []));
163
+ rootClasses = computed(() => {
164
+ const base = this.variantResult().root();
165
+ return this.dismissible() ? `${base} pr-10` : base;
166
+ }, ...(ngDevMode ? [{ debugName: "rootClasses" }] : /* istanbul ignore next */ []));
167
+ iconClasses = computed(() => this.variantResult().icon(), ...(ngDevMode ? [{ debugName: "iconClasses" }] : /* istanbul ignore next */ []));
168
+ titleClasses = computed(() => this.variantResult().title(), ...(ngDevMode ? [{ debugName: "titleClasses" }] : /* istanbul ignore next */ []));
169
+ contentClasses = computed(() => this.variantResult().content(), ...(ngDevMode ? [{ debugName: "contentClasses" }] : /* istanbul ignore next */ []));
170
+ actionsClasses = computed(() => this.variantResult().actions(), ...(ngDevMode ? [{ debugName: "actionsClasses" }] : /* istanbul ignore next */ []));
171
+ dismissClasses = computed(() => this.variantResult().dismiss(), ...(ngDevMode ? [{ debugName: "dismissClasses" }] : /* istanbul ignore next */ []));
172
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
173
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: AlertComponent, isStandalone: true, selector: "tw-alert", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, politeness: { classPropertyName: "politeness", publicName: "politeness", isSignal: true, isRequired: false, transformFunction: null }, dismissLabel: { classPropertyName: "dismissLabel", publicName: "dismissLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismissed: "dismissed" }, host: { properties: { "attr.role": "computedRole()", "class": "rootClasses()", "animate.leave": "\"fade-out\"" } }, queries: [{ propertyName: "iconDirective", first: true, predicate: AlertIconDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
174
+ @if (hasIcon()) {
175
+ <ng-content select="[twAlertIcon]" />
176
+ }
177
+ <div class="min-w-0 flex-1">
178
+ <ng-content select="[twAlertTitle]" />
179
+ <ng-content select="[twAlertContent]" />
180
+ <ng-content />
181
+ <ng-content select="[twAlertActions]" />
182
+ </div>
183
+ @if (dismissible()) {
184
+ <button
185
+ type="button"
186
+ [attr.aria-label]="dismissLabel()"
187
+ [class]="dismissClasses()"
188
+ (click)="dismissed.emit()"
189
+ >
190
+ <!-- size-3.5 (14px) is the half-step between size-3 and size-4 — the only icon size that visually aligns with the alert title's text-sm metric inside the compact xs-density dismiss button. -->
191
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-3.5">
192
+ <path d="M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z"/>
193
+ </svg>
194
+ </button>
195
+ }
196
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
197
+ }
198
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AlertComponent, decorators: [{
199
+ type: Component,
200
+ args: [{
201
+ selector: 'tw-alert',
202
+ changeDetection: ChangeDetectionStrategy.OnPush,
203
+ host: {
204
+ '[attr.role]': 'computedRole()',
205
+ '[class]': 'rootClasses()',
206
+ '[animate.leave]': '"fade-out"',
207
+ },
208
+ template: `
209
+ @if (hasIcon()) {
210
+ <ng-content select="[twAlertIcon]" />
211
+ }
212
+ <div class="min-w-0 flex-1">
213
+ <ng-content select="[twAlertTitle]" />
214
+ <ng-content select="[twAlertContent]" />
215
+ <ng-content />
216
+ <ng-content select="[twAlertActions]" />
217
+ </div>
218
+ @if (dismissible()) {
219
+ <button
220
+ type="button"
221
+ [attr.aria-label]="dismissLabel()"
222
+ [class]="dismissClasses()"
223
+ (click)="dismissed.emit()"
224
+ >
225
+ <!-- size-3.5 (14px) is the half-step between size-3 and size-4 — the only icon size that visually aligns with the alert title's text-sm metric inside the compact xs-density dismiss button. -->
226
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-3.5">
227
+ <path d="M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z"/>
228
+ </svg>
229
+ </button>
230
+ }
231
+ `,
232
+ }]
233
+ }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], politeness: [{ type: i0.Input, args: [{ isSignal: true, alias: "politeness", required: false }] }], dismissLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissLabel", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }], iconDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => AlertIconDirective), { isSignal: true }] }] } });
234
+
235
+ /**
236
+ * Generated bundle index. Do not edit.
237
+ */
238
+
239
+ export { AlertActionsDirective, AlertComponent, AlertContentDirective, AlertIconDirective, AlertTitleDirective };
240
+ //# sourceMappingURL=cdevhub-ngx-tw-alert.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-alert.mjs","sources":["../../../projects/ngx-tw/alert/alert.ts","../../../projects/ngx-tw/alert/cdevhub-ngx-tw-alert.ts"],"sourcesContent":["import {\n booleanAttribute,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n Directive,\n inject,\n input,\n output,\n} from '@angular/core';\nimport { tv } from 'tailwind-variants';\nimport type { TwColor } from '@cdevhub/ngx-tw/core';\n\n/** Visual style of the alert container. */\nexport type AlertVariant = 'solid' | 'outline' | 'soft';\n\n/** ARIA live-region politeness for the alert. Maps to the host `role`. */\nexport type AlertPoliteness = 'polite' | 'assertive' | 'off';\n\n/**\n * Alert variants use the semantic role slot tokens defined in\n * `projects/ngx-tw/theme/_semantic.css` (and redefined per-theme in\n * `_dark.css` / `_high-contrast.css`). The mapping role × variant → slots\n * is the same for every color, so the variant table is expressed as a single\n * function template over the role name — no per-role copy-paste, no shade\n * picks, no `dark:` overrides. Dark / high-contrast contrast is owned by the\n * theme tokens; components only consume slots.\n */\ntype AlertSlotClasses = {\n root: string;\n icon: string;\n title: string;\n content: string;\n dismiss: string;\n};\n\nfunction softSlots(role: TwColor): AlertSlotClasses {\n return {\n root: `bg-${role}-soft text-${role}-soft-fg-muted`,\n icon: `text-${role}-icon`,\n title: `text-${role}-soft-fg`,\n content: `text-${role}-soft-fg-muted`,\n dismiss: `text-${role}-icon hover:bg-${role}-soft-hover`,\n };\n}\n\nfunction outlineSlots(role: TwColor): AlertSlotClasses {\n return {\n root: `border-${role}-border text-${role}-soft-fg-muted`,\n icon: `text-${role}-icon`,\n title: `text-${role}-soft-fg`,\n content: `text-${role}-soft-fg-muted`,\n dismiss: `text-${role}-icon hover:bg-${role}-soft`,\n };\n}\n\nfunction solidSlots(role: TwColor): AlertSlotClasses {\n return {\n root: `bg-${role}-solid text-${role}-solid-fg`,\n icon: `text-${role}-solid-fg`,\n title: `text-${role}-solid-fg`,\n content: `text-${role}-solid-fg`,\n dismiss: `text-${role}-solid-fg/80 hover:bg-${role}-solid-hover`,\n };\n}\n\nconst ROLES: readonly TwColor[] = [\n 'primary', 'secondary', 'accent', 'neutral',\n 'info', 'success', 'warning', 'error',\n] as const;\n\nconst alertVariants = tv({\n slots: {\n root: 'relative flex gap-3 rounded-lg p-4 text-sm',\n icon: 'size-5 shrink-0 mt-0.5',\n title: 'text-sm font-semibold',\n content: 'text-sm',\n actions: 'flex items-center gap-2 mt-2',\n // size-3.5 inner glyph: half-step decorative — keeps the X visually centred\n // in the size-6 square-interactive target without dominating the button.\n dismiss:\n 'absolute top-2.5 right-2.5 inline-flex items-center justify-center size-6 rounded-md cursor-pointer transition-colors duration-normal motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',\n },\n variants: {\n variant: {\n solid: { root: '' },\n outline: { root: 'border' },\n soft: { root: '' },\n },\n color: Object.fromEntries(ROLES.map((r) => [r, {}])) as Record<TwColor, {}>,\n },\n compoundVariants: ROLES.flatMap((role) => [\n { variant: 'soft' as const, color: role, class: softSlots(role) },\n { variant: 'outline' as const, color: role, class: outlineSlots(role) },\n { variant: 'solid' as const, color: role, class: solidSlots(role) },\n ]),\n defaultVariants: {\n variant: 'soft',\n color: 'info',\n },\n}, {\n twMerge: true,\n});\n\n@Directive({\n selector: '[twAlertIcon]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class AlertIconDirective {\n private readonly alert = inject(AlertComponent);\n readonly classes = this.alert.iconClasses;\n}\n\n@Directive({\n selector: '[twAlertTitle]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class AlertTitleDirective {\n private readonly alert = inject(AlertComponent);\n readonly classes = this.alert.titleClasses;\n}\n\n@Directive({\n selector: '[twAlertContent]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class AlertContentDirective {\n private readonly alert = inject(AlertComponent);\n readonly classes = this.alert.contentClasses;\n}\n\n@Directive({\n selector: '[twAlertActions]',\n host: {\n '[class]': 'classes()',\n },\n})\nexport class AlertActionsDirective {\n private readonly alert = inject(AlertComponent);\n readonly classes = this.alert.actionsClasses;\n}\n\n@Component({\n selector: 'tw-alert',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[attr.role]': 'computedRole()',\n '[class]': 'rootClasses()',\n '[animate.leave]': '\"fade-out\"',\n },\n template: `\n @if (hasIcon()) {\n <ng-content select=\"[twAlertIcon]\" />\n }\n <div class=\"min-w-0 flex-1\">\n <ng-content select=\"[twAlertTitle]\" />\n <ng-content select=\"[twAlertContent]\" />\n <ng-content />\n <ng-content select=\"[twAlertActions]\" />\n </div>\n @if (dismissible()) {\n <button\n type=\"button\"\n [attr.aria-label]=\"dismissLabel()\"\n [class]=\"dismissClasses()\"\n (click)=\"dismissed.emit()\"\n >\n <!-- size-3.5 (14px) is the half-step between size-3 and size-4 — the only icon size that visually aligns with the alert title's text-sm metric inside the compact xs-density dismiss button. -->\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-3.5\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </button>\n }\n `,\n})\nexport class AlertComponent {\n /** Controls the visual style of the alert. Defaults to `'soft'`. */\n readonly variant = input<AlertVariant>('soft');\n\n /** Sets the semantic color palette. Defaults to `'info'`. */\n readonly color = input<TwColor>('info');\n\n /** When true, renders a dismiss button. Defaults to `false`. */\n readonly dismissible = input(false, { transform: booleanAttribute });\n\n /**\n * Sets the ARIA live-region politeness. Maps to the host `role`:\n * `'assertive'` → `role=\"alert\"`, `'polite'` → `role=\"status\"`,\n * `'off'` → no role. Use `'off'` to suppress re-announcement when the\n * alert content updates after initial render — assistive tech treats the\n * alert as a static region rather than a live region. Defaults to `'polite'`.\n */\n readonly politeness = input<AlertPoliteness>('polite');\n\n /** Accessible label for the dismiss button. Override for localization. Defaults to `'Dismiss'`. */\n readonly dismissLabel = input<string>('Dismiss');\n\n /** Fires when the dismiss button is clicked. */\n readonly dismissed = output<void>();\n\n /** @internal */\n readonly iconDirective = contentChild(AlertIconDirective);\n\n readonly hasIcon = computed(() => !!this.iconDirective());\n\n readonly computedRole = computed(() => {\n switch (this.politeness()) {\n case 'assertive':\n return 'alert';\n case 'polite':\n return 'status';\n default:\n return null;\n }\n });\n\n private readonly variantResult = computed(() =>\n alertVariants({\n variant: this.variant(),\n color: this.color(),\n }),\n );\n\n readonly rootClasses = computed(() => {\n const base = this.variantResult().root();\n return this.dismissible() ? `${base} pr-10` : base;\n });\n\n readonly iconClasses = computed(() => this.variantResult().icon());\n readonly titleClasses = computed(() => this.variantResult().title());\n readonly contentClasses = computed(() => this.variantResult().content());\n readonly actionsClasses = computed(() => this.variantResult().actions());\n readonly dismissClasses = computed(() => this.variantResult().dismiss());\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}