@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
@@ -35,10 +35,10 @@ class HlmIcon {
35
35
  }
36
36
  }, /* @ts-ignore */
37
37
  ...(ngDevMode ? [{ debugName: "_computedSize" }] : /* istanbul ignore next */ []));
38
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive });
39
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: HlmIcon, isStandalone: true, selector: "ng-icon[hlm]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ng-icon__size": "_computedSize()" } }, ngImport: i0 });
38
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive });
39
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmIcon, isStandalone: true, selector: "ng-icon[hlm]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--ng-icon__size": "_computedSize()" } }, ngImport: i0 });
40
40
  }
41
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmIcon, decorators: [{
41
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmIcon, decorators: [{
42
42
  type: Directive,
43
43
  args: [{
44
44
  selector: 'ng-icon[hlm]',
@@ -53,11 +53,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
53
53
  */
54
54
  const HlmIconImports = [HlmIcon];
55
55
  class HlmIconModule {
56
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmIconModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
57
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: HlmIconModule, imports: [HlmIcon], exports: [HlmIcon] });
58
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmIconModule });
56
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmIconModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
57
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmIconModule, imports: [HlmIcon], exports: [HlmIcon] });
58
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmIconModule });
59
59
  }
60
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmIconModule, decorators: [{
60
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmIconModule, decorators: [{
61
61
  type: NgModule,
62
62
  args: [{
63
63
  imports: [...HlmIconImports],
@@ -70,4 +70,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
70
70
  */
71
71
 
72
72
  export { HlmIcon, HlmIconImports, HlmIconModule, injectHlmIconConfig, provideHlmIconConfig };
73
- //# sourceMappingURL=icon.mjs.map
73
+
package/input/README.md CHANGED
@@ -1,64 +1,270 @@
1
- # Input
1
+ # Input (`@egose/shadcn-theme-ng/input`)
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.2.0.
3
+ `HlmInput` is a thin styling directive that gives any native `<input>` (or `<textarea>`) the shadcn/ui _Input_ look — the Angular counterpart of shadcn/ui's `<Input />`. Behavior comes from spartan-ng's `BrnInput` (plus field `aria-describedby` propagation); this directive adds the theme classes, `data-slot="input"`, invalid-state rings, and disabled/file styles.
4
4
 
5
- ## Code scaffolding
5
+ > **Ships as:** `@egose/shadcn-theme-ng/input` (plain Tailwind) and `@egose/shadcn-theme-ng-tw/input` (`tw:`-prefixed variant). See the [package README](../../README.md) for installation, peer dependencies, and the Tailwind-variant contract. Do not publish this project directory independently.
6
6
 
7
- Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
7
+ ## Installation
8
8
 
9
9
  ```bash
10
- ng generate component component-name
10
+ # Plain Tailwind (no prefix)
11
+ npm install @egose/shadcn-theme-ng
12
+
13
+ # Or the tw:-prefixed variant
14
+ npm install @egose/shadcn-theme-ng-tw
11
15
  ```
12
16
 
13
- For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
17
+ Peer dependencies (Angular, `@angular/forms`, CDK, `@spartan-ng/brain`, `rxjs`) are documented in the [package README](../../README.md#peer-dependencies).
14
18
 
15
- ```bash
16
- ng generate --help
19
+ ```ts
20
+ import { HlmInputImports } from '@egose/shadcn-theme-ng/input';
21
+ // tw variant:
22
+ // import { HlmInputImports } from '@egose/shadcn-theme-ng-tw/input';
17
23
  ```
18
24
 
19
- ## Building
25
+ ## Imports
20
26
 
21
- To build the library, run:
27
+ ```ts
28
+ // Standalone component — spread the imports array:
29
+ import { HlmInputImports } from '@egose/shadcn-theme-ng/input';
22
30
 
23
- ```bash
24
- ng build input
31
+ @Component({
32
+ standalone: true,
33
+ imports: [ReactiveFormsModule, HlmInputImports],
34
+ template: `<input hlmInput formControlName="email" type="email" />`,
35
+ })
36
+ export class MyComp {}
25
37
  ```
26
38
 
27
- This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
39
+ ```ts
40
+ // NgModule-based — import the module:
41
+ import { HlmInputModule } from '@egose/shadcn-theme-ng/input';
28
42
 
29
- ### Publishing the Library
43
+ @NgModule({ imports: [HlmInputModule] })
44
+ export class MyModule {}
45
+ ```
30
46
 
31
- Once the project is built, you can publish your library by following these steps:
47
+ Exported from `src/public-api.ts`: `HlmInput`, plus `HlmInputImports` and `HlmInputModule`. Import the directive class directly (`import { HlmInput } from '…'`) when you only need the one symbol.
32
48
 
33
- 1. Navigate to the `dist` directory:
49
+ ## Anatomy / Structure
34
50
 
35
- ```bash
36
- cd dist/input
37
- ```
51
+ ```html
52
+ <label for="email">Email</label> <input hlmInput id="email" type="email" placeholder="you@example.com" />
53
+ ```
38
54
 
39
- 2. Run the `npm publish` command to publish your library to the npm registry:
40
- ```bash
41
- npm publish
42
- ```
55
+ The directive matches `input[hlmInput]` usage in practice (selector `[hlmInput]`), sets `data-slot="input"`, binds `[attr.aria-describedby]` from its own input, and composes `BrnInput` (`id`, `forceInvalid`) + `BrnFieldControlDescribedBy` via `hostDirectives`. It is also the class hook reused by `textarea[hlmInput]` (see `form-textarea`) and by `input[hlmInputGroupInput]`.
43
56
 
44
- ## Running unit tests
57
+ ## API reference
45
58
 
46
- To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
59
+ ### `[hlmInput]` — `HlmInput`
47
60
 
48
- ```bash
49
- ng test
61
+ | Input | Type | Default | Description |
62
+ | ----------------- | ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
63
+ | `ariaDescribedby` | `string \| null` | `null` | Bound to `aria-describedby`. Combine with `<hlm-error>`/`<hlm-hint>` ids (the form wrappers do this automatically). |
64
+ | `id` | (via `BrnInput`) | — | Forwarded to the `BrnInput` host directive. |
65
+ | `forceInvalid` | (via `BrnInput`) | — | Forwarded to the `BrnInput` host directive; forces the `data-matches-spartan-invalid` error styles. |
66
+
67
+ No outputs. Visual states are attribute-driven: `data-matches-spartan-invalid=true` switches the border/ring to destructive; `disabled` applies `pointer-events-none`, `cursor-not-allowed`, `opacity-50`. Base geometry: `h-9`, `rounded-md`, `text-base` (`md:text-sm`), full width.
68
+
69
+ ## Examples
70
+
71
+ ### 1. Basic text + reactive form
72
+
73
+ ```ts
74
+ import { Component } from '@angular/core';
75
+ import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
76
+ import { HlmInputImports } from '@egose/shadcn-theme-ng/input';
77
+
78
+ @Component({
79
+ standalone: true,
80
+ imports: [ReactiveFormsModule, HlmInputImports],
81
+ template: `
82
+ <form [formGroup]="form">
83
+ <label for="username">Username</label>
84
+ <input hlmInput id="username" formControlName="username" placeholder="jane_doe" />
85
+ </form>
86
+ `,
87
+ })
88
+ export class BasicExample {
89
+ readonly form = new FormGroup({
90
+ username: new FormControl<string>('', { nonNullable: true }),
91
+ });
92
+ }
50
93
  ```
51
94
 
52
- ## Running end-to-end tests
95
+ ### 2. Template-driven with `ngModel`
53
96
 
54
- For end-to-end (e2e) testing, run:
97
+ ```ts
98
+ import { Component } from '@angular/core';
99
+ import { FormsModule } from '@angular/forms';
100
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
55
101
 
56
- ```bash
57
- ng e2e
102
+ @Component({
103
+ standalone: true,
104
+ imports: [FormsModule, HlmInput],
105
+ template: `
106
+ <label for="nickname">Nickname</label>
107
+ <input hlmInput id="nickname" name="nickname" [(ngModel)]="nickname" placeholder="janey" />
108
+ <p>Hello, {{ nickname || 'stranger' }}!</p>
109
+ `,
110
+ })
111
+ export class NgModelExample {
112
+ nickname = '';
113
+ }
58
114
  ```
59
115
 
60
- Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
116
+ ### 3. Types: email, password, number, search, file
117
+
118
+ ```ts
119
+ import { Component } from '@angular/core';
120
+ import { HlmInputImports } from '@egose/shadcn-theme-ng/input';
121
+
122
+ @Component({
123
+ standalone: true,
124
+ imports: [HlmInputImports],
125
+ template: `
126
+ <div class="tw:grid tw:gap-3">
127
+ <input hlmInput type="email" placeholder="Email" aria-label="Email" autocomplete="email" />
128
+ <input hlmInput type="password" placeholder="Password" aria-label="Password" autocomplete="current-password" />
129
+ <input hlmInput type="number" placeholder="0" aria-label="Amount" min="0" />
130
+ <input hlmInput type="search" placeholder="Search…" aria-label="Search" />
131
+ <input hlmInput type="file" aria-label="Upload avatar" />
132
+ </div>
133
+ `,
134
+ })
135
+ export class TypesExample {}
136
+ ```
137
+
138
+ > File inputs inherit the directive's `file:` styles (sized button text, transparent track) — no extra markup needed.
139
+
140
+ ### 4. Disabled + invalid states
141
+
142
+ ```ts
143
+ import { Component, signal } from '@angular/core';
144
+ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
145
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
146
+
147
+ @Component({
148
+ standalone: true,
149
+ imports: [ReactiveFormsModule, HlmInput],
150
+ template: `
151
+ <form [formGroup]="form">
152
+ <input hlmInput formControlName="email" type="email" placeholder="you@example.com" aria-label="Email" />
153
+ @if (form.controls.email.invalid && form.controls.email.touched) {
154
+ <p class="tw:text-sm tw:text-red-600">Enter a valid email.</p>
155
+ }
156
+ <input hlmInput placeholder="Disabled field" aria-label="Disabled field" [disabled]="true" />
157
+ <!-- force the error ring regardless of touch state -->
158
+ <input hlmInput placeholder="Forced invalid" aria-label="Forced invalid" [forceInvalid]="true" />
159
+ </form>
160
+ `,
161
+ })
162
+ export class StatesExample {
163
+ readonly form = new FormGroup({
164
+ email: new FormControl<string>('', { nonNullable: true, validators: [Validators.email] }),
165
+ });
166
+ }
167
+ ```
168
+
169
+ ### 5. Manual `aria-describedby` with hint + error (no form wrapper)
170
+
171
+ ```ts
172
+ import { Component } from '@angular/core';
173
+ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
174
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
175
+ import { HlmError, HlmHint } from '@egose/shadcn-theme-ng/form-field';
176
+
177
+ @Component({
178
+ standalone: true,
179
+ imports: [ReactiveFormsModule, HlmInput, HlmError, HlmHint],
180
+ template: `
181
+ <form [formGroup]="form">
182
+ <label for="handle">Handle</label>
183
+ <input
184
+ hlmInput
185
+ id="handle"
186
+ formControlName="handle"
187
+ placeholder="@jane"
188
+ [ariaDescribedby]="describedBy()"
189
+ />
190
+ @if (showError()) {
191
+ <hlm-error id="handle-error">Use 3+ lowercase letters.</hlm-error>
192
+ } @else {
193
+ <hlm-hint id="handle-hint">Your public @name.</hlm-hint>
194
+ }
195
+ </form>
196
+ `,
197
+ })
198
+ export class DescribedByExample {
199
+ readonly form = new FormGroup({
200
+ handle: new FormControl<string>('', {
201
+ nonNullable: true,
202
+ validators: [Validators.minLength(3), Validators.pattern(/^[a-z]+$/)],
203
+ }),
204
+ });
205
+
206
+ showError(): boolean {
207
+ const c = this.form.controls.handle;
208
+ return c.invalid && (c.dirty || c.touched);
209
+ }
210
+
211
+ describedBy(): string {
212
+ return this.showError() ? 'handle-error' : 'handle-hint';
213
+ }
214
+ }
215
+ ```
216
+
217
+ ### 6. Composition: search row with button (input + button)
218
+
219
+ ```ts
220
+ import { Component, signal } from '@angular/core';
221
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
222
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
223
+
224
+ @Component({
225
+ standalone: true,
226
+ imports: [HlmInput, HlmButton],
227
+ template: `
228
+ <div class="tw:flex tw:gap-2">
229
+ <input
230
+ hlmInput
231
+ aria-label="Search docs"
232
+ placeholder="Search docs…"
233
+ [value]="query()"
234
+ (input)="query.set($any($event.target).value)"
235
+ (keydown.enter)="search()"
236
+ />
237
+ <button hlmBtn type="button" (click)="search()">Search</button>
238
+ </div>
239
+ @if (searched()) {
240
+ <p role="status" class="tw:text-sm">Searching for “{{ query() }}”…</p>
241
+ }
242
+ `,
243
+ })
244
+ export class SearchRowExample {
245
+ readonly query = signal('');
246
+ readonly searched = signal(false);
247
+
248
+ search() {
249
+ this.searched.set(true);
250
+ }
251
+ }
252
+ ```
253
+
254
+ ## Accessibility notes
255
+
256
+ - Always pair the input with a `<label for>` (or `aria-label`/`aria-labelledby` when the design is label-less). The directive does not generate labels.
257
+ - Wire `ariaDescribedby` to hint/error ids so screen readers announce help and validation together with the field. The `eg-form-*` wrappers automate this — copy their pattern when hand-rolling.
258
+ - Invalid styling is visual only until you expose the message text (e.g. `<hlm-error>` or `role="alert"`); use `forceInvalid` sparingly and only alongside a message.
259
+ - Keep native semantics: correct `type`, `autocomplete`, `required`, and `disabled` (not `aria-disabled` + click-guard) so AT and password managers behave.
260
+
261
+ ## Theming / CSS variables
262
+
263
+ No component-specific CSS variables; colors/spacing come from the shared theme tokens (`--input`, `--ring`, `--destructive`, `--radius`, …). Taller fields: add `tw:h-11`; monospace/code looks: add `tw:font-mono`.
61
264
 
62
- ## Additional Resources
265
+ ## Related subpaths
63
266
 
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.
267
+ - `@egose/shadcn-theme-ng/form-text-input` — labeled + validated reactive-forms wrapper (prefer for forms).
268
+ - `@egose/shadcn-theme-ng/form-textarea` — multiline sibling reusing the same class hook.
269
+ - `@egose/shadcn-theme-ng/input-group` — joined prefix/input/suffix compositions.
270
+ - `@egose/shadcn-theme-ng/label` — `HlmLabel` for the `<label>` side.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, NgModule } from '@angular/core';
2
+ import { input, Directive, NgModule } from '@angular/core';
3
3
  import * as i2 from '@spartan-ng/brain/field';
4
4
  import { BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
5
5
  import * as i1 from '@spartan-ng/brain/input';
@@ -7,31 +7,36 @@ import { BrnInput } from '@spartan-ng/brain/input';
7
7
  import { classes } from '@egose/shadcn-theme-ng-tw/utils';
8
8
 
9
9
  class HlmInput {
10
+ ariaDescribedby = input(null, /* @ts-ignore */
11
+ ...(ngDevMode ? [{ debugName: "ariaDescribedby" }] : /* istanbul ignore next */ []));
10
12
  constructor() {
11
- classes(() => 'dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 data-[matches-spartan-invalid=true]:ring-destructive/20 dark:data-[matches-spartan-invalid=true]:ring-destructive/40 data-[matches-spartan-invalid=true]:border-destructive dark:data-[matches-spartan-invalid=true]:border-destructive/50 h-9 rounded-md border bg-transparent px-2.5 py-1 text-base shadow-xs transition-[color,box-shadow] file:h-7 file:text-sm file:font-medium focus-visible:ring-3 data-[matches-spartan-invalid=true]:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50');
13
+ classes(() => 'tw:dark:bg-input/30 tw:border-input tw:focus-visible:border-ring tw:focus-visible:ring-ring/50 tw:data-[matches-spartan-invalid=true]:ring-destructive/20 tw:dark:data-[matches-spartan-invalid=true]:ring-destructive/40 tw:data-[matches-spartan-invalid=true]:border-destructive tw:dark:data-[matches-spartan-invalid=true]:border-destructive/50 tw:h-9 tw:rounded-md tw:border tw:bg-transparent tw:px-2.5 tw:py-1 tw:text-base tw:shadow-xs tw:transition-[color,box-shadow] tw:file:h-7 tw:file:text-sm tw:file:font-medium tw:focus-visible:ring-3 tw:data-[matches-spartan-invalid=true]:ring-3 tw:md:text-sm tw:file:text-foreground tw:placeholder:text-muted-foreground tw:w-full tw:min-w-0 tw:outline-none tw:file:inline-flex tw:file:border-0 tw:file:bg-transparent tw:disabled:pointer-events-none tw:disabled:cursor-not-allowed tw:disabled:opacity-50');
12
14
  }
13
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
14
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmInput, isStandalone: true, selector: "[hlmInput]", host: { attributes: { "data-slot": "input" } }, hostDirectives: [{ directive: i1.BrnInput, inputs: ["id", "id", "forceInvalid", "forceInvalid"] }, { directive: i2.BrnFieldControlDescribedBy }], ngImport: i0 });
15
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
16
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmInput, isStandalone: true, selector: "[hlmInput]", inputs: { ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "input" }, properties: { "attr.aria-describedby": "ariaDescribedby()" } }, hostDirectives: [{ directive: i1.BrnInput, inputs: ["id", "id", "forceInvalid", "forceInvalid"] }, { directive: i2.BrnFieldControlDescribedBy }], ngImport: i0 });
15
17
  }
16
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmInput, decorators: [{
18
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInput, decorators: [{
17
19
  type: Directive,
18
20
  args: [{
19
21
  selector: '[hlmInput]',
20
22
  hostDirectives: [{ directive: BrnInput, inputs: ['id', 'forceInvalid'] }, BrnFieldControlDescribedBy],
21
- host: { 'data-slot': 'input' },
23
+ host: {
24
+ 'data-slot': 'input',
25
+ '[attr.aria-describedby]': 'ariaDescribedby()',
26
+ },
22
27
  }]
23
- }], ctorParameters: () => [] });
28
+ }], ctorParameters: () => [], propDecorators: { ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }] } });
24
29
 
25
30
  /*
26
31
  * Public API Surface of input
27
32
  */
28
33
  const HlmInputImports = [HlmInput];
29
34
  class HlmInputModule {
30
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmInputModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
31
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: HlmInputModule, imports: [HlmInput], exports: [HlmInput] });
32
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmInputModule });
35
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInputModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
36
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmInputModule, imports: [HlmInput], exports: [HlmInput] });
37
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInputModule });
33
38
  }
34
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmInputModule, decorators: [{
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInputModule, decorators: [{
35
40
  type: NgModule,
36
41
  args: [{
37
42
  imports: [...HlmInputImports],
@@ -44,4 +49,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
44
49
  */
45
50
 
46
51
  export { HlmInput, HlmInputImports, HlmInputModule };
47
- //# sourceMappingURL=input.mjs.map
52
+
@@ -3,9 +3,10 @@ import * as i1 from '@spartan-ng/brain/input';
3
3
  import * as i2 from '@spartan-ng/brain/field';
4
4
 
5
5
  declare class HlmInput {
6
+ readonly ariaDescribedby: i0.InputSignal<string | null>;
6
7
  constructor();
7
8
  static ɵfac: i0.ɵɵFactoryDeclaration<HlmInput, never>;
8
- static ɵdir: i0.ɵɵDirectiveDeclaration<HlmInput, "[hlmInput]", never, {}, {}, never, never, true, [{ directive: typeof i1.BrnInput; inputs: { "id": "id"; "forceInvalid": "forceInvalid"; }; outputs: {}; }, { directive: typeof i2.BrnFieldControlDescribedBy; inputs: {}; outputs: {}; }]>;
9
+ static ɵdir: i0.ɵɵDirectiveDeclaration<HlmInput, "[hlmInput]", never, { "ariaDescribedby": { "alias": "ariaDescribedby"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.BrnInput; inputs: { "id": "id"; "forceInvalid": "forceInvalid"; }; outputs: {}; }, { directive: typeof i2.BrnFieldControlDescribedBy; inputs: {}; outputs: {}; }]>;
9
10
  }
10
11
 
11
12
  declare const HlmInputImports: readonly [typeof HlmInput];