@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.
- package/LICENSE +21 -0
- package/README.md +134 -0
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +108 -0
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-alert.mjs +240 -0
- package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +287 -0
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +332 -0
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +452 -0
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-button.mjs +227 -0
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +417 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +232 -0
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +4482 -0
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-card.mjs +157 -0
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +1454 -0
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +593 -0
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +228 -0
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +510 -0
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +1721 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +721 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-core.mjs +861 -0
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +1558 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +1833 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +693 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +331 -0
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +289 -0
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +572 -0
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +36 -0
- package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +278 -0
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-input.mjs +355 -0
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-item.mjs +241 -0
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +433 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +691 -0
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +678 -0
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +335 -0
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +708 -0
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +319 -0
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +1722 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-separator.mjs +115 -0
- package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +768 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +1147 -0
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +346 -0
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-spinner.mjs +186 -0
- package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-split.mjs +1082 -0
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +579 -0
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +443 -0
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +391 -0
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +315 -0
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-table.mjs +994 -0
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +508 -0
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +147 -0
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +178 -0
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +1344 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +1136 -0
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +1311 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +533 -0
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw.mjs +61 -0
- package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -0
- package/package.json +265 -0
- package/theme/_base.css +394 -0
- package/theme/_dark.css +510 -0
- package/theme/_high-contrast.css +290 -0
- package/theme/_semantic.css +317 -0
- package/theme/_typography.css +9 -0
- package/theme/index.css +54 -0
- package/types/cdevhub-ngx-tw-accordion.d.ts +48 -0
- package/types/cdevhub-ngx-tw-alert.d.ts +67 -0
- package/types/cdevhub-ngx-tw-avatar.d.ts +79 -0
- package/types/cdevhub-ngx-tw-badge.d.ts +94 -0
- package/types/cdevhub-ngx-tw-breadcrumbs.d.ts +227 -0
- package/types/cdevhub-ngx-tw-button.d.ts +74 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +200 -0
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +113 -0
- package/types/cdevhub-ngx-tw-calendar.d.ts +1704 -0
- package/types/cdevhub-ngx-tw-card.d.ts +48 -0
- package/types/cdevhub-ngx-tw-carousel.d.ts +406 -0
- package/types/cdevhub-ngx-tw-checkbox.d.ts +136 -0
- package/types/cdevhub-ngx-tw-code-block.d.ts +93 -0
- package/types/cdevhub-ngx-tw-collapsible.d.ts +151 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +389 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +215 -0
- package/types/cdevhub-ngx-tw-core.d.ts +719 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +317 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +313 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +303 -0
- package/types/cdevhub-ngx-tw-empty-state.d.ts +104 -0
- package/types/cdevhub-ngx-tw-flip-card.d.ts +95 -0
- package/types/cdevhub-ngx-tw-form-field.d.ts +210 -0
- package/types/cdevhub-ngx-tw-icon-lucide.d.ts +29 -0
- package/types/cdevhub-ngx-tw-icon.d.ts +134 -0
- package/types/cdevhub-ngx-tw-input.d.ts +110 -0
- package/types/cdevhub-ngx-tw-item.d.ts +70 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +99 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +305 -0
- package/types/cdevhub-ngx-tw-popover.d.ts +157 -0
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +100 -0
- package/types/cdevhub-ngx-tw-radio.d.ts +174 -0
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +66 -0
- package/types/cdevhub-ngx-tw-select.d.ts +384 -0
- package/types/cdevhub-ngx-tw-separator.d.ts +28 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +335 -0
- package/types/cdevhub-ngx-tw-skeleton.d.ts +52 -0
- package/types/cdevhub-ngx-tw-slider.d.ts +258 -0
- package/types/cdevhub-ngx-tw-sort.d.ts +136 -0
- package/types/cdevhub-ngx-tw-spinner.d.ts +50 -0
- package/types/cdevhub-ngx-tw-split.d.ts +265 -0
- package/types/cdevhub-ngx-tw-stat.d.ts +140 -0
- package/types/cdevhub-ngx-tw-stepper.d.ts +127 -0
- package/types/cdevhub-ngx-tw-switch.d.ts +88 -0
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +107 -0
- package/types/cdevhub-ngx-tw-table.d.ts +479 -0
- package/types/cdevhub-ngx-tw-tabs.d.ts +121 -0
- package/types/cdevhub-ngx-tw-textarea.d.ts +62 -0
- package/types/cdevhub-ngx-tw-theme.d.ts +106 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +303 -0
- package/types/cdevhub-ngx-tw-timeline.d.ts +278 -0
- package/types/cdevhub-ngx-tw-toast.d.ts +388 -0
- package/types/cdevhub-ngx-tw-tooltip.d.ts +95 -0
- 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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"}
|