@egose/shadcn-theme-ng 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.
- package/README.md +130 -13
- package/accordion/README.md +376 -34
- package/accordion/fesm2022/accordion.mjs +27 -39
- package/alert/README.md +343 -34
- package/alert/fesm2022/alert.mjs +47 -47
- package/alert-dialog/README.md +471 -5
- package/alert-dialog/fesm2022/alert-dialog.mjs +47 -47
- package/aspect-ratio/README.md +272 -5
- package/aspect-ratio/fesm2022/aspect-ratio.mjs +9 -9
- package/autocomplete/README.md +473 -34
- package/autocomplete/fesm2022/autocomplete.mjs +53 -71
- package/avatar/README.md +357 -5
- package/avatar/fesm2022/avatar.mjs +32 -32
- package/badge/README.md +289 -34
- package/badge/fesm2022/badge.mjs +57 -57
- package/basic-alert/README.md +324 -34
- package/basic-alert/fesm2022/basic-alert.mjs +6 -18
- package/breadcrumb/README.md +406 -5
- package/breadcrumb/fesm2022/breadcrumb.mjs +33 -39
- package/button/README.md +453 -34
- package/button/fesm2022/button.mjs +147 -219
- package/button/types/button.d.ts +7 -10
- package/button-group/README.md +318 -5
- package/button-group/fesm2022/button-group.mjs +20 -20
- package/calendar/README.md +328 -34
- package/calendar/fesm2022/calendar.mjs +29 -743
- package/card/README.md +331 -5
- package/card/fesm2022/card.mjs +33 -33
- package/carousel/README.md +333 -5
- package/carousel/fesm2022/carousel.mjs +39 -78
- package/checkbox/README.md +291 -34
- package/checkbox/fesm2022/checkbox.mjs +20 -58
- package/checkbox/types/checkbox.d.ts +5 -4
- package/collapsible/README.md +332 -5
- package/collapsible/fesm2022/collapsible.mjs +15 -15
- package/combobox/README.md +507 -5
- package/combobox/fesm2022/combobox.mjs +91 -224
- package/command/README.md +435 -5
- package/command/fesm2022/command.mjs +49 -109
- package/confirmation-dialog/README.md +272 -34
- package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +15 -40
- package/confirmation-dialog/types/confirmation-dialog.d.ts +8 -4
- package/context-menu/README.md +366 -5
- package/context-menu/fesm2022/context-menu.mjs +9 -9
- package/date-picker/README.md +436 -34
- package/date-picker/fesm2022/date-picker.mjs +64 -267
- package/date-picker/types/date-picker.d.ts +7 -3
- package/dialog/README.md +419 -34
- package/dialog/fesm2022/dialog.mjs +45 -71
- package/drawer/README.md +395 -5
- package/drawer/fesm2022/drawer.mjs +44 -54
- package/dropdown-menu/README.md +417 -5
- package/dropdown-menu/fesm2022/dropdown-menu.mjs +82 -70
- package/dropdown-menu/types/dropdown-menu.d.ts +4 -0
- package/empty/README.md +329 -5
- package/empty/fesm2022/empty.mjs +30 -30
- package/field/README.md +385 -5
- package/field/fesm2022/field.mjs +56 -72
- package/form-checkbox/README.md +283 -34
- package/form-checkbox/fesm2022/form-checkbox.mjs +25 -85
- package/form-checkbox/types/form-checkbox.d.ts +7 -1
- package/form-date-picker/README.md +293 -34
- package/form-date-picker/fesm2022/form-date-picker.mjs +31 -84
- package/form-date-picker/types/form-date-picker.d.ts +7 -1
- package/form-field/README.md +327 -34
- package/form-field/fesm2022/form-field.mjs +33 -19
- package/form-field/types/form-field.d.ts +28 -20
- package/form-field-simple/README.md +311 -34
- package/form-field-simple/fesm2022/form-field-simple.mjs +4 -4
- package/form-searchable-multiselect/README.md +332 -34
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +31 -91
- package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +7 -1
- package/form-select/README.md +321 -34
- package/form-select/fesm2022/form-select.mjs +32 -149
- package/form-select/types/form-select.d.ts +7 -1
- package/form-text-input/README.md +342 -34
- package/form-text-input/fesm2022/form-text-input.mjs +35 -149
- package/form-text-input/types/form-text-input.d.ts +9 -12
- package/form-textarea/README.md +318 -34
- package/form-textarea/fesm2022/form-textarea.mjs +34 -109
- package/form-textarea/types/form-textarea.d.ts +8 -1
- package/hover-card/README.md +256 -5
- package/hover-card/fesm2022/hover-card.mjs +19 -19
- package/icon/README.md +210 -34
- package/icon/fesm2022/icon.mjs +8 -8
- package/input/README.md +240 -34
- package/input/fesm2022/input.mjs +17 -12
- package/input/types/input.d.ts +2 -1
- package/input-group/README.md +335 -5
- package/input-group/fesm2022/input-group.mjs +34 -34
- package/input-otp/README.md +375 -5
- package/input-otp/fesm2022/input-otp.mjs +26 -26
- package/item/README.md +385 -5
- package/item/fesm2022/item.mjs +53 -53
- package/kbd/README.md +291 -5
- package/kbd/fesm2022/kbd.mjs +12 -12
- package/label/README.md +243 -34
- package/label/fesm2022/label.mjs +10 -10
- package/label/types/label.d.ts +1 -1
- package/layout-simple/README.md +174 -44
- package/layout-simple/fesm2022/layout-simple.mjs +508 -603
- package/layout-simple/types/layout-simple.d.ts +179 -128
- package/menu/README.md +418 -0
- package/menu/fesm2022/menu.mjs +455 -0
- package/menu/package.json +24 -0
- package/menu/types/menu.d.ts +137 -0
- package/menubar/README.md +343 -5
- package/menubar/fesm2022/menubar.mjs +13 -13
- package/native-select/README.md +323 -5
- package/native-select/fesm2022/native-select.mjs +19 -19
- package/navigation-menu/README.md +369 -5
- package/navigation-menu/fesm2022/navigation-menu.mjs +35 -47
- package/package.json +183 -154
- package/pagination/README.md +388 -5
- package/pagination/fesm2022/pagination.mjs +45 -331
- package/popover/README.md +302 -34
- package/popover/fesm2022/popover.mjs +30 -30
- package/progress/README.md +311 -5
- package/progress/fesm2022/progress.mjs +13 -13
- package/radio-group/README.md +335 -34
- package/radio-group/fesm2022/radio-group.mjs +26 -19
- package/radio-group/types/radio-group.d.ts +1 -1
- package/resizable/README.md +269 -5
- package/resizable/fesm2022/resizable.mjs +18 -26
- package/scroll-area/README.md +233 -5
- package/scroll-area/fesm2022/scroll-area.mjs +9 -9
- package/searchable-multiselect/README.md +294 -34
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +28 -117
- package/searchable-multiselect/types/searchable-multiselect.d.ts +8 -2
- package/select/README.md +408 -34
- package/select/fesm2022/select.mjs +71 -111
- package/select/types/select.d.ts +3 -1
- package/separator/README.md +193 -34
- package/separator/fesm2022/separator.mjs +9 -9
- package/separator/types/separator.d.ts +1 -1
- package/sheet/README.md +282 -34
- package/sheet/fesm2022/sheet.mjs +41 -53
- package/sidebar/README.md +457 -5
- package/sidebar/fesm2022/sidebar.mjs +125 -227
- package/skeleton/README.md +217 -5
- package/skeleton/fesm2022/skeleton.mjs +9 -9
- package/slider/README.md +273 -5
- package/slider/fesm2022/slider.mjs +10 -80
- package/sonner/README.md +317 -34
- package/sonner/fesm2022/sonner.mjs +13 -13
- package/spinner/README.md +255 -34
- package/spinner/fesm2022/spinner.mjs +11 -11
- package/switch/README.md +281 -34
- package/switch/fesm2022/switch.mjs +13 -15
- package/table/README.md +423 -5
- package/table/fesm2022/table.mjs +41 -41
- package/tabs/README.md +382 -34
- package/tabs/fesm2022/tabs.mjs +35 -111
- package/textarea/README.md +282 -5
- package/textarea/fesm2022/textarea.mjs +9 -9
- package/toggle/README.md +270 -5
- package/toggle/fesm2022/toggle.mjs +13 -13
- package/toggle-group/README.md +340 -5
- package/toggle-group/fesm2022/toggle-group.mjs +13 -13
- package/toggle-group/types/toggle-group.d.ts +13 -7
- package/tooltip/README.md +240 -34
- package/tooltip/fesm2022/tooltip.mjs +14 -14
- package/typography/README.md +271 -5
- package/typography/fesm2022/typography.mjs +53 -53
- package/typography/types/typography.d.ts +19 -19
- package/utils/README.md +274 -34
- package/utils/fesm2022/utils.mjs +68 -44
- package/accordion/fesm2022/accordion.mjs.map +0 -1
- package/alert/fesm2022/alert.mjs.map +0 -1
- package/alert-dialog/fesm2022/alert-dialog.mjs.map +0 -1
- package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +0 -1
- package/autocomplete/fesm2022/autocomplete.mjs.map +0 -1
- package/avatar/fesm2022/avatar.mjs.map +0 -1
- package/badge/fesm2022/badge.mjs.map +0 -1
- package/basic-alert/fesm2022/basic-alert.mjs.map +0 -1
- package/breadcrumb/fesm2022/breadcrumb.mjs.map +0 -1
- package/button/fesm2022/button.mjs.map +0 -1
- package/button-group/fesm2022/button-group.mjs.map +0 -1
- package/calendar/fesm2022/calendar.mjs.map +0 -1
- package/card/fesm2022/card.mjs.map +0 -1
- package/carousel/fesm2022/carousel.mjs.map +0 -1
- package/checkbox/fesm2022/checkbox.mjs.map +0 -1
- package/collapsible/fesm2022/collapsible.mjs.map +0 -1
- package/combobox/fesm2022/combobox.mjs.map +0 -1
- package/command/fesm2022/command.mjs.map +0 -1
- package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +0 -1
- package/context-menu/fesm2022/context-menu.mjs.map +0 -1
- package/date-picker/fesm2022/date-picker.mjs.map +0 -1
- package/dialog/fesm2022/dialog.mjs.map +0 -1
- package/drawer/fesm2022/drawer.mjs.map +0 -1
- package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +0 -1
- package/empty/fesm2022/empty.mjs.map +0 -1
- package/field/fesm2022/field.mjs.map +0 -1
- package/form-checkbox/fesm2022/form-checkbox.mjs.map +0 -1
- package/form-date-picker/fesm2022/form-date-picker.mjs.map +0 -1
- package/form-field/fesm2022/form-field.mjs.map +0 -1
- package/form-field-simple/fesm2022/form-field-simple.mjs.map +0 -1
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +0 -1
- package/form-select/fesm2022/form-select.mjs.map +0 -1
- package/form-text-input/fesm2022/form-text-input.mjs.map +0 -1
- package/form-textarea/fesm2022/form-textarea.mjs.map +0 -1
- package/hover-card/fesm2022/hover-card.mjs.map +0 -1
- package/icon/fesm2022/icon.mjs.map +0 -1
- package/input/fesm2022/input.mjs.map +0 -1
- package/input-group/fesm2022/input-group.mjs.map +0 -1
- package/input-otp/fesm2022/input-otp.mjs.map +0 -1
- package/item/fesm2022/item.mjs.map +0 -1
- package/kbd/fesm2022/kbd.mjs.map +0 -1
- package/label/fesm2022/label.mjs.map +0 -1
- package/layout-simple/fesm2022/layout-simple.mjs.map +0 -1
- package/menubar/fesm2022/menubar.mjs.map +0 -1
- package/native-select/fesm2022/native-select.mjs.map +0 -1
- package/navigation-menu/fesm2022/navigation-menu.mjs.map +0 -1
- package/pagination/fesm2022/pagination.mjs.map +0 -1
- package/popover/fesm2022/popover.mjs.map +0 -1
- package/progress/fesm2022/progress.mjs.map +0 -1
- package/radio-group/fesm2022/radio-group.mjs.map +0 -1
- package/resizable/fesm2022/resizable.mjs.map +0 -1
- package/scroll-area/fesm2022/scroll-area.mjs.map +0 -1
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +0 -1
- package/select/fesm2022/select.mjs.map +0 -1
- package/separator/fesm2022/separator.mjs.map +0 -1
- package/sheet/fesm2022/sheet.mjs.map +0 -1
- package/sidebar/fesm2022/sidebar.mjs.map +0 -1
- package/skeleton/fesm2022/skeleton.mjs.map +0 -1
- package/slider/fesm2022/slider.mjs.map +0 -1
- package/sonner/fesm2022/sonner.mjs.map +0 -1
- package/spinner/fesm2022/spinner.mjs.map +0 -1
- package/switch/fesm2022/switch.mjs.map +0 -1
- package/table/fesm2022/table.mjs.map +0 -1
- package/tabs/fesm2022/tabs.mjs.map +0 -1
- package/textarea/fesm2022/textarea.mjs.map +0 -1
- package/toggle/fesm2022/toggle.mjs.map +0 -1
- package/toggle-group/fesm2022/toggle-group.mjs.map +0 -1
- package/tooltip/fesm2022/tooltip.mjs.map +0 -1
- package/typography/fesm2022/typography.mjs.map +0 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|