@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
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Composer
|
|
2
|
+
|
|
3
|
+
Configurable prompt composer for chat, AI, and message surfaces.
|
|
4
|
+
|
|
5
|
+
This Angular implementation takes conceptual inspiration from Flux Composer, but the API, styling, and composition model follow the shadcn-style patterns already established in this library.
|
|
6
|
+
|
|
7
|
+
## Import
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import {
|
|
11
|
+
ComposerActionsLeadingComponent,
|
|
12
|
+
ComposerActionsTrailingComponent,
|
|
13
|
+
ComposerComponent,
|
|
14
|
+
ComposerFooterComponent,
|
|
15
|
+
ComposerHeaderComponent,
|
|
16
|
+
ComposerInputComponent,
|
|
17
|
+
ComposerTextareaComponent,
|
|
18
|
+
} from '@edsis/ui/composer';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Composition
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
ui-composer
|
|
25
|
+
├── ui-composer-header (optional)
|
|
26
|
+
├── ui-composer-actions-leading (optional)
|
|
27
|
+
├── textarea[ui-composer-input] or ui-composer-input
|
|
28
|
+
├── ui-composer-actions-trailing (optional)
|
|
29
|
+
└── ui-composer-footer (optional)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use `textarea[ui-composer-input]` when you want native textarea behavior, template-driven forms, or reactive forms.
|
|
33
|
+
Use `ui-composer-input` when you want to project a custom rich-text surface or editor shell.
|
|
34
|
+
|
|
35
|
+
## Basic Usage
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<form (ngSubmit)="send()">
|
|
39
|
+
<ui-composer (submitRequested)="send()">
|
|
40
|
+
<textarea
|
|
41
|
+
ui-composer-input
|
|
42
|
+
rows="2"
|
|
43
|
+
maxRows="6"
|
|
44
|
+
placeholder="How can I help you today?"
|
|
45
|
+
[(ngModel)]="prompt"
|
|
46
|
+
name="prompt"></textarea>
|
|
47
|
+
|
|
48
|
+
<ui-composer-actions-trailing>
|
|
49
|
+
<button ui-button type="submit" size="icon-sm" aria-label="Send prompt">Send</button>
|
|
50
|
+
</ui-composer-actions-trailing>
|
|
51
|
+
</ui-composer>
|
|
52
|
+
</form>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## With Header
|
|
56
|
+
|
|
57
|
+
Use the header slot for file previews, avatars, upload summaries, or compact context cards.
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<ui-composer>
|
|
61
|
+
<ui-composer-header>
|
|
62
|
+
<div class="flex items-center gap-3 rounded-lg border border-border bg-muted/40 px-3 py-2">
|
|
63
|
+
<img src="/avatar.png" alt="Uploaded file owner" class="size-10 rounded-md object-cover" />
|
|
64
|
+
<div class="min-w-0">
|
|
65
|
+
<p class="truncate text-sm font-medium">profile-shot.png</p>
|
|
66
|
+
<p class="text-xs text-muted-foreground">2.1 MB</p>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</ui-composer-header>
|
|
70
|
+
|
|
71
|
+
<textarea ui-composer-input rows="2" maxRows="6" placeholder="Ask about this asset..."></textarea>
|
|
72
|
+
|
|
73
|
+
<ui-composer-actions-trailing>
|
|
74
|
+
<button ui-button type="button" size="sm">Send</button>
|
|
75
|
+
</ui-composer-actions-trailing>
|
|
76
|
+
</ui-composer>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Inline Layout
|
|
80
|
+
|
|
81
|
+
Set `inline` when actions and input should share a compact single-row shell.
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<ui-composer inline submit="enter">
|
|
85
|
+
<ui-composer-actions-leading>
|
|
86
|
+
<button ui-button type="button" variant="ghost" size="icon-sm" aria-label="Add attachment">+</button>
|
|
87
|
+
</ui-composer-actions-leading>
|
|
88
|
+
|
|
89
|
+
<textarea ui-composer-input rows="1" maxRows="4" placeholder="Reply..."></textarea>
|
|
90
|
+
|
|
91
|
+
<ui-composer-actions-trailing>
|
|
92
|
+
<button ui-button type="button" variant="secondary" size="icon-sm" aria-label="Voice input">Mic</button>
|
|
93
|
+
<button ui-button type="submit" size="icon-sm" aria-label="Send reply">Send</button>
|
|
94
|
+
</ui-composer-actions-trailing>
|
|
95
|
+
</ui-composer>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Input Variant
|
|
99
|
+
|
|
100
|
+
Set `variant="input"` when the composer should align more closely with the radius and density of other input surfaces.
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<ui-composer variant="input">
|
|
104
|
+
<textarea ui-composer-input rows="2" maxRows="5" placeholder="What's on your mind?"></textarea>
|
|
105
|
+
</ui-composer>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Height And Autosize
|
|
109
|
+
|
|
110
|
+
`rows` sets the initial height of the native textarea surface.
|
|
111
|
+
`maxRows` caps autosize growth before the textarea begins scrolling.
|
|
112
|
+
|
|
113
|
+
```html
|
|
114
|
+
<ui-composer>
|
|
115
|
+
<textarea ui-composer-input rows="3" maxRows="8" placeholder="Write a longer prompt..."></textarea>
|
|
116
|
+
</ui-composer>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Submit Behavior
|
|
120
|
+
|
|
121
|
+
By default, keyboard submission uses `cmd-enter`, which means `Cmd+Enter` on macOS and `Ctrl+Enter` on Windows/Linux.
|
|
122
|
+
|
|
123
|
+
Use `submit="enter"` when pressing `Enter` should submit immediately. `Shift+Enter` still inserts a new line.
|
|
124
|
+
|
|
125
|
+
```html
|
|
126
|
+
<ui-composer submit="enter" (submitRequested)="send()">
|
|
127
|
+
<textarea ui-composer-input rows="1" maxRows="4" placeholder="Quick reply..."></textarea>
|
|
128
|
+
</ui-composer>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
When `submitForm` stays `true`, the composer also calls the nearest native `form.requestSubmit()` after emitting `submitRequested`.
|
|
132
|
+
|
|
133
|
+
## Rich Text Slot
|
|
134
|
+
|
|
135
|
+
Project a custom editor shell through `ui-composer-input` when you want a richer surface without changing the composer container API.
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<ui-composer>
|
|
139
|
+
<ui-composer-input>
|
|
140
|
+
<div
|
|
141
|
+
contenteditable="true"
|
|
142
|
+
role="textbox"
|
|
143
|
+
aria-multiline="true"
|
|
144
|
+
class="min-h-20 w-full rounded-sm bg-transparent px-2 py-2 outline-none">
|
|
145
|
+
Draft a richer message...
|
|
146
|
+
</div>
|
|
147
|
+
</ui-composer-input>
|
|
148
|
+
|
|
149
|
+
<ui-composer-actions-leading>
|
|
150
|
+
<button ui-button type="button" variant="ghost" size="icon-sm" aria-label="Insert file">+</button>
|
|
151
|
+
</ui-composer-actions-leading>
|
|
152
|
+
|
|
153
|
+
<ui-composer-actions-trailing>
|
|
154
|
+
<button ui-button type="button" size="icon-sm" aria-label="Send rich text message">Send</button>
|
|
155
|
+
</ui-composer-actions-trailing>
|
|
156
|
+
</ui-composer>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Disabled And Invalid
|
|
160
|
+
|
|
161
|
+
Use the root inputs for shared composer state.
|
|
162
|
+
|
|
163
|
+
```html
|
|
164
|
+
<ui-composer [disabled]="isSending" [invalid]="promptInvalid">
|
|
165
|
+
<textarea ui-composer-input rows="2" maxRows="6"></textarea>
|
|
166
|
+
</ui-composer>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For native textarea integrations, `aria-invalid` can still be supplied directly on `textarea[ui-composer-input]` when state comes from another layer.
|
|
170
|
+
|
|
171
|
+
## API Reference
|
|
172
|
+
|
|
173
|
+
### `ComposerComponent`
|
|
174
|
+
|
|
175
|
+
| Input | Type | Default | Notes |
|
|
176
|
+
| ------------ | ------------------------ | ------------- | --------------------------------------------------------------------- |
|
|
177
|
+
| `variant` | `'default' \| 'input'` | `'default'` | Controls shell radius and density. |
|
|
178
|
+
| `inline` | `boolean` | `false` | Places leading actions, input, and trailing actions in a compact row. |
|
|
179
|
+
| `disabled` | `boolean` | `false` | Applies shared disabled treatment and prevents keyboard submit. |
|
|
180
|
+
| `invalid` | `boolean` | `false` | Applies destructive border and ring treatment. |
|
|
181
|
+
| `submit` | `'cmd-enter' \| 'enter'` | `'cmd-enter'` | Controls keyboard submit behavior. |
|
|
182
|
+
| `submitForm` | `boolean` | `true` | Requests native form submission after `submitRequested`. |
|
|
183
|
+
| `class` | `string` | `''` | Appends classes to the composer host. |
|
|
184
|
+
|
|
185
|
+
### `ComposerComponent` output
|
|
186
|
+
|
|
187
|
+
| Output | Type | Notes |
|
|
188
|
+
| ----------------- | --------------- | --------------------------------------------------------------------- |
|
|
189
|
+
| `submitRequested` | `KeyboardEvent` | Emitted when keyboard submission is triggered from the input surface. |
|
|
190
|
+
|
|
191
|
+
### `ComposerTextareaComponent`
|
|
192
|
+
|
|
193
|
+
| Input | Type | Default | Notes |
|
|
194
|
+
| -------------- | ---------------- | ------- | --------------------------------------------------- |
|
|
195
|
+
| `rows` | `number` | `2` | Initial line count. |
|
|
196
|
+
| `maxRows` | `number \| null` | `null` | Maximum autosize line count before scrolling. |
|
|
197
|
+
| `disabled` | `boolean` | `false` | Disables the textarea even if the root is enabled. |
|
|
198
|
+
| `aria-invalid` | `boolean` | `false` | Applies invalid styling on the textarea input slot. |
|
|
199
|
+
| `class` | `string` | `''` | Appends classes to the textarea host. |
|
|
200
|
+
|
|
201
|
+
### Slot Components
|
|
202
|
+
|
|
203
|
+
`ComposerHeaderComponent`, `ComposerFooterComponent`, `ComposerActionsLeadingComponent`, `ComposerActionsTrailingComponent`, and `ComposerInputComponent` each accept a single `class` input.
|
|
204
|
+
|
|
205
|
+
## Accessibility
|
|
206
|
+
|
|
207
|
+
- Pair `textarea[ui-composer-input]` with an accessible label from surrounding copy, `aria-label`, or form-field composition.
|
|
208
|
+
- Give icon-only buttons inside action slots explicit `aria-label` values.
|
|
209
|
+
- Keep meaningful supporting text in `ui-composer-footer` or nearby description content.
|
|
210
|
+
- Use `submit="enter"` carefully in multiline experiences so users still understand `Shift+Enter` for a new line.
|
|
211
|
+
- When projecting a custom editor through `ui-composer-input`, provide `role="textbox"`, `aria-multiline="true"`, and clear keyboard handling in the editor surface itself.
|
|
212
|
+
|
|
213
|
+
## Keyboard Interactions
|
|
214
|
+
|
|
215
|
+
- `Cmd+Enter` or `Ctrl+Enter` submits by default.
|
|
216
|
+
- `Enter` submits when `submit="enter"`.
|
|
217
|
+
- `Shift+Enter` keeps inserting new lines in `submit="enter"` mode.
|
|
218
|
+
- Standard textarea editing, selection, clipboard, and IME behavior remain native when using `textarea[ui-composer-input]`.
|
|
219
|
+
|
|
220
|
+
## Styling And Theming
|
|
221
|
+
|
|
222
|
+
The composer uses the shared `border-input`, `bg-background`, `ring-ring`, `text-foreground`, and `placeholder:text-muted-foreground` tokens.
|
|
223
|
+
|
|
224
|
+
Override layout and density by passing `class` to the root or individual slot components.
|
|
225
|
+
Keep the projected input surface transparent so the composer shell remains the visible boundary.
|
|
226
|
+
|
|
227
|
+
## Angular Notes
|
|
228
|
+
|
|
229
|
+
- `textarea[ui-composer-input]` remains a native textarea surface and autosizes without replacing native browser editing behavior.
|
|
230
|
+
- `ui-composer-input` is intentionally presentational. It is meant for custom editor projection, not as a built-in rich-text editor.
|
|
231
|
+
- The composer shell is presentational and does not import layout or theme services, which keeps the entrypoint compatible with the library's component-layer rules.
|
|
232
|
+
|
|
233
|
+
## Source Inspiration
|
|
234
|
+
|
|
235
|
+
This component borrows the high-level idea of a structured prompt composer from Flux Composer, but the Angular API, slot names, styling tokens, keyboard behavior contract, and examples are implemented specifically for this library's shadcn-style component system.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Context Menu
|
|
2
|
+
|
|
3
|
+
Displays a menu of actions triggered by a right click. The Angular version maps the
|
|
4
|
+
shadcn `ContextMenuTrigger` to a directive on any focusable host and reuses the
|
|
5
|
+
shared menu primitives from [Dropdown Menu](../dropdown-menu/README.md) for the
|
|
6
|
+
overlay content.
|
|
7
|
+
|
|
8
|
+
## Import
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { ContextMenuTriggerDirective } from '@edsis/ui/context-menu';
|
|
12
|
+
import {
|
|
13
|
+
MenuCheckboxItemComponent,
|
|
14
|
+
MenuContentDirective,
|
|
15
|
+
MenuGroupComponent,
|
|
16
|
+
MenuItemComponent,
|
|
17
|
+
MenuLabelComponent,
|
|
18
|
+
MenuRadioGroupComponent,
|
|
19
|
+
MenuRadioItemComponent,
|
|
20
|
+
MenuSeparatorComponent,
|
|
21
|
+
MenuShortcutComponent,
|
|
22
|
+
MenuSurfaceComponent,
|
|
23
|
+
MenuTriggerDirective,
|
|
24
|
+
} from '@edsis/ui/dropdown-menu';
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Composition
|
|
28
|
+
|
|
29
|
+
The Angular composition stays close to shadcn while exposing the root behavior
|
|
30
|
+
through directives and shared menu primitives.
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
div[uiContextMenuTrigger]
|
|
34
|
+
└── ng-template[uiMenuContent]
|
|
35
|
+
└── ui-menu-surface
|
|
36
|
+
├── ui-menu-group
|
|
37
|
+
│ └── button[ui-menu-item]
|
|
38
|
+
├── ui-menu-separator
|
|
39
|
+
├── button[ui-menu-checkbox-item]
|
|
40
|
+
├── ui-menu-label
|
|
41
|
+
├── ui-menu-radio-group
|
|
42
|
+
│ └── button[ui-menu-radio-item]
|
|
43
|
+
└── button[ui-menu-item][uiMenuTrigger]
|
|
44
|
+
└── ng-template[uiMenuContent]
|
|
45
|
+
└── ui-menu-surface
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Basic usage
|
|
49
|
+
|
|
50
|
+
Prefer a focusable trigger so pointer users can right-click and keyboard users can
|
|
51
|
+
open the same menu with Shift+F10 or the context-menu key.
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<div
|
|
55
|
+
[uiContextMenuTrigger]="menu"
|
|
56
|
+
tabindex="0"
|
|
57
|
+
aria-label="Open file actions"
|
|
58
|
+
class="flex h-32 w-full max-w-sm items-center justify-center rounded-xl border border-dashed border-border">
|
|
59
|
+
Right-click here
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<ng-template uiMenuContent #menu="uiMenuContent">
|
|
63
|
+
<ui-menu-surface class="w-56">
|
|
64
|
+
<ui-menu-group>
|
|
65
|
+
<button ui-menu-item>Profile</button>
|
|
66
|
+
<button ui-menu-item>Billing</button>
|
|
67
|
+
<button ui-menu-item>Team</button>
|
|
68
|
+
</ui-menu-group>
|
|
69
|
+
</ui-menu-surface>
|
|
70
|
+
</ng-template>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Common patterns
|
|
74
|
+
|
|
75
|
+
### Browser-style actions
|
|
76
|
+
|
|
77
|
+
Use grouped commands and shortcuts for browser or editor surfaces.
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<ui-menu-surface class="w-60">
|
|
81
|
+
<ui-menu-group>
|
|
82
|
+
<button ui-menu-item>
|
|
83
|
+
Back
|
|
84
|
+
<span ui-menu-shortcut>⌘[</span>
|
|
85
|
+
</button>
|
|
86
|
+
<button ui-menu-item [disabled]="true">
|
|
87
|
+
Forward
|
|
88
|
+
<span ui-menu-shortcut>⌘]</span>
|
|
89
|
+
</button>
|
|
90
|
+
<button ui-menu-item>
|
|
91
|
+
Reload
|
|
92
|
+
<span ui-menu-shortcut>⌘R</span>
|
|
93
|
+
</button>
|
|
94
|
+
</ui-menu-group>
|
|
95
|
+
</ui-menu-surface>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Nested tools menu
|
|
99
|
+
|
|
100
|
+
Map shadcn `ContextMenuSub` to `uiMenuTrigger` on a menu item. This keeps submenu
|
|
101
|
+
composition explicit and works with the same overlay primitive used by dropdown menus.
|
|
102
|
+
|
|
103
|
+
```html
|
|
104
|
+
<ng-template uiMenuContent #moreTools="uiMenuContent">
|
|
105
|
+
<ui-menu-surface class="w-48">
|
|
106
|
+
<button ui-menu-item>Save Page...</button>
|
|
107
|
+
<button ui-menu-item>Create Shortcut...</button>
|
|
108
|
+
<button ui-menu-item>Name Window...</button>
|
|
109
|
+
</ui-menu-surface>
|
|
110
|
+
</ng-template>
|
|
111
|
+
|
|
112
|
+
<ui-menu-surface class="w-56">
|
|
113
|
+
<button ui-menu-item [uiMenuTrigger]="moreTools" side="right" align="start">
|
|
114
|
+
More tools
|
|
115
|
+
<span class="ml-auto text-xs text-muted-foreground">›</span>
|
|
116
|
+
</button>
|
|
117
|
+
</ui-menu-surface>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Checkbox rows
|
|
121
|
+
|
|
122
|
+
Use checkbox rows for independent toggles such as browser preferences.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const showBookmarks = signal(true);
|
|
126
|
+
const showFullUrls = signal(false);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```html
|
|
130
|
+
<ui-menu-surface class="w-56">
|
|
131
|
+
<ui-menu-group>
|
|
132
|
+
<button ui-menu-checkbox-item [(checked)]="showBookmarks">Show bookmarks</button>
|
|
133
|
+
<button ui-menu-checkbox-item [(checked)]="showFullUrls">Show full URLs</button>
|
|
134
|
+
</ui-menu-group>
|
|
135
|
+
</ui-menu-surface>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Radio groups
|
|
139
|
+
|
|
140
|
+
Use `ui-menu-radio-group` when the menu exposes an exclusive choice.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const selectedTheme = signal<'light' | 'dark' | 'system'>('system');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```html
|
|
147
|
+
<ui-menu-surface class="w-56">
|
|
148
|
+
<ui-menu-label [inset]="true">Theme</ui-menu-label>
|
|
149
|
+
<ui-menu-radio-group [(value)]="selectedTheme">
|
|
150
|
+
<button ui-menu-radio-item value="light">Light</button>
|
|
151
|
+
<button ui-menu-radio-item value="dark">Dark</button>
|
|
152
|
+
<button ui-menu-radio-item value="system">System</button>
|
|
153
|
+
</ui-menu-radio-group>
|
|
154
|
+
</ui-menu-surface>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Destructive rows
|
|
158
|
+
|
|
159
|
+
Pass `variant="destructive"` when the row should read as irreversible.
|
|
160
|
+
|
|
161
|
+
```html
|
|
162
|
+
<ui-menu-surface class="w-56">
|
|
163
|
+
<ui-menu-group>
|
|
164
|
+
<button ui-menu-item>Edit</button>
|
|
165
|
+
<button ui-menu-item>Share</button>
|
|
166
|
+
</ui-menu-group>
|
|
167
|
+
<ui-menu-separator />
|
|
168
|
+
<ui-menu-group>
|
|
169
|
+
<button ui-menu-item variant="destructive">Delete</button>
|
|
170
|
+
</ui-menu-group>
|
|
171
|
+
</ui-menu-surface>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### RTL
|
|
175
|
+
|
|
176
|
+
Set `dir="rtl"` on the surface and prefer `side="left"` for nested menus so the
|
|
177
|
+
submenu opens toward the visual start edge.
|
|
178
|
+
|
|
179
|
+
```html
|
|
180
|
+
<ng-template uiMenuContent #rtlTools="uiMenuContent">
|
|
181
|
+
<ui-menu-surface dir="rtl" lang="ar" class="w-44 text-right">
|
|
182
|
+
<button ui-menu-item>حفظ الصفحة...</button>
|
|
183
|
+
<button ui-menu-item>إنشاء اختصار...</button>
|
|
184
|
+
</ui-menu-surface>
|
|
185
|
+
</ng-template>
|
|
186
|
+
|
|
187
|
+
<ui-menu-surface dir="rtl" lang="ar" class="w-56 text-right">
|
|
188
|
+
<button ui-menu-item [uiMenuTrigger]="rtlTools" side="left" align="start">
|
|
189
|
+
المزيد من الأدوات
|
|
190
|
+
<span class="mr-auto text-xs text-muted-foreground">‹</span>
|
|
191
|
+
</button>
|
|
192
|
+
</ui-menu-surface>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## API reference
|
|
196
|
+
|
|
197
|
+
### `[uiContextMenuTrigger]`
|
|
198
|
+
|
|
199
|
+
| Input | Type | Default |
|
|
200
|
+
| ---------------------- | ---------------------- | ---------- |
|
|
201
|
+
| `uiContextMenuTrigger` | `MenuContentDirective` | _required_ |
|
|
202
|
+
| `disabled` | `boolean` | `false` |
|
|
203
|
+
|
|
204
|
+
Output: `openedChange: boolean`
|
|
205
|
+
|
|
206
|
+
Methods:
|
|
207
|
+
|
|
208
|
+
- `openAt(x, y)` opens the projected surface at the given viewport coordinates.
|
|
209
|
+
- `close()` closes the active overlay.
|
|
210
|
+
|
|
211
|
+
### Shared menu parts
|
|
212
|
+
|
|
213
|
+
| Part | Purpose |
|
|
214
|
+
| ------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
215
|
+
| `ui-menu-surface` | Overlay container with roving focus, typeahead, Escape close, and Tab-to-close behavior. |
|
|
216
|
+
| `ui-menu-group` | Lightweight grouping wrapper for related rows. |
|
|
217
|
+
| `button[ui-menu-item]` | Standard command row with optional `variant="destructive"`. |
|
|
218
|
+
| `button[ui-menu-checkbox-item]` | Toggle row with `[(checked)]` and `role="menuitemcheckbox"`. |
|
|
219
|
+
| `ui-menu-radio-group` | Exclusive-selection container with signal-friendly `[(value)]`. |
|
|
220
|
+
| `button[ui-menu-radio-item]` | Exclusive option row with `role="menuitemradio"`. |
|
|
221
|
+
| `ui-menu-label` | Non-interactive label row. |
|
|
222
|
+
| `ui-menu-shortcut` | Right-aligned shortcut hint. |
|
|
223
|
+
| `ui-menu-separator` | Visual divider between command groups. |
|
|
224
|
+
|
|
225
|
+
For lower-level behavior details, see the Radix Context Menu API reference:
|
|
226
|
+
<https://www.radix-ui.com/docs/primitives/components/context-menu#api-reference>.
|
|
227
|
+
|
|
228
|
+
## Styling and theming
|
|
229
|
+
|
|
230
|
+
Pass `class` to `ui-menu-surface`, `ui-menu-group`, labels, and items to tune width,
|
|
231
|
+
spacing, alignment, and emphasis. Destructive rows use the shared `destructive` theme
|
|
232
|
+
tokens. Visible dividers and borders follow the shared border tokens rather than the
|
|
233
|
+
current text color.
|
|
234
|
+
|
|
235
|
+
## Accessibility
|
|
236
|
+
|
|
237
|
+
- Make the trigger focusable if keyboard users need access to the menu.
|
|
238
|
+
- Native `contextmenu` is captured and its default prevented.
|
|
239
|
+
- Menu rows expose the expected `menuitem`, `menuitemcheckbox`, and `menuitemradio`
|
|
240
|
+
roles plus `aria-checked` and `aria-disabled` where appropriate.
|
|
241
|
+
- Keep item labels short and descriptive, and avoid placing unrelated interactive
|
|
242
|
+
controls inside a menu row.
|
|
243
|
+
|
|
244
|
+
## Keyboard interactions
|
|
245
|
+
|
|
246
|
+
- Right click opens the menu at the pointer location.
|
|
247
|
+
- Shift+F10 and the context-menu key open the menu at the trigger center when the
|
|
248
|
+
trigger is focusable.
|
|
249
|
+
- Arrow Up and Arrow Down move between enabled items.
|
|
250
|
+
- Home and End jump to the start or end of the list.
|
|
251
|
+
- Typeahead matches row text.
|
|
252
|
+
- Enter and Space activate the focused row.
|
|
253
|
+
- Escape and Tab close the surface.
|
|
254
|
+
|
|
255
|
+
## Angular notes
|
|
256
|
+
|
|
257
|
+
- There is no dedicated `ui-context-menu` root component. The root behavior lives on the
|
|
258
|
+
`[uiContextMenuTrigger]` directive plus `ng-template[uiMenuContent]`.
|
|
259
|
+
- Use signals with `[(checked)]` and `[(value)]` for checkbox and radio rows.
|
|
260
|
+
- Reuse `uiMenuTrigger` when a submenu is needed.
|
|
261
|
+
- Long-press support depends on the browser firing the native `contextmenu` event.
|
|
262
|
+
|
|
263
|
+
## Source parity
|
|
264
|
+
|
|
265
|
+
This implementation keeps the shadcn information architecture while mapping the trigger
|
|
266
|
+
to Angular directives, submenu behavior to nested `uiMenuTrigger` composition, and
|
|
267
|
+
checkbox or radio state to signal-friendly APIs.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Date Picker
|
|
2
|
+
|
|
3
|
+
Popup date input backed by Angular Material `MatDatepicker`, styled through the shared shadcn token bridge.
|
|
4
|
+
|
|
5
|
+
The upstream shadcn Date Picker is composed from Popover and Calendar. This Angular library exposes `ui-date-picker` as the app-level wrapper while preserving the same product behavior: an input trigger, a calendar popup, selected state, and date constraints.
|
|
6
|
+
|
|
7
|
+
## Requires a date adapter
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { provideNativeDateAdapter } from '@angular/material/core';
|
|
11
|
+
|
|
12
|
+
export const appConfig = { providers: [provideNativeDateAdapter()] };
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Import
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { DatePickerComponent } from '@edsis/ui/date-picker';
|
|
19
|
+
import { LabelComponent } from '@edsis/ui/label';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
Pair the picker with a visible label through the `id` input, then bind the selected date through the signal model.
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<label ui-label for="date-picker-demo">Date</label>
|
|
28
|
+
<ui-date-picker id="date-picker-demo" class="w-72" [(value)]="date" placeholder="Pick a date" />
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The component also implements `ControlValueAccessor`, so it can be used with reactive forms or `ngModel`.
|
|
32
|
+
|
|
33
|
+
## Common patterns
|
|
34
|
+
|
|
35
|
+
### Basic
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<label ui-label for="date-picker-simple">Date</label>
|
|
39
|
+
<ui-date-picker id="date-picker-simple" class="w-44" [(value)]="basicDate" placeholder="Pick a date" />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Coordinated range
|
|
43
|
+
|
|
44
|
+
Use two date pickers when the product needs a start and end date but does not need a dedicated range-calendar primitive.
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<div class="grid gap-4 sm:grid-cols-2">
|
|
48
|
+
<div class="grid gap-2">
|
|
49
|
+
<label ui-label for="date-range-start">Start date</label>
|
|
50
|
+
<ui-date-picker id="date-range-start" [(value)]="rangeStart" [max]="rangeEnd()" />
|
|
51
|
+
</div>
|
|
52
|
+
<div class="grid gap-2">
|
|
53
|
+
<label ui-label for="date-range-end">End date</label>
|
|
54
|
+
<ui-date-picker id="date-range-end" [(value)]="rangeEnd" [min]="rangeStart()" />
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Date of birth
|
|
60
|
+
|
|
61
|
+
Use `startView="multi-year"` and `startAt` for dates that are usually far away from the current month.
|
|
62
|
+
|
|
63
|
+
```html
|
|
64
|
+
<label ui-label for="date-picker-birth">Date of birth</label>
|
|
65
|
+
<ui-date-picker
|
|
66
|
+
id="date-picker-birth"
|
|
67
|
+
class="w-48"
|
|
68
|
+
[(value)]="birthDate"
|
|
69
|
+
placeholder="Select date"
|
|
70
|
+
[startAt]="birthStartAt"
|
|
71
|
+
startView="multi-year" />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Date plus time
|
|
75
|
+
|
|
76
|
+
Pair the date picker with a native `input[type="time"]` for date-time forms.
|
|
77
|
+
|
|
78
|
+
```html
|
|
79
|
+
<div class="grid gap-4 sm:grid-cols-[minmax(0,12rem)_8rem]">
|
|
80
|
+
<div class="grid gap-2">
|
|
81
|
+
<label ui-label for="date-picker-time-date">Date</label>
|
|
82
|
+
<ui-date-picker id="date-picker-time-date" [(value)]="timeDate" />
|
|
83
|
+
</div>
|
|
84
|
+
<div class="grid gap-2">
|
|
85
|
+
<label ui-label for="date-picker-time-input">Time</label>
|
|
86
|
+
<input id="date-picker-time-input" ui-input type="time" step="1" [value]="timeValue()" />
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Disabled dates
|
|
92
|
+
|
|
93
|
+
Use `min`, `max`, and `dateFilter` to prevent invalid choices in the calendar before submit.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
readonly minBookingDate = new Date(2026, 0, 1);
|
|
97
|
+
readonly maxBookingDate = new Date(2026, 11, 31);
|
|
98
|
+
readonly weekdayFilter = (date: Date | null): boolean => {
|
|
99
|
+
const day = date?.getDay();
|
|
100
|
+
return day !== 0 && day !== 6;
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<ui-date-picker
|
|
106
|
+
id="date-picker-subscription"
|
|
107
|
+
[(value)]="subscriptionDate"
|
|
108
|
+
[min]="minBookingDate"
|
|
109
|
+
[max]="maxBookingDate"
|
|
110
|
+
[dateFilter]="weekdayFilter" />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### RTL
|
|
114
|
+
|
|
115
|
+
Set `dir="rtl"` on a wrapping container or at the application shell. The picker follows the surrounding direction.
|
|
116
|
+
|
|
117
|
+
```html
|
|
118
|
+
<div dir="rtl" lang="ar" class="grid max-w-xs gap-2 text-right">
|
|
119
|
+
<label ui-label for="date-picker-rtl">Date</label>
|
|
120
|
+
<ui-date-picker id="date-picker-rtl" [(value)]="rtlDate" placeholder="Pick a date" />
|
|
121
|
+
</div>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## API reference
|
|
125
|
+
|
|
126
|
+
| Input / Model | Type | Default |
|
|
127
|
+
| ----------------- | ----------------------------------- | ----------------------- |
|
|
128
|
+
| `value` | `Date \| null` | `null` |
|
|
129
|
+
| `id` | `string \| null` | `null` |
|
|
130
|
+
| `placeholder` | `string` | `'Pick a date'` |
|
|
131
|
+
| `required` | `boolean` | `false` |
|
|
132
|
+
| `min` | `Date \| null` | `null` |
|
|
133
|
+
| `max` | `Date \| null` | `null` |
|
|
134
|
+
| `startAt` | `Date \| null` | `null` |
|
|
135
|
+
| `startView` | `'month' \| 'year' \| 'multi-year'` | `'month'` |
|
|
136
|
+
| `touchUi` | `boolean` | `false` |
|
|
137
|
+
| `dateFilter` | `(date: Date \| null) => boolean` | `null` |
|
|
138
|
+
| `panelClass` | `string \| string[]` | `'ui-datepicker-panel'` |
|
|
139
|
+
| `aria-label` | `string \| null` | `null` |
|
|
140
|
+
| `aria-labelledby` | `string \| null` | `null` |
|
|
141
|
+
| `disabled` | `boolean` | `false` |
|
|
142
|
+
| `class` | `string` | `''` |
|
|
143
|
+
|
|
144
|
+
## Styling and theming
|
|
145
|
+
|
|
146
|
+
The host accepts `class` for width and layout utilities. The inner Material form field is full width, so classes such as `w-44`, `w-72`, and `w-full` should be placed on `ui-date-picker`.
|
|
147
|
+
|
|
148
|
+
The popup panel defaults to `ui-datepicker-panel`, and calendar colors come from the shared Material token bridge for popover, foreground, primary, and ring colors.
|
|
149
|
+
|
|
150
|
+
## Accessibility
|
|
151
|
+
|
|
152
|
+
- Pair the date picker with a visible label using the `id` input, or provide `aria-label` / `aria-labelledby`.
|
|
153
|
+
- The input, toggle, popup focus management, calendar grid roles, and date keyboard navigation come from `MatDatepicker`.
|
|
154
|
+
- Use constraints such as `min`, `max`, and `dateFilter` when dates are not selectable.
|
|
155
|
+
- Keep the visible label specific, such as `Start date`, `End date`, or `Subscription date`.
|
|
156
|
+
|
|
157
|
+
## Keyboard interactions
|
|
158
|
+
|
|
159
|
+
- Tab moves focus to the date input and toggle button.
|
|
160
|
+
- Enter or Space on the toggle opens the calendar popup.
|
|
161
|
+
- Arrow keys navigate dates while the calendar is open.
|
|
162
|
+
- Enter selects the focused date.
|
|
163
|
+
- Escape closes the popup and returns focus to the trigger.
|
|
164
|
+
|
|
165
|
+
## Angular notes
|
|
166
|
+
|
|
167
|
+
- Provide a Material date adapter once at the application root.
|
|
168
|
+
- Use `[(value)]` when binding to a signal-backed `Date | null` value.
|
|
169
|
+
- Use the component as a CVA inside Angular forms when validation and form submission belong to a `FormControl`.
|
|
170
|
+
- `startView="multi-year"` is useful for birthdays and other far-past dates.
|
|
171
|
+
- For range selection today, coordinate two `ui-date-picker` instances with reciprocal `min` and `max` bindings.
|
|
172
|
+
|
|
173
|
+
## Source parity
|
|
174
|
+
|
|
175
|
+
This Angular implementation follows the current shadcn Date Picker information architecture while translating React Popover plus Calendar composition into the local Material-backed wrapper.
|
|
176
|
+
|
|
177
|
+
The upstream Range Picker example is represented as two coordinated `ui-date-picker` controls rather than a single range-calendar API. The upstream Natural Language example can be built by parsing text into a `Date | null` value and binding that value to `ui-date-picker`.
|