@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/field/README.md CHANGED
@@ -1,11 +1,391 @@
1
- # Field
1
+ # Field (`@egose/shadcn-theme-ng/field`)
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli).
3
+ The shadcn/ui Field layout system for Angular: composable label / title / description / error / content wrappers, groups, fieldsets, legends, and separators for building accessible forms — including card-style selectable rows. Equivalent to shadcn/ui `Field`.
4
4
 
5
- ## Building
5
+ The Angular implementation layers shadcn classes over headless
6
+ [`BrnField` / `BrnFieldA11yService` from `@spartan-ng/brain/field`](https://www.spartan-ng.com/):
7
+ `HlmField` hosts `BrnField` (validation state), `HlmFieldDescription` / `HlmFieldError` register
8
+ `aria-describedby` ids with the a11y service, and `HlmFieldLabel` composes `HlmLabel`. Pure-layout
9
+ pieces (content, group, set, separator, title) carry no behavior.
6
10
 
7
- To build the library, run:
11
+ > **Ships as:** `@egose/shadcn-theme-ng/field` and `@egose/shadcn-theme-ng-tw/field`
12
+ > (the `tw:`-prefixed Tailwind variant). Both expose the identical TypeScript surface; only the
13
+ > emitted Tailwind class strings differ. See the [package README](../../README.md) for install
14
+ > steps, peer dependencies, and Tailwind setup. Do not publish this project directory independently.
15
+
16
+ ## Installation
8
17
 
9
18
  ```bash
10
- ng build field
19
+ # Plain Tailwind (no prefix)
20
+ npm install @egose/shadcn-theme-ng
21
+
22
+ # tw:-prefixed Tailwind variant
23
+ npm install @egose/shadcn-theme-ng-tw
24
+ ```
25
+
26
+ Peer dependencies (Angular, `@spartan-ng/brain`, `@ng-icons/*`, `rxjs`, …) are documented in the
27
+ [package README](../../README.md#peer-dependencies). This subpath additionally relies at runtime on
28
+ `@egose/shadcn-theme-ng/label`, `@egose/shadcn-theme-ng/separator`, and
29
+ `@egose/shadcn-theme-ng/utils`.
30
+
31
+ ## Imports
32
+
33
+ All symbols are exported from the subpath root (`projects/field/src/public-api.ts`):
34
+
35
+ ```ts
36
+ import {
37
+ HlmField,
38
+ HlmFieldLabel,
39
+ HlmFieldTitle,
40
+ HlmFieldDescription,
41
+ HlmFieldError,
42
+ HlmFieldContent,
43
+ HlmFieldGroup,
44
+ HlmFieldSet,
45
+ HlmFieldLegend,
46
+ HlmFieldSeparator,
47
+ HlmFieldImports,
48
+ HlmFieldModule,
49
+ } from '@egose/shadcn-theme-ng/field';
50
+ // tw variant: replace with '@egose/shadcn-theme-ng-tw/field'
51
+ ```
52
+
53
+ Standalone component — spread the `*Imports` array:
54
+
55
+ ```ts
56
+ import { Component } from '@angular/core';
57
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
58
+
59
+ @Component({
60
+ selector: 'app-demo',
61
+ standalone: true,
62
+ imports: [...HlmFieldImports],
63
+ template: `...`,
64
+ })
65
+ export class DemoComponent {}
66
+ ```
67
+
68
+ NgModule-based consumer — import the module:
69
+
70
+ ```ts
71
+ import { NgModule } from '@angular/core';
72
+ import { HlmFieldModule } from '@egose/shadcn-theme-ng/field';
73
+
74
+ @NgModule({ imports: [HlmFieldModule] })
75
+ export class DemoModule {}
76
+ ```
77
+
78
+ ## Anatomy / Structure
79
+
80
+ ```html
81
+ <div hlmFieldGroup>
82
+ <div hlmField>
83
+ <label hlmFieldLabel for="name">Name</label>
84
+ <div hlmFieldContent>
85
+ <input hlmInput id="name" placeholder="Ada Lovelace" />
86
+ <p hlmFieldDescription>Your public display name.</p>
87
+ <hlm-field-error validator="required">Name is required.</hlm-field-error>
88
+ </div>
89
+ </div>
90
+
91
+ <hlm-field-separator>or continue with</hlm-field-separator>
92
+
93
+ <fieldset hlmFieldSet>
94
+ <legend hlmFieldLegend>Notifications</legend>
95
+ <div hlmField orientation="horizontal">
96
+ <div hlmFieldContent>
97
+ <span hlmFieldTitle>Email alerts</span>
98
+ <p hlmFieldDescription>Get emailed on mentions.</p>
99
+ </div>
100
+ <hlm-switch />
101
+ </div>
102
+ </fieldset>
103
+ </div>
104
+ ```
105
+
106
+ Real selectors (from source):
107
+
108
+ | Class | Selector(s) | Kind |
109
+ | --------------------- | ---------------------------------------------- | ------------------------------------- |
110
+ | `HlmField` | `[hlmField], hlm-field` | Directive (hosts `BrnField`) |
111
+ | `HlmFieldLabel` | `[hlmFieldLabel], hlm-field-label` | Directive (hosts `HlmLabel`) |
112
+ | `HlmFieldTitle` | `[hlmFieldTitle], hlm-field-title` | Directive (`data-slot="field-label"`) |
113
+ | `HlmFieldDescription` | `[hlmFieldDescription], hlm-field-description` | Directive |
114
+ | `HlmFieldError` | `hlm-field-error` | Component (element only) |
115
+ | `HlmFieldContent` | `[hlmFieldContent], hlm-field-content` | Directive |
116
+ | `HlmFieldGroup` | `[hlmFieldGroup], hlm-field-group` | Directive |
117
+ | `HlmFieldSet` | `fieldset[hlmFieldSet]` | Directive (fieldset only) |
118
+ | `HlmFieldLegend` | `legend[hlmFieldLegend]` | Directive (legend only) |
119
+ | `HlmFieldSeparator` | `hlm-field-separator` | Component (element only) |
120
+
121
+ ## API reference
122
+
123
+ ### `HlmField` — `[hlmField], hlm-field`
124
+
125
+ Field row. Hosts `BrnField` (`role="group"`, `data-slot="field"`, `data-orientation`).
126
+
127
+ | Input | Type | Default | Description |
128
+ | ------------------------------- | -------------------------------------------- | ------------ | ---------------------------------------------------------------------------- |
129
+ | `orientation` | `'vertical' \| 'horizontal' \| 'responsive'` | `'vertical'` | Row layout; `responsive` stacks on small screens (`@container/field-group`). |
130
+ | `data-invalid` / `forceInvalid` | forwarded to `BrnField` | — | Manual invalid-state control. |
131
+
132
+ ### `HlmFieldLabel` — `[hlmFieldLabel], hlm-field-label`
133
+
134
+ Label for a control. Hosts `HlmLabel` (all label inputs forwarded). Card-style when wrapping a nested `[data-slot=field]`. No new inputs.
135
+
136
+ ### `HlmFieldTitle` — `[hlmFieldTitle], hlm-field-title`
137
+
138
+ Non-`<label>` title (used beside switches/checkboxes inside `hlmFieldContent`). No inputs. Note: its `data-slot` is `field-label`, not `field-title`.
139
+
140
+ ### `HlmFieldDescription` — `[hlmFieldDescription], hlm-field-description`
141
+
142
+ Hint text. Registers its id with `BrnFieldA11yService` so controls pick it up via `aria-describedby`.
143
+
144
+ | Input | Type | Default | Description |
145
+ | ----- | -------- | --------------------------- | ----------------------- |
146
+ | `id` | `string` | `hlm-field-description-<n>` | Description element id. |
147
+
148
+ ### `HlmFieldError` — `hlm-field-error`
149
+
150
+ Error message (`role="alert"`, hidden until it should display). Reads validation state from the parent `BrnField`; registers with the a11y service only while visible.
151
+
152
+ | Input | Type | Default | Description |
153
+ | ----------- | --------- | --------------------- | -------------------------------------------------------------------------------------------- |
154
+ | `id` | `string` | `hlm-field-error-<n>` | Error element id. |
155
+ | `validator` | `string` | — | Show only when this validator key (e.g. `'required'`) is present; omit to show on any error. |
156
+ | `forceShow` | `boolean` | `false` | Show regardless of control state. |
157
+
158
+ Without a parent field it always displays (useful for static demos).
159
+
160
+ ### `HlmFieldContent` — `[hlmFieldContent], hlm-field-content`
161
+
162
+ Flex column for control + description + errors. No inputs.
163
+
164
+ ### `HlmFieldGroup` — `[hlmFieldGroup], hlm-field-group`
165
+
166
+ Vertical stack of fields (`gap-7`, container-query scope for `responsive` fields). No inputs.
167
+
168
+ ### `HlmFieldSet` — `fieldset[hlmFieldSet]` / `HlmFieldLegend` — `legend[hlmFieldLegend]`
169
+
170
+ Native grouping elements with shadcn spacing. Legend only:
171
+
172
+ | Input | Type | Default | Description |
173
+ | --------- | --------------------- | ---------- | ------------------------------------- |
174
+ | `variant` | `'label' \| 'legend'` | `'legend'` | Text size (`text-sm` vs `text-base`). |
175
+
176
+ ### `HlmFieldSeparator` — `hlm-field-separator`
177
+
178
+ Centered labelled divider (hosts `hlm-separator` + centered text span). Content is the label text. No inputs.
179
+
180
+ ## Examples
181
+
182
+ ### 1. Basic labelled field with hint + error
183
+
184
+ ```ts
185
+ import { Component, inject } from '@angular/core';
186
+ import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
187
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
188
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
189
+
190
+ @Component({
191
+ selector: 'app-basic-field',
192
+ standalone: true,
193
+ imports: [ReactiveFormsModule, HlmInput, ...HlmFieldImports],
194
+ template: `
195
+ <div hlmFieldGroup [formGroup]="form">
196
+ <div hlmField>
197
+ <label hlmFieldLabel for="username">Username</label>
198
+ <div hlmFieldContent>
199
+ <input hlmInput id="username" formControlName="username" placeholder="ada" />
200
+ <p hlmFieldDescription>Letters and numbers only.</p>
201
+ <hlm-field-error validator="required">Username is required.</hlm-field-error>
202
+ </div>
203
+ </div>
204
+ </div>
205
+ `,
206
+ })
207
+ export class BasicFieldComponent {
208
+ private readonly fb = inject(FormBuilder);
209
+ readonly form = this.fb.group({ username: ['', Validators.required] });
210
+ }
211
+ ```
212
+
213
+ > Note: `hlmField` hosts `BrnField`; controls that implement `BrnFieldControl` feed its error state.
214
+ > Plain `hlmInput` + reactive forms drive `hlm-field-error` through the parent field where supported;
215
+ > for guaranteed wiring use `hlm-form-field` or a brain field control.
216
+
217
+ ### 2. Horizontal switch row
218
+
219
+ ```ts
220
+ import { Component, signal } from '@angular/core';
221
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
222
+ import { HlmSwitchImports } from '@egose/shadcn-theme-ng/switch';
223
+
224
+ @Component({
225
+ selector: 'app-switch-row',
226
+ standalone: true,
227
+ imports: [...HlmFieldImports, ...HlmSwitchImports],
228
+ template: `
229
+ <div hlmField orientation="horizontal">
230
+ <div hlmFieldContent>
231
+ <span hlmFieldTitle>Email notifications</span>
232
+ <p hlmFieldDescription>Receive an email on every mention.</p>
233
+ </div>
234
+ <hlm-switch [checked]="on()" (checkedChange)="on.set($event)" />
235
+ </div>
236
+ `,
237
+ })
238
+ export class SwitchRowComponent {
239
+ readonly on = signal(true);
240
+ }
11
241
  ```
242
+
243
+ ### 3. Fieldset + legend + responsive rows
244
+
245
+ ```ts
246
+ import { Component } from '@angular/core';
247
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
248
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
249
+
250
+ @Component({
251
+ selector: 'app-fieldset',
252
+ standalone: true,
253
+ imports: [...HlmFieldImports, HlmInput],
254
+ template: `
255
+ <fieldset hlmFieldSet>
256
+ <legend hlmFieldLegend>Profile</legend>
257
+ <div hlmField orientation="responsive">
258
+ <label hlmFieldLabel for="first">First name</label>
259
+ <div hlmFieldContent>
260
+ <input hlmInput id="first" placeholder="Ada" />
261
+ </div>
262
+ </div>
263
+ <div hlmField orientation="responsive">
264
+ <label hlmFieldLabel for="last">Last name</label>
265
+ <div hlmFieldContent>
266
+ <input hlmInput id="last" placeholder="Lovelace" />
267
+ </div>
268
+ </div>
269
+ </fieldset>
270
+ `,
271
+ })
272
+ export class FieldsetComponent {}
273
+ ```
274
+
275
+ ### 4. Selectable card rows (label wrapping a field)
276
+
277
+ ```ts
278
+ import { Component, signal } from '@angular/core';
279
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
280
+ import { HlmRadioGroupImports } from '@egose/shadcn-theme-ng/radio-group';
281
+
282
+ @Component({
283
+ selector: 'app-plan-cards',
284
+ standalone: true,
285
+ imports: [...HlmFieldImports, ...HlmRadioGroupImports],
286
+ template: `
287
+ <div hlmFieldGroup data-slot="checkbox-group">
288
+ @for (plan of plans; track plan) {
289
+ <label hlmFieldLabel>
290
+ <input
291
+ type="radio"
292
+ name="plan"
293
+ [value]="plan"
294
+ [checked]="selected() === plan"
295
+ (change)="selected.set(plan)"
296
+ />
297
+ <div hlmFieldContent>
298
+ <span hlmFieldTitle>{{ plan }}</span>
299
+ <p hlmFieldDescription>{{ plan }} billing, cancel anytime.</p>
300
+ </div>
301
+ </label>
302
+ }
303
+ </div>
304
+ `,
305
+ })
306
+ export class PlanCardsComponent {
307
+ readonly plans = ['Monthly', 'Yearly'];
308
+ readonly selected = signal('Monthly');
309
+ }
310
+ ```
311
+
312
+ ### 5. Separator between groups + per-validator errors
313
+
314
+ ```ts
315
+ import { Component, inject } from '@angular/core';
316
+ import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
317
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
318
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
319
+
320
+ @Component({
321
+ selector: 'app-validators',
322
+ standalone: true,
323
+ imports: [ReactiveFormsModule, HlmInput, ...HlmFieldImports],
324
+ template: `
325
+ <div hlmFieldGroup [formGroup]="form">
326
+ <div hlmField>
327
+ <label hlmFieldLabel for="email">Email</label>
328
+ <div hlmFieldContent>
329
+ <input hlmInput id="email" formControlName="email" type="email" />
330
+ <hlm-field-error validator="required">Email is required.</hlm-field-error>
331
+ <hlm-field-error validator="email">Enter a valid email address.</hlm-field-error>
332
+ </div>
333
+ </div>
334
+ <hlm-field-separator>or continue with</hlm-field-separator>
335
+ <div hlmField>
336
+ <label hlmFieldLabel for="phone">Phone (optional)</label>
337
+ <div hlmFieldContent>
338
+ <input hlmInput id="phone" formControlName="phone" />
339
+ <p hlmFieldDescription>We'll only call about your order.</p>
340
+ </div>
341
+ </div>
342
+ </div>
343
+ `,
344
+ })
345
+ export class ValidatorsComponent {
346
+ private readonly fb = inject(FormBuilder);
347
+ readonly form = this.fb.group({ email: ['', [Validators.required, Validators.email]], phone: [''] });
348
+ }
349
+ ```
350
+
351
+ ### 6. Forced error preview (docs / visual testing)
352
+
353
+ ```ts
354
+ import { Component } from '@angular/core';
355
+ import { HlmFieldImports } from '@egose/shadcn-theme-ng/field';
356
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
357
+
358
+ @Component({
359
+ selector: 'app-forced-error',
360
+ standalone: true,
361
+ imports: [...HlmFieldImports, HlmInput],
362
+ template: `
363
+ <div hlmField forceInvalid>
364
+ <label hlmFieldLabel for="demo">API key</label>
365
+ <div hlmFieldContent>
366
+ <input hlmInput id="demo" value="sk-…" />
367
+ <hlm-field-error forceShow>This key has been revoked.</hlm-field-error>
368
+ </div>
369
+ </div>
370
+ `,
371
+ })
372
+ export class ForcedErrorComponent {}
373
+ ```
374
+
375
+ ## Accessibility notes
376
+
377
+ - `HlmField` sets `role="group"`; always give the group an accessible name via `HlmFieldLabel` / `HlmFieldTitle` / `legend`.
378
+ - Descriptions and visible errors are registered with `BrnFieldA11yService` and referenced from controls via `aria-describedby`; keep ids unique (defaults auto-increment).
379
+ - Errors use `role="alert"` and only render when the parent field reports a matching validation error — screen readers announce them on appearance.
380
+ - Native `fieldset` + `legend` remain the most robust grouping for related controls; prefer `hlmFieldSet` for notification groups and radio sets.
381
+
382
+ ## Theming / CSS variables
383
+
384
+ No component-specific CSS variables. Orientation, invalid color (`text-destructive` on `data-matches-spartan-invalid`), and spacing derive from `fieldVariants` cva + global tokens. Extend with `class` on any directive.
385
+
386
+ ## Related subpaths
387
+
388
+ - `@egose/shadcn-theme-ng/form-field` — `hlm-form-field` reactive-form wrapper with automatic hint/error switching.
389
+ - `@egose/shadcn-theme-ng/label` — `HlmLabel` hosted by `HlmFieldLabel`.
390
+ - `@egose/shadcn-theme-ng/separator` — `HlmSeparator` rendered inside `hlm-field-separator`.
391
+ - `@egose/shadcn-theme-ng/field` pairs with `@egose/shadcn-theme-ng/checkbox`, `.../radio-group`, `.../switch` for selectable rows.