@egose/shadcn-theme-ng-tw 0.0.28 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/README.md +130 -13
  2. package/accordion/README.md +376 -34
  3. package/accordion/fesm2022/accordion.mjs +20 -20
  4. package/alert/README.md +343 -34
  5. package/alert/fesm2022/alert.mjs +18 -18
  6. package/alert-dialog/README.md +471 -5
  7. package/alert-dialog/fesm2022/alert-dialog.mjs +48 -48
  8. package/alert-dialog/types/alert-dialog.d.ts +1 -1
  9. package/aspect-ratio/README.md +272 -5
  10. package/aspect-ratio/fesm2022/aspect-ratio.mjs +9 -9
  11. package/autocomplete/README.md +473 -34
  12. package/autocomplete/fesm2022/autocomplete.mjs +54 -54
  13. package/autocomplete/types/autocomplete.d.ts +1 -1
  14. package/avatar/README.md +357 -5
  15. package/avatar/fesm2022/avatar.mjs +32 -32
  16. package/badge/README.md +289 -34
  17. package/badge/fesm2022/badge.mjs +4 -4
  18. package/basic-alert/README.md +324 -34
  19. package/basic-alert/fesm2022/basic-alert.mjs +4 -4
  20. package/basic-alert/types/basic-alert.d.ts +1 -1
  21. package/breadcrumb/README.md +406 -5
  22. package/breadcrumb/fesm2022/breadcrumb.mjs +34 -34
  23. package/button/README.md +453 -34
  24. package/button/fesm2022/button.mjs +96 -118
  25. package/button/types/button.d.ts +7 -10
  26. package/button-group/README.md +318 -5
  27. package/button-group/fesm2022/button-group.mjs +20 -20
  28. package/calendar/README.md +328 -34
  29. package/calendar/fesm2022/calendar.mjs +154 -154
  30. package/card/README.md +331 -5
  31. package/card/fesm2022/card.mjs +33 -33
  32. package/carousel/README.md +333 -5
  33. package/carousel/fesm2022/carousel.mjs +47 -44
  34. package/carousel/types/carousel.d.ts +1 -1
  35. package/checkbox/README.md +291 -34
  36. package/checkbox/fesm2022/checkbox.mjs +22 -20
  37. package/checkbox/types/checkbox.d.ts +5 -4
  38. package/collapsible/README.md +332 -5
  39. package/collapsible/fesm2022/collapsible.mjs +15 -15
  40. package/combobox/README.md +507 -5
  41. package/combobox/fesm2022/combobox.mjs +95 -92
  42. package/combobox/types/combobox.d.ts +1 -1
  43. package/command/README.md +435 -5
  44. package/command/fesm2022/command.mjs +56 -56
  45. package/confirmation-dialog/README.md +272 -34
  46. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +13 -12
  47. package/confirmation-dialog/types/confirmation-dialog.d.ts +9 -5
  48. package/context-menu/README.md +366 -5
  49. package/context-menu/fesm2022/context-menu.mjs +9 -9
  50. package/date-picker/README.md +436 -34
  51. package/date-picker/fesm2022/date-picker.mjs +79 -68
  52. package/date-picker/types/date-picker.d.ts +8 -4
  53. package/dialog/README.md +419 -34
  54. package/dialog/fesm2022/dialog.mjs +48 -48
  55. package/drawer/README.md +395 -5
  56. package/drawer/fesm2022/drawer.mjs +45 -45
  57. package/dropdown-menu/README.md +417 -5
  58. package/dropdown-menu/fesm2022/dropdown-menu.mjs +85 -73
  59. package/dropdown-menu/types/dropdown-menu.d.ts +4 -0
  60. package/empty/README.md +329 -5
  61. package/empty/fesm2022/empty.mjs +31 -31
  62. package/field/README.md +385 -5
  63. package/field/fesm2022/field.mjs +59 -59
  64. package/field/types/field.d.ts +1 -1
  65. package/form-checkbox/README.md +283 -34
  66. package/form-checkbox/fesm2022/form-checkbox.mjs +37 -19
  67. package/form-checkbox/types/form-checkbox.d.ts +7 -1
  68. package/form-date-picker/README.md +293 -34
  69. package/form-date-picker/fesm2022/form-date-picker.mjs +59 -24
  70. package/form-date-picker/types/form-date-picker.d.ts +7 -1
  71. package/form-field/README.md +327 -34
  72. package/form-field/fesm2022/form-field.mjs +30 -16
  73. package/form-field/types/form-field.d.ts +28 -20
  74. package/form-field-simple/README.md +311 -34
  75. package/form-field-simple/fesm2022/form-field-simple.mjs +4 -4
  76. package/form-searchable-multiselect/README.md +332 -34
  77. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +41 -21
  78. package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +8 -2
  79. package/form-select/README.md +321 -34
  80. package/form-select/fesm2022/form-select.mjs +62 -29
  81. package/form-select/types/form-select.d.ts +7 -1
  82. package/form-text-input/README.md +342 -34
  83. package/form-text-input/fesm2022/form-text-input.mjs +43 -55
  84. package/form-text-input/types/form-text-input.d.ts +9 -12
  85. package/form-textarea/README.md +318 -34
  86. package/form-textarea/fesm2022/form-textarea.mjs +42 -23
  87. package/form-textarea/types/form-textarea.d.ts +8 -1
  88. package/hover-card/README.md +256 -5
  89. package/hover-card/fesm2022/hover-card.mjs +19 -19
  90. package/icon/README.md +210 -34
  91. package/icon/fesm2022/icon.mjs +8 -8
  92. package/input/README.md +240 -34
  93. package/input/fesm2022/input.mjs +17 -12
  94. package/input/types/input.d.ts +2 -1
  95. package/input-group/README.md +335 -5
  96. package/input-group/fesm2022/input-group.mjs +37 -37
  97. package/input-group/types/input-group.d.ts +3 -3
  98. package/input-otp/README.md +375 -5
  99. package/input-otp/fesm2022/input-otp.mjs +27 -27
  100. package/item/README.md +385 -5
  101. package/item/fesm2022/item.mjs +54 -54
  102. package/kbd/README.md +291 -5
  103. package/kbd/fesm2022/kbd.mjs +13 -13
  104. package/label/README.md +243 -34
  105. package/label/fesm2022/label.mjs +9 -9
  106. package/label/types/label.d.ts +1 -1
  107. package/layout-simple/README.md +174 -44
  108. package/layout-simple/fesm2022/layout-simple.mjs +917 -398
  109. package/layout-simple/types/layout-simple.d.ts +180 -129
  110. package/menu/README.md +418 -0
  111. package/menu/fesm2022/menu.mjs +461 -0
  112. package/menu/package.json +24 -0
  113. package/menu/types/menu.d.ts +137 -0
  114. package/menubar/README.md +343 -5
  115. package/menubar/fesm2022/menubar.mjs +13 -13
  116. package/native-select/README.md +323 -5
  117. package/native-select/fesm2022/native-select.mjs +19 -19
  118. package/navigation-menu/README.md +369 -5
  119. package/navigation-menu/fesm2022/navigation-menu.mjs +37 -37
  120. package/package.json +183 -154
  121. package/pagination/README.md +388 -5
  122. package/pagination/fesm2022/pagination.mjs +63 -63
  123. package/popover/README.md +302 -34
  124. package/popover/fesm2022/popover.mjs +30 -30
  125. package/progress/README.md +311 -5
  126. package/progress/fesm2022/progress.mjs +13 -13
  127. package/radio-group/README.md +335 -34
  128. package/radio-group/fesm2022/radio-group.mjs +26 -19
  129. package/resizable/README.md +269 -5
  130. package/resizable/fesm2022/resizable.mjs +19 -19
  131. package/scroll-area/README.md +233 -5
  132. package/scroll-area/fesm2022/scroll-area.mjs +9 -9
  133. package/searchable-multiselect/README.md +294 -34
  134. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +63 -16
  135. package/searchable-multiselect/types/searchable-multiselect.d.ts +8 -2
  136. package/select/README.md +408 -34
  137. package/select/fesm2022/select.mjs +80 -72
  138. package/select/types/select.d.ts +3 -1
  139. package/separator/README.md +193 -34
  140. package/separator/fesm2022/separator.mjs +9 -9
  141. package/separator/types/separator.d.ts +1 -1
  142. package/sheet/README.md +282 -34
  143. package/sheet/fesm2022/sheet.mjs +30 -30
  144. package/sidebar/README.md +457 -5
  145. package/sidebar/fesm2022/sidebar.mjs +136 -134
  146. package/sidebar/types/sidebar.d.ts +3 -3
  147. package/skeleton/README.md +217 -5
  148. package/skeleton/fesm2022/skeleton.mjs +9 -9
  149. package/slider/README.md +273 -5
  150. package/slider/fesm2022/slider.mjs +29 -25
  151. package/sonner/README.md +317 -34
  152. package/sonner/fesm2022/sonner.mjs +9 -9
  153. package/spinner/README.md +255 -34
  154. package/spinner/fesm2022/spinner.mjs +8 -8
  155. package/switch/README.md +281 -34
  156. package/switch/fesm2022/switch.mjs +12 -14
  157. package/table/README.md +423 -5
  158. package/table/fesm2022/table.mjs +41 -41
  159. package/tabs/README.md +382 -34
  160. package/tabs/fesm2022/tabs.mjs +48 -38
  161. package/textarea/README.md +282 -5
  162. package/textarea/fesm2022/textarea.mjs +9 -9
  163. package/toggle/README.md +270 -5
  164. package/toggle/fesm2022/toggle.mjs +14 -14
  165. package/toggle-group/README.md +340 -5
  166. package/toggle-group/fesm2022/toggle-group.mjs +13 -13
  167. package/toggle-group/types/toggle-group.d.ts +13 -7
  168. package/tooltip/README.md +240 -34
  169. package/tooltip/fesm2022/tooltip.mjs +14 -14
  170. package/typography/README.md +271 -5
  171. package/typography/fesm2022/typography.mjs +53 -53
  172. package/typography/types/typography.d.ts +12 -12
  173. package/utils/README.md +274 -34
  174. package/utils/fesm2022/utils.mjs +68 -44
  175. package/accordion/fesm2022/accordion.mjs.map +0 -1
  176. package/alert/fesm2022/alert.mjs.map +0 -1
  177. package/alert-dialog/fesm2022/alert-dialog.mjs.map +0 -1
  178. package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +0 -1
  179. package/autocomplete/fesm2022/autocomplete.mjs.map +0 -1
  180. package/avatar/fesm2022/avatar.mjs.map +0 -1
  181. package/badge/fesm2022/badge.mjs.map +0 -1
  182. package/basic-alert/fesm2022/basic-alert.mjs.map +0 -1
  183. package/breadcrumb/fesm2022/breadcrumb.mjs.map +0 -1
  184. package/button/fesm2022/button.mjs.map +0 -1
  185. package/button-group/fesm2022/button-group.mjs.map +0 -1
  186. package/calendar/fesm2022/calendar.mjs.map +0 -1
  187. package/card/fesm2022/card.mjs.map +0 -1
  188. package/carousel/fesm2022/carousel.mjs.map +0 -1
  189. package/checkbox/fesm2022/checkbox.mjs.map +0 -1
  190. package/collapsible/fesm2022/collapsible.mjs.map +0 -1
  191. package/combobox/fesm2022/combobox.mjs.map +0 -1
  192. package/command/fesm2022/command.mjs.map +0 -1
  193. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +0 -1
  194. package/context-menu/fesm2022/context-menu.mjs.map +0 -1
  195. package/date-picker/fesm2022/date-picker.mjs.map +0 -1
  196. package/dialog/fesm2022/dialog.mjs.map +0 -1
  197. package/drawer/fesm2022/drawer.mjs.map +0 -1
  198. package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +0 -1
  199. package/empty/fesm2022/empty.mjs.map +0 -1
  200. package/field/fesm2022/field.mjs.map +0 -1
  201. package/form-checkbox/fesm2022/form-checkbox.mjs.map +0 -1
  202. package/form-date-picker/fesm2022/form-date-picker.mjs.map +0 -1
  203. package/form-field/fesm2022/form-field.mjs.map +0 -1
  204. package/form-field-simple/fesm2022/form-field-simple.mjs.map +0 -1
  205. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +0 -1
  206. package/form-select/fesm2022/form-select.mjs.map +0 -1
  207. package/form-text-input/fesm2022/form-text-input.mjs.map +0 -1
  208. package/form-textarea/fesm2022/form-textarea.mjs.map +0 -1
  209. package/hover-card/fesm2022/hover-card.mjs.map +0 -1
  210. package/icon/fesm2022/icon.mjs.map +0 -1
  211. package/input/fesm2022/input.mjs.map +0 -1
  212. package/input-group/fesm2022/input-group.mjs.map +0 -1
  213. package/input-otp/fesm2022/input-otp.mjs.map +0 -1
  214. package/item/fesm2022/item.mjs.map +0 -1
  215. package/kbd/fesm2022/kbd.mjs.map +0 -1
  216. package/label/fesm2022/label.mjs.map +0 -1
  217. package/layout-simple/fesm2022/layout-simple.mjs.map +0 -1
  218. package/menubar/fesm2022/menubar.mjs.map +0 -1
  219. package/native-select/fesm2022/native-select.mjs.map +0 -1
  220. package/navigation-menu/fesm2022/navigation-menu.mjs.map +0 -1
  221. package/pagination/fesm2022/pagination.mjs.map +0 -1
  222. package/popover/fesm2022/popover.mjs.map +0 -1
  223. package/progress/fesm2022/progress.mjs.map +0 -1
  224. package/radio-group/fesm2022/radio-group.mjs.map +0 -1
  225. package/resizable/fesm2022/resizable.mjs.map +0 -1
  226. package/scroll-area/fesm2022/scroll-area.mjs.map +0 -1
  227. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +0 -1
  228. package/select/fesm2022/select.mjs.map +0 -1
  229. package/separator/fesm2022/separator.mjs.map +0 -1
  230. package/sheet/fesm2022/sheet.mjs.map +0 -1
  231. package/sidebar/fesm2022/sidebar.mjs.map +0 -1
  232. package/skeleton/fesm2022/skeleton.mjs.map +0 -1
  233. package/slider/fesm2022/slider.mjs.map +0 -1
  234. package/sonner/fesm2022/sonner.mjs.map +0 -1
  235. package/spinner/fesm2022/spinner.mjs.map +0 -1
  236. package/switch/fesm2022/switch.mjs.map +0 -1
  237. package/table/fesm2022/table.mjs.map +0 -1
  238. package/tabs/fesm2022/tabs.mjs.map +0 -1
  239. package/textarea/fesm2022/textarea.mjs.map +0 -1
  240. package/toggle/fesm2022/toggle.mjs.map +0 -1
  241. package/toggle-group/fesm2022/toggle-group.mjs.map +0 -1
  242. package/tooltip/fesm2022/tooltip.mjs.map +0 -1
  243. package/typography/fesm2022/typography.mjs.map +0 -1
  244. package/utils/fesm2022/utils.mjs.map +0 -1
package/select/README.md CHANGED
@@ -1,64 +1,438 @@
1
- # Select
1
+ # Select (`@egose/shadcn-theme-ng/select`)
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.2.0.
3
+ A shadcn/ui-style **Select** dropdown — button trigger, floating panel, grouped options with check-mark selection. This is the Angular equivalent of shadcn/ui `Select` (`SelectTrigger`, `SelectContent`, `SelectItem`, …).
4
4
 
5
- ## Code scaffolding
5
+ Behavior comes from **spartan-ng/brain** (`BrnSelect` / `BrnSelectMultiple`, `BrnSelectContent`, `BrnSelectItem`, …, plus `BrnPopover` for positioning): popover open/close, keyboard navigation, type-ahead, single- and multi-value models. This package adds the shadcn structure and styling, including the check icon (`lucideCheck` via `@ng-icons`), scroll buttons, and the `sm`/`default` trigger sizes.
6
6
 
7
- Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
7
+ > **Ships as:** `@egose/shadcn-theme-ng/select` and `@egose/shadcn-theme-ng-tw/select` (the `tw:`-prefixed Tailwind variant — same API, class strings prefixed with `tw:`).
8
+ > See the [package README](../../README.md) for installation, peer dependencies, and Tailwind setup. Do not publish this project directory independently.
9
+
10
+ ## Installation
8
11
 
9
12
  ```bash
10
- ng generate component component-name
13
+ # Plain Tailwind (no prefix)
14
+ npm install @egose/shadcn-theme-ng
15
+
16
+ # Or the tw:-prefixed variant
17
+ npm install @egose/shadcn-theme-ng-tw
11
18
  ```
12
19
 
13
- For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
20
+ ```ts
21
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
22
+ // tw variant:
23
+ // import { HlmSelectImports } from '@egose/shadcn-theme-ng-tw/select';
24
+ ```
14
25
 
15
- ```bash
16
- ng generate --help
26
+ Peer dependencies (see [package README](../../README.md) for versions): `@angular/core`, `@angular/common`, `@spartan-ng/brain`. Icons come from `@ng-icons` (installed transitively).
27
+
28
+ ## Imports
29
+
30
+ Real exported symbols (from `src/public-api.ts`):
31
+
32
+ | Symbol | Kind | Selector |
33
+ | ------------------------ | ------------- | ------------------------------------------------------------ |
34
+ | `HlmSelect` | Directive | `[hlmSelect],hlm-select` (single value) |
35
+ | `HlmSelectMultiple` | Directive | `[hlmSelectMultiple],hlm-select-multiple` (multi value) |
36
+ | `HlmSelectTrigger` | Component | `hlm-select-trigger` |
37
+ | `HlmSelectContent` | Component | `hlm-select-content` |
38
+ | `HlmSelectItem` | Component | `hlm-select-item` |
39
+ | `HlmSelectGroup` | Directive | `[hlmSelectGroup],hlm-select-group` |
40
+ | `HlmSelectLabel` | Directive | `[hlmSelectLabel],hlm-select-label` |
41
+ | `HlmSelectValue` | Directive | `[hlmSelectValue],hlm-select-value` |
42
+ | `HlmSelectValues` | Directive | `[hlmSelectValues]` (multi) |
43
+ | `HlmSelectValuesContent` | Directive | `[hlmSelectValuesContent],hlm-select-values-content` (multi) |
44
+ | `HlmSelectPlaceholder` | Directive | `[hlmSelectPlaceholder],hlm-select-placeholder` |
45
+ | `HlmSelectSeparator` | Directive | `[hlmSelectSeparator],hlm-select-separator` |
46
+ | `HlmSelectScrollUp` | Component | `hlm-select-scroll-up` |
47
+ | `HlmSelectScrollDown` | Component | `hlm-select-scroll-down` |
48
+ | `HlmSelectPortal` | Directive | `[hlmSelectPortal]` |
49
+ | `HlmSelectValueTemplate` | Directive | `[hlmSelectValueTemplate]` |
50
+ | `HlmSelectImports` | `const` array | All of the above, for standalone `imports` |
51
+ | `HlmSelectModule` | `NgModule` | NgModule wrapper re-exporting all of the above |
52
+
53
+ Standalone usage:
54
+
55
+ ```ts
56
+ import { Component } from '@angular/core';
57
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
58
+
59
+ @Component({
60
+ selector: 'app-demo',
61
+ standalone: true,
62
+ imports: [HlmSelectImports],
63
+ template: `...`,
64
+ })
65
+ export class DemoComponent {}
17
66
  ```
18
67
 
19
- ## Building
68
+ NgModule usage:
20
69
 
21
- To build the library, run:
70
+ ```ts
71
+ import { NgModule } from '@angular/core';
72
+ import { HlmSelectModule } from '@egose/shadcn-theme-ng/select';
22
73
 
23
- ```bash
24
- ng build select
74
+ @NgModule({ imports: [HlmSelectModule] })
75
+ export class DemoModule {}
25
76
  ```
26
77
 
27
- This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
78
+ ## Anatomy / Structure
28
79
 
29
- ### Publishing the Library
80
+ Single select:
30
81
 
31
- Once the project is built, you can publish your library by following these steps:
82
+ ```html
83
+ <div hlmSelect [(value)]="fruit">
84
+ <hlm-select-trigger>
85
+ <hlm-select-value placeholder="Pick a fruit" />
86
+ </hlm-select-trigger>
32
87
 
33
- 1. Navigate to the `dist` directory:
88
+ <hlm-select-content *hlmSelectPortal>
89
+ <div hlmSelectGroup>
90
+ <div hlmSelectLabel>Fruits</div>
91
+ <hlm-select-item value="apple">Apple</hlm-select-item>
92
+ <hlm-select-item value="banana">Banana</hlm-select-item>
93
+ <hlm-select-item value="blueberry" disabled>Blueberry</hlm-select-item>
94
+ </div>
34
95
 
35
- ```bash
36
- cd dist/select
37
- ```
96
+ <hlm-select-separator />
38
97
 
39
- 2. Run the `npm publish` command to publish your library to the npm registry:
40
- ```bash
41
- npm publish
42
- ```
98
+ <hlm-select-item value="other">Other</hlm-select-item>
99
+ </hlm-select-content>
100
+ </div>
101
+ ```
43
102
 
44
- ## Running unit tests
103
+ Multi select (same skeleton, `hlmSelectMultiple` + `hlmSelectValues`):
45
104
 
46
- To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
105
+ ```html
106
+ <div hlmSelectMultiple [(value)]="toppings">
107
+ <hlm-select-trigger>
108
+ <span hlmSelectValues>
109
+ <span hlmSelectValuesContent>
110
+ <span hlmSelectValue placeholder="Pick toppings" />
111
+ </span>
112
+ </span>
113
+ </hlm-select-trigger>
47
114
 
48
- ```bash
49
- ng test
115
+ <hlm-select-content *hlmSelectPortal>
116
+ <hlm-select-item value="cheese">Cheese</hlm-select-item>
117
+ <hlm-select-item value="bacon">Bacon</hlm-select-item>
118
+ </hlm-select-content>
119
+ </div>
50
120
  ```
51
121
 
52
- ## Running end-to-end tests
122
+ Selector/slot summary:
53
123
 
54
- For end-to-end (e2e) testing, run:
124
+ | Selector | `data-slot` | Notes |
125
+ | ---------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------- |
126
+ | `[hlmSelect],hlm-select` | `select` | Provides popover config (`align: start`, `sideOffset: 6`) |
127
+ | `[hlmSelectMultiple],hlm-select-multiple` | `select` | Same popover config, multi-value model |
128
+ | `hlm-select-trigger` | `select-trigger` (on inner button) | Renders its own `<button brnSelectTrigger>` + chevron icon |
129
+ | `hlm-select-content` | — | Floating panel; optional `showScroll` scroll buttons |
130
+ | `hlm-select-item` | `select-item` | Option row; check icon appears when active |
131
+ | `[hlmSelectGroup],hlm-select-group` | `select-group` | Option grouping wrapper |
132
+ | `[hlmSelectLabel],hlm-select-label` | `select-label` | Group heading |
133
+ | `[hlmSelectValue],hlm-select-value` | `select-value` (when visible) | Current-value display (single) |
134
+ | `[hlmSelectValues]` | — | Current-values host (multi) |
135
+ | `[hlmSelectValuesContent],hlm-select-values-content` | — | Layout row for multi values |
136
+ | `[hlmSelectPlaceholder],hlm-select-placeholder` | `select-placeholder` | Shown when nothing is selected |
137
+ | `[hlmSelectSeparator],hlm-select-separator` | `select-separator` | Divider line (has `orientation` input) |
138
+ | `hlm-select-scroll-up` / `hlm-select-scroll-down` | — | Chevron buttons (auto-rendered by content when `showScroll`) |
139
+ | `[hlmSelectPortal]` | — | Binds the content to the popover overlay (`*hlmSelectPortal`) |
140
+ | `[hlmSelectValueTemplate]` | — | Custom value template marker |
55
141
 
56
- ```bash
57
- ng e2e
142
+ ## API reference
143
+
144
+ ### HlmSelect / HlmSelectMultiple (directives)
145
+
146
+ Thin wrappers. Forwarded `BrnSelect` / `BrnSelectMultiple` bindings:
147
+
148
+ | Binding | Kind | Description |
149
+ | -------------------- | ------ | ------------------------------------------------------------ |
150
+ | `disabled` | input | Disables the select |
151
+ | `value` | input | Selected value (single) / values (multiple); use `[(value)]` |
152
+ | `isItemEqualToValue` | input | Custom equality fn for object values |
153
+ | `itemToString` | input | Custom label fn for object values |
154
+ | `valueChange` | output | Emits on selection change |
155
+
156
+ Forwarded `BrnPopover` bindings (positioning of the floating panel):
157
+
158
+ | Binding | Kind | Description |
159
+ | ----------------------------- | ------ | ---------------------------------------------------- |
160
+ | `align` | input | Overlay alignment (default from provider: `'start'`) |
161
+ | `sideOffset` | input | Offset px (default from provider: `6`) |
162
+ | `closeOnOutsidePointerEvents` | input | Close on outside pointer down |
163
+ | `state` | input | Controlled open state |
164
+ | `offsetX` | input | Extra X offset |
165
+ | `stateChanged` | output | Emits on open-state change |
166
+ | `closed` | output | Emits when the panel closes |
167
+
168
+ ### HlmSelectTrigger (component, `hlm-select-trigger`)
169
+
170
+ Own inputs (it renders an inner `<button brnSelectTrigger brnFieldControlDescribedBy>`):
171
+
172
+ | Input | Type | Default | Description |
173
+ | --------------------- | ------------------- | ----------------------------- | -------------------------------------------- |
174
+ | `buttonId` | `string` | auto (`hlm-select-trigger-N`) | `id` of the inner button |
175
+ | `ariaDescribedby` | `string \| null` | `null` | `aria-describedby` for the inner button |
176
+ | `wrapperDisabled` | `boolean` | `false` | Renders `disabled` attr on the inner button |
177
+ | `size` | `'default' \| 'sm'` | `'default'` | Height variant (`data-size`; `h-9` vs `h-8`) |
178
+ | `forceInvalid` | `boolean` | `false` | Forces the invalid ring styling |
179
+ | `class` (`userClass`) | `ClassValue` | `''` | Extra classes |
180
+
181
+ Invalid styling keys off `data-[matches-spartan-invalid=true]` (from the form control state) unless `forceInvalid` is set.
182
+
183
+ ### HlmSelectContent (component, `hlm-select-content`)
184
+
185
+ | Input | Type | Default | Description |
186
+ | ------------ | --------- | ------- | -------------------------------------------------------------------------------- |
187
+ | `showScroll` | `boolean` | `false` | Render `hlm-select-scroll-up/down` chevrons around the listbox (boolean-coerced) |
188
+
189
+ Panel width tracks the trigger (`w-(--brn-select-width)`), max height `tw:max-h-72`, with open/close animations.
190
+
191
+ ### HlmSelectItem (component, `hlm-select-item`)
192
+
193
+ Forwarded `BrnSelectItem` inputs: `id`, `disabled`, `value`. Shows a `lucideCheck` icon at the end when its `active` signal is true. `data-disabled` options are non-interactive (`pointer-events-none`, dimmed).
194
+
195
+ ### Remaining pieces
196
+
197
+ | Class | Forwarded inputs | Notes |
198
+ | ------------------------ | -------------------------------------------- | ----------------------------------------------- |
199
+ | `HlmSelectGroup` | — (plain `BrnSelectGroup`) | Padding wrapper |
200
+ | `HlmSelectLabel` | `id` (via `BrnSelectLabel`) | Muted small-caps-ish heading |
201
+ | `HlmSelectValue` | `placeholder` (via `BrnSelectValue`) | Hides itself (`data-hidden`) when a value shows |
202
+ | `HlmSelectValues` | — (plain `BrnSelectValues`) | Multi-value host |
203
+ | `HlmSelectValuesContent` | — | Flex row with gap |
204
+ | `HlmSelectPlaceholder` | — (plain `BrnSelectPlaceholder`) | Hides when a value shows (`data-hidden`) |
205
+ | `HlmSelectSeparator` | `orientation` (via `BrnSelectSeparator`) | 1px divider |
206
+ | `HlmSelectScrollUp/Down` | — | Sticky chevron affordances |
207
+ | `HlmSelectPortal` | `context`, `class` (via `BrnPopoverContent`) | Structural use: `*hlmSelectPortal="let ctx"` |
208
+ | `HlmSelectValueTemplate` | — (plain `BrnSelectValueTemplate`) | Marker for custom value rendering |
209
+
210
+ ## Examples
211
+
212
+ ### 1. Basic single select
213
+
214
+ ```ts
215
+ import { Component, signal } from '@angular/core';
216
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
217
+
218
+ @Component({
219
+ selector: 'app-basic-select',
220
+ standalone: true,
221
+ imports: [HlmSelectImports],
222
+ template: `
223
+ <div hlmSelect [(value)]="fruit">
224
+ <hlm-select-trigger>
225
+ <hlm-select-value placeholder="Pick a fruit" />
226
+ </hlm-select-trigger>
227
+ <hlm-select-content *hlmSelectPortal>
228
+ <hlm-select-item value="apple">Apple</hlm-select-item>
229
+ <hlm-select-item value="banana">Banana</hlm-select-item>
230
+ <hlm-select-item value="orange">Orange</hlm-select-item>
231
+ </hlm-select-content>
232
+ </div>
233
+ <p>Selected: {{ fruit() ?? 'none' }}</p>
234
+ `,
235
+ })
236
+ export class BasicSelectComponent {
237
+ readonly fruit = signal<string | null>(null);
238
+ }
239
+ ```
240
+
241
+ ### 2. Grouped options with labels, separator, disabled item, scroll buttons
242
+
243
+ ```html
244
+ <div hlmSelect [(value)]="city">
245
+ <hlm-select-trigger>
246
+ <hlm-select-value placeholder="Pick a city" />
247
+ </hlm-select-trigger>
248
+
249
+ <hlm-select-content *hlmSelectPortal showScroll>
250
+ <div hlmSelectGroup>
251
+ <div hlmSelectLabel>Germany</div>
252
+ <hlm-select-item value="berlin">Berlin</hlm-select-item>
253
+ <hlm-select-item value="munich">Munich</hlm-select-item>
254
+ </div>
255
+
256
+ <hlm-select-separator />
257
+
258
+ <div hlmSelectGroup>
259
+ <div hlmSelectLabel>France</div>
260
+ <hlm-select-item value="paris">Paris</hlm-select-item>
261
+ <hlm-select-item value="lyon" disabled>Lyon (unavailable)</hlm-select-item>
262
+ </div>
263
+ </hlm-select-content>
264
+ </div>
265
+ ```
266
+
267
+ ### 3. Reactive forms + small trigger + forced invalid demo
268
+
269
+ `BrnSelect` is a `ControlValueAccessor`: bind `formControlName` on the `hlmSelect` host.
270
+
271
+ ```ts
272
+ import { Component } from '@angular/core';
273
+ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
274
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
275
+
276
+ @Component({
277
+ selector: 'app-form-select',
278
+ standalone: true,
279
+ imports: [HlmSelectImports, ReactiveFormsModule],
280
+ template: `
281
+ <form [formGroup]="form" (ngSubmit)="submit()">
282
+ <div hlmSelect formControlName="country">
283
+ <hlm-select-trigger size="sm" ariaDescribedby="country-hint">
284
+ <hlm-select-value placeholder="Country" />
285
+ </hlm-select-trigger>
286
+ <hlm-select-content *hlmSelectPortal>
287
+ <hlm-select-item value="de">Germany</hlm-select-item>
288
+ <hlm-select-item value="fr">France</hlm-select-item>
289
+ <hlm-select-item value="es">Spain</hlm-select-item>
290
+ </hlm-select-content>
291
+ </div>
292
+ <p id="country-hint" class="tw:text-muted-foreground tw:text-xs">Used for shipping.</p>
293
+ <button type="submit">Save</button>
294
+ </form>
295
+ `,
296
+ })
297
+ export class FormSelectComponent {
298
+ readonly form = new FormGroup({
299
+ country: new FormControl<string | null>(null, Validators.required),
300
+ });
301
+
302
+ submit(): void {
303
+ this.form.markAllAsTouched();
304
+ }
305
+ }
306
+ ```
307
+
308
+ ### 4. Multi select with placeholder
309
+
310
+ ```ts
311
+ import { Component, signal } from '@angular/core';
312
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
313
+
314
+ @Component({
315
+ selector: 'app-multi-select',
316
+ standalone: true,
317
+ imports: [HlmSelectImports],
318
+ template: `
319
+ <div hlmSelectMultiple [(value)]="toppings">
320
+ <hlm-select-trigger>
321
+ <span hlmSelectValues>
322
+ <span hlmSelectValuesContent>
323
+ <span hlmSelectValue placeholder="Pick toppings" />
324
+ </span>
325
+ </span>
326
+ </hlm-select-trigger>
327
+ <hlm-select-content *hlmSelectPortal>
328
+ <hlm-select-item value="cheese">Extra cheese</hlm-select-item>
329
+ <hlm-select-item value="bacon">Bacon</hlm-select-item>
330
+ <hlm-select-item value="mushrooms">Mushrooms</hlm-select-item>
331
+ </hlm-select-content>
332
+ </div>
333
+ <p>{{ toppings().length }} selected</p>
334
+ `,
335
+ })
336
+ export class MultiSelectComponent {
337
+ readonly toppings = signal<string[]>([]);
338
+ }
339
+ ```
340
+
341
+ ### 5. Object values with custom equality/labels + disabled select
342
+
343
+ ```ts
344
+ import { Component, signal } from '@angular/core';
345
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
346
+
347
+ interface User {
348
+ id: string;
349
+ name: string;
350
+ }
351
+
352
+ @Component({
353
+ selector: 'app-object-select',
354
+ standalone: true,
355
+ imports: [HlmSelectImports],
356
+ template: `
357
+ <div hlmSelect [(value)]="assignee" [isItemEqualToValue]="byId" [itemToString]="toName" [disabled]="locked()">
358
+ <hlm-select-trigger>
359
+ <hlm-select-value placeholder="Assign to…" />
360
+ </hlm-select-trigger>
361
+ <hlm-select-content *hlmSelectPortal>
362
+ @for (user of users; track user.id) {
363
+ <hlm-select-item [value]="user">{{ user.name }}</hlm-select-item>
364
+ }
365
+ </hlm-select-content>
366
+ </div>
367
+ `,
368
+ })
369
+ export class ObjectSelectComponent {
370
+ readonly users: User[] = [
371
+ { id: 'u1', name: 'Ada' },
372
+ { id: 'u2', name: 'Grace' },
373
+ ];
374
+ readonly assignee = signal<User | null>(null);
375
+ readonly locked = signal(false);
376
+
377
+ readonly byId = (a: User | null, b: User | null) => a?.id === b?.id;
378
+ readonly toName = (u: User | null) => u?.name ?? '';
379
+ }
380
+ ```
381
+
382
+ ### 6. Controlled popover state + custom value template
383
+
384
+ ```ts
385
+ import { Component, signal } from '@angular/core';
386
+ import { HlmSelectImports } from '@egose/shadcn-theme-ng/select';
387
+
388
+ @Component({
389
+ selector: 'app-advanced-select',
390
+ standalone: true,
391
+ imports: [HlmSelectImports],
392
+ template: `
393
+ <button type="button" (click)="open.set(!open())">Toggle from outside</button>
394
+
395
+ <div
396
+ hlmSelect
397
+ [(value)]="plan"
398
+ [state]="open() ? 'open' : 'closed'"
399
+ (stateChanged)="open.set($event === 'open')"
400
+ (closed)="onClosed()"
401
+ >
402
+ <hlm-select-trigger>
403
+ <span hlmSelectValueTemplate>⭐ {{ plan() ?? 'Pick a plan' }}</span>
404
+ </hlm-select-trigger>
405
+ <hlm-select-content *hlmSelectPortal="let ctx">
406
+ <hlm-select-item value="hobby">Hobby</hlm-select-item>
407
+ <hlm-select-item value="pro">Pro</hlm-select-item>
408
+ </hlm-select-content>
409
+ </div>
410
+ `,
411
+ })
412
+ export class AdvancedSelectComponent {
413
+ readonly plan = signal<string | null>(null);
414
+ readonly open = signal(false);
415
+
416
+ onClosed(): void {
417
+ console.log('panel closed');
418
+ }
419
+ }
58
420
  ```
59
421
 
60
- Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
422
+ ## Accessibility notes
423
+
424
+ - The trigger is a native `<button>` with popover/listbox semantics from brain: it announces expanded state and the selected value; keep the `hlm-select-value`/`placeholder` inside the trigger so there is always an accessible name.
425
+ - `hlm-select-content` renders `role="listbox"`; options are keyboard-navigable with type-ahead — do not intercept arrow keys inside the panel.
426
+ - Disabled items (`disabled` on `hlm-select-item`) are skipped by the key manager and dimmed; the whole select can be disabled via `disabled` on the host.
427
+ - Invalid form state surfaces through `data-[matches-spartan-invalid]` on the trigger (ring + border) — pair with a visible error message and `ariaDescribedby` pointing at it.
428
+
429
+ ## Theming / CSS variables
430
+
431
+ Class-driven (popover tokens `--popover`, trigger/input tokens, accent highlight). The panel width follows `--brn-select-width` (measured from the trigger). Override density via `size="sm"` on the trigger or the `class` input on any piece.
61
432
 
62
- ## Additional Resources
433
+ ## Related subpaths
63
434
 
64
- For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
435
+ - `@egose/shadcn-theme-ng/searchable-multiselect` — chip-style multi pick with popover checkboxes
436
+ - `@egose/shadcn-theme-ng/popover` — the underlying floating-panel primitive
437
+ - `@egose/shadcn-theme-ng/form-select` — form-field wrapper (label/description/error) for selects
438
+ - `@egose/shadcn-theme-ng/native-select` — lightweight native `<select>` alternative