@ojiepermana/angular-component 22.0.27

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 (244) hide show
  1. package/README.md +82 -0
  2. package/accordion/README.md +193 -0
  3. package/alert/README.md +180 -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 +208 -0
  11. package/calendar/README.md +135 -0
  12. package/card/README.md +220 -0
  13. package/carousel/README.md +276 -0
  14. package/checkbox/README.md +149 -0
  15. package/collapsible/README.md +195 -0
  16. package/combobox/README.md +198 -0
  17. package/command/README.md +275 -0
  18. package/composer/README.md +235 -0
  19. package/context-menu/README.md +267 -0
  20. package/date-picker/README.md +179 -0
  21. package/dialog/README.md +235 -0
  22. package/drawer/README.md +145 -0
  23. package/dropdown-menu/README.md +311 -0
  24. package/editor/README.md +136 -0
  25. package/empty/README.md +183 -0
  26. package/fesm2022/ojiepermana-angular-component-accordion.mjs +186 -0
  27. package/fesm2022/ojiepermana-angular-component-accordion.mjs.map +1 -0
  28. package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs +276 -0
  29. package/fesm2022/ojiepermana-angular-component-alert-dialog.mjs.map +1 -0
  30. package/fesm2022/ojiepermana-angular-component-alert.mjs +99 -0
  31. package/fesm2022/ojiepermana-angular-component-alert.mjs.map +1 -0
  32. package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs +37 -0
  33. package/fesm2022/ojiepermana-angular-component-aspect-ratio.mjs.map +1 -0
  34. package/fesm2022/ojiepermana-angular-component-avatar.mjs +139 -0
  35. package/fesm2022/ojiepermana-angular-component-avatar.mjs.map +1 -0
  36. package/fesm2022/ojiepermana-angular-component-badge.mjs +50 -0
  37. package/fesm2022/ojiepermana-angular-component-badge.mjs.map +1 -0
  38. package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs +200 -0
  39. package/fesm2022/ojiepermana-angular-component-breadcrumb.mjs.map +1 -0
  40. package/fesm2022/ojiepermana-angular-component-button-group.mjs +103 -0
  41. package/fesm2022/ojiepermana-angular-component-button-group.mjs.map +1 -0
  42. package/fesm2022/ojiepermana-angular-component-button.mjs +68 -0
  43. package/fesm2022/ojiepermana-angular-component-button.mjs.map +1 -0
  44. package/fesm2022/ojiepermana-angular-component-calendar.mjs +103 -0
  45. package/fesm2022/ojiepermana-angular-component-calendar.mjs.map +1 -0
  46. package/fesm2022/ojiepermana-angular-component-card.mjs +152 -0
  47. package/fesm2022/ojiepermana-angular-component-card.mjs.map +1 -0
  48. package/fesm2022/ojiepermana-angular-component-carousel.mjs +334 -0
  49. package/fesm2022/ojiepermana-angular-component-carousel.mjs.map +1 -0
  50. package/fesm2022/ojiepermana-angular-component-checkbox.mjs +165 -0
  51. package/fesm2022/ojiepermana-angular-component-checkbox.mjs.map +1 -0
  52. package/fesm2022/ojiepermana-angular-component-collapsible.mjs +121 -0
  53. package/fesm2022/ojiepermana-angular-component-collapsible.mjs.map +1 -0
  54. package/fesm2022/ojiepermana-angular-component-combobox.mjs +274 -0
  55. package/fesm2022/ojiepermana-angular-component-combobox.mjs.map +1 -0
  56. package/fesm2022/ojiepermana-angular-component-command.mjs +297 -0
  57. package/fesm2022/ojiepermana-angular-component-command.mjs.map +1 -0
  58. package/fesm2022/ojiepermana-angular-component-composer.mjs +352 -0
  59. package/fesm2022/ojiepermana-angular-component-composer.mjs.map +1 -0
  60. package/fesm2022/ojiepermana-angular-component-context-menu.mjs +108 -0
  61. package/fesm2022/ojiepermana-angular-component-context-menu.mjs.map +1 -0
  62. package/fesm2022/ojiepermana-angular-component-date-picker.mjs +186 -0
  63. package/fesm2022/ojiepermana-angular-component-date-picker.mjs.map +1 -0
  64. package/fesm2022/ojiepermana-angular-component-dialog.mjs +283 -0
  65. package/fesm2022/ojiepermana-angular-component-dialog.mjs.map +1 -0
  66. package/fesm2022/ojiepermana-angular-component-drawer.mjs +6 -0
  67. package/fesm2022/ojiepermana-angular-component-drawer.mjs.map +1 -0
  68. package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs +494 -0
  69. package/fesm2022/ojiepermana-angular-component-dropdown-menu.mjs.map +1 -0
  70. package/fesm2022/ojiepermana-angular-component-editor.mjs +680 -0
  71. package/fesm2022/ojiepermana-angular-component-editor.mjs.map +1 -0
  72. package/fesm2022/ojiepermana-angular-component-empty.mjs +145 -0
  73. package/fesm2022/ojiepermana-angular-component-empty.mjs.map +1 -0
  74. package/fesm2022/ojiepermana-angular-component-form.mjs +364 -0
  75. package/fesm2022/ojiepermana-angular-component-form.mjs.map +1 -0
  76. package/fesm2022/ojiepermana-angular-component-hover-card.mjs +275 -0
  77. package/fesm2022/ojiepermana-angular-component-hover-card.mjs.map +1 -0
  78. package/fesm2022/ojiepermana-angular-component-icon.mjs +86 -0
  79. package/fesm2022/ojiepermana-angular-component-icon.mjs.map +1 -0
  80. package/fesm2022/ojiepermana-angular-component-input-group.mjs +179 -0
  81. package/fesm2022/ojiepermana-angular-component-input-group.mjs.map +1 -0
  82. package/fesm2022/ojiepermana-angular-component-input-otp.mjs +517 -0
  83. package/fesm2022/ojiepermana-angular-component-input-otp.mjs.map +1 -0
  84. package/fesm2022/ojiepermana-angular-component-input.mjs +45 -0
  85. package/fesm2022/ojiepermana-angular-component-input.mjs.map +1 -0
  86. package/fesm2022/ojiepermana-angular-component-item.mjs +264 -0
  87. package/fesm2022/ojiepermana-angular-component-item.mjs.map +1 -0
  88. package/fesm2022/ojiepermana-angular-component-kanban.mjs +314 -0
  89. package/fesm2022/ojiepermana-angular-component-kanban.mjs.map +1 -0
  90. package/fesm2022/ojiepermana-angular-component-kbd.mjs +55 -0
  91. package/fesm2022/ojiepermana-angular-component-kbd.mjs.map +1 -0
  92. package/fesm2022/ojiepermana-angular-component-label.mjs +33 -0
  93. package/fesm2022/ojiepermana-angular-component-label.mjs.map +1 -0
  94. package/fesm2022/ojiepermana-angular-component-menubar.mjs +311 -0
  95. package/fesm2022/ojiepermana-angular-component-menubar.mjs.map +1 -0
  96. package/fesm2022/ojiepermana-angular-component-native-select.mjs +67 -0
  97. package/fesm2022/ojiepermana-angular-component-native-select.mjs.map +1 -0
  98. package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs +408 -0
  99. package/fesm2022/ojiepermana-angular-component-navigation-menu.mjs.map +1 -0
  100. package/fesm2022/ojiepermana-angular-component-pagination.mjs +226 -0
  101. package/fesm2022/ojiepermana-angular-component-pagination.mjs.map +1 -0
  102. package/fesm2022/ojiepermana-angular-component-pillbox.mjs +810 -0
  103. package/fesm2022/ojiepermana-angular-component-pillbox.mjs.map +1 -0
  104. package/fesm2022/ojiepermana-angular-component-popover.mjs +145 -0
  105. package/fesm2022/ojiepermana-angular-component-popover.mjs.map +1 -0
  106. package/fesm2022/ojiepermana-angular-component-progress.mjs +60 -0
  107. package/fesm2022/ojiepermana-angular-component-progress.mjs.map +1 -0
  108. package/fesm2022/ojiepermana-angular-component-radio.mjs +173 -0
  109. package/fesm2022/ojiepermana-angular-component-radio.mjs.map +1 -0
  110. package/fesm2022/ojiepermana-angular-component-resizable.mjs +478 -0
  111. package/fesm2022/ojiepermana-angular-component-resizable.mjs.map +1 -0
  112. package/fesm2022/ojiepermana-angular-component-scroll-area.mjs +54 -0
  113. package/fesm2022/ojiepermana-angular-component-scroll-area.mjs.map +1 -0
  114. package/fesm2022/ojiepermana-angular-component-select.mjs +297 -0
  115. package/fesm2022/ojiepermana-angular-component-select.mjs.map +1 -0
  116. package/fesm2022/ojiepermana-angular-component-separator.mjs +37 -0
  117. package/fesm2022/ojiepermana-angular-component-separator.mjs.map +1 -0
  118. package/fesm2022/ojiepermana-angular-component-sheet.mjs +297 -0
  119. package/fesm2022/ojiepermana-angular-component-sheet.mjs.map +1 -0
  120. package/fesm2022/ojiepermana-angular-component-skeleton.mjs +31 -0
  121. package/fesm2022/ojiepermana-angular-component-skeleton.mjs.map +1 -0
  122. package/fesm2022/ojiepermana-angular-component-slider.mjs +423 -0
  123. package/fesm2022/ojiepermana-angular-component-slider.mjs.map +1 -0
  124. package/fesm2022/ojiepermana-angular-component-spinner.mjs +60 -0
  125. package/fesm2022/ojiepermana-angular-component-spinner.mjs.map +1 -0
  126. package/fesm2022/ojiepermana-angular-component-switch.mjs +140 -0
  127. package/fesm2022/ojiepermana-angular-component-switch.mjs.map +1 -0
  128. package/fesm2022/ojiepermana-angular-component-table.mjs +155 -0
  129. package/fesm2022/ojiepermana-angular-component-table.mjs.map +1 -0
  130. package/fesm2022/ojiepermana-angular-component-tabs.mjs +271 -0
  131. package/fesm2022/ojiepermana-angular-component-tabs.mjs.map +1 -0
  132. package/fesm2022/ojiepermana-angular-component-textarea.mjs +39 -0
  133. package/fesm2022/ojiepermana-angular-component-textarea.mjs.map +1 -0
  134. package/fesm2022/ojiepermana-angular-component-timeline.mjs +237 -0
  135. package/fesm2022/ojiepermana-angular-component-timeline.mjs.map +1 -0
  136. package/fesm2022/ojiepermana-angular-component-toast.mjs +161 -0
  137. package/fesm2022/ojiepermana-angular-component-toast.mjs.map +1 -0
  138. package/fesm2022/ojiepermana-angular-component-toggle-group.mjs +289 -0
  139. package/fesm2022/ojiepermana-angular-component-toggle-group.mjs.map +1 -0
  140. package/fesm2022/ojiepermana-angular-component-toggle.mjs +82 -0
  141. package/fesm2022/ojiepermana-angular-component-toggle.mjs.map +1 -0
  142. package/fesm2022/ojiepermana-angular-component-tooltip.mjs +410 -0
  143. package/fesm2022/ojiepermana-angular-component-tooltip.mjs.map +1 -0
  144. package/fesm2022/ojiepermana-angular-component-utils.mjs +81 -0
  145. package/fesm2022/ojiepermana-angular-component-utils.mjs.map +1 -0
  146. package/fesm2022/ojiepermana-angular-component.mjs +11 -0
  147. package/fesm2022/ojiepermana-angular-component.mjs.map +1 -0
  148. package/form/README.md +210 -0
  149. package/hover-card/README.md +142 -0
  150. package/icon/README.md +25 -0
  151. package/input/README.md +159 -0
  152. package/input-group/README.md +237 -0
  153. package/input-otp/README.md +278 -0
  154. package/item/README.md +247 -0
  155. package/kanban/README.md +81 -0
  156. package/kbd/README.md +139 -0
  157. package/label/README.md +135 -0
  158. package/menubar/README.md +269 -0
  159. package/native-select/README.md +176 -0
  160. package/navigation-menu/README.md +160 -0
  161. package/package.json +291 -0
  162. package/pagination/README.md +144 -0
  163. package/pillbox/README.md +67 -0
  164. package/popover/README.md +43 -0
  165. package/progress/README.md +160 -0
  166. package/radio/README.md +209 -0
  167. package/resizable/README.md +168 -0
  168. package/scroll-area/README.md +143 -0
  169. package/select/README.md +174 -0
  170. package/separator/README.md +170 -0
  171. package/sheet/README.md +183 -0
  172. package/skeleton/README.md +158 -0
  173. package/slider/README.md +207 -0
  174. package/spinner/README.md +160 -0
  175. package/switch/README.md +166 -0
  176. package/table/README.md +291 -0
  177. package/tabs/README.md +214 -0
  178. package/textarea/README.md +153 -0
  179. package/timeline/README.md +94 -0
  180. package/toast/README.md +321 -0
  181. package/toggle/README.md +131 -0
  182. package/toggle-group/README.md +206 -0
  183. package/tooltip/README.md +207 -0
  184. package/types/ojiepermana-angular-component-accordion.d.ts +51 -0
  185. package/types/ojiepermana-angular-component-alert-dialog.d.ts +93 -0
  186. package/types/ojiepermana-angular-component-alert.d.ts +37 -0
  187. package/types/ojiepermana-angular-component-aspect-ratio.d.ts +12 -0
  188. package/types/ojiepermana-angular-component-avatar.d.ts +51 -0
  189. package/types/ojiepermana-angular-component-badge.d.ts +19 -0
  190. package/types/ojiepermana-angular-component-breadcrumb.d.ts +46 -0
  191. package/types/ojiepermana-angular-component-button-group.d.ts +26 -0
  192. package/types/ojiepermana-angular-component-button.d.ts +22 -0
  193. package/types/ojiepermana-angular-component-calendar.d.ts +39 -0
  194. package/types/ojiepermana-angular-component-card.d.ts +60 -0
  195. package/types/ojiepermana-angular-component-carousel.d.ts +86 -0
  196. package/types/ojiepermana-angular-component-checkbox.d.ts +42 -0
  197. package/types/ojiepermana-angular-component-collapsible.d.ts +42 -0
  198. package/types/ojiepermana-angular-component-combobox.d.ts +53 -0
  199. package/types/ojiepermana-angular-component-command.d.ts +102 -0
  200. package/types/ojiepermana-angular-component-composer.d.ts +90 -0
  201. package/types/ojiepermana-angular-component-context-menu.d.ts +36 -0
  202. package/types/ojiepermana-angular-component-date-picker.d.ts +48 -0
  203. package/types/ojiepermana-angular-component-dialog.d.ts +87 -0
  204. package/types/ojiepermana-angular-component-drawer.d.ts +1 -0
  205. package/types/ojiepermana-angular-component-dropdown-menu.d.ts +140 -0
  206. package/types/ojiepermana-angular-component-editor.d.ts +126 -0
  207. package/types/ojiepermana-angular-component-empty.d.ts +50 -0
  208. package/types/ojiepermana-angular-component-form.d.ts +140 -0
  209. package/types/ojiepermana-angular-component-hover-card.d.ts +75 -0
  210. package/types/ojiepermana-angular-component-icon.d.ts +31 -0
  211. package/types/ojiepermana-angular-component-input-group.d.ts +51 -0
  212. package/types/ojiepermana-angular-component-input-otp.d.ts +142 -0
  213. package/types/ojiepermana-angular-component-input.d.ts +16 -0
  214. package/types/ojiepermana-angular-component-item.d.ts +88 -0
  215. package/types/ojiepermana-angular-component-kanban.d.ts +70 -0
  216. package/types/ojiepermana-angular-component-kbd.d.ts +16 -0
  217. package/types/ojiepermana-angular-component-label.d.ts +11 -0
  218. package/types/ojiepermana-angular-component-menubar.d.ts +69 -0
  219. package/types/ojiepermana-angular-component-native-select.d.ts +26 -0
  220. package/types/ojiepermana-angular-component-navigation-menu.d.ts +98 -0
  221. package/types/ojiepermana-angular-component-pagination.d.ts +33 -0
  222. package/types/ojiepermana-angular-component-pillbox.d.ts +156 -0
  223. package/types/ojiepermana-angular-component-popover.d.ts +50 -0
  224. package/types/ojiepermana-angular-component-progress.d.ts +17 -0
  225. package/types/ojiepermana-angular-component-radio.d.ts +57 -0
  226. package/types/ojiepermana-angular-component-resizable.d.ts +99 -0
  227. package/types/ojiepermana-angular-component-scroll-area.d.ts +19 -0
  228. package/types/ojiepermana-angular-component-select.d.ts +56 -0
  229. package/types/ojiepermana-angular-component-separator.d.ts +14 -0
  230. package/types/ojiepermana-angular-component-sheet.d.ts +78 -0
  231. package/types/ojiepermana-angular-component-skeleton.d.ts +10 -0
  232. package/types/ojiepermana-angular-component-slider.d.ts +74 -0
  233. package/types/ojiepermana-angular-component-spinner.d.ts +13 -0
  234. package/types/ojiepermana-angular-component-switch.d.ts +44 -0
  235. package/types/ojiepermana-angular-component-table.d.ts +52 -0
  236. package/types/ojiepermana-angular-component-tabs.d.ts +92 -0
  237. package/types/ojiepermana-angular-component-textarea.d.ts +12 -0
  238. package/types/ojiepermana-angular-component-timeline.d.ts +63 -0
  239. package/types/ojiepermana-angular-component-toast.d.ts +51 -0
  240. package/types/ojiepermana-angular-component-toggle-group.d.ts +89 -0
  241. package/types/ojiepermana-angular-component-toggle.d.ts +25 -0
  242. package/types/ojiepermana-angular-component-tooltip.d.ts +101 -0
  243. package/types/ojiepermana-angular-component-utils.d.ts +30 -0
  244. package/types/ojiepermana-angular-component.d.ts +2 -0
@@ -0,0 +1,139 @@
1
+ # Button
2
+
3
+ Displays a native button or anchor that looks like a shadcn-style button, translated to Angular attribute selectors and standalone imports.
4
+
5
+ Use Button for primary actions, secondary actions, icon-only controls, and semantic links that should share the same visual language.
6
+
7
+ ## Import
8
+
9
+ ```ts
10
+ import { ButtonComponent } from '@ojiepermana/angular-component/button';
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```html
16
+ <button Button type="button" variant="default">Save</button>
17
+ <button Button variant="outline" size="sm">Cancel</button>
18
+ <a Button variant="link" href="/learn-more">Learn more</a>
19
+ ```
20
+
21
+ Choose the correct native host for the job: `<button>` for actions and `<a>` for navigation.
22
+
23
+ ## Common patterns
24
+
25
+ ### Variants
26
+
27
+ Use `variant` for emphasis: `default`, `secondary`, `destructive`, `outline`, `ghost`, or `link`.
28
+
29
+ ```html
30
+ <button Button variant="default">Save</button>
31
+ <button Button variant="secondary">Duplicate</button>
32
+ <button Button variant="destructive">Delete</button>
33
+ <button Button variant="outline">Outline</button>
34
+ <button Button variant="ghost">Ghost</button>
35
+ <a Button variant="link" href="/learn-more">Learn more</a>
36
+ ```
37
+
38
+ ### Sizes
39
+
40
+ Use `size` for compact or icon-only controls: `xs`, `sm`, `default`, `lg`, `icon-xs`, `icon-sm`, `icon`, `icon-lg`.
41
+
42
+ ```html
43
+ <button Button size="xs" variant="outline">Extra small</button>
44
+ <button Button size="sm" variant="outline">Small</button>
45
+ <button Button size="default" variant="outline">Default</button>
46
+ <button Button size="lg" variant="outline">Large</button>
47
+ <button Button size="icon-xs" variant="outline" aria-label="Extra small icon button">+</button>
48
+ <button Button size="icon-sm" variant="outline" aria-label="Small icon button">+</button>
49
+ <button Button size="icon" variant="outline" aria-label="Default icon button">+</button>
50
+ <button Button size="icon-lg" variant="outline" aria-label="Large icon button">+</button>
51
+ ```
52
+
53
+ ### Rounded buttons
54
+
55
+ Pass `class="rounded-full"` when you want a pill or circular button without changing the base API.
56
+
57
+ ```html
58
+ <button Button variant="outline" class="rounded-full px-5">Invite teammate</button>
59
+ <button Button variant="outline" size="icon" class="rounded-full" aria-label="Scroll to top">
60
+ <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
61
+ <path d="m12 19 0-14" />
62
+ <path d="m5 12 7-7 7 7" />
63
+ </svg>
64
+ </button>
65
+ ```
66
+
67
+ ### Loading and disabled states
68
+
69
+ Project a spinner element into the button and set `disabled` while async work is pending.
70
+
71
+ ```html
72
+ <button Button variant="outline" disabled>
73
+ <span
74
+ aria-hidden="true"
75
+ class="inline-block h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent"></span>
76
+ Generating
77
+ </button>
78
+ ```
79
+
80
+ ### Semantic host mapping
81
+
82
+ React's `asChild` pattern maps to choosing the right native host directly in Angular templates.
83
+
84
+ ```html
85
+ <button Button type="button">Save changes</button> <a Button href="/account" variant="link">Go to account</a>
86
+ ```
87
+
88
+ ## API reference
89
+
90
+ | Input | Type | Default |
91
+ | --------- | ------------------------------------------------------------------------------------ | ----------- |
92
+ | `variant` | `'default' \| 'secondary' \| 'destructive' \| 'outline' \| 'ghost' \| 'link'` | `'default'` |
93
+ | `size` | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'icon-xs' \| 'icon-sm' \| 'icon' \| 'icon-lg'` | `'default'` |
94
+ | `class` | `string` | `''` |
95
+
96
+ The selected variant + size are also exposed via `data-variant` / `data-size`
97
+ attributes on the host for styling overrides.
98
+
99
+ Hosts: `button[Button]` and `a[Button]`.
100
+
101
+ Re-exports: `buttonVariants`, `ButtonVariant`, `ButtonSize`.
102
+
103
+ ## Styling and theming
104
+
105
+ Tokens: `--primary`, `--primary-foreground`, `--secondary`, `--destructive`,
106
+ `--border`, `--accent`, `--ring`.
107
+
108
+ Every state (hover, focus-visible, active, disabled) is covered by the variants.
109
+ Focus-visible uses a 2px `ring-ring` outline for keyboard users.
110
+
111
+ Pass `class` to layer width, shape, and spacing overrides such as `rounded-full`, `w-full`, or responsive layout utilities.
112
+
113
+ The local primitive already opts into `cursor-pointer` for interactive hosts, so you do not need an extra Tailwind base-layer override to restore button cursors.
114
+
115
+ ## Accessibility
116
+
117
+ Attribute selectors force you to pick a real semantic element:
118
+
119
+ - Use `<button Button>` for actions that don't navigate.
120
+ - Use `<a Button href="…">` for navigation.
121
+ - Add an `aria-label` to icon-only buttons.
122
+ - Use `type="button"` inside forms unless the button should submit.
123
+
124
+ Avoid faking buttons with `<div>` — keyboard and screen-reader support depend on
125
+ the native element.
126
+
127
+ ## Keyboard interactions
128
+
129
+ - Native buttons support Tab, Enter, and Space automatically.
130
+ - Anchors with `href` participate in normal link focus and Enter activation.
131
+
132
+ ## Angular notes
133
+
134
+ - Import `ButtonComponent` into the standalone component that renders the host element.
135
+ - There is no Angular `asChild` input; pick the semantic host element directly.
136
+
137
+ ## Source parity
138
+
139
+ This Angular version follows the shadcn Button information architecture while translating examples to native hosts, standalone imports, and Angular-friendly template patterns.
@@ -0,0 +1,208 @@
1
+ # Button Group
2
+
3
+ Groups related action buttons, text pills, inputs, and nested control clusters into a single visual control boundary.
4
+
5
+ Use Button Group for toolbars, split actions, search bars, and compact action clusters where neighboring controls should read as one control family rather than isolated buttons.
6
+
7
+ ## Import
8
+
9
+ ```ts
10
+ import { ButtonComponent } from '@ojiepermana/angular-component/button';
11
+ import {
12
+ ButtonGroupComponent,
13
+ ButtonGroupSeparatorComponent,
14
+ ButtonGroupTextComponent,
15
+ } from '@ojiepermana/angular-component/button-group';
16
+ import { InputComponent } from '@ojiepermana/angular-component/input';
17
+ import {
18
+ InputGroupAddonComponent,
19
+ InputGroupComponent,
20
+ InputGroupInputComponent,
21
+ InputGroupTextComponent,
22
+ } from '@ojiepermana/angular-component/input-group';
23
+ ```
24
+
25
+ ## Composition
26
+
27
+ The Angular structure mirrors the shadcn composition while translating `asChild` to normal Angular content projection.
28
+
29
+ ```text
30
+ ButtonGroup
31
+ ├── button[Button] or a[Button]
32
+ ├── input[Input] or textarea[Textarea]
33
+ ├── ButtonGroupText
34
+ ├── ButtonGroupSeparator
35
+ └── ButtonGroup
36
+ ```
37
+
38
+ ## Basic usage
39
+
40
+ Label the group with `aria-label` or `aria-labelledby` whenever the buttons act as a single tool cluster.
41
+
42
+ ```html
43
+ <ButtonGroup aria-label="Search actions" class="w-full max-w-md">
44
+ <input Input placeholder="Search..." />
45
+ <button Button type="button" variant="outline" aria-label="Run search">Search</button>
46
+ </ButtonGroup>
47
+ ```
48
+
49
+ ## Common patterns
50
+
51
+ ### Orientation
52
+
53
+ Use `orientation="vertical"` when the group should stack actions instead of lining them up horizontally.
54
+
55
+ ```html
56
+ <ButtonGroup orientation="vertical" aria-label="Zoom controls" class="h-fit">
57
+ <button Button type="button" variant="outline" size="icon">+</button>
58
+ <button Button type="button" variant="outline" size="icon">-</button>
59
+ </ButtonGroup>
60
+ ```
61
+
62
+ ### Text and field pairing
63
+
64
+ `ButtonGroupText` is the Angular translation of shadcn's `ButtonGroupText`. Project any semantic content inside it, including a native label.
65
+
66
+ ```html
67
+ <ButtonGroup class="w-full max-w-lg">
68
+ <ButtonGroupText>
69
+ <label for="project-name">Project</label>
70
+ </ButtonGroupText>
71
+ <input Input id="project-name" placeholder="Type a name..." />
72
+ </ButtonGroup>
73
+ ```
74
+
75
+ ### Separator
76
+
77
+ Use `ButtonGroupSeparator` when filled or secondary buttons still need a visible division.
78
+
79
+ ```html
80
+ <ButtonGroup aria-label="Clipboard actions">
81
+ <button Button type="button" variant="secondary" size="sm">Copy</button>
82
+ <ButtonGroupSeparator />
83
+ <button Button type="button" variant="secondary" size="sm">Paste</button>
84
+ </ButtonGroup>
85
+ ```
86
+
87
+ ### Split action
88
+
89
+ Split buttons are just two neighboring buttons with a separator between the primary action and the disclosure or icon action.
90
+
91
+ ```html
92
+ <ButtonGroup aria-label="Create actions">
93
+ <button Button type="button" variant="secondary">Create</button>
94
+ <ButtonGroupSeparator />
95
+ <button Button type="button" variant="secondary" size="icon" aria-label="Open create menu">+</button>
96
+ </ButtonGroup>
97
+ ```
98
+
99
+ ### Search input
100
+
101
+ Button Group works directly with the local `Input` primitive because both controls own their border on the host element.
102
+
103
+ ```html
104
+ <ButtonGroup aria-label="Repository search" class="w-full max-w-lg">
105
+ <input Input placeholder="Search repositories..." />
106
+ <button Button type="button" variant="outline" aria-label="Search">Search</button>
107
+ </ButtonGroup>
108
+ ```
109
+
110
+ ### Nested groups
111
+
112
+ Nest `ButtonGroup` when you want separate clusters with spacing between them while keeping each inner cluster visually fused.
113
+
114
+ ```html
115
+ <ButtonGroup aria-label="Message composer" class="w-full max-w-xl">
116
+ <ButtonGroup>
117
+ <button Button type="button" variant="outline" size="icon" aria-label="Add attachment">+</button>
118
+ </ButtonGroup>
119
+
120
+ <ButtonGroup class="min-w-0 flex-1">
121
+ <InputGroup>
122
+ <input InputGroupInput placeholder="Send a message..." />
123
+ <InputGroupAddon align="inline-end">
124
+ <InputGroupText>⌘↵</InputGroupText>
125
+ </InputGroupAddon>
126
+ </InputGroup>
127
+ </ButtonGroup>
128
+ </ButtonGroup>
129
+ ```
130
+
131
+ ### Popover companion
132
+
133
+ Use a neighboring popover trigger when the primary button opens a short follow-up form or assistant prompt.
134
+
135
+ ```html
136
+ <ButtonGroup aria-label="Copilot actions">
137
+ <button Button type="button" variant="outline">Copilot</button>
138
+ <button Button type="button" variant="outline" size="icon" aria-label="Open Copilot options">⋯</button>
139
+ </ButtonGroup>
140
+ ```
141
+
142
+ ## API reference
143
+
144
+ ### `ButtonGroupComponent`
145
+
146
+ | Input | Type | Default |
147
+ | ------------- | ---------------------------- | -------------- |
148
+ | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` |
149
+ | `class` | `string` | `''` |
150
+
151
+ Host behavior:
152
+
153
+ - Renders `role="group"`.
154
+ - Adds `data-orientation` and `data-slot="button-group"`.
155
+ - Collapses adjoining corner radius and internal border width with RTL-safe logical properties.
156
+
157
+ ### `ButtonGroupSeparatorComponent`
158
+
159
+ | Input | Type | Default |
160
+ | ------------- | ---------------------------- | ------------ |
161
+ | `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` |
162
+ | `class` | `string` | `''` |
163
+
164
+ ### `ButtonGroupTextComponent`
165
+
166
+ | Input | Type | Default |
167
+ | ------- | -------- | ------- |
168
+ | `class` | `string` | `''` |
169
+
170
+ Angular mapping note: there is no `asChild` input. Project the semantic element you need, such as `<label>` or `<span>`, inside `ButtonGroupText`.
171
+
172
+ ## Styling and theming
173
+
174
+ - The root collapses adjacent corners and borders with logical start/end utilities so the same component works in LTR and RTL layouts.
175
+ - Nested `ButtonGroup` children automatically create spacing between groups while preserving the fused inner boundaries of each nested group.
176
+ - `ButtonGroupText` uses `border-border`, `bg-muted`, and shared radius tokens so it matches the rest of the component package.
177
+ - `Input` and `InputGroup` compose cleanly inside Button Group because their border and radius live on the visible host. The current Material-backed `SelectField` does not expose the same host-level border contract yet, so the upstream Select example is intentionally not shipped as a parity demo.
178
+
179
+ ## Accessibility
180
+
181
+ - `ButtonGroup` renders with `role="group"`; provide an accessible name with `aria-label` or `aria-labelledby` when the controls act as one tool cluster.
182
+ - Button Group is for actions. If the clustered controls represent pressed or selected state, use a toggle-group style pattern instead.
183
+ - Add `aria-label` to icon-only buttons inside the group.
184
+ - `ButtonGroupText` is non-interactive content. Keep labels, helper text, or status copy inside it and leave action handling to the actual button or input controls.
185
+
186
+ ## Keyboard interactions
187
+
188
+ - Tab order follows the DOM order of the projected controls.
189
+ - Native buttons keep their built-in Enter and Space activation behavior.
190
+ - Inputs and textareas keep their native editing behavior.
191
+ - Popover and menu triggers inside a group keep the keyboard behavior of their own directives; the group container does not intercept those interactions.
192
+
193
+ ## Button Group vs Toggle Group
194
+
195
+ - Use Button Group when each item performs an immediate action.
196
+ - Use Toggle Group when each item represents persistent pressed, selected, or filter state.
197
+
198
+ ## Angular notes
199
+
200
+ - Import `ButtonGroupComponent` plus only the child primitives you render on the page.
201
+ - There is no React-style `asChild` prop. Angular templates already let you choose the semantic element directly.
202
+ - Use nested `ButtonGroup` elements for spacing between related clusters rather than adding gap utilities to a single fused group.
203
+
204
+ ## Source parity
205
+
206
+ This Angular implementation follows the shadcn Button Group surface with a grouped root, text pill, separator, nested-group spacing, dropdown and popover composition, and RTL-friendly border collapsing.
207
+
208
+ The main documented deviation is the upstream Select example: the local `SelectField` remains Material-backed, so it is better composed next to the group in surrounding layout for now instead of being presented as a fused host-level group item.
@@ -0,0 +1,135 @@
1
+ # Calendar
2
+
3
+ Inline single-date calendar built on Angular Material `MatCalendar` and wrapped with shadcn-style theme tokens.
4
+
5
+ Use Calendar when the date grid should stay visible in the page. Use `DatePickerComponent` when the same selection should live behind an input and popover trigger.
6
+
7
+ ## Import
8
+
9
+ ```ts
10
+ import { CalendarComponent } from '@ojiepermana/angular-component/calendar';
11
+ ```
12
+
13
+ ## Date adapter
14
+
15
+ The component self-provides a native `DateAdapter`, so it works out of the box in any
16
+ consumer — including when federated into a host app that never wired one. You only need
17
+ to add a date adapter at the application root if you want a non-native one or a custom
18
+ locale (`MAT_DATE_LOCALE` flows in from the parent injector):
19
+
20
+ ```ts
21
+ // app.config.ts — optional, only for a custom adapter/locale
22
+ import { provideNativeDateAdapter } from '@angular/material/core';
23
+
24
+ export const appConfig = {
25
+ providers: [provideNativeDateAdapter()],
26
+ };
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ Bind `[(value)]` to a `Date | null` signal or component field. Use `startAt` when the first visible month should differ from the selected value.
32
+
33
+ ```html
34
+ <Calendar [(value)]="selectedDate" [startAt]="selectedDate()" />
35
+ ```
36
+
37
+ ```ts
38
+ protected readonly selectedDate = signal<Date | null>(new Date(2026, 4, 22));
39
+ ```
40
+
41
+ ## Common patterns
42
+
43
+ ### Constrained range
44
+
45
+ Use `min` and `max` to disable dates outside an allowed window.
46
+
47
+ ```html
48
+ <Calendar [(value)]="billingDate" [min]="minDate" [max]="maxDate" [startAt]="billingDate()" />
49
+ ```
50
+
51
+ ```ts
52
+ protected readonly billingDate = signal<Date | null>(new Date(2026, 4, 15));
53
+ protected readonly minDate = new Date(2026, 4, 5);
54
+ protected readonly maxDate = new Date(2026, 4, 25);
55
+ ```
56
+
57
+ ### Disabled or booked dates
58
+
59
+ Pass a `dateFilter` function. Angular Material expects the function to return `true` for selectable dates and `false` for disabled dates.
60
+
61
+ ```html
62
+ <Calendar [(value)]="visitDate" [dateFilter]="availableDateFilter" [startAt]="visitDate()" />
63
+ ```
64
+
65
+ ```ts
66
+ protected readonly bookedDates = [new Date(2026, 1, 12), new Date(2026, 1, 13)];
67
+
68
+ protected readonly availableDateFilter = (candidate: Date | null): boolean =>
69
+ !!candidate && !this.bookedDates.some((bookedDate) => this.isSameDay(bookedDate, candidate));
70
+ ```
71
+
72
+ ### Presets
73
+
74
+ Compose preset buttons around the calendar and update the same `value` model.
75
+
76
+ ```html
77
+ <Calendar [(value)]="presetDate" [startAt]="presetDate()" class="border-0" />
78
+
79
+ <button Button type="button" variant="outline" size="sm" (click)="selectPreset(7)">In a week</button>
80
+ ```
81
+
82
+ ### Date and time
83
+
84
+ Calendar owns the date. Native time inputs or `InputGroupComponent` can own the time value next to it.
85
+
86
+ ```html
87
+ <Calendar [(value)]="meetingDate" [startAt]="meetingDate()" />
88
+
89
+ <InputGroup>
90
+ <input InputGroupInput type="time" [value]="startTime()" (input)="updateStartTime($event)" />
91
+ </InputGroup>
92
+ ```
93
+
94
+ ## API reference
95
+
96
+ | Input / Model | Type | Default |
97
+ | ------------- | ----------------------------------- | --------- |
98
+ | `value` | `Date \| null` | `null` |
99
+ | `min` | `Date \| null` | `null` |
100
+ | `max` | `Date \| null` | `null` |
101
+ | `startAt` | `Date \| null` | `null` |
102
+ | `startView` | `'month' \| 'year' \| 'multi-year'` | `'month'` |
103
+ | `dateFilter` | `(date: Date \| null) => boolean` | `null` |
104
+ | `disabled` | `boolean` | `false` |
105
+ | `class` | `string` | `''` |
106
+
107
+ Implements `ControlValueAccessor` — usable with `[(ngModel)]` and reactive forms.
108
+
109
+ ## Styling and theming
110
+
111
+ The host uses `--border`, `--background`, `--foreground`, and `--radius`. Pass `class` for layout utilities such as `shadow-sm`, `border-0`, or `[--calendar-width:20rem]`.
112
+
113
+ The inner Material calendar keeps Angular Material's a11y and navigation behavior while sitting inside the shadcn token wrapper. Use `DatePickerComponent` for popover input flows; this primitive intentionally stays inline.
114
+
115
+ ## Accessibility
116
+
117
+ `MatCalendar` supplies the ARIA grid semantics, focus management, active date state, and disabled date handling. Provide a visible label or surrounding section heading when the calendar appears in a form-like surface.
118
+
119
+ ## Keyboard interactions
120
+
121
+ - Arrow keys move between dates.
122
+ - Page Up and Page Down move by month.
123
+ - Home and End move to the start or end of the row.
124
+ - Enter selects the focused date.
125
+
126
+ ## Angular notes
127
+
128
+ - A native date adapter is built in; provide one at app bootstrap only for a custom adapter/locale.
129
+ - `dateFilter` returns `true` for enabled dates, unlike some predicate APIs that return `true` for blocked dates.
130
+ - `disabled` marks the host as inert and updates the CVA disabled state.
131
+ - This component is a single-date primitive. Range selection is best modeled as a separate range primitive or by composing two calendars with application state.
132
+
133
+ ## Source parity
134
+
135
+ The shadcn Calendar is built on React DayPicker. This Angular implementation maps the same inline calendar concept to `MatCalendar`, standalone imports, signal-friendly `[(value)]` binding, `min` and `max` constraints, `dateFilter` disabled dates, preset composition, and RTL-friendly container usage.