@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.
Files changed (237) hide show
  1. package/README.md +130 -13
  2. package/accordion/README.md +376 -34
  3. package/accordion/fesm2022/accordion.mjs +27 -39
  4. package/alert/README.md +343 -34
  5. package/alert/fesm2022/alert.mjs +47 -47
  6. package/alert-dialog/README.md +471 -5
  7. package/alert-dialog/fesm2022/alert-dialog.mjs +47 -47
  8. package/aspect-ratio/README.md +272 -5
  9. package/aspect-ratio/fesm2022/aspect-ratio.mjs +9 -9
  10. package/autocomplete/README.md +473 -34
  11. package/autocomplete/fesm2022/autocomplete.mjs +53 -71
  12. package/avatar/README.md +357 -5
  13. package/avatar/fesm2022/avatar.mjs +32 -32
  14. package/badge/README.md +289 -34
  15. package/badge/fesm2022/badge.mjs +57 -57
  16. package/basic-alert/README.md +324 -34
  17. package/basic-alert/fesm2022/basic-alert.mjs +6 -18
  18. package/breadcrumb/README.md +406 -5
  19. package/breadcrumb/fesm2022/breadcrumb.mjs +33 -39
  20. package/button/README.md +453 -34
  21. package/button/fesm2022/button.mjs +147 -219
  22. package/button/types/button.d.ts +7 -10
  23. package/button-group/README.md +318 -5
  24. package/button-group/fesm2022/button-group.mjs +20 -20
  25. package/calendar/README.md +328 -34
  26. package/calendar/fesm2022/calendar.mjs +29 -743
  27. package/card/README.md +331 -5
  28. package/card/fesm2022/card.mjs +33 -33
  29. package/carousel/README.md +333 -5
  30. package/carousel/fesm2022/carousel.mjs +39 -78
  31. package/checkbox/README.md +291 -34
  32. package/checkbox/fesm2022/checkbox.mjs +20 -58
  33. package/checkbox/types/checkbox.d.ts +5 -4
  34. package/collapsible/README.md +332 -5
  35. package/collapsible/fesm2022/collapsible.mjs +15 -15
  36. package/combobox/README.md +507 -5
  37. package/combobox/fesm2022/combobox.mjs +91 -224
  38. package/command/README.md +435 -5
  39. package/command/fesm2022/command.mjs +49 -109
  40. package/confirmation-dialog/README.md +272 -34
  41. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +15 -40
  42. package/confirmation-dialog/types/confirmation-dialog.d.ts +8 -4
  43. package/context-menu/README.md +366 -5
  44. package/context-menu/fesm2022/context-menu.mjs +9 -9
  45. package/date-picker/README.md +436 -34
  46. package/date-picker/fesm2022/date-picker.mjs +64 -267
  47. package/date-picker/types/date-picker.d.ts +7 -3
  48. package/dialog/README.md +419 -34
  49. package/dialog/fesm2022/dialog.mjs +45 -71
  50. package/drawer/README.md +395 -5
  51. package/drawer/fesm2022/drawer.mjs +44 -54
  52. package/dropdown-menu/README.md +417 -5
  53. package/dropdown-menu/fesm2022/dropdown-menu.mjs +82 -70
  54. package/dropdown-menu/types/dropdown-menu.d.ts +4 -0
  55. package/empty/README.md +329 -5
  56. package/empty/fesm2022/empty.mjs +30 -30
  57. package/field/README.md +385 -5
  58. package/field/fesm2022/field.mjs +56 -72
  59. package/form-checkbox/README.md +283 -34
  60. package/form-checkbox/fesm2022/form-checkbox.mjs +25 -85
  61. package/form-checkbox/types/form-checkbox.d.ts +7 -1
  62. package/form-date-picker/README.md +293 -34
  63. package/form-date-picker/fesm2022/form-date-picker.mjs +31 -84
  64. package/form-date-picker/types/form-date-picker.d.ts +7 -1
  65. package/form-field/README.md +327 -34
  66. package/form-field/fesm2022/form-field.mjs +33 -19
  67. package/form-field/types/form-field.d.ts +28 -20
  68. package/form-field-simple/README.md +311 -34
  69. package/form-field-simple/fesm2022/form-field-simple.mjs +4 -4
  70. package/form-searchable-multiselect/README.md +332 -34
  71. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +31 -91
  72. package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +7 -1
  73. package/form-select/README.md +321 -34
  74. package/form-select/fesm2022/form-select.mjs +32 -149
  75. package/form-select/types/form-select.d.ts +7 -1
  76. package/form-text-input/README.md +342 -34
  77. package/form-text-input/fesm2022/form-text-input.mjs +35 -149
  78. package/form-text-input/types/form-text-input.d.ts +9 -12
  79. package/form-textarea/README.md +318 -34
  80. package/form-textarea/fesm2022/form-textarea.mjs +34 -109
  81. package/form-textarea/types/form-textarea.d.ts +8 -1
  82. package/hover-card/README.md +256 -5
  83. package/hover-card/fesm2022/hover-card.mjs +19 -19
  84. package/icon/README.md +210 -34
  85. package/icon/fesm2022/icon.mjs +8 -8
  86. package/input/README.md +240 -34
  87. package/input/fesm2022/input.mjs +17 -12
  88. package/input/types/input.d.ts +2 -1
  89. package/input-group/README.md +335 -5
  90. package/input-group/fesm2022/input-group.mjs +34 -34
  91. package/input-otp/README.md +375 -5
  92. package/input-otp/fesm2022/input-otp.mjs +26 -26
  93. package/item/README.md +385 -5
  94. package/item/fesm2022/item.mjs +53 -53
  95. package/kbd/README.md +291 -5
  96. package/kbd/fesm2022/kbd.mjs +12 -12
  97. package/label/README.md +243 -34
  98. package/label/fesm2022/label.mjs +10 -10
  99. package/label/types/label.d.ts +1 -1
  100. package/layout-simple/README.md +174 -44
  101. package/layout-simple/fesm2022/layout-simple.mjs +508 -603
  102. package/layout-simple/types/layout-simple.d.ts +179 -128
  103. package/menu/README.md +418 -0
  104. package/menu/fesm2022/menu.mjs +455 -0
  105. package/menu/package.json +24 -0
  106. package/menu/types/menu.d.ts +137 -0
  107. package/menubar/README.md +343 -5
  108. package/menubar/fesm2022/menubar.mjs +13 -13
  109. package/native-select/README.md +323 -5
  110. package/native-select/fesm2022/native-select.mjs +19 -19
  111. package/navigation-menu/README.md +369 -5
  112. package/navigation-menu/fesm2022/navigation-menu.mjs +35 -47
  113. package/package.json +183 -154
  114. package/pagination/README.md +388 -5
  115. package/pagination/fesm2022/pagination.mjs +45 -331
  116. package/popover/README.md +302 -34
  117. package/popover/fesm2022/popover.mjs +30 -30
  118. package/progress/README.md +311 -5
  119. package/progress/fesm2022/progress.mjs +13 -13
  120. package/radio-group/README.md +335 -34
  121. package/radio-group/fesm2022/radio-group.mjs +26 -19
  122. package/radio-group/types/radio-group.d.ts +1 -1
  123. package/resizable/README.md +269 -5
  124. package/resizable/fesm2022/resizable.mjs +18 -26
  125. package/scroll-area/README.md +233 -5
  126. package/scroll-area/fesm2022/scroll-area.mjs +9 -9
  127. package/searchable-multiselect/README.md +294 -34
  128. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +28 -117
  129. package/searchable-multiselect/types/searchable-multiselect.d.ts +8 -2
  130. package/select/README.md +408 -34
  131. package/select/fesm2022/select.mjs +71 -111
  132. package/select/types/select.d.ts +3 -1
  133. package/separator/README.md +193 -34
  134. package/separator/fesm2022/separator.mjs +9 -9
  135. package/separator/types/separator.d.ts +1 -1
  136. package/sheet/README.md +282 -34
  137. package/sheet/fesm2022/sheet.mjs +41 -53
  138. package/sidebar/README.md +457 -5
  139. package/sidebar/fesm2022/sidebar.mjs +125 -227
  140. package/skeleton/README.md +217 -5
  141. package/skeleton/fesm2022/skeleton.mjs +9 -9
  142. package/slider/README.md +273 -5
  143. package/slider/fesm2022/slider.mjs +10 -80
  144. package/sonner/README.md +317 -34
  145. package/sonner/fesm2022/sonner.mjs +13 -13
  146. package/spinner/README.md +255 -34
  147. package/spinner/fesm2022/spinner.mjs +11 -11
  148. package/switch/README.md +281 -34
  149. package/switch/fesm2022/switch.mjs +13 -15
  150. package/table/README.md +423 -5
  151. package/table/fesm2022/table.mjs +41 -41
  152. package/tabs/README.md +382 -34
  153. package/tabs/fesm2022/tabs.mjs +35 -111
  154. package/textarea/README.md +282 -5
  155. package/textarea/fesm2022/textarea.mjs +9 -9
  156. package/toggle/README.md +270 -5
  157. package/toggle/fesm2022/toggle.mjs +13 -13
  158. package/toggle-group/README.md +340 -5
  159. package/toggle-group/fesm2022/toggle-group.mjs +13 -13
  160. package/toggle-group/types/toggle-group.d.ts +13 -7
  161. package/tooltip/README.md +240 -34
  162. package/tooltip/fesm2022/tooltip.mjs +14 -14
  163. package/typography/README.md +271 -5
  164. package/typography/fesm2022/typography.mjs +53 -53
  165. package/typography/types/typography.d.ts +19 -19
  166. package/utils/README.md +274 -34
  167. package/utils/fesm2022/utils.mjs +68 -44
  168. package/accordion/fesm2022/accordion.mjs.map +0 -1
  169. package/alert/fesm2022/alert.mjs.map +0 -1
  170. package/alert-dialog/fesm2022/alert-dialog.mjs.map +0 -1
  171. package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +0 -1
  172. package/autocomplete/fesm2022/autocomplete.mjs.map +0 -1
  173. package/avatar/fesm2022/avatar.mjs.map +0 -1
  174. package/badge/fesm2022/badge.mjs.map +0 -1
  175. package/basic-alert/fesm2022/basic-alert.mjs.map +0 -1
  176. package/breadcrumb/fesm2022/breadcrumb.mjs.map +0 -1
  177. package/button/fesm2022/button.mjs.map +0 -1
  178. package/button-group/fesm2022/button-group.mjs.map +0 -1
  179. package/calendar/fesm2022/calendar.mjs.map +0 -1
  180. package/card/fesm2022/card.mjs.map +0 -1
  181. package/carousel/fesm2022/carousel.mjs.map +0 -1
  182. package/checkbox/fesm2022/checkbox.mjs.map +0 -1
  183. package/collapsible/fesm2022/collapsible.mjs.map +0 -1
  184. package/combobox/fesm2022/combobox.mjs.map +0 -1
  185. package/command/fesm2022/command.mjs.map +0 -1
  186. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +0 -1
  187. package/context-menu/fesm2022/context-menu.mjs.map +0 -1
  188. package/date-picker/fesm2022/date-picker.mjs.map +0 -1
  189. package/dialog/fesm2022/dialog.mjs.map +0 -1
  190. package/drawer/fesm2022/drawer.mjs.map +0 -1
  191. package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +0 -1
  192. package/empty/fesm2022/empty.mjs.map +0 -1
  193. package/field/fesm2022/field.mjs.map +0 -1
  194. package/form-checkbox/fesm2022/form-checkbox.mjs.map +0 -1
  195. package/form-date-picker/fesm2022/form-date-picker.mjs.map +0 -1
  196. package/form-field/fesm2022/form-field.mjs.map +0 -1
  197. package/form-field-simple/fesm2022/form-field-simple.mjs.map +0 -1
  198. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +0 -1
  199. package/form-select/fesm2022/form-select.mjs.map +0 -1
  200. package/form-text-input/fesm2022/form-text-input.mjs.map +0 -1
  201. package/form-textarea/fesm2022/form-textarea.mjs.map +0 -1
  202. package/hover-card/fesm2022/hover-card.mjs.map +0 -1
  203. package/icon/fesm2022/icon.mjs.map +0 -1
  204. package/input/fesm2022/input.mjs.map +0 -1
  205. package/input-group/fesm2022/input-group.mjs.map +0 -1
  206. package/input-otp/fesm2022/input-otp.mjs.map +0 -1
  207. package/item/fesm2022/item.mjs.map +0 -1
  208. package/kbd/fesm2022/kbd.mjs.map +0 -1
  209. package/label/fesm2022/label.mjs.map +0 -1
  210. package/layout-simple/fesm2022/layout-simple.mjs.map +0 -1
  211. package/menubar/fesm2022/menubar.mjs.map +0 -1
  212. package/native-select/fesm2022/native-select.mjs.map +0 -1
  213. package/navigation-menu/fesm2022/navigation-menu.mjs.map +0 -1
  214. package/pagination/fesm2022/pagination.mjs.map +0 -1
  215. package/popover/fesm2022/popover.mjs.map +0 -1
  216. package/progress/fesm2022/progress.mjs.map +0 -1
  217. package/radio-group/fesm2022/radio-group.mjs.map +0 -1
  218. package/resizable/fesm2022/resizable.mjs.map +0 -1
  219. package/scroll-area/fesm2022/scroll-area.mjs.map +0 -1
  220. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +0 -1
  221. package/select/fesm2022/select.mjs.map +0 -1
  222. package/separator/fesm2022/separator.mjs.map +0 -1
  223. package/sheet/fesm2022/sheet.mjs.map +0 -1
  224. package/sidebar/fesm2022/sidebar.mjs.map +0 -1
  225. package/skeleton/fesm2022/skeleton.mjs.map +0 -1
  226. package/slider/fesm2022/slider.mjs.map +0 -1
  227. package/sonner/fesm2022/sonner.mjs.map +0 -1
  228. package/spinner/fesm2022/spinner.mjs.map +0 -1
  229. package/switch/fesm2022/switch.mjs.map +0 -1
  230. package/table/fesm2022/table.mjs.map +0 -1
  231. package/tabs/fesm2022/tabs.mjs.map +0 -1
  232. package/textarea/fesm2022/textarea.mjs.map +0 -1
  233. package/toggle/fesm2022/toggle.mjs.map +0 -1
  234. package/toggle-group/fesm2022/toggle-group.mjs.map +0 -1
  235. package/tooltip/fesm2022/tooltip.mjs.map +0 -1
  236. package/typography/fesm2022/typography.mjs.map +0 -1
  237. package/utils/fesm2022/utils.mjs.map +0 -1
package/empty/README.md CHANGED
@@ -1,11 +1,335 @@
1
- # Empty
1
+ # Empty (`@egose/shadcn-theme-ng/empty`)
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli).
3
+ An empty-state placeholder in the shadcn/ui Empty style: dashed bordered panel with media (icon/illustration), title, description, and action content. Equivalent to shadcn/ui `Empty`.
4
4
 
5
- ## Building
5
+ The Angular implementation is a set of pure styling directives — there is no headless primitive or
6
+ behavioral code. Each directive applies its `data-slot` shadcn classes via `classes()` from
7
+ `@egose/shadcn-theme-ng/utils`; `HlmEmptyMedia` adds a `cva` variant (`default` | `icon`).
6
8
 
7
- To build the library, run:
9
+ > **Ships as:** `@egose/shadcn-theme-ng/empty` and `@egose/shadcn-theme-ng-tw/empty`
10
+ > (the `tw:`-prefixed Tailwind variant). Both expose the identical TypeScript surface; only the
11
+ > emitted Tailwind class strings differ. See the [package README](../../README.md) for install
12
+ > steps, peer dependencies, and Tailwind setup. Do not publish this project directory independently.
13
+
14
+ ## Installation
8
15
 
9
16
  ```bash
10
- ng build empty
17
+ # Plain Tailwind (no prefix)
18
+ npm install @egose/shadcn-theme-ng
19
+
20
+ # tw:-prefixed Tailwind variant
21
+ npm install @egose/shadcn-theme-ng-tw
22
+ ```
23
+
24
+ Peer dependencies (Angular, `@spartan-ng/brain`, `@ng-icons/*`, `rxjs`, …) are documented in the
25
+ [package README](../../README.md#peer-dependencies). This subpath has no extra runtime component
26
+ dependencies beyond `@egose/shadcn-theme-ng/utils` and `class-variance-authority` (media variant).
27
+
28
+ ## Imports
29
+
30
+ All symbols are exported from the subpath root (`projects/empty/src/public-api.ts`):
31
+
32
+ ```ts
33
+ import {
34
+ HlmEmpty,
35
+ HlmEmptyHeader,
36
+ HlmEmptyTitle,
37
+ HlmEmptyDescription,
38
+ HlmEmptyContent,
39
+ HlmEmptyMedia,
40
+ HlmEmptyImports,
41
+ HlmEmptyModule,
42
+ } from '@egose/shadcn-theme-ng/empty';
43
+ // tw variant: replace with '@egose/shadcn-theme-ng-tw/empty'
44
+ ```
45
+
46
+ Standalone component — spread the `*Imports` array:
47
+
48
+ ```ts
49
+ import { Component } from '@angular/core';
50
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
51
+
52
+ @Component({
53
+ selector: 'app-demo',
54
+ standalone: true,
55
+ imports: [...HlmEmptyImports],
56
+ template: `...`,
57
+ })
58
+ export class DemoComponent {}
59
+ ```
60
+
61
+ NgModule-based consumer — import the module:
62
+
63
+ ```ts
64
+ import { NgModule } from '@angular/core';
65
+ import { HlmEmptyModule } from '@egose/shadcn-theme-ng/empty';
66
+
67
+ @NgModule({ imports: [HlmEmptyModule] })
68
+ export class DemoModule {}
11
69
  ```
70
+
71
+ ## Anatomy / Structure
72
+
73
+ ```html
74
+ <div hlmEmpty>
75
+ <div hlmEmptyMedia variant="icon">
76
+ <ng-icon name="lucideInbox" />
77
+ </div>
78
+ <div hlmEmptyHeader>
79
+ <h3 hlmEmptyTitle>No results found</h3>
80
+ <p hlmEmptyDescription>Try adjusting your search or filters.</p>
81
+ </div>
82
+ <div hlmEmptyContent>
83
+ <button hlmBtn variant="outline">Clear filters</button>
84
+ </div>
85
+ </div>
86
+ ```
87
+
88
+ Real selectors (from source):
89
+
90
+ | Class | Selector(s) | Kind |
91
+ | --------------------- | -------------------------------------- | -------------------------- |
92
+ | `HlmEmpty` | `[hlmEmpty], hlm-empty` | Directive |
93
+ | `HlmEmptyHeader` | `[hlmEmptyHeader], hlm-empty-header` | Directive |
94
+ | `HlmEmptyTitle` | `[hlmEmptyTitle]` | Directive (attribute only) |
95
+ | `HlmEmptyDescription` | `[hlmEmptyDescription]` | Directive (attribute only) |
96
+ | `HlmEmptyContent` | `[hlmEmptyContent], hlm-empty-content` | Directive |
97
+ | `HlmEmptyMedia` | `[hlmEmptyMedia], hlm-empty-media` | Directive |
98
+
99
+ ## API reference
100
+
101
+ All directives are style-only (no inputs except media, no outputs).
102
+
103
+ | Directive | Selector | Description |
104
+ | --------------------- | -------------------------------------- | ------------------------------------------------------------ |
105
+ | `HlmEmpty` | `[hlmEmpty], hlm-empty` | Dashed rounded panel, centered column layout. |
106
+ | `HlmEmptyHeader` | `[hlmEmptyHeader], hlm-empty-header` | Narrow centered stack for title + description. |
107
+ | `HlmEmptyTitle` | `[hlmEmptyTitle]` | Large medium title. Apply to a heading element. |
108
+ | `HlmEmptyDescription` | `[hlmEmptyDescription]` | Muted small description with link styling. Apply to a `<p>`. |
109
+ | `HlmEmptyContent` | `[hlmEmptyContent], hlm-empty-content` | Action area (buttons, inputs) below the header. |
110
+
111
+ ### `HlmEmptyMedia` — `[hlmEmptyMedia], hlm-empty-media`
112
+
113
+ | Input | Type | Default | Description |
114
+ | --------- | --------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------- |
115
+ | `variant` | `'default' \| 'icon'` | `'default'` (cva default) | `'icon'` renders a muted rounded tile sized for an `ng-icon`; `'default'` is transparent (for illustrations). |
116
+
117
+ Host sets `data-slot="empty-media"` and `data-variant`.
118
+
119
+ ## Examples
120
+
121
+ ### 1. Basic no-results state
122
+
123
+ ```ts
124
+ import { Component } from '@angular/core';
125
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
126
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
127
+
128
+ @Component({
129
+ selector: 'app-no-results',
130
+ standalone: true,
131
+ imports: [...HlmEmptyImports, HlmButton],
132
+ template: `
133
+ <div hlmEmpty>
134
+ <div hlmEmptyHeader>
135
+ <h3 hlmEmptyTitle>No results found</h3>
136
+ <p hlmEmptyDescription>Try adjusting your search or filter to find what you're looking for.</p>
137
+ </div>
138
+ <div hlmEmptyContent>
139
+ <button hlmBtn variant="outline" (click)="clear()">Clear filters</button>
140
+ </div>
141
+ </div>
142
+ `,
143
+ })
144
+ export class NoResultsComponent {
145
+ clear() {
146
+ console.log('filters cleared');
147
+ }
148
+ }
149
+ ```
150
+
151
+ ### 2. Icon media variant
152
+
153
+ ```ts
154
+ import { Component } from '@angular/core';
155
+ import { NgIcon, provideIcons } from '@ng-icons/core';
156
+ import { lucideInbox } from '@ng-icons/lucide';
157
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
158
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
159
+
160
+ @Component({
161
+ selector: 'app-inbox-empty',
162
+ standalone: true,
163
+ imports: [...HlmEmptyImports, HlmButton, NgIcon],
164
+ providers: [provideIcons({ lucideInbox })],
165
+ template: `
166
+ <div hlmEmpty>
167
+ <div hlmEmptyMedia variant="icon">
168
+ <ng-icon name="lucideInbox" />
169
+ </div>
170
+ <div hlmEmptyHeader>
171
+ <h3 hlmEmptyTitle>Inbox zero</h3>
172
+ <p hlmEmptyDescription>You're all caught up. New messages will appear here.</p>
173
+ </div>
174
+ <div hlmEmptyContent>
175
+ <button hlmBtn>Compose</button>
176
+ </div>
177
+ </div>
178
+ `,
179
+ })
180
+ export class InboxEmptyComponent {}
181
+ ```
182
+
183
+ ### 3. Illustration media (default variant)
184
+
185
+ ```ts
186
+ import { Component } from '@angular/core';
187
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
188
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
189
+
190
+ @Component({
191
+ selector: 'app-illustration',
192
+ standalone: true,
193
+ imports: [...HlmEmptyImports, HlmButton],
194
+ template: `
195
+ <div hlmEmpty>
196
+ <div hlmEmptyMedia>
197
+ <img src="/assets/empty-projects.svg" alt="" width="120" height="120" />
198
+ </div>
199
+ <div hlmEmptyHeader>
200
+ <h3 hlmEmptyTitle>No projects yet</h3>
201
+ <p hlmEmptyDescription>
202
+ Get started by creating your first project. Read the <a href="/docs">docs</a> for ideas.
203
+ </p>
204
+ </div>
205
+ <div hlmEmptyContent>
206
+ <button hlmBtn>Create project</button>
207
+ <button hlmBtn variant="ghost">Import</button>
208
+ </div>
209
+ </div>
210
+ `,
211
+ })
212
+ export class IllustrationComponent {}
213
+ ```
214
+
215
+ ### 4. Element spellings
216
+
217
+ ```ts
218
+ import { Component } from '@angular/core';
219
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
220
+
221
+ @Component({
222
+ selector: 'app-elements',
223
+ standalone: true,
224
+ imports: [...HlmEmptyImports],
225
+ template: `
226
+ <hlm-empty>
227
+ <hlm-empty-header>
228
+ <h3 hlmEmptyTitle>Nothing here</h3>
229
+ <p hlmEmptyDescription>This space is intentionally left blank.</p>
230
+ </hlm-empty-header>
231
+ <hlm-empty-content>
232
+ <p class="tw:text-sm">Custom element selectors work identically.</p>
233
+ </hlm-empty-content>
234
+ </hlm-empty>
235
+ `,
236
+ })
237
+ export class ElementsComponent {}
238
+ ```
239
+
240
+ ### 5. Search empty state with input action
241
+
242
+ ```ts
243
+ import { Component, signal } from '@angular/core';
244
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
245
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
246
+ import { HlmInput } from '@egose/shadcn-theme-ng/input';
247
+ import { NgIcon, provideIcons } from '@ng-icons/core';
248
+ import { lucideSearchX } from '@ng-icons/lucide';
249
+
250
+ @Component({
251
+ selector: 'app-search-empty',
252
+ standalone: true,
253
+ imports: [...HlmEmptyImports, HlmButton, HlmInput, NgIcon],
254
+ providers: [provideIcons({ lucideSearchX })],
255
+ template: `
256
+ <div hlmEmpty>
257
+ <div hlmEmptyMedia variant="icon">
258
+ <ng-icon name="lucideSearchX" />
259
+ </div>
260
+ <div hlmEmptyHeader>
261
+ <h3 hlmEmptyTitle>No matches for "{{ query() }}"</h3>
262
+ <p hlmEmptyDescription>Check your spelling or try a different keyword.</p>
263
+ </div>
264
+ <div hlmEmptyContent>
265
+ <input hlmInput [value]="query()" (input)="query.set($any($event.target).value)" placeholder="Search again" />
266
+ <button hlmBtn variant="outline" (click)="query.set('')">Reset search</button>
267
+ </div>
268
+ </div>
269
+ `,
270
+ })
271
+ export class SearchEmptyComponent {
272
+ readonly query = signal('qwerty');
273
+ }
274
+ ```
275
+
276
+ ### 6. Error / offline state
277
+
278
+ ```ts
279
+ import { Component, signal } from '@angular/core';
280
+ import { HlmEmptyImports } from '@egose/shadcn-theme-ng/empty';
281
+ import { HlmButton } from '@egose/shadcn-theme-ng/button';
282
+ import { HlmSpinner } from '@egose/shadcn-theme-ng/spinner';
283
+ import { NgIcon, provideIcons } from '@ng-icons/core';
284
+ import { lucideWifiOff } from '@ng-icons/lucide';
285
+
286
+ @Component({
287
+ selector: 'app-offline',
288
+ standalone: true,
289
+ imports: [...HlmEmptyImports, HlmButton, HlmSpinner, NgIcon],
290
+ providers: [provideIcons({ lucideWifiOff })],
291
+ template: `
292
+ <div hlmEmpty>
293
+ <div hlmEmptyMedia variant="icon">
294
+ @if (retrying()) {
295
+ <hlm-spinner />
296
+ } @else {
297
+ <ng-icon name="lucideWifiOff" />
298
+ }
299
+ </div>
300
+ <div hlmEmptyHeader>
301
+ <h3 hlmEmptyTitle>You're offline</h3>
302
+ <p hlmEmptyDescription>We couldn't load your data. Check your connection and retry.</p>
303
+ </div>
304
+ <div hlmEmptyContent>
305
+ <button hlmBtn variant="outline" [disabled]="retrying()" (click)="retry()">Try again</button>
306
+ </div>
307
+ </div>
308
+ `,
309
+ })
310
+ export class OfflineComponent {
311
+ readonly retrying = signal(false);
312
+ retry() {
313
+ this.retrying.set(true);
314
+ setTimeout(() => this.retrying.set(false), 1200);
315
+ }
316
+ }
317
+ ```
318
+
319
+ ## Accessibility notes
320
+
321
+ - Use a real heading level for `hlmEmptyTitle` (`h2`/`h3` matching the page outline) — the directive adds no role or level itself.
322
+ - Mark decorative media `aria-hidden="true"` (or `alt=""` on images); give meaningful illustrations an `alt` or `role="img"` + `aria-label`.
323
+ - Keep the empty panel out of the tab order except for its interactive content (buttons/inputs); do not add `tabindex` to the container.
324
+ - For async states (loading → empty → results), announce changes with an `aria-live` region around the title or content.
325
+
326
+ ## Theming / CSS variables
327
+
328
+ No component-specific CSS variables. Geometry comes from the directives; colors from global tokens (`--muted`, `--muted-foreground`, `--background`). The `icon` media variant sizes `ng-icon` via `[&_ng-icon]` selectors — pass icon size through the icon itself if you need a different size.
329
+
330
+ ## Related subpaths
331
+
332
+ - `@egose/shadcn-theme-ng/card` — bordered container alternative when the state needs richer layout.
333
+ - `@egose/shadcn-theme-ng/skeleton` — loading placeholder to show before the empty state resolves.
334
+ - `@egose/shadcn-theme-ng/button` — `hlmBtn` actions inside `hlmEmptyContent`.
335
+ - `@egose/shadcn-theme-ng/spinner` — loading indicator for retrying/error empties.
@@ -5,12 +5,12 @@ import { cva } from 'class-variance-authority';
5
5
 
6
6
  class HlmEmpty {
7
7
  constructor() {
8
- classes(() => 'gap-4 rounded-lg border-dashed p-12 flex w-full min-w-0 flex-1 flex-col items-center justify-center text-center text-balance');
8
+ classes(() => "gap-4 rounded-lg border-dashed p-12 flex w-full min-w-0 flex-1 flex-col items-center justify-center text-center text-balance");
9
9
  }
10
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmpty, deps: [], target: i0.ɵɵFactoryTarget.Directive });
11
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmEmpty, isStandalone: true, selector: "[hlmEmpty],hlm-empty", host: { attributes: { "data-slot": "empty" } }, ngImport: i0 });
10
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmpty, deps: [], target: i0.ɵɵFactoryTarget.Directive });
11
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmEmpty, isStandalone: true, selector: "[hlmEmpty],hlm-empty", host: { attributes: { "data-slot": "empty" } }, ngImport: i0 });
12
12
  }
13
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmpty, decorators: [{
13
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmpty, decorators: [{
14
14
  type: Directive,
15
15
  args: [{
16
16
  selector: '[hlmEmpty],hlm-empty',
@@ -20,12 +20,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
20
20
 
21
21
  class HlmEmptyContent {
22
22
  constructor() {
23
- classes(() => 'gap-4 text-sm flex w-full max-w-sm min-w-0 flex-col items-center text-balance');
23
+ classes(() => "gap-4 text-sm flex w-full max-w-sm min-w-0 flex-col items-center text-balance");
24
24
  }
25
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
26
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmEmptyContent, isStandalone: true, selector: "[hlmEmptyContent],hlm-empty-content", host: { attributes: { "data-slot": "empty-content" } }, ngImport: i0 });
25
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
26
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmEmptyContent, isStandalone: true, selector: "[hlmEmptyContent],hlm-empty-content", host: { attributes: { "data-slot": "empty-content" } }, ngImport: i0 });
27
27
  }
28
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyContent, decorators: [{
28
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyContent, decorators: [{
29
29
  type: Directive,
30
30
  args: [{
31
31
  selector: '[hlmEmptyContent],hlm-empty-content',
@@ -35,12 +35,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
35
35
 
36
36
  class HlmEmptyDescription {
37
37
  constructor() {
38
- classes(() => 'text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4');
38
+ classes(() => "text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4");
39
39
  }
40
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyDescription, deps: [], target: i0.ɵɵFactoryTarget.Directive });
41
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmEmptyDescription, isStandalone: true, selector: "[hlmEmptyDescription]", host: { attributes: { "data-slot": "empty-description" } }, ngImport: i0 });
40
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyDescription, deps: [], target: i0.ɵɵFactoryTarget.Directive });
41
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmEmptyDescription, isStandalone: true, selector: "[hlmEmptyDescription]", host: { attributes: { "data-slot": "empty-description" } }, ngImport: i0 });
42
42
  }
43
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyDescription, decorators: [{
43
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyDescription, decorators: [{
44
44
  type: Directive,
45
45
  args: [{
46
46
  selector: '[hlmEmptyDescription]',
@@ -50,12 +50,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
50
50
 
51
51
  class HlmEmptyHeader {
52
52
  constructor() {
53
- classes(() => 'gap-2 flex max-w-sm flex-col items-center');
53
+ classes(() => "gap-2 flex max-w-sm flex-col items-center");
54
54
  }
55
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
56
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmEmptyHeader, isStandalone: true, selector: "[hlmEmptyHeader],hlm-empty-header", host: { attributes: { "data-slot": "empty-header" } }, ngImport: i0 });
55
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive });
56
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmEmptyHeader, isStandalone: true, selector: "[hlmEmptyHeader],hlm-empty-header", host: { attributes: { "data-slot": "empty-header" } }, ngImport: i0 });
57
57
  }
58
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyHeader, decorators: [{
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyHeader, decorators: [{
59
59
  type: Directive,
60
60
  args: [{
61
61
  selector: '[hlmEmptyHeader],hlm-empty-header',
@@ -63,10 +63,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
63
63
  }]
64
64
  }], ctorParameters: () => [] });
65
65
 
66
- const emptyMediaVariants = cva('mb-2 flex shrink-0 items-center justify-center [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0', {
66
+ const emptyMediaVariants = cva("mb-2 flex shrink-0 items-center justify-center [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0", {
67
67
  variants: {
68
68
  variant: {
69
- default: 'bg-transparent',
69
+ default: "bg-transparent",
70
70
  icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_ng-icon:not([class*='text-'])]:text-[length:--spacing(6)]",
71
71
  },
72
72
  },
@@ -80,10 +80,10 @@ class HlmEmptyMedia {
80
80
  constructor() {
81
81
  classes(() => emptyMediaVariants({ variant: this.variant() }));
82
82
  }
83
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyMedia, deps: [], target: i0.ɵɵFactoryTarget.Directive });
84
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: HlmEmptyMedia, isStandalone: true, selector: "[hlmEmptyMedia],hlm-empty-media", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "empty-media" }, properties: { "attr.data-variant": "variant()" } }, ngImport: i0 });
83
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyMedia, deps: [], target: i0.ɵɵFactoryTarget.Directive });
84
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmEmptyMedia, isStandalone: true, selector: "[hlmEmptyMedia],hlm-empty-media", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "empty-media" }, properties: { "attr.data-variant": "variant()" } }, ngImport: i0 });
85
85
  }
86
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyMedia, decorators: [{
86
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyMedia, decorators: [{
87
87
  type: Directive,
88
88
  args: [{
89
89
  selector: '[hlmEmptyMedia],hlm-empty-media',
@@ -96,12 +96,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
96
96
 
97
97
  class HlmEmptyTitle {
98
98
  constructor() {
99
- classes(() => 'text-lg font-medium tracking-tight');
99
+ classes(() => "text-lg font-medium tracking-tight");
100
100
  }
101
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyTitle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
102
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmEmptyTitle, isStandalone: true, selector: "[hlmEmptyTitle]", host: { attributes: { "data-slot": "empty-title" } }, ngImport: i0 });
101
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyTitle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
102
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmEmptyTitle, isStandalone: true, selector: "[hlmEmptyTitle]", host: { attributes: { "data-slot": "empty-title" } }, ngImport: i0 });
103
103
  }
104
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyTitle, decorators: [{
104
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyTitle, decorators: [{
105
105
  type: Directive,
106
106
  args: [{
107
107
  selector: '[hlmEmptyTitle]',
@@ -121,8 +121,8 @@ const HlmEmptyImports = [
121
121
  HlmEmptyMedia,
122
122
  ];
123
123
  class HlmEmptyModule {
124
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
125
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyModule, imports: [HlmEmpty,
124
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
125
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyModule, imports: [HlmEmpty,
126
126
  HlmEmptyContent,
127
127
  HlmEmptyDescription,
128
128
  HlmEmptyHeader,
@@ -133,9 +133,9 @@ class HlmEmptyModule {
133
133
  HlmEmptyHeader,
134
134
  HlmEmptyTitle,
135
135
  HlmEmptyMedia] });
136
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyModule });
136
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyModule });
137
137
  }
138
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmEmptyModule, decorators: [{
138
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmEmptyModule, decorators: [{
139
139
  type: NgModule,
140
140
  args: [{
141
141
  imports: [...HlmEmptyImports],
@@ -148,4 +148,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
148
148
  */
149
149
 
150
150
  export { HlmEmpty, HlmEmptyContent, HlmEmptyDescription, HlmEmptyHeader, HlmEmptyImports, HlmEmptyMedia, HlmEmptyModule, HlmEmptyTitle };
151
- //# sourceMappingURL=empty.mjs.map
151
+