@edsis/ui 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/accordion/README.md +195 -0
- package/alert/README.md +177 -0
- package/alert-dialog/README.md +239 -0
- package/aspect-ratio/README.md +112 -0
- package/avatar/README.md +176 -0
- package/badge/README.md +133 -0
- package/breadcrumb/README.md +216 -0
- package/button/README.md +139 -0
- package/button-group/README.md +204 -0
- package/calendar/README.md +132 -0
- package/card/README.md +220 -0
- package/carousel/README.md +276 -0
- package/chart/README.md +249 -0
- package/checkbox/README.md +149 -0
- package/collapsible/README.md +191 -0
- package/combobox/README.md +198 -0
- package/command/README.md +275 -0
- package/composer/README.md +235 -0
- package/context-menu/README.md +267 -0
- package/date-picker/README.md +177 -0
- package/dialog/README.md +237 -0
- package/drawer/README.md +145 -0
- package/dropdown-menu/README.md +311 -0
- package/editor/README.md +136 -0
- package/empty/README.md +183 -0
- package/fesm2022/edsis-ui-accordion.mjs +174 -0
- package/fesm2022/edsis-ui-accordion.mjs.map +1 -0
- package/fesm2022/edsis-ui-alert-dialog.mjs +242 -0
- package/fesm2022/edsis-ui-alert-dialog.mjs.map +1 -0
- package/fesm2022/edsis-ui-alert.mjs +90 -0
- package/fesm2022/edsis-ui-alert.mjs.map +1 -0
- package/fesm2022/edsis-ui-aspect-ratio.mjs +33 -0
- package/fesm2022/edsis-ui-aspect-ratio.mjs.map +1 -0
- package/fesm2022/edsis-ui-avatar.mjs +123 -0
- package/fesm2022/edsis-ui-avatar.mjs.map +1 -0
- package/fesm2022/edsis-ui-badge.mjs +47 -0
- package/fesm2022/edsis-ui-badge.mjs.map +1 -0
- package/fesm2022/edsis-ui-breadcrumb.mjs +186 -0
- package/fesm2022/edsis-ui-breadcrumb.mjs.map +1 -0
- package/fesm2022/edsis-ui-button-group.mjs +95 -0
- package/fesm2022/edsis-ui-button-group.mjs.map +1 -0
- package/fesm2022/edsis-ui-button.mjs +64 -0
- package/fesm2022/edsis-ui-button.mjs.map +1 -0
- package/fesm2022/edsis-ui-calendar.mjs +78 -0
- package/fesm2022/edsis-ui-calendar.mjs.map +1 -0
- package/fesm2022/edsis-ui-card.mjs +137 -0
- package/fesm2022/edsis-ui-card.mjs.map +1 -0
- package/fesm2022/edsis-ui-carousel.mjs +310 -0
- package/fesm2022/edsis-ui-carousel.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-area.mjs +6 -0
- package/fesm2022/edsis-ui-chart-area.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-bar.mjs +6 -0
- package/fesm2022/edsis-ui-chart-bar.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-line.mjs +6 -0
- package/fesm2022/edsis-ui-chart-line.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-pie.mjs +6 -0
- package/fesm2022/edsis-ui-chart-pie.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-radar.mjs +6 -0
- package/fesm2022/edsis-ui-chart-radar.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-radial.mjs +6 -0
- package/fesm2022/edsis-ui-chart-radial.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart-scatter.mjs +6 -0
- package/fesm2022/edsis-ui-chart-scatter.mjs.map +1 -0
- package/fesm2022/edsis-ui-chart.mjs +3714 -0
- package/fesm2022/edsis-ui-chart.mjs.map +1 -0
- package/fesm2022/edsis-ui-checkbox.mjs +104 -0
- package/fesm2022/edsis-ui-checkbox.mjs.map +1 -0
- package/fesm2022/edsis-ui-collapsible.mjs +116 -0
- package/fesm2022/edsis-ui-collapsible.mjs.map +1 -0
- package/fesm2022/edsis-ui-combobox.mjs +263 -0
- package/fesm2022/edsis-ui-combobox.mjs.map +1 -0
- package/fesm2022/edsis-ui-command.mjs +268 -0
- package/fesm2022/edsis-ui-command.mjs.map +1 -0
- package/fesm2022/edsis-ui-composer.mjs +329 -0
- package/fesm2022/edsis-ui-composer.mjs.map +1 -0
- package/fesm2022/edsis-ui-context-menu.mjs +100 -0
- package/fesm2022/edsis-ui-context-menu.mjs.map +1 -0
- package/fesm2022/edsis-ui-date-picker.mjs +155 -0
- package/fesm2022/edsis-ui-date-picker.mjs.map +1 -0
- package/fesm2022/edsis-ui-dialog.mjs +262 -0
- package/fesm2022/edsis-ui-dialog.mjs.map +1 -0
- package/fesm2022/edsis-ui-drawer.mjs +6 -0
- package/fesm2022/edsis-ui-drawer.mjs.map +1 -0
- package/fesm2022/edsis-ui-dropdown-menu.mjs +466 -0
- package/fesm2022/edsis-ui-dropdown-menu.mjs.map +1 -0
- package/fesm2022/edsis-ui-editor.mjs +692 -0
- package/fesm2022/edsis-ui-editor.mjs.map +1 -0
- package/fesm2022/edsis-ui-empty.mjs +132 -0
- package/fesm2022/edsis-ui-empty.mjs.map +1 -0
- package/fesm2022/edsis-ui-form.mjs +334 -0
- package/fesm2022/edsis-ui-form.mjs.map +1 -0
- package/fesm2022/edsis-ui-hover-card.mjs +284 -0
- package/fesm2022/edsis-ui-hover-card.mjs.map +1 -0
- package/fesm2022/edsis-ui-input-group.mjs +164 -0
- package/fesm2022/edsis-ui-input-group.mjs.map +1 -0
- package/fesm2022/edsis-ui-input-otp.mjs +485 -0
- package/fesm2022/edsis-ui-input-otp.mjs.map +1 -0
- package/fesm2022/edsis-ui-input.mjs +43 -0
- package/fesm2022/edsis-ui-input.mjs.map +1 -0
- package/fesm2022/edsis-ui-item.mjs +241 -0
- package/fesm2022/edsis-ui-item.mjs.map +1 -0
- package/fesm2022/edsis-ui-kanban.mjs +289 -0
- package/fesm2022/edsis-ui-kanban.mjs.map +1 -0
- package/fesm2022/edsis-ui-kbd.mjs +51 -0
- package/fesm2022/edsis-ui-kbd.mjs.map +1 -0
- package/fesm2022/edsis-ui-label.mjs +30 -0
- package/fesm2022/edsis-ui-label.mjs.map +1 -0
- package/fesm2022/edsis-ui-menubar.mjs +302 -0
- package/fesm2022/edsis-ui-menubar.mjs.map +1 -0
- package/fesm2022/edsis-ui-native-select.mjs +61 -0
- package/fesm2022/edsis-ui-native-select.mjs.map +1 -0
- package/fesm2022/edsis-ui-navigation-menu.mjs +399 -0
- package/fesm2022/edsis-ui-navigation-menu.mjs.map +1 -0
- package/fesm2022/edsis-ui-pagination.mjs +216 -0
- package/fesm2022/edsis-ui-pagination.mjs.map +1 -0
- package/fesm2022/edsis-ui-pillbox.mjs +777 -0
- package/fesm2022/edsis-ui-pillbox.mjs.map +1 -0
- package/fesm2022/edsis-ui-popover.mjs +163 -0
- package/fesm2022/edsis-ui-popover.mjs.map +1 -0
- package/fesm2022/edsis-ui-progress.mjs +53 -0
- package/fesm2022/edsis-ui-progress.mjs.map +1 -0
- package/fesm2022/edsis-ui-radio.mjs +111 -0
- package/fesm2022/edsis-ui-radio.mjs.map +1 -0
- package/fesm2022/edsis-ui-resizable.mjs +454 -0
- package/fesm2022/edsis-ui-resizable.mjs.map +1 -0
- package/fesm2022/edsis-ui-scroll-area.mjs +48 -0
- package/fesm2022/edsis-ui-scroll-area.mjs.map +1 -0
- package/fesm2022/edsis-ui-select.mjs +164 -0
- package/fesm2022/edsis-ui-select.mjs.map +1 -0
- package/fesm2022/edsis-ui-separator.mjs +33 -0
- package/fesm2022/edsis-ui-separator.mjs.map +1 -0
- package/fesm2022/edsis-ui-sheet.mjs +264 -0
- package/fesm2022/edsis-ui-sheet.mjs.map +1 -0
- package/fesm2022/edsis-ui-skeleton.mjs +29 -0
- package/fesm2022/edsis-ui-skeleton.mjs.map +1 -0
- package/fesm2022/edsis-ui-slider.mjs +405 -0
- package/fesm2022/edsis-ui-slider.mjs.map +1 -0
- package/fesm2022/edsis-ui-spinner.mjs +58 -0
- package/fesm2022/edsis-ui-spinner.mjs.map +1 -0
- package/fesm2022/edsis-ui-switch.mjs +107 -0
- package/fesm2022/edsis-ui-switch.mjs.map +1 -0
- package/fesm2022/edsis-ui-table.mjs +139 -0
- package/fesm2022/edsis-ui-table.mjs.map +1 -0
- package/fesm2022/edsis-ui-tabs.mjs +252 -0
- package/fesm2022/edsis-ui-tabs.mjs.map +1 -0
- package/fesm2022/edsis-ui-textarea.mjs +37 -0
- package/fesm2022/edsis-ui-textarea.mjs.map +1 -0
- package/fesm2022/edsis-ui-timeline.mjs +213 -0
- package/fesm2022/edsis-ui-timeline.mjs.map +1 -0
- package/fesm2022/edsis-ui-toast.mjs +71 -0
- package/fesm2022/edsis-ui-toast.mjs.map +1 -0
- package/fesm2022/edsis-ui-toggle-group.mjs +269 -0
- package/fesm2022/edsis-ui-toggle-group.mjs.map +1 -0
- package/fesm2022/edsis-ui-toggle.mjs +76 -0
- package/fesm2022/edsis-ui-toggle.mjs.map +1 -0
- package/fesm2022/edsis-ui-tooltip.mjs +339 -0
- package/fesm2022/edsis-ui-tooltip.mjs.map +1 -0
- package/fesm2022/edsis-ui-utils.mjs +13 -0
- package/fesm2022/edsis-ui-utils.mjs.map +1 -0
- package/fesm2022/edsis-ui.mjs +11 -0
- package/fesm2022/edsis-ui.mjs.map +1 -0
- package/form/README.md +210 -0
- package/hover-card/README.md +146 -0
- package/input/README.md +159 -0
- package/input-group/README.md +234 -0
- package/input-otp/README.md +273 -0
- package/item/README.md +247 -0
- package/kanban/README.md +81 -0
- package/kbd/README.md +139 -0
- package/label/README.md +136 -0
- package/menubar/README.md +269 -0
- package/native-select/README.md +176 -0
- package/navigation-menu/README.md +160 -0
- package/package.json +310 -0
- package/pagination/README.md +144 -0
- package/pillbox/README.md +67 -0
- package/popover/README.md +43 -0
- package/progress/README.md +160 -0
- package/radio/README.md +209 -0
- package/resizable/README.md +164 -0
- package/scroll-area/README.md +143 -0
- package/select/README.md +174 -0
- package/separator/README.md +170 -0
- package/sheet/README.md +183 -0
- package/skeleton/README.md +158 -0
- package/slider/README.md +207 -0
- package/spinner/README.md +160 -0
- package/switch/README.md +166 -0
- package/table/README.md +291 -0
- package/tabs/README.md +214 -0
- package/textarea/README.md +154 -0
- package/timeline/README.md +94 -0
- package/toast/README.md +321 -0
- package/toggle/README.md +131 -0
- package/toggle-group/README.md +206 -0
- package/tooltip/README.md +211 -0
- package/types/edsis-ui-accordion.d.ts +51 -0
- package/types/edsis-ui-alert-dialog.d.ts +93 -0
- package/types/edsis-ui-alert.d.ts +37 -0
- package/types/edsis-ui-aspect-ratio.d.ts +12 -0
- package/types/edsis-ui-avatar.d.ts +51 -0
- package/types/edsis-ui-badge.d.ts +19 -0
- package/types/edsis-ui-breadcrumb.d.ts +46 -0
- package/types/edsis-ui-button-group.d.ts +26 -0
- package/types/edsis-ui-button.d.ts +22 -0
- package/types/edsis-ui-calendar.d.ts +33 -0
- package/types/edsis-ui-card.d.ts +60 -0
- package/types/edsis-ui-carousel.d.ts +86 -0
- package/types/edsis-ui-chart-area.d.ts +1 -0
- package/types/edsis-ui-chart-bar.d.ts +1 -0
- package/types/edsis-ui-chart-line.d.ts +1 -0
- package/types/edsis-ui-chart-pie.d.ts +1 -0
- package/types/edsis-ui-chart-radar.d.ts +1 -0
- package/types/edsis-ui-chart-radial.d.ts +1 -0
- package/types/edsis-ui-chart-scatter.d.ts +1 -0
- package/types/edsis-ui-chart.d.ts +1094 -0
- package/types/edsis-ui-checkbox.d.ts +35 -0
- package/types/edsis-ui-collapsible.d.ts +42 -0
- package/types/edsis-ui-combobox.d.ts +51 -0
- package/types/edsis-ui-command.d.ts +99 -0
- package/types/edsis-ui-composer.d.ts +90 -0
- package/types/edsis-ui-context-menu.d.ts +35 -0
- package/types/edsis-ui-date-picker.d.ts +41 -0
- package/types/edsis-ui-dialog.d.ts +87 -0
- package/types/edsis-ui-drawer.d.ts +1 -0
- package/types/edsis-ui-dropdown-menu.d.ts +136 -0
- package/types/edsis-ui-editor.d.ts +123 -0
- package/types/edsis-ui-empty.d.ts +50 -0
- package/types/edsis-ui-form.d.ts +141 -0
- package/types/edsis-ui-hover-card.d.ts +74 -0
- package/types/edsis-ui-input-group.d.ts +51 -0
- package/types/edsis-ui-input-otp.d.ts +136 -0
- package/types/edsis-ui-input.d.ts +16 -0
- package/types/edsis-ui-item.d.ts +88 -0
- package/types/edsis-ui-kanban.d.ts +70 -0
- package/types/edsis-ui-kbd.d.ts +16 -0
- package/types/edsis-ui-label.d.ts +11 -0
- package/types/edsis-ui-menubar.d.ts +67 -0
- package/types/edsis-ui-native-select.d.ts +26 -0
- package/types/edsis-ui-navigation-menu.d.ts +96 -0
- package/types/edsis-ui-pagination.d.ts +34 -0
- package/types/edsis-ui-pillbox.d.ts +157 -0
- package/types/edsis-ui-popover.d.ts +43 -0
- package/types/edsis-ui-progress.d.ts +17 -0
- package/types/edsis-ui-radio.d.ts +40 -0
- package/types/edsis-ui-resizable.d.ts +99 -0
- package/types/edsis-ui-scroll-area.d.ts +19 -0
- package/types/edsis-ui-select.d.ts +57 -0
- package/types/edsis-ui-separator.d.ts +14 -0
- package/types/edsis-ui-sheet.d.ts +76 -0
- package/types/edsis-ui-skeleton.d.ts +10 -0
- package/types/edsis-ui-slider.d.ts +74 -0
- package/types/edsis-ui-spinner.d.ts +13 -0
- package/types/edsis-ui-switch.d.ts +40 -0
- package/types/edsis-ui-table.d.ts +52 -0
- package/types/edsis-ui-tabs.d.ts +92 -0
- package/types/edsis-ui-textarea.d.ts +12 -0
- package/types/edsis-ui-timeline.d.ts +63 -0
- package/types/edsis-ui-toast.d.ts +38 -0
- package/types/edsis-ui-toggle-group.d.ts +89 -0
- package/types/edsis-ui-toggle.d.ts +25 -0
- package/types/edsis-ui-tooltip.d.ts +89 -0
- package/types/edsis-ui-utils.d.ts +5 -0
- package/types/edsis-ui.d.ts +2 -0
package/editor/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Editor
|
|
2
|
+
|
|
3
|
+
Rich text editor shell with an accessible toolbar, configurable toolbar items, contenteditable form control support, and shadcn-style tokens.
|
|
4
|
+
|
|
5
|
+
This component is conceptually inspired by Flux Editor. It does not bundle Tiptap or Flux JavaScript; instead, it provides a lightweight Angular primitive that applications can compose, bind, and extend.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { FormsModule } from '@angular/forms';
|
|
11
|
+
import {
|
|
12
|
+
EditorButtonComponent,
|
|
13
|
+
EditorComponent,
|
|
14
|
+
EditorContentComponent,
|
|
15
|
+
EditorSeparatorComponent,
|
|
16
|
+
EditorSpacerComponent,
|
|
17
|
+
EditorToolbarComponent,
|
|
18
|
+
} from '@edsis/ui/editor';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<ui-editor>
|
|
25
|
+
<ui-editor-toolbar items="heading | bold italic underline | align ~ undo redo" />
|
|
26
|
+
<ui-editor-content placeholder="Write something..." aria-label="Article body">
|
|
27
|
+
<h3>What's changed</h3>
|
|
28
|
+
<p>Draft release notes, article copy, or support responses here.</p>
|
|
29
|
+
</ui-editor-content>
|
|
30
|
+
</ui-editor>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Forms
|
|
34
|
+
|
|
35
|
+
`ui-editor-content` implements `ControlValueAccessor`, so it can bind to Angular forms as an HTML string.
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<ui-editor>
|
|
39
|
+
<ui-editor-toolbar />
|
|
40
|
+
<ui-editor-content [(ngModel)]="content" name="content" aria-label="Article body" />
|
|
41
|
+
</ui-editor>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Sanitize persisted HTML at the application boundary before rendering it elsewhere.
|
|
45
|
+
|
|
46
|
+
## Toolbar Items
|
|
47
|
+
|
|
48
|
+
The toolbar accepts a space-separated `items` string. Use `|` for a separator and `~` for a spacer.
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<ui-editor-toolbar items="heading | bold italic strike underline | bullet ordered blockquote link align ~ undo redo" />
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Supported item names:
|
|
55
|
+
|
|
56
|
+
| Item | Behavior |
|
|
57
|
+
| ------------- | ---------------------------------------------------- |
|
|
58
|
+
| `heading` | Text, heading 1, heading 2, and heading 3 selector. |
|
|
59
|
+
| `bold` | Bold formatting. |
|
|
60
|
+
| `italic` | Italic formatting. |
|
|
61
|
+
| `strike` | Strikethrough formatting. |
|
|
62
|
+
| `underline` | Underline formatting. |
|
|
63
|
+
| `bullet` | Bulleted list. |
|
|
64
|
+
| `ordered` | Numbered list. |
|
|
65
|
+
| `blockquote` | Block quote block. |
|
|
66
|
+
| `subscript` | Subscript formatting. |
|
|
67
|
+
| `superscript` | Superscript formatting. |
|
|
68
|
+
| `highlight` | Highlight selected text. |
|
|
69
|
+
| `link` | Create a placeholder link for the current selection. |
|
|
70
|
+
| `code` | Code block. |
|
|
71
|
+
| `align` | Left, center, and right alignment selector. |
|
|
72
|
+
| `undo` | Undo last edit. |
|
|
73
|
+
| `redo` | Redo last edit. |
|
|
74
|
+
|
|
75
|
+
## Custom Toolbar
|
|
76
|
+
|
|
77
|
+
Pass `items=""` and project custom toolbar controls.
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<ui-editor>
|
|
81
|
+
<ui-editor-toolbar items="">
|
|
82
|
+
<button ui-editor-button command="bold" aria-label="Bold">B</button>
|
|
83
|
+
<button ui-editor-button command="italic" aria-label="Italic">I</button>
|
|
84
|
+
<ui-editor-separator />
|
|
85
|
+
<button ui-editor-button command="highlight" aria-label="Highlight">H</button>
|
|
86
|
+
<ui-editor-spacer />
|
|
87
|
+
<button ui-editor-button command="undo" aria-label="Undo">
|
|
88
|
+
<svg
|
|
89
|
+
aria-hidden="true"
|
|
90
|
+
class="size-4"
|
|
91
|
+
viewBox="0 0 24 24"
|
|
92
|
+
fill="none"
|
|
93
|
+
stroke="currentColor"
|
|
94
|
+
stroke-width="1.75"
|
|
95
|
+
stroke-linecap="round"
|
|
96
|
+
stroke-linejoin="round">
|
|
97
|
+
<path d="M9 14 4 9l5-5" />
|
|
98
|
+
<path d="M4 9h10a6 6 0 0 1 0 12h-2" />
|
|
99
|
+
</svg>
|
|
100
|
+
</button>
|
|
101
|
+
</ui-editor-toolbar>
|
|
102
|
+
<ui-editor-content aria-label="Custom editor" />
|
|
103
|
+
</ui-editor>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Keyboard Shortcuts
|
|
107
|
+
|
|
108
|
+
| Action | Shortcut |
|
|
109
|
+
| ------------- | ----------------- |
|
|
110
|
+
| Bold | Cmd/Ctrl+B |
|
|
111
|
+
| Italic | Cmd/Ctrl+I |
|
|
112
|
+
| Underline | Cmd/Ctrl+U |
|
|
113
|
+
| Strikethrough | Cmd/Ctrl+Shift+X |
|
|
114
|
+
| Ordered list | Cmd/Ctrl+Shift+7 |
|
|
115
|
+
| Bulleted list | Cmd/Ctrl+Shift+8 |
|
|
116
|
+
| Heading 1-3 | Cmd/Ctrl+Alt+1..3 |
|
|
117
|
+
| Undo | Cmd/Ctrl+Z |
|
|
118
|
+
| Redo | Cmd/Ctrl+Shift+Z |
|
|
119
|
+
|
|
120
|
+
## Styling
|
|
121
|
+
|
|
122
|
+
The editor uses `border-input`, `bg-background`, `ring-ring`, `text-foreground`, `text-muted-foreground`, and `bg-muted` tokens. Pass sizing classes directly to the content slot when adjusting height.
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<ui-editor>
|
|
126
|
+
<ui-editor-toolbar />
|
|
127
|
+
<ui-editor-content class="min-h-30 max-h-60" aria-label="Compact editor" />
|
|
128
|
+
</ui-editor>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Accessibility
|
|
132
|
+
|
|
133
|
+
- `ui-editor-toolbar` renders `role="toolbar"`.
|
|
134
|
+
- `ui-editor-content` renders `role="textbox"` and `aria-multiline="true"`.
|
|
135
|
+
- Provide a clear `aria-label` for each editor content surface.
|
|
136
|
+
- Give terse or icon-only custom toolbar buttons an explicit `aria-label`.
|
package/empty/README.md
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Empty
|
|
2
|
+
|
|
3
|
+
Displays a reusable empty state with header, media, title, description, and content slots.
|
|
4
|
+
|
|
5
|
+
Use Empty for onboarding gaps, no-results screens, no-notification panels, and 404-like recovery surfaces that need a clear next action.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
EmptyComponent,
|
|
12
|
+
EmptyContentComponent,
|
|
13
|
+
EmptyDescriptionComponent,
|
|
14
|
+
EmptyHeaderComponent,
|
|
15
|
+
EmptyMediaComponent,
|
|
16
|
+
EmptyTitleComponent,
|
|
17
|
+
} from '@edsis/ui/empty';
|
|
18
|
+
import { ButtonComponent } from '@edsis/ui/button';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Composition
|
|
22
|
+
|
|
23
|
+
The Angular structure follows the shadcn Empty information architecture while keeping actions on native buttons and anchors.
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
ui-empty
|
|
27
|
+
├── ui-empty-header
|
|
28
|
+
│ ├── ui-empty-media
|
|
29
|
+
│ ├── ui-empty-title
|
|
30
|
+
│ └── ui-empty-description
|
|
31
|
+
└── ui-empty-content
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Basic usage
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<ui-empty class="max-w-xl rounded-2xl border border-border bg-card/40">
|
|
38
|
+
<ui-empty-header>
|
|
39
|
+
<ui-empty-media variant="icon">
|
|
40
|
+
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
41
|
+
<path d="M12 6v12" />
|
|
42
|
+
<path d="M6 12h12" />
|
|
43
|
+
</svg>
|
|
44
|
+
</ui-empty-media>
|
|
45
|
+
<ui-empty-title>No projects yet</ui-empty-title>
|
|
46
|
+
<ui-empty-description>
|
|
47
|
+
You have not created any projects yet. Start by creating a new project or importing an existing one.
|
|
48
|
+
</ui-empty-description>
|
|
49
|
+
</ui-empty-header>
|
|
50
|
+
|
|
51
|
+
<ui-empty-content class="sm:flex-row">
|
|
52
|
+
<button ui-button type="button">Create project</button>
|
|
53
|
+
<button ui-button type="button" variant="outline">Import project</button>
|
|
54
|
+
</ui-empty-content>
|
|
55
|
+
|
|
56
|
+
<a ui-button href="/docs/getting-started" variant="link" class="text-muted-foreground">Learn more</a>
|
|
57
|
+
</ui-empty>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Common patterns
|
|
61
|
+
|
|
62
|
+
### Outline shell
|
|
63
|
+
|
|
64
|
+
Use border utilities on the root when the empty state should read like an inset card or dashboard panel.
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<ui-empty class="rounded-2xl border border-dashed border-border">
|
|
68
|
+
<ui-empty-header>
|
|
69
|
+
<ui-empty-media variant="icon">...</ui-empty-media>
|
|
70
|
+
<ui-empty-title>Cloud storage empty</ui-empty-title>
|
|
71
|
+
<ui-empty-description>Upload files to your cloud storage to access them anywhere.</ui-empty-description>
|
|
72
|
+
</ui-empty-header>
|
|
73
|
+
<ui-empty-content>
|
|
74
|
+
<button ui-button type="button" variant="outline" size="sm">Upload files</button>
|
|
75
|
+
</ui-empty-content>
|
|
76
|
+
</ui-empty>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Avatar media
|
|
80
|
+
|
|
81
|
+
Leave `ui-empty-media` on the default variant when projecting an avatar, avatar group, or any other custom artwork.
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<ui-empty>
|
|
85
|
+
<ui-empty-header>
|
|
86
|
+
<ui-empty-media>
|
|
87
|
+
<ui-avatar class="size-12">
|
|
88
|
+
<ui-avatar-image src="https://github.com/shadcn.png" alt="shadcn" />
|
|
89
|
+
<ui-avatar-fallback>CN</ui-avatar-fallback>
|
|
90
|
+
</ui-avatar>
|
|
91
|
+
</ui-empty-media>
|
|
92
|
+
<ui-empty-title>User offline</ui-empty-title>
|
|
93
|
+
<ui-empty-description>Leave a message and they will be notified when they come back online.</ui-empty-description>
|
|
94
|
+
</ui-empty-header>
|
|
95
|
+
<ui-empty-content>
|
|
96
|
+
<button ui-button type="button" size="sm">Leave message</button>
|
|
97
|
+
</ui-empty-content>
|
|
98
|
+
</ui-empty>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Input group recovery
|
|
102
|
+
|
|
103
|
+
Compose `ui-empty-content` with the existing input-group primitives when the empty state should immediately guide recovery or search.
|
|
104
|
+
|
|
105
|
+
```html
|
|
106
|
+
<ui-empty class="max-w-xl rounded-2xl border border-border">
|
|
107
|
+
<ui-empty-header>
|
|
108
|
+
<ui-empty-title>404 - Not found</ui-empty-title>
|
|
109
|
+
<ui-empty-description>
|
|
110
|
+
The page you are looking for does not exist. Try searching for what you need below.
|
|
111
|
+
</ui-empty-description>
|
|
112
|
+
</ui-empty-header>
|
|
113
|
+
<ui-empty-content class="max-w-md">
|
|
114
|
+
<ui-input-group class="w-full">
|
|
115
|
+
<input ui-input-group-input aria-label="Search pages" placeholder="Try searching for pages..." />
|
|
116
|
+
<ui-input-group-addon>
|
|
117
|
+
<span aria-hidden="true">⌕</span>
|
|
118
|
+
</ui-input-group-addon>
|
|
119
|
+
<ui-input-group-addon align="inline-end">
|
|
120
|
+
<span
|
|
121
|
+
aria-hidden="true"
|
|
122
|
+
class="inline-flex h-6 items-center rounded-md border border-border bg-background px-2 font-mono text-[11px] font-medium text-foreground shadow-sm">
|
|
123
|
+
/
|
|
124
|
+
</span>
|
|
125
|
+
</ui-input-group-addon>
|
|
126
|
+
</ui-input-group>
|
|
127
|
+
</ui-empty-content>
|
|
128
|
+
</ui-empty>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## API reference
|
|
132
|
+
|
|
133
|
+
### `EmptyComponent`
|
|
134
|
+
|
|
135
|
+
| Input | Type | Default |
|
|
136
|
+
| ------- | -------- | ------- |
|
|
137
|
+
| `class` | `string` | `''` |
|
|
138
|
+
|
|
139
|
+
### `EmptyMediaComponent`
|
|
140
|
+
|
|
141
|
+
| Input | Type | Default |
|
|
142
|
+
| --------- | --------------------- | ----------- |
|
|
143
|
+
| `variant` | `'default' \| 'icon'` | `'default'` |
|
|
144
|
+
| `class` | `string` | `''` |
|
|
145
|
+
|
|
146
|
+
### Parts
|
|
147
|
+
|
|
148
|
+
- `ui-empty-header` centers the media, title, and description stack.
|
|
149
|
+
- `ui-empty-title` provides the primary heading.
|
|
150
|
+
- `ui-empty-description` renders supporting copy with muted foreground color.
|
|
151
|
+
- `ui-empty-content` groups actions, inputs, or recovery affordances under the header.
|
|
152
|
+
|
|
153
|
+
All Empty parts also accept a `class` input.
|
|
154
|
+
|
|
155
|
+
## Styling and theming
|
|
156
|
+
|
|
157
|
+
The primitive keeps styling neutral by default: the root controls spacing and alignment, while visual shells such as borders, gradients, and muted backgrounds are layered through `class`.
|
|
158
|
+
|
|
159
|
+
`ui-empty-media` uses `border-border` and `bg-muted/40` for the icon variant so the icon chip matches the rest of the theme without inheriting text color for borders.
|
|
160
|
+
|
|
161
|
+
Use `class` on the root or parts to add panel borders, gradient backgrounds, tighter widths, or horizontal action layouts.
|
|
162
|
+
|
|
163
|
+
## Accessibility
|
|
164
|
+
|
|
165
|
+
- Keep the title and description visible so the empty state communicates both the missing content and the next step.
|
|
166
|
+
- Put actions on native `<button>` or `<a ui-button>` hosts instead of faking interactivity with generic elements.
|
|
167
|
+
- Mark decorative icons inside `ui-empty-media` as `aria-hidden="true"` unless the icon itself provides unique meaning.
|
|
168
|
+
|
|
169
|
+
## Keyboard interactions
|
|
170
|
+
|
|
171
|
+
- The Empty primitives themselves are passive layout containers and do not enter the tab order.
|
|
172
|
+
- Projected buttons, anchors, and inputs keep their native Tab, Enter, and Space behavior.
|
|
173
|
+
- When `ui-empty-content` contains an input group, the control remains first in the DOM so tab order stays predictable.
|
|
174
|
+
|
|
175
|
+
## Angular notes
|
|
176
|
+
|
|
177
|
+
- `ui-empty` is a reusable content primitive, not the same surface as `@edsis/ui/layout/empty`, which remains a route-shell layout.
|
|
178
|
+
- The link action from the upstream shadcn preview maps cleanly to `<a ui-button variant="link">` in Angular.
|
|
179
|
+
- Project any custom artwork into `ui-empty-media`; only the `icon` variant applies a circular icon shell.
|
|
180
|
+
|
|
181
|
+
## Source parity
|
|
182
|
+
|
|
183
|
+
This Angular implementation follows the shadcn Empty page structure, examples, and API reference while translating React composition to Angular selectors and keeping page-shell layout concerns separate from the reusable empty-state primitive.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Directive, input, model, computed, forwardRef, ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
|
3
|
+
import { cn } from '@edsis/ui/utils';
|
|
4
|
+
|
|
5
|
+
class AccordionContextBase {
|
|
6
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionContextBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
7
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: AccordionContextBase, isStandalone: true, ngImport: i0 });
|
|
8
|
+
}
|
|
9
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionContextBase, decorators: [{
|
|
10
|
+
type: Directive
|
|
11
|
+
}] });
|
|
12
|
+
class AccordionComponent extends AccordionContextBase {
|
|
13
|
+
type = input('single', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
14
|
+
collapsible = input(true, ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
|
|
15
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
16
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
17
|
+
classes = computed(() => cn('block', this.class()), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
18
|
+
openSet = computed(() => {
|
|
19
|
+
const v = this.value();
|
|
20
|
+
if (v == null)
|
|
21
|
+
return new Set();
|
|
22
|
+
return new Set(Array.isArray(v) ? v : [v]);
|
|
23
|
+
}, ...(ngDevMode ? [{ debugName: "openSet" }] : /* istanbul ignore next */ []));
|
|
24
|
+
isOpen(value) {
|
|
25
|
+
return this.openSet().has(value);
|
|
26
|
+
}
|
|
27
|
+
toggle(value) {
|
|
28
|
+
const isMulti = this.type() === 'multiple';
|
|
29
|
+
const current = this.openSet();
|
|
30
|
+
const open = current.has(value);
|
|
31
|
+
if (isMulti) {
|
|
32
|
+
const next = new Set(current);
|
|
33
|
+
open ? next.delete(value) : next.add(value);
|
|
34
|
+
this.value.set([...next]);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (open) {
|
|
38
|
+
if (this.collapsible())
|
|
39
|
+
this.value.set(null);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this.value.set(value);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
47
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: AccordionComponent, isStandalone: true, selector: "ui-accordion", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "class": "classes()" } }, providers: [{ provide: AccordionContextBase, useExisting: forwardRef(() => AccordionComponent) }], usesInheritance: true, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
48
|
+
}
|
|
49
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionComponent, decorators: [{
|
|
50
|
+
type: Component,
|
|
51
|
+
args: [{
|
|
52
|
+
selector: 'ui-accordion',
|
|
53
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
54
|
+
providers: [{ provide: AccordionContextBase, useExisting: forwardRef(() => AccordionComponent) }],
|
|
55
|
+
host: { '[class]': 'classes()' },
|
|
56
|
+
template: `<ng-content />`,
|
|
57
|
+
}]
|
|
58
|
+
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
59
|
+
class AccordionItemComponent {
|
|
60
|
+
ctx = inject(AccordionContextBase);
|
|
61
|
+
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
62
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
63
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
64
|
+
triggerId = `ui-accordion-trigger-${nextId()}`;
|
|
65
|
+
contentId = `ui-accordion-content-${nextId()}`;
|
|
66
|
+
classes = computed(() => cn('block border-b border-border', this.class()), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
67
|
+
open = computed(() => this.ctx.isOpen(this.value()), ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
68
|
+
toggle() {
|
|
69
|
+
if (!this.disabled())
|
|
70
|
+
this.ctx.toggle(this.value());
|
|
71
|
+
}
|
|
72
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
73
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: AccordionItemComponent, isStandalone: true, selector: "ui-accordion-item", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.data-state": "open() ? \"open\" : \"closed\"", "attr.data-disabled": "disabled() ? \"\" : null" } }, ngImport: i0, template: `<ng-content />`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
74
|
+
}
|
|
75
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionItemComponent, decorators: [{
|
|
76
|
+
type: Component,
|
|
77
|
+
args: [{
|
|
78
|
+
selector: 'ui-accordion-item',
|
|
79
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
80
|
+
host: {
|
|
81
|
+
'[class]': 'classes()',
|
|
82
|
+
'[attr.data-state]': 'open() ? "open" : "closed"',
|
|
83
|
+
'[attr.data-disabled]': 'disabled() ? "" : null',
|
|
84
|
+
},
|
|
85
|
+
template: `<ng-content />`,
|
|
86
|
+
}]
|
|
87
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
88
|
+
class AccordionTriggerComponent {
|
|
89
|
+
item = inject(AccordionItemComponent);
|
|
90
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
91
|
+
classes = computed(() => cn('flex flex-1 w-full items-center justify-between py-4 text-sm font-medium', 'transition-all hover:underline', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', 'disabled:pointer-events-none disabled:opacity-50', this.class()), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
92
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionTriggerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
93
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: AccordionTriggerComponent, isStandalone: true, selector: "button[ui-accordion-trigger]", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button" }, listeners: { "click": "item.toggle()" }, properties: { "class": "classes()", "attr.id": "item.triggerId", "attr.aria-controls": "item.contentId", "attr.aria-expanded": "item.open()", "attr.data-state": "item.open() ? \"open\" : \"closed\"", "disabled": "item.disabled() || null" } }, ngImport: i0, template: `
|
|
94
|
+
<ng-content />
|
|
95
|
+
<svg
|
|
96
|
+
aria-hidden="true"
|
|
97
|
+
class="h-4 w-4 shrink-0 transition-transform duration-200"
|
|
98
|
+
[class.rotate-180]="item.open()"
|
|
99
|
+
viewBox="0 0 24 24"
|
|
100
|
+
fill="none"
|
|
101
|
+
stroke="currentColor"
|
|
102
|
+
stroke-width="2"
|
|
103
|
+
stroke-linecap="round"
|
|
104
|
+
stroke-linejoin="round">
|
|
105
|
+
<polyline points="6 9 12 15 18 9" />
|
|
106
|
+
</svg>
|
|
107
|
+
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
108
|
+
}
|
|
109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionTriggerComponent, decorators: [{
|
|
110
|
+
type: Component,
|
|
111
|
+
args: [{
|
|
112
|
+
selector: 'button[ui-accordion-trigger]',
|
|
113
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
114
|
+
host: {
|
|
115
|
+
'[class]': 'classes()',
|
|
116
|
+
type: 'button',
|
|
117
|
+
'[attr.id]': 'item.triggerId',
|
|
118
|
+
'[attr.aria-controls]': 'item.contentId',
|
|
119
|
+
'[attr.aria-expanded]': 'item.open()',
|
|
120
|
+
'[attr.data-state]': 'item.open() ? "open" : "closed"',
|
|
121
|
+
'[disabled]': 'item.disabled() || null',
|
|
122
|
+
'(click)': 'item.toggle()',
|
|
123
|
+
},
|
|
124
|
+
template: `
|
|
125
|
+
<ng-content />
|
|
126
|
+
<svg
|
|
127
|
+
aria-hidden="true"
|
|
128
|
+
class="h-4 w-4 shrink-0 transition-transform duration-200"
|
|
129
|
+
[class.rotate-180]="item.open()"
|
|
130
|
+
viewBox="0 0 24 24"
|
|
131
|
+
fill="none"
|
|
132
|
+
stroke="currentColor"
|
|
133
|
+
stroke-width="2"
|
|
134
|
+
stroke-linecap="round"
|
|
135
|
+
stroke-linejoin="round">
|
|
136
|
+
<polyline points="6 9 12 15 18 9" />
|
|
137
|
+
</svg>
|
|
138
|
+
`,
|
|
139
|
+
}]
|
|
140
|
+
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
141
|
+
class AccordionContentComponent {
|
|
142
|
+
item = inject(AccordionItemComponent);
|
|
143
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
|
|
144
|
+
classes = computed(() => cn('block overflow-hidden text-sm', this.class()), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
145
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
146
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.14", type: AccordionContentComponent, isStandalone: true, selector: "ui-accordion-content", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()", "attr.id": "item.contentId", "attr.role": "\"region\"", "attr.aria-labelledby": "item.triggerId", "attr.data-state": "item.open() ? \"open\" : \"closed\"", "hidden": "!item.open()" } }, ngImport: i0, template: `<div class="pb-4 pt-0 text-sm"><ng-content /></div>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
147
|
+
}
|
|
148
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: AccordionContentComponent, decorators: [{
|
|
149
|
+
type: Component,
|
|
150
|
+
args: [{
|
|
151
|
+
selector: 'ui-accordion-content',
|
|
152
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
153
|
+
host: {
|
|
154
|
+
'[class]': 'classes()',
|
|
155
|
+
'[attr.id]': 'item.contentId',
|
|
156
|
+
'[attr.role]': '"region"',
|
|
157
|
+
'[attr.aria-labelledby]': 'item.triggerId',
|
|
158
|
+
'[attr.data-state]': 'item.open() ? "open" : "closed"',
|
|
159
|
+
'[hidden]': '!item.open()',
|
|
160
|
+
},
|
|
161
|
+
template: `<div class="pb-4 pt-0 text-sm"><ng-content /></div>`,
|
|
162
|
+
}]
|
|
163
|
+
}], propDecorators: { class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
164
|
+
let _id = 0;
|
|
165
|
+
function nextId() {
|
|
166
|
+
return ++_id;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Generated bundle index. Do not edit.
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
export { AccordionComponent, AccordionContentComponent, AccordionContextBase, AccordionItemComponent, AccordionTriggerComponent };
|
|
174
|
+
//# sourceMappingURL=edsis-ui-accordion.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edsis-ui-accordion.mjs","sources":["../../../library/ui/accordion/accordion.component.ts","../../../library/ui/accordion/edsis-ui-accordion.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Directive,\n computed,\n forwardRef,\n inject,\n input,\n model,\n signal,\n} from '@angular/core';\nimport { cn } from '@edsis/ui/utils';\n\nexport type AccordionType = 'single' | 'multiple';\n\n@Directive()\nexport abstract class AccordionContextBase {\n abstract isOpen(value: string): boolean;\n abstract toggle(value: string): void;\n}\n\n@Component({\n selector: 'ui-accordion',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [{ provide: AccordionContextBase, useExisting: forwardRef(() => AccordionComponent) }],\n host: { '[class]': 'classes()' },\n template: `<ng-content />`,\n})\nexport class AccordionComponent extends AccordionContextBase {\n readonly type = input<AccordionType>('single');\n readonly collapsible = input<boolean>(true);\n readonly value = model<string | string[] | null>(null);\n readonly class = input<string>('');\n\n protected readonly classes = computed(() => cn('block', this.class()));\n\n private readonly openSet = computed<Set<string>>(() => {\n const v = this.value();\n if (v == null) return new Set();\n return new Set(Array.isArray(v) ? v : [v]);\n });\n\n override isOpen(value: string): boolean {\n return this.openSet().has(value);\n }\n\n override toggle(value: string): void {\n const isMulti = this.type() === 'multiple';\n const current = this.openSet();\n const open = current.has(value);\n if (isMulti) {\n const next = new Set(current);\n open ? next.delete(value) : next.add(value);\n this.value.set([...next]);\n } else {\n if (open) {\n if (this.collapsible()) this.value.set(null);\n } else {\n this.value.set(value);\n }\n }\n }\n}\n\n@Component({\n selector: 'ui-accordion-item',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'classes()',\n '[attr.data-state]': 'open() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'disabled() ? \"\" : null',\n },\n template: `<ng-content />`,\n})\nexport class AccordionItemComponent {\n protected readonly ctx = inject(AccordionContextBase);\n readonly value = input.required<string>();\n readonly disabled = input<boolean>(false);\n readonly class = input<string>('');\n\n readonly triggerId = `ui-accordion-trigger-${nextId()}`;\n readonly contentId = `ui-accordion-content-${nextId()}`;\n\n protected readonly classes = computed(() => cn('block border-b border-border', this.class()));\n\n readonly open = computed(() => this.ctx.isOpen(this.value()));\n\n toggle(): void {\n if (!this.disabled()) this.ctx.toggle(this.value());\n }\n}\n\n@Component({\n selector: 'button[ui-accordion-trigger]',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'classes()',\n type: 'button',\n '[attr.id]': 'item.triggerId',\n '[attr.aria-controls]': 'item.contentId',\n '[attr.aria-expanded]': 'item.open()',\n '[attr.data-state]': 'item.open() ? \"open\" : \"closed\"',\n '[disabled]': 'item.disabled() || null',\n '(click)': 'item.toggle()',\n },\n template: `\n <ng-content />\n <svg\n aria-hidden=\"true\"\n class=\"h-4 w-4 shrink-0 transition-transform duration-200\"\n [class.rotate-180]=\"item.open()\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\">\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n `,\n})\nexport class AccordionTriggerComponent {\n protected readonly item = inject(AccordionItemComponent);\n readonly class = input<string>('');\n protected readonly classes = computed(() =>\n cn(\n 'flex flex-1 w-full items-center justify-between py-4 text-sm font-medium',\n 'transition-all hover:underline',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n 'disabled:pointer-events-none disabled:opacity-50',\n this.class(),\n ),\n );\n}\n\n@Component({\n selector: 'ui-accordion-content',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'classes()',\n '[attr.id]': 'item.contentId',\n '[attr.role]': '\"region\"',\n '[attr.aria-labelledby]': 'item.triggerId',\n '[attr.data-state]': 'item.open() ? \"open\" : \"closed\"',\n '[hidden]': '!item.open()',\n },\n template: `<div class=\"pb-4 pt-0 text-sm\"><ng-content /></div>`,\n})\nexport class AccordionContentComponent {\n protected readonly item = inject(AccordionItemComponent);\n readonly class = input<string>('');\n protected readonly classes = computed(() => cn('block overflow-hidden text-sm', this.class()));\n}\n\nlet _id = 0;\nfunction nextId(): number {\n return ++_id;\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|