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