@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.
Files changed (265) hide show
  1. package/README.md +40 -0
  2. package/accordion/README.md +195 -0
  3. package/alert/README.md +177 -0
  4. package/alert-dialog/README.md +239 -0
  5. package/aspect-ratio/README.md +112 -0
  6. package/avatar/README.md +176 -0
  7. package/badge/README.md +133 -0
  8. package/breadcrumb/README.md +216 -0
  9. package/button/README.md +139 -0
  10. package/button-group/README.md +204 -0
  11. package/calendar/README.md +132 -0
  12. package/card/README.md +220 -0
  13. package/carousel/README.md +276 -0
  14. package/chart/README.md +249 -0
  15. package/checkbox/README.md +149 -0
  16. package/collapsible/README.md +191 -0
  17. package/combobox/README.md +198 -0
  18. package/command/README.md +275 -0
  19. package/composer/README.md +235 -0
  20. package/context-menu/README.md +267 -0
  21. package/date-picker/README.md +177 -0
  22. package/dialog/README.md +237 -0
  23. package/drawer/README.md +145 -0
  24. package/dropdown-menu/README.md +311 -0
  25. package/editor/README.md +136 -0
  26. package/empty/README.md +183 -0
  27. package/fesm2022/edsis-ui-accordion.mjs +174 -0
  28. package/fesm2022/edsis-ui-accordion.mjs.map +1 -0
  29. package/fesm2022/edsis-ui-alert-dialog.mjs +242 -0
  30. package/fesm2022/edsis-ui-alert-dialog.mjs.map +1 -0
  31. package/fesm2022/edsis-ui-alert.mjs +90 -0
  32. package/fesm2022/edsis-ui-alert.mjs.map +1 -0
  33. package/fesm2022/edsis-ui-aspect-ratio.mjs +33 -0
  34. package/fesm2022/edsis-ui-aspect-ratio.mjs.map +1 -0
  35. package/fesm2022/edsis-ui-avatar.mjs +123 -0
  36. package/fesm2022/edsis-ui-avatar.mjs.map +1 -0
  37. package/fesm2022/edsis-ui-badge.mjs +47 -0
  38. package/fesm2022/edsis-ui-badge.mjs.map +1 -0
  39. package/fesm2022/edsis-ui-breadcrumb.mjs +186 -0
  40. package/fesm2022/edsis-ui-breadcrumb.mjs.map +1 -0
  41. package/fesm2022/edsis-ui-button-group.mjs +95 -0
  42. package/fesm2022/edsis-ui-button-group.mjs.map +1 -0
  43. package/fesm2022/edsis-ui-button.mjs +64 -0
  44. package/fesm2022/edsis-ui-button.mjs.map +1 -0
  45. package/fesm2022/edsis-ui-calendar.mjs +78 -0
  46. package/fesm2022/edsis-ui-calendar.mjs.map +1 -0
  47. package/fesm2022/edsis-ui-card.mjs +137 -0
  48. package/fesm2022/edsis-ui-card.mjs.map +1 -0
  49. package/fesm2022/edsis-ui-carousel.mjs +310 -0
  50. package/fesm2022/edsis-ui-carousel.mjs.map +1 -0
  51. package/fesm2022/edsis-ui-chart-area.mjs +6 -0
  52. package/fesm2022/edsis-ui-chart-area.mjs.map +1 -0
  53. package/fesm2022/edsis-ui-chart-bar.mjs +6 -0
  54. package/fesm2022/edsis-ui-chart-bar.mjs.map +1 -0
  55. package/fesm2022/edsis-ui-chart-line.mjs +6 -0
  56. package/fesm2022/edsis-ui-chart-line.mjs.map +1 -0
  57. package/fesm2022/edsis-ui-chart-pie.mjs +6 -0
  58. package/fesm2022/edsis-ui-chart-pie.mjs.map +1 -0
  59. package/fesm2022/edsis-ui-chart-radar.mjs +6 -0
  60. package/fesm2022/edsis-ui-chart-radar.mjs.map +1 -0
  61. package/fesm2022/edsis-ui-chart-radial.mjs +6 -0
  62. package/fesm2022/edsis-ui-chart-radial.mjs.map +1 -0
  63. package/fesm2022/edsis-ui-chart-scatter.mjs +6 -0
  64. package/fesm2022/edsis-ui-chart-scatter.mjs.map +1 -0
  65. package/fesm2022/edsis-ui-chart.mjs +3714 -0
  66. package/fesm2022/edsis-ui-chart.mjs.map +1 -0
  67. package/fesm2022/edsis-ui-checkbox.mjs +104 -0
  68. package/fesm2022/edsis-ui-checkbox.mjs.map +1 -0
  69. package/fesm2022/edsis-ui-collapsible.mjs +116 -0
  70. package/fesm2022/edsis-ui-collapsible.mjs.map +1 -0
  71. package/fesm2022/edsis-ui-combobox.mjs +263 -0
  72. package/fesm2022/edsis-ui-combobox.mjs.map +1 -0
  73. package/fesm2022/edsis-ui-command.mjs +268 -0
  74. package/fesm2022/edsis-ui-command.mjs.map +1 -0
  75. package/fesm2022/edsis-ui-composer.mjs +329 -0
  76. package/fesm2022/edsis-ui-composer.mjs.map +1 -0
  77. package/fesm2022/edsis-ui-context-menu.mjs +100 -0
  78. package/fesm2022/edsis-ui-context-menu.mjs.map +1 -0
  79. package/fesm2022/edsis-ui-date-picker.mjs +155 -0
  80. package/fesm2022/edsis-ui-date-picker.mjs.map +1 -0
  81. package/fesm2022/edsis-ui-dialog.mjs +262 -0
  82. package/fesm2022/edsis-ui-dialog.mjs.map +1 -0
  83. package/fesm2022/edsis-ui-drawer.mjs +6 -0
  84. package/fesm2022/edsis-ui-drawer.mjs.map +1 -0
  85. package/fesm2022/edsis-ui-dropdown-menu.mjs +466 -0
  86. package/fesm2022/edsis-ui-dropdown-menu.mjs.map +1 -0
  87. package/fesm2022/edsis-ui-editor.mjs +692 -0
  88. package/fesm2022/edsis-ui-editor.mjs.map +1 -0
  89. package/fesm2022/edsis-ui-empty.mjs +132 -0
  90. package/fesm2022/edsis-ui-empty.mjs.map +1 -0
  91. package/fesm2022/edsis-ui-form.mjs +334 -0
  92. package/fesm2022/edsis-ui-form.mjs.map +1 -0
  93. package/fesm2022/edsis-ui-hover-card.mjs +284 -0
  94. package/fesm2022/edsis-ui-hover-card.mjs.map +1 -0
  95. package/fesm2022/edsis-ui-input-group.mjs +164 -0
  96. package/fesm2022/edsis-ui-input-group.mjs.map +1 -0
  97. package/fesm2022/edsis-ui-input-otp.mjs +485 -0
  98. package/fesm2022/edsis-ui-input-otp.mjs.map +1 -0
  99. package/fesm2022/edsis-ui-input.mjs +43 -0
  100. package/fesm2022/edsis-ui-input.mjs.map +1 -0
  101. package/fesm2022/edsis-ui-item.mjs +241 -0
  102. package/fesm2022/edsis-ui-item.mjs.map +1 -0
  103. package/fesm2022/edsis-ui-kanban.mjs +289 -0
  104. package/fesm2022/edsis-ui-kanban.mjs.map +1 -0
  105. package/fesm2022/edsis-ui-kbd.mjs +51 -0
  106. package/fesm2022/edsis-ui-kbd.mjs.map +1 -0
  107. package/fesm2022/edsis-ui-label.mjs +30 -0
  108. package/fesm2022/edsis-ui-label.mjs.map +1 -0
  109. package/fesm2022/edsis-ui-menubar.mjs +302 -0
  110. package/fesm2022/edsis-ui-menubar.mjs.map +1 -0
  111. package/fesm2022/edsis-ui-native-select.mjs +61 -0
  112. package/fesm2022/edsis-ui-native-select.mjs.map +1 -0
  113. package/fesm2022/edsis-ui-navigation-menu.mjs +399 -0
  114. package/fesm2022/edsis-ui-navigation-menu.mjs.map +1 -0
  115. package/fesm2022/edsis-ui-pagination.mjs +216 -0
  116. package/fesm2022/edsis-ui-pagination.mjs.map +1 -0
  117. package/fesm2022/edsis-ui-pillbox.mjs +777 -0
  118. package/fesm2022/edsis-ui-pillbox.mjs.map +1 -0
  119. package/fesm2022/edsis-ui-popover.mjs +163 -0
  120. package/fesm2022/edsis-ui-popover.mjs.map +1 -0
  121. package/fesm2022/edsis-ui-progress.mjs +53 -0
  122. package/fesm2022/edsis-ui-progress.mjs.map +1 -0
  123. package/fesm2022/edsis-ui-radio.mjs +111 -0
  124. package/fesm2022/edsis-ui-radio.mjs.map +1 -0
  125. package/fesm2022/edsis-ui-resizable.mjs +454 -0
  126. package/fesm2022/edsis-ui-resizable.mjs.map +1 -0
  127. package/fesm2022/edsis-ui-scroll-area.mjs +48 -0
  128. package/fesm2022/edsis-ui-scroll-area.mjs.map +1 -0
  129. package/fesm2022/edsis-ui-select.mjs +164 -0
  130. package/fesm2022/edsis-ui-select.mjs.map +1 -0
  131. package/fesm2022/edsis-ui-separator.mjs +33 -0
  132. package/fesm2022/edsis-ui-separator.mjs.map +1 -0
  133. package/fesm2022/edsis-ui-sheet.mjs +264 -0
  134. package/fesm2022/edsis-ui-sheet.mjs.map +1 -0
  135. package/fesm2022/edsis-ui-skeleton.mjs +29 -0
  136. package/fesm2022/edsis-ui-skeleton.mjs.map +1 -0
  137. package/fesm2022/edsis-ui-slider.mjs +405 -0
  138. package/fesm2022/edsis-ui-slider.mjs.map +1 -0
  139. package/fesm2022/edsis-ui-spinner.mjs +58 -0
  140. package/fesm2022/edsis-ui-spinner.mjs.map +1 -0
  141. package/fesm2022/edsis-ui-switch.mjs +107 -0
  142. package/fesm2022/edsis-ui-switch.mjs.map +1 -0
  143. package/fesm2022/edsis-ui-table.mjs +139 -0
  144. package/fesm2022/edsis-ui-table.mjs.map +1 -0
  145. package/fesm2022/edsis-ui-tabs.mjs +252 -0
  146. package/fesm2022/edsis-ui-tabs.mjs.map +1 -0
  147. package/fesm2022/edsis-ui-textarea.mjs +37 -0
  148. package/fesm2022/edsis-ui-textarea.mjs.map +1 -0
  149. package/fesm2022/edsis-ui-timeline.mjs +213 -0
  150. package/fesm2022/edsis-ui-timeline.mjs.map +1 -0
  151. package/fesm2022/edsis-ui-toast.mjs +71 -0
  152. package/fesm2022/edsis-ui-toast.mjs.map +1 -0
  153. package/fesm2022/edsis-ui-toggle-group.mjs +269 -0
  154. package/fesm2022/edsis-ui-toggle-group.mjs.map +1 -0
  155. package/fesm2022/edsis-ui-toggle.mjs +76 -0
  156. package/fesm2022/edsis-ui-toggle.mjs.map +1 -0
  157. package/fesm2022/edsis-ui-tooltip.mjs +339 -0
  158. package/fesm2022/edsis-ui-tooltip.mjs.map +1 -0
  159. package/fesm2022/edsis-ui-utils.mjs +13 -0
  160. package/fesm2022/edsis-ui-utils.mjs.map +1 -0
  161. package/fesm2022/edsis-ui.mjs +11 -0
  162. package/fesm2022/edsis-ui.mjs.map +1 -0
  163. package/form/README.md +210 -0
  164. package/hover-card/README.md +146 -0
  165. package/input/README.md +159 -0
  166. package/input-group/README.md +234 -0
  167. package/input-otp/README.md +273 -0
  168. package/item/README.md +247 -0
  169. package/kanban/README.md +81 -0
  170. package/kbd/README.md +139 -0
  171. package/label/README.md +136 -0
  172. package/menubar/README.md +269 -0
  173. package/native-select/README.md +176 -0
  174. package/navigation-menu/README.md +160 -0
  175. package/package.json +310 -0
  176. package/pagination/README.md +144 -0
  177. package/pillbox/README.md +67 -0
  178. package/popover/README.md +43 -0
  179. package/progress/README.md +160 -0
  180. package/radio/README.md +209 -0
  181. package/resizable/README.md +164 -0
  182. package/scroll-area/README.md +143 -0
  183. package/select/README.md +174 -0
  184. package/separator/README.md +170 -0
  185. package/sheet/README.md +183 -0
  186. package/skeleton/README.md +158 -0
  187. package/slider/README.md +207 -0
  188. package/spinner/README.md +160 -0
  189. package/switch/README.md +166 -0
  190. package/table/README.md +291 -0
  191. package/tabs/README.md +214 -0
  192. package/textarea/README.md +154 -0
  193. package/timeline/README.md +94 -0
  194. package/toast/README.md +321 -0
  195. package/toggle/README.md +131 -0
  196. package/toggle-group/README.md +206 -0
  197. package/tooltip/README.md +211 -0
  198. package/types/edsis-ui-accordion.d.ts +51 -0
  199. package/types/edsis-ui-alert-dialog.d.ts +93 -0
  200. package/types/edsis-ui-alert.d.ts +37 -0
  201. package/types/edsis-ui-aspect-ratio.d.ts +12 -0
  202. package/types/edsis-ui-avatar.d.ts +51 -0
  203. package/types/edsis-ui-badge.d.ts +19 -0
  204. package/types/edsis-ui-breadcrumb.d.ts +46 -0
  205. package/types/edsis-ui-button-group.d.ts +26 -0
  206. package/types/edsis-ui-button.d.ts +22 -0
  207. package/types/edsis-ui-calendar.d.ts +33 -0
  208. package/types/edsis-ui-card.d.ts +60 -0
  209. package/types/edsis-ui-carousel.d.ts +86 -0
  210. package/types/edsis-ui-chart-area.d.ts +1 -0
  211. package/types/edsis-ui-chart-bar.d.ts +1 -0
  212. package/types/edsis-ui-chart-line.d.ts +1 -0
  213. package/types/edsis-ui-chart-pie.d.ts +1 -0
  214. package/types/edsis-ui-chart-radar.d.ts +1 -0
  215. package/types/edsis-ui-chart-radial.d.ts +1 -0
  216. package/types/edsis-ui-chart-scatter.d.ts +1 -0
  217. package/types/edsis-ui-chart.d.ts +1094 -0
  218. package/types/edsis-ui-checkbox.d.ts +35 -0
  219. package/types/edsis-ui-collapsible.d.ts +42 -0
  220. package/types/edsis-ui-combobox.d.ts +51 -0
  221. package/types/edsis-ui-command.d.ts +99 -0
  222. package/types/edsis-ui-composer.d.ts +90 -0
  223. package/types/edsis-ui-context-menu.d.ts +35 -0
  224. package/types/edsis-ui-date-picker.d.ts +41 -0
  225. package/types/edsis-ui-dialog.d.ts +87 -0
  226. package/types/edsis-ui-drawer.d.ts +1 -0
  227. package/types/edsis-ui-dropdown-menu.d.ts +136 -0
  228. package/types/edsis-ui-editor.d.ts +123 -0
  229. package/types/edsis-ui-empty.d.ts +50 -0
  230. package/types/edsis-ui-form.d.ts +141 -0
  231. package/types/edsis-ui-hover-card.d.ts +74 -0
  232. package/types/edsis-ui-input-group.d.ts +51 -0
  233. package/types/edsis-ui-input-otp.d.ts +136 -0
  234. package/types/edsis-ui-input.d.ts +16 -0
  235. package/types/edsis-ui-item.d.ts +88 -0
  236. package/types/edsis-ui-kanban.d.ts +70 -0
  237. package/types/edsis-ui-kbd.d.ts +16 -0
  238. package/types/edsis-ui-label.d.ts +11 -0
  239. package/types/edsis-ui-menubar.d.ts +67 -0
  240. package/types/edsis-ui-native-select.d.ts +26 -0
  241. package/types/edsis-ui-navigation-menu.d.ts +96 -0
  242. package/types/edsis-ui-pagination.d.ts +34 -0
  243. package/types/edsis-ui-pillbox.d.ts +157 -0
  244. package/types/edsis-ui-popover.d.ts +43 -0
  245. package/types/edsis-ui-progress.d.ts +17 -0
  246. package/types/edsis-ui-radio.d.ts +40 -0
  247. package/types/edsis-ui-resizable.d.ts +99 -0
  248. package/types/edsis-ui-scroll-area.d.ts +19 -0
  249. package/types/edsis-ui-select.d.ts +57 -0
  250. package/types/edsis-ui-separator.d.ts +14 -0
  251. package/types/edsis-ui-sheet.d.ts +76 -0
  252. package/types/edsis-ui-skeleton.d.ts +10 -0
  253. package/types/edsis-ui-slider.d.ts +74 -0
  254. package/types/edsis-ui-spinner.d.ts +13 -0
  255. package/types/edsis-ui-switch.d.ts +40 -0
  256. package/types/edsis-ui-table.d.ts +52 -0
  257. package/types/edsis-ui-tabs.d.ts +92 -0
  258. package/types/edsis-ui-textarea.d.ts +12 -0
  259. package/types/edsis-ui-timeline.d.ts +63 -0
  260. package/types/edsis-ui-toast.d.ts +38 -0
  261. package/types/edsis-ui-toggle-group.d.ts +89 -0
  262. package/types/edsis-ui-toggle.d.ts +25 -0
  263. package/types/edsis-ui-tooltip.d.ts +89 -0
  264. package/types/edsis-ui-utils.d.ts +5 -0
  265. 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`.