@cdevhub/ngx-tw 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +264 -49
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +11 -7
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-alert.mjs +43 -29
- package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-aspect-ratio.mjs +103 -0
- package/fesm2022/cdevhub-ngx-tw-aspect-ratio.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +56 -31
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +61 -35
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +154 -93
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-button.mjs +24 -15
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +3 -3
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +408 -215
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-card.mjs +33 -24
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +144 -79
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +99 -47
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +34 -20
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +46 -29
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +195 -110
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +140 -73
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-core.mjs +16 -11
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +393 -149
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +305 -150
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +56 -43
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +51 -33
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +905 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +49 -26
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +133 -74
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +2 -2
- package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +28 -17
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-input.mjs +37 -21
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-item.mjs +33 -24
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +63 -48
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs +622 -0
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +137 -71
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +101 -46
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +57 -30
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +108 -57
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +46 -26
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-select.mjs +217 -122
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-separator.mjs +21 -12
- package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +58 -44
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +25 -14
- package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +155 -79
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +44 -25
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-spinner.mjs +29 -16
- package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -42
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +107 -64
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +113 -47
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +61 -32
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +88 -42
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-table.mjs +266 -118
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +101 -51
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +798 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +11 -7
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +22 -14
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +243 -95
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +149 -82
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +89 -55
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +50 -28
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs +1129 -0
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tree.mjs +554 -0
- package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw.mjs +7 -0
- package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -1
- package/package.json +45 -20
- package/theme/index.css +10 -2
- package/types/cdevhub-ngx-tw-aspect-ratio.d.ts +40 -0
- package/types/cdevhub-ngx-tw-calendar.d.ts +39 -8
- package/types/cdevhub-ngx-tw-command-palette.d.ts +7 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +36 -10
- package/types/cdevhub-ngx-tw-file-upload.d.ts +250 -0
- package/types/cdevhub-ngx-tw-form-field.d.ts +22 -3
- package/types/cdevhub-ngx-tw-icon-lucide.d.ts +21 -3
- package/types/cdevhub-ngx-tw-number-input.d.ts +130 -0
- package/types/cdevhub-ngx-tw-popover.d.ts +8 -0
- package/types/cdevhub-ngx-tw-stepper.d.ts +30 -2
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +8 -0
- package/types/cdevhub-ngx-tw-table.d.ts +30 -1
- package/types/cdevhub-ngx-tw-tabs.d.ts +8 -0
- package/types/cdevhub-ngx-tw-tags-input.d.ts +217 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +31 -6
- package/types/cdevhub-ngx-tw-transfer.d.ts +330 -0
- package/types/cdevhub-ngx-tw-tree.d.ts +189 -0
- package/types/cdevhub-ngx-tw.d.ts +7 -0
package/README.md
CHANGED
|
@@ -5,16 +5,20 @@ and **Angular CDK**. The quality bar is [Angular Material](https://material.angu
|
|
|
5
5
|
— well-tested, accessible, composable — but styled with Tailwind utility classes
|
|
6
6
|
instead of Material Design tokens.
|
|
7
7
|
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
- **Standalone, signal-based APIs** — Angular
|
|
11
|
-
NgModules, `OnPush`, `input()
|
|
8
|
+
- **54 components** spanning forms, overlays, navigation, data display, layout,
|
|
9
|
+
and feedback.
|
|
10
|
+
- **Standalone, signal-based APIs** — Angular v22 idioms throughout (no
|
|
11
|
+
NgModules, `OnPush`, `input()` / `output()` / `model()`).
|
|
12
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
|
|
15
|
-
through semantic tokens.
|
|
13
|
+
overlays, a11y, collections). Targets WCAG AA and is checked with AXE.
|
|
14
|
+
- **Tailwind v4 native** — no component CSS files; consumers control appearance
|
|
15
|
+
through semantic design tokens.
|
|
16
|
+
- **Theme runtime included** — light / dark / high-contrast / system with a
|
|
17
|
+
persisted `ThemeService`, or pure-CSS dark mode with no JS.
|
|
16
18
|
- **Tree-shakeable secondary entry points** — import only what you use.
|
|
17
19
|
|
|
20
|
+
> **Live demo & API reference:** <https://avs2001.github.io/ngx-tw/>
|
|
21
|
+
|
|
18
22
|
## Installation
|
|
19
23
|
|
|
20
24
|
```bash
|
|
@@ -23,31 +27,90 @@ npm install @cdevhub/ngx-tw @angular/cdk tailwindcss tailwind-variants
|
|
|
23
27
|
|
|
24
28
|
**Peer requirements**
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
| Package | Version |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `@angular/core`, `@angular/common` | `^22.0.0` |
|
|
33
|
+
| `@angular/cdk` | `^22.0.0` |
|
|
34
|
+
| `tailwindcss` | `^4.0.0` |
|
|
35
|
+
| `tailwind-variants` | `^0.3.0` |
|
|
36
|
+
|
|
37
|
+
Form controls additionally use `@angular/forms` (ships with Angular). Node
|
|
38
|
+
`^22.22.3`, `^24.15.0`, or `>=26.0.0`.
|
|
30
39
|
|
|
31
40
|
## Setup
|
|
32
41
|
|
|
33
42
|
### 1. Import the default theme
|
|
34
43
|
|
|
35
|
-
Tailwind v4 has no JS config file — all customization happens in CSS.
|
|
36
|
-
|
|
44
|
+
Tailwind v4 has no JS config file — all customization happens in CSS. One
|
|
45
|
+
import is all that is needed:
|
|
37
46
|
|
|
38
47
|
```css
|
|
39
48
|
/* src/styles.css */
|
|
40
|
-
@import 'tailwindcss';
|
|
41
49
|
@import '@cdevhub/ngx-tw/theme/index.css';
|
|
42
50
|
```
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
That single line pulls in Tailwind itself, the semantic tokens, and a `@source`
|
|
53
|
+
directive pointing at the library's compiled bundles — the last one matters
|
|
54
|
+
because Tailwind v4 never scans `node_modules` on its own, so without it your
|
|
55
|
+
build would emit tokens but no component utilities. You do not need to add a
|
|
56
|
+
`@source` line yourself, and you do not need a separate `@import 'tailwindcss'`
|
|
57
|
+
(a duplicate is harmless if you already have one).
|
|
58
|
+
|
|
59
|
+
If you use any overlay-based component (dialog, sheet, menu, popover, select,
|
|
60
|
+
tooltip, combobox, date-picker, time-picker, command-palette), also import the
|
|
61
|
+
CDK overlay stylesheet:
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
@import '@angular/cdk/overlay-prebuilt.css';
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The theme maps semantic roles (`info`, `success`, `warning`, `error`,
|
|
45
68
|
`primary`, `secondary`, `accent`, `neutral`) and structural tokens (`surface`,
|
|
46
|
-
`fg`, `border`) to Tailwind's palette,
|
|
69
|
+
`fg`, `border`) to Tailwind's palette, and ships **dark** and **high-contrast**
|
|
70
|
+
variants out of the box.
|
|
47
71
|
|
|
48
|
-
### 2.
|
|
72
|
+
### 2. Register providers
|
|
49
73
|
|
|
50
|
-
|
|
74
|
+
A handful of subsystems are provider-based. Register the ones you use once, in
|
|
75
|
+
your application config:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// src/app/app.config.ts
|
|
79
|
+
import { ApplicationConfig } from '@angular/core';
|
|
80
|
+
import { provideTheme } from '@cdevhub/ngx-tw/theme';
|
|
81
|
+
import { provideNativeDateAdapter } from '@cdevhub/ngx-tw/calendar';
|
|
82
|
+
import { provideTwLucideIcons } from '@cdevhub/ngx-tw/icon/lucide';
|
|
83
|
+
import { provideTwDialog } from '@cdevhub/ngx-tw/dialog';
|
|
84
|
+
import { provideSheet } from '@cdevhub/ngx-tw/sheet';
|
|
85
|
+
import { provideToast } from '@cdevhub/ngx-tw/toast';
|
|
86
|
+
import { Star, Search, Settings } from 'lucide';
|
|
87
|
+
|
|
88
|
+
export const appConfig: ApplicationConfig = {
|
|
89
|
+
providers: [
|
|
90
|
+
provideTheme(), // theme service + persistence
|
|
91
|
+
provideNativeDateAdapter(), // calendar / date pickers
|
|
92
|
+
provideTwLucideIcons({ Star, Search, Settings }), // register named icons
|
|
93
|
+
provideTwDialog(), // tw-dialog overlay service
|
|
94
|
+
provideSheet(), // side-sheet overlay service
|
|
95
|
+
provideToast({ position: 'bottom-right', duration: 4000 }),
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
You only need the providers for the features you use:
|
|
101
|
+
|
|
102
|
+
| Provider | Required for | Entry point |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `provideTheme()` | runtime theme switching / `ThemeService` (optional — see below) | `@cdevhub/ngx-tw/theme` |
|
|
105
|
+
| `provideNativeDateAdapter()` | `calendar`, `date-picker`, `date-range-picker` | `@cdevhub/ngx-tw/calendar` |
|
|
106
|
+
| `provideTwLucideIcons()` / `provideTwIcons()` | `<tw-icon>` and any component that renders glyphs | `@cdevhub/ngx-tw/icon/lucide`, `@cdevhub/ngx-tw/icon` |
|
|
107
|
+
| `provideTwDialog()` | imperative dialogs via the `TwDialog` service | `@cdevhub/ngx-tw/dialog` |
|
|
108
|
+
| `provideSheet()` | imperative side sheets via the `Sheet` service | `@cdevhub/ngx-tw/sheet` |
|
|
109
|
+
| `provideToast()` | `ToastService` notifications | `@cdevhub/ngx-tw/toast` |
|
|
110
|
+
|
|
111
|
+
### 3. Use components
|
|
112
|
+
|
|
113
|
+
Import from the per-component entry points for the best tree-shaking:
|
|
51
114
|
|
|
52
115
|
```ts
|
|
53
116
|
import { Component } from '@angular/core';
|
|
@@ -65,9 +128,14 @@ import { AlertComponent } from '@cdevhub/ngx-tw/alert';
|
|
|
65
128
|
export class AppComponent {}
|
|
66
129
|
```
|
|
67
130
|
|
|
68
|
-
##
|
|
131
|
+
## Theming
|
|
132
|
+
|
|
133
|
+
### Semantic tokens
|
|
69
134
|
|
|
70
|
-
|
|
135
|
+
Components never reference raw palette colors. They use **semantic roles** on a
|
|
136
|
+
50–950 scale (`bg-primary-500`, `text-error-800`) plus structural tokens
|
|
137
|
+
(`surface`, `surface-raised`, `fg`, `fg-muted`, `border`). Re-theme the whole
|
|
138
|
+
library — including dark mode and brand palettes — by overriding those tokens.
|
|
71
139
|
|
|
72
140
|
```css
|
|
73
141
|
@import '@cdevhub/ngx-tw/theme/index.css';
|
|
@@ -77,54 +145,199 @@ Override any semantic token in your own CSS using Tailwind v4's `@theme` block:
|
|
|
77
145
|
--color-primary-500: oklch(0.55 0.2 260);
|
|
78
146
|
--color-primary-600: oklch(0.48 0.2 260);
|
|
79
147
|
|
|
80
|
-
/* Remap "info"
|
|
148
|
+
/* Remap "info" onto the sky palette */
|
|
81
149
|
--color-info-50: var(--color-sky-50);
|
|
82
150
|
--color-info-500: var(--color-sky-500);
|
|
83
151
|
}
|
|
84
152
|
```
|
|
85
153
|
|
|
86
|
-
Dark mode
|
|
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.
|
|
154
|
+
### Dark mode & runtime switching
|
|
90
155
|
|
|
91
|
-
|
|
156
|
+
Dark mode is driven by a `data-theme` attribute on `<html>` (with a
|
|
157
|
+
`prefers-color-scheme` fallback when no attribute is set), so the simplest setup
|
|
158
|
+
needs **no JavaScript** — the imported theme CSS already responds to the OS
|
|
159
|
+
preference.
|
|
160
|
+
|
|
161
|
+
For explicit, persisted switching, register `provideTheme()` and inject
|
|
162
|
+
`ThemeService`:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { ThemeService } from '@cdevhub/ngx-tw/theme';
|
|
92
166
|
|
|
93
|
-
|
|
167
|
+
export class ThemeToggle {
|
|
168
|
+
private readonly theme = inject(ThemeService);
|
|
94
169
|
|
|
170
|
+
readonly current = this.theme.theme; // 'light' | 'dark' | 'high-contrast' | 'system'
|
|
171
|
+
readonly resolved = this.theme.resolvedTheme; // never 'system'
|
|
172
|
+
readonly isDark = this.theme.isDark; // boolean signal
|
|
173
|
+
|
|
174
|
+
toggle() {
|
|
175
|
+
this.theme.cycleTheme(); // light → dark → high-contrast → system → …
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
dark() {
|
|
179
|
+
this.theme.setTheme('dark'); // also: 'light' | 'high-contrast' | 'system'
|
|
180
|
+
}
|
|
181
|
+
}
|
|
95
182
|
```
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
183
|
+
|
|
184
|
+
`ThemeService` writes the active theme to `data-theme` on `documentElement`,
|
|
185
|
+
tracks the OS preference, and persists the selection to `localStorage`
|
|
186
|
+
(`ngx-tw-theme` by default). Configure via `provideTheme({ defaultTheme,
|
|
187
|
+
storageKey, attribute, target })`. A `[twTheme]` directive is also available to
|
|
188
|
+
scope a theme to a subtree.
|
|
189
|
+
|
|
190
|
+
## Icons
|
|
191
|
+
|
|
192
|
+
`<tw-icon>` uses a registry: a glyph renders only after its name is registered.
|
|
193
|
+
The Lucide adapter is the quickest path — register the icons you need at
|
|
194
|
+
bootstrap:
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { provideTwLucideIcons } from '@cdevhub/ngx-tw/icon/lucide';
|
|
198
|
+
import { Star, Search } from 'lucide';
|
|
199
|
+
|
|
200
|
+
// in providers:
|
|
201
|
+
provideTwLucideIcons({ Star, Search });
|
|
110
202
|
```
|
|
111
203
|
|
|
112
|
-
|
|
204
|
+
```html
|
|
205
|
+
<tw-icon name="Star" size="md" />
|
|
206
|
+
```
|
|
113
207
|
|
|
114
|
-
|
|
115
|
-
|
|
208
|
+
Bring your own SVGs with `provideTwIcons()` / `IconRegistry` from
|
|
209
|
+
`@cdevhub/ngx-tw/icon`.
|
|
210
|
+
|
|
211
|
+
## Date & time
|
|
212
|
+
|
|
213
|
+
The calendar and date pickers require a date adapter. The native adapter works
|
|
214
|
+
zero-config:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { provideNativeDateAdapter } from '@cdevhub/ngx-tw/calendar';
|
|
218
|
+
// providers: [ provideNativeDateAdapter() ]
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
A Luxon adapter is available from the `@cdevhub/ngx-tw/calendar/luxon`
|
|
222
|
+
sub-entry, and calendar test helpers from `@cdevhub/ngx-tw/calendar/testing`.
|
|
223
|
+
Calendar UI strings are localizable via `CalendarIntl` / `provideCalendarIntl`.
|
|
116
224
|
|
|
117
225
|
## Form controls
|
|
118
226
|
|
|
119
|
-
Interactive controls
|
|
120
|
-
date-picker
|
|
121
|
-
|
|
122
|
-
|
|
227
|
+
Interactive controls — `input`, `textarea`, `select`, `combobox`, `checkbox`,
|
|
228
|
+
`radio`, `switch`, `slider`, `date-picker`, `date-range-picker`, `time-picker` —
|
|
229
|
+
implement `ControlValueAccessor` and work with all three Angular form
|
|
230
|
+
strategies: template-driven, reactive, and signal forms. Pair them with
|
|
231
|
+
`tw-form-field` for labels, hints, and error messages.
|
|
232
|
+
|
|
233
|
+
## Components
|
|
234
|
+
|
|
235
|
+
54 components, each published as an independent secondary entry point
|
|
236
|
+
(`@cdevhub/ngx-tw/<name>`). See the [live demo](https://avs2001.github.io/ngx-tw/)
|
|
237
|
+
for full API tables and examples.
|
|
238
|
+
|
|
239
|
+
### Actions & inputs
|
|
240
|
+
|
|
241
|
+
| Component | Selector | Purpose |
|
|
242
|
+
|---|---|---|
|
|
243
|
+
| button | `[twButton]` | Multi-variant button (color / size / variant) |
|
|
244
|
+
| checkbox | `tw-checkbox` | Accessible checkbox control |
|
|
245
|
+
| radio | `tw-radio-group` / `tw-radio` | Single-choice radio group |
|
|
246
|
+
| switch | `tw-switch` | Boolean toggle |
|
|
247
|
+
| slider | `tw-slider` | Numeric range selector |
|
|
248
|
+
| input | `[twInput]` | Text input styling directive |
|
|
249
|
+
| textarea | `[twTextarea]` | Multi-line text input |
|
|
250
|
+
| select | `tw-select` | Single/multi dropdown select |
|
|
251
|
+
| combobox | `tw-combobox` | Autocomplete / filterable input |
|
|
252
|
+
| segmented-control | `tw-segmented-control` | Single-select button group |
|
|
253
|
+
| form-field | `tw-form-field` | Label / hint / error wrapper |
|
|
254
|
+
|
|
255
|
+
### Date & time
|
|
256
|
+
|
|
257
|
+
| Component | Selector | Purpose |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| calendar | `tw-calendar` | Single / multiple / range calendar |
|
|
260
|
+
| date-picker | `tw-date-picker` | Single date input + overlay |
|
|
261
|
+
| date-range-picker | `tw-date-range-picker` | Date-range input + overlay |
|
|
262
|
+
| time-picker | `tw-time-picker` | Hours / minutes selector |
|
|
263
|
+
|
|
264
|
+
### Overlays & feedback
|
|
265
|
+
|
|
266
|
+
| Component | Selector / API | Purpose |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| dialog | `TwDialog` service | Modal dialog overlay |
|
|
269
|
+
| sheet | `Sheet` service | Side drawer / sheet |
|
|
270
|
+
| popover | `[twPopover]` | Floating anchored content |
|
|
271
|
+
| tooltip | `[twTooltip]` | Hover / focus tooltip |
|
|
272
|
+
| menu | `tw-menu` + `[twMenuTrigger]` | Dropdown & context menus |
|
|
273
|
+
| toast | `ToastService` | Transient notifications |
|
|
274
|
+
| command-palette | `tw-command-palette` | Keyboard command finder |
|
|
275
|
+
| alert | `tw-alert` | Inline status message |
|
|
276
|
+
|
|
277
|
+
### Navigation
|
|
278
|
+
|
|
279
|
+
| Component | Selector | Purpose |
|
|
280
|
+
|---|---|---|
|
|
281
|
+
| tabs | `tw-tabs` | Tabbed content panels |
|
|
282
|
+
| tab-nav | `[twTabNav]` / `[twTabLink]` | Router-aware tab bar |
|
|
283
|
+
| breadcrumbs | `tw-breadcrumbs` | Hierarchical path navigation |
|
|
284
|
+
| paginator | `tw-paginator` | Page-size / range pagination |
|
|
285
|
+
| stepper | `tw-stepper` | Multi-step flow |
|
|
286
|
+
|
|
287
|
+
### Data display
|
|
288
|
+
|
|
289
|
+
| Component | Selector | Purpose |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| table | `tw-table` | Data table (sort, expand, sticky) |
|
|
292
|
+
| sort | `[twSort]` | Sortable column headers |
|
|
293
|
+
| card | `tw-card` | Elevated / outlined container |
|
|
294
|
+
| item | `tw-item` | List item with leading/trailing slots |
|
|
295
|
+
| stat | `tw-stat` | KPI value with delta |
|
|
296
|
+
| badge | `[twBadge]` | Count / status indicator |
|
|
297
|
+
| avatar | `tw-avatar` / `tw-avatar-group` | Image / initials avatar |
|
|
298
|
+
| timeline | `tw-timeline` | Chronological event list |
|
|
299
|
+
| code-block | `tw-code-block` | Code display with header |
|
|
300
|
+
| separator | `tw-separator` | Divider line |
|
|
301
|
+
|
|
302
|
+
### Layout & disclosure
|
|
303
|
+
|
|
304
|
+
| Component | Selector | Purpose |
|
|
305
|
+
|---|---|---|
|
|
306
|
+
| accordion | `tw-accordion` | Single / multi-panel disclosure |
|
|
307
|
+
| collapsible | `tw-collapsible` | Collapsible region + group |
|
|
308
|
+
| split | `tw-split` | Resizable split panes |
|
|
309
|
+
| carousel | `tw-carousel` | Slide carousel |
|
|
310
|
+
| flip-card | `tw-flip-card` | Front/back flip animation |
|
|
311
|
+
|
|
312
|
+
### Status & utility
|
|
313
|
+
|
|
314
|
+
| Component | Selector | Purpose |
|
|
315
|
+
|---|---|---|
|
|
316
|
+
| spinner | `tw-spinner` | Loading spinner |
|
|
317
|
+
| progress-bar | `tw-progress-bar` | Determinate / indeterminate progress |
|
|
318
|
+
| skeleton | `tw-skeleton` | Content placeholder |
|
|
319
|
+
| empty-state | `tw-empty-state` | No-data / empty screen |
|
|
320
|
+
| icon | `tw-icon` | Registry-backed SVG icon |
|
|
321
|
+
|
|
322
|
+
## Entry points
|
|
323
|
+
|
|
324
|
+
| Entry point | Contents |
|
|
325
|
+
|---|---|
|
|
326
|
+
| `@cdevhub/ngx-tw/<component>` | One per component (preferred — tree-shakeable) |
|
|
327
|
+
| `@cdevhub/ngx-tw` | Catch-all re-export of every public API (convenience) |
|
|
328
|
+
| `@cdevhub/ngx-tw/core` | Shared types (`TwColor`, `TwSize`) and `TW_ERROR_STATE_MATCHER` |
|
|
329
|
+
| `@cdevhub/ngx-tw/theme` | `ThemeService`, `provideTheme`, `[twTheme]`, theme types |
|
|
330
|
+
| `@cdevhub/ngx-tw/theme/index.css` | Default semantic theme stylesheet (asset) |
|
|
331
|
+
| `@cdevhub/ngx-tw/icon/lucide` | `provideTwLucideIcons`, `fromLucideIcon` |
|
|
332
|
+
| `@cdevhub/ngx-tw/calendar/luxon` | Luxon date adapter |
|
|
333
|
+
| `@cdevhub/ngx-tw/calendar/testing` | Calendar test harnesses |
|
|
334
|
+
|
|
335
|
+
Per-component imports are preferred over the catch-all for tree-shaking.
|
|
123
336
|
|
|
124
337
|
## Building locally
|
|
125
338
|
|
|
126
339
|
```bash
|
|
127
|
-
ng build ngx-tw # build library to dist/ngx-tw
|
|
340
|
+
ng build ngx-tw # build the library to dist/ngx-tw
|
|
128
341
|
ng test ngx-tw --no-watch # run unit tests (Vitest)
|
|
129
342
|
ng serve demo # run the demo app
|
|
130
343
|
```
|
|
@@ -132,3 +345,5 @@ ng serve demo # run the demo app
|
|
|
132
345
|
## License
|
|
133
346
|
|
|
134
347
|
[MIT](./LICENSE) © Iuga Ciprian
|
|
348
|
+
</content>
|
|
349
|
+
</invoke>
|
|
@@ -46,9 +46,11 @@ const accordionVariants = tv({
|
|
|
46
46
|
*/
|
|
47
47
|
class AccordionComponent extends CollapsibleGroupComponent {
|
|
48
48
|
/** Open mode. `'single'` allows one panel open at a time; `'multiple'` allows many. Defaults to `'single'`. */
|
|
49
|
-
type = input('single',
|
|
49
|
+
type = input('single', /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
50
51
|
/** Visual style of the accordion container. Defaults to `'default'`. */
|
|
51
|
-
variant = input('default',
|
|
52
|
+
variant = input('default', /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
52
54
|
/** In `'single'` mode, whether re-clicking the open panel closes it. Defaults to `true` — accordions are collapsible by definition; opt-out only. */
|
|
53
55
|
collapsible = input(true, { ...(ngDevMode ? { debugName: "collapsible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
54
56
|
/** Accessible name for the accordion. Use when surrounding context doesn't make the purpose obvious. */
|
|
@@ -57,9 +59,11 @@ class AccordionComponent extends CollapsibleGroupComponent {
|
|
|
57
59
|
ariaLabelledby = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabelledby" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
|
|
58
60
|
// ── Inherited-binding overrides ──
|
|
59
61
|
/** @internal APG: accordions don't carry `role="group"`. */
|
|
60
|
-
hostRole = computed(() => null,
|
|
62
|
+
hostRole = computed(() => null, /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "hostRole" }] : /* istanbul ignore next */ []));
|
|
61
64
|
/** @internal Variant-driven container classes; replaces the parent's default group string. */
|
|
62
|
-
hostClasses = computed(() => accordionVariants({ variant: this.variant() }).root(),
|
|
65
|
+
hostClasses = computed(() => accordionVariants({ variant: this.variant() }).root(), /* @ts-ignore */
|
|
66
|
+
...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
|
|
63
67
|
// ── Virtual-hook overrides ──
|
|
64
68
|
/** @internal Drive single-open-panel behaviour from `type`, ignoring the inherited `accordion` input. */
|
|
65
69
|
isAccordionMode() {
|
|
@@ -69,15 +73,15 @@ class AccordionComponent extends CollapsibleGroupComponent {
|
|
|
69
73
|
canCollapseSingleMode() {
|
|
70
74
|
return this.collapsible();
|
|
71
75
|
}
|
|
72
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
73
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "
|
|
76
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AccordionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
77
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.7", 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
78
|
{
|
|
75
79
|
provide: CollapsibleGroupComponent,
|
|
76
80
|
useExisting: forwardRef(() => AccordionComponent),
|
|
77
81
|
},
|
|
78
82
|
], usesInheritance: true, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
79
83
|
}
|
|
80
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
84
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AccordionComponent, decorators: [{
|
|
81
85
|
type: Component,
|
|
82
86
|
args: [{
|
|
83
87
|
selector: 'tw-accordion',
|
|
@@ -1 +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":";;;;;AAiBA;AAEA,MAAM,iBAAiB,GAAG,EAAE,CAC1B;AACE,IAAA,KAAK,EAAE;AACL,QAAA,IAAI,EAAE,OAAO;AACd,KAAA;AACD,IAAA,QAAQ,EAAE;AACR,QAAA,OAAO,EAAE;AACP,YAAA,OAAO,EAAE;AACP,gBAAA,IAAI,EAAE,mDAAmD;AAC1D,aAAA;AACD,YAAA,QAAQ,EAAE;AACR,gBAAA,IAAI,EAAE,wEAAwE;AAC/E,aAAA;AACD,YAAA,KAAK,EAAE;AACL,gBAAA,IAAI,EAAE,EAAE;AACT,aAAA;AACF,SAAA;AACF,KAAA;AACD,IAAA,eAAe,EAAE;AACf,QAAA,OAAO,EAAE,SAAS;AACnB,KAAA;CACF,EACD;AACE,IAAA,OAAO,EAAE,IAAI;AACd,CAAA,CACF;AAED;AAEA;;;;;;;;;;;;;;;AAeG;AAoBG,MAAO,kBAAmB,SAAQ,yBAAyB,CAAA;;
|
|
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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"}
|
|
@@ -67,10 +67,10 @@ const alertVariants = tv({
|
|
|
67
67
|
class AlertIconDirective {
|
|
68
68
|
alert = inject(AlertComponent);
|
|
69
69
|
classes = this.alert.iconClasses;
|
|
70
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
71
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
70
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
71
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: AlertIconDirective, isStandalone: true, selector: "[twAlertIcon]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
|
|
72
72
|
}
|
|
73
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
73
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertIconDirective, decorators: [{
|
|
74
74
|
type: Directive,
|
|
75
75
|
args: [{
|
|
76
76
|
selector: '[twAlertIcon]',
|
|
@@ -82,10 +82,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
82
82
|
class AlertTitleDirective {
|
|
83
83
|
alert = inject(AlertComponent);
|
|
84
84
|
classes = this.alert.titleClasses;
|
|
85
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
86
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
85
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertTitleDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
86
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: AlertTitleDirective, isStandalone: true, selector: "[twAlertTitle]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
|
|
87
87
|
}
|
|
88
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
88
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertTitleDirective, decorators: [{
|
|
89
89
|
type: Directive,
|
|
90
90
|
args: [{
|
|
91
91
|
selector: '[twAlertTitle]',
|
|
@@ -97,10 +97,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
97
97
|
class AlertContentDirective {
|
|
98
98
|
alert = inject(AlertComponent);
|
|
99
99
|
classes = this.alert.contentClasses;
|
|
100
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
101
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
100
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
101
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: AlertContentDirective, isStandalone: true, selector: "[twAlertContent]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
|
|
102
102
|
}
|
|
103
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
103
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertContentDirective, decorators: [{
|
|
104
104
|
type: Directive,
|
|
105
105
|
args: [{
|
|
106
106
|
selector: '[twAlertContent]',
|
|
@@ -112,10 +112,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
112
112
|
class AlertActionsDirective {
|
|
113
113
|
alert = inject(AlertComponent);
|
|
114
114
|
classes = this.alert.actionsClasses;
|
|
115
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
116
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
115
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertActionsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
116
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: AlertActionsDirective, isStandalone: true, selector: "[twAlertActions]", host: { properties: { "class": "classes()" } }, ngImport: i0 });
|
|
117
117
|
}
|
|
118
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
118
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertActionsDirective, decorators: [{
|
|
119
119
|
type: Directive,
|
|
120
120
|
args: [{
|
|
121
121
|
selector: '[twAlertActions]',
|
|
@@ -126,9 +126,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
126
126
|
}] });
|
|
127
127
|
class AlertComponent {
|
|
128
128
|
/** Controls the visual style of the alert. Defaults to `'soft'`. */
|
|
129
|
-
variant = input('soft',
|
|
129
|
+
variant = input('soft', /* @ts-ignore */
|
|
130
|
+
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
130
131
|
/** Sets the semantic color palette. Defaults to `'info'`. */
|
|
131
|
-
color = input('info',
|
|
132
|
+
color = input('info', /* @ts-ignore */
|
|
133
|
+
...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
132
134
|
/** When true, renders a dismiss button. Defaults to `false`. */
|
|
133
135
|
dismissible = input(false, { ...(ngDevMode ? { debugName: "dismissible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
134
136
|
/**
|
|
@@ -138,14 +140,18 @@ class AlertComponent {
|
|
|
138
140
|
* alert content updates after initial render — assistive tech treats the
|
|
139
141
|
* alert as a static region rather than a live region. Defaults to `'polite'`.
|
|
140
142
|
*/
|
|
141
|
-
politeness = input('polite',
|
|
143
|
+
politeness = input('polite', /* @ts-ignore */
|
|
144
|
+
...(ngDevMode ? [{ debugName: "politeness" }] : /* istanbul ignore next */ []));
|
|
142
145
|
/** Accessible label for the dismiss button. Override for localization. Defaults to `'Dismiss'`. */
|
|
143
|
-
dismissLabel = input('Dismiss',
|
|
146
|
+
dismissLabel = input('Dismiss', /* @ts-ignore */
|
|
147
|
+
...(ngDevMode ? [{ debugName: "dismissLabel" }] : /* istanbul ignore next */ []));
|
|
144
148
|
/** Fires when the dismiss button is clicked. */
|
|
145
149
|
dismissed = output();
|
|
146
150
|
/** @internal */
|
|
147
|
-
iconDirective = contentChild(AlertIconDirective,
|
|
148
|
-
|
|
151
|
+
iconDirective = contentChild(AlertIconDirective, /* @ts-ignore */
|
|
152
|
+
...(ngDevMode ? [{ debugName: "iconDirective" }] : /* istanbul ignore next */ []));
|
|
153
|
+
hasIcon = computed(() => !!this.iconDirective(), /* @ts-ignore */
|
|
154
|
+
...(ngDevMode ? [{ debugName: "hasIcon" }] : /* istanbul ignore next */ []));
|
|
149
155
|
computedRole = computed(() => {
|
|
150
156
|
switch (this.politeness()) {
|
|
151
157
|
case 'assertive':
|
|
@@ -155,22 +161,30 @@ class AlertComponent {
|
|
|
155
161
|
default:
|
|
156
162
|
return null;
|
|
157
163
|
}
|
|
158
|
-
},
|
|
164
|
+
}, /* @ts-ignore */
|
|
165
|
+
...(ngDevMode ? [{ debugName: "computedRole" }] : /* istanbul ignore next */ []));
|
|
159
166
|
variantResult = computed(() => alertVariants({
|
|
160
167
|
variant: this.variant(),
|
|
161
168
|
color: this.color(),
|
|
162
|
-
}),
|
|
169
|
+
}), /* @ts-ignore */
|
|
170
|
+
...(ngDevMode ? [{ debugName: "variantResult" }] : /* istanbul ignore next */ []));
|
|
163
171
|
rootClasses = computed(() => {
|
|
164
172
|
const base = this.variantResult().root();
|
|
165
173
|
return this.dismissible() ? `${base} pr-10` : base;
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
}, /* @ts-ignore */
|
|
175
|
+
...(ngDevMode ? [{ debugName: "rootClasses" }] : /* istanbul ignore next */ []));
|
|
176
|
+
iconClasses = computed(() => this.variantResult().icon(), /* @ts-ignore */
|
|
177
|
+
...(ngDevMode ? [{ debugName: "iconClasses" }] : /* istanbul ignore next */ []));
|
|
178
|
+
titleClasses = computed(() => this.variantResult().title(), /* @ts-ignore */
|
|
179
|
+
...(ngDevMode ? [{ debugName: "titleClasses" }] : /* istanbul ignore next */ []));
|
|
180
|
+
contentClasses = computed(() => this.variantResult().content(), /* @ts-ignore */
|
|
181
|
+
...(ngDevMode ? [{ debugName: "contentClasses" }] : /* istanbul ignore next */ []));
|
|
182
|
+
actionsClasses = computed(() => this.variantResult().actions(), /* @ts-ignore */
|
|
183
|
+
...(ngDevMode ? [{ debugName: "actionsClasses" }] : /* istanbul ignore next */ []));
|
|
184
|
+
dismissClasses = computed(() => this.variantResult().dismiss(), /* @ts-ignore */
|
|
185
|
+
...(ngDevMode ? [{ debugName: "dismissClasses" }] : /* istanbul ignore next */ []));
|
|
186
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
187
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", 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
188
|
@if (hasIcon()) {
|
|
175
189
|
<ng-content select="[twAlertIcon]" />
|
|
176
190
|
}
|
|
@@ -195,7 +209,7 @@ class AlertComponent {
|
|
|
195
209
|
}
|
|
196
210
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
197
211
|
}
|
|
198
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
212
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: AlertComponent, decorators: [{
|
|
199
213
|
type: Component,
|
|
200
214
|
args: [{
|
|
201
215
|
selector: 'tw-alert',
|