@egose/shadcn-theme-ng-tw 0.0.28 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. package/README.md +130 -13
  2. package/accordion/README.md +376 -34
  3. package/accordion/fesm2022/accordion.mjs +20 -20
  4. package/alert/README.md +343 -34
  5. package/alert/fesm2022/alert.mjs +18 -18
  6. package/alert-dialog/README.md +471 -5
  7. package/alert-dialog/fesm2022/alert-dialog.mjs +48 -48
  8. package/alert-dialog/types/alert-dialog.d.ts +1 -1
  9. package/aspect-ratio/README.md +272 -5
  10. package/aspect-ratio/fesm2022/aspect-ratio.mjs +9 -9
  11. package/autocomplete/README.md +473 -34
  12. package/autocomplete/fesm2022/autocomplete.mjs +54 -54
  13. package/autocomplete/types/autocomplete.d.ts +1 -1
  14. package/avatar/README.md +357 -5
  15. package/avatar/fesm2022/avatar.mjs +32 -32
  16. package/badge/README.md +289 -34
  17. package/badge/fesm2022/badge.mjs +4 -4
  18. package/basic-alert/README.md +324 -34
  19. package/basic-alert/fesm2022/basic-alert.mjs +4 -4
  20. package/basic-alert/types/basic-alert.d.ts +1 -1
  21. package/breadcrumb/README.md +406 -5
  22. package/breadcrumb/fesm2022/breadcrumb.mjs +34 -34
  23. package/button/README.md +453 -34
  24. package/button/fesm2022/button.mjs +96 -118
  25. package/button/types/button.d.ts +7 -10
  26. package/button-group/README.md +318 -5
  27. package/button-group/fesm2022/button-group.mjs +20 -20
  28. package/calendar/README.md +328 -34
  29. package/calendar/fesm2022/calendar.mjs +154 -154
  30. package/card/README.md +331 -5
  31. package/card/fesm2022/card.mjs +33 -33
  32. package/carousel/README.md +333 -5
  33. package/carousel/fesm2022/carousel.mjs +47 -44
  34. package/carousel/types/carousel.d.ts +1 -1
  35. package/checkbox/README.md +291 -34
  36. package/checkbox/fesm2022/checkbox.mjs +22 -20
  37. package/checkbox/types/checkbox.d.ts +5 -4
  38. package/collapsible/README.md +332 -5
  39. package/collapsible/fesm2022/collapsible.mjs +15 -15
  40. package/combobox/README.md +507 -5
  41. package/combobox/fesm2022/combobox.mjs +95 -92
  42. package/combobox/types/combobox.d.ts +1 -1
  43. package/command/README.md +435 -5
  44. package/command/fesm2022/command.mjs +56 -56
  45. package/confirmation-dialog/README.md +272 -34
  46. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +13 -12
  47. package/confirmation-dialog/types/confirmation-dialog.d.ts +9 -5
  48. package/context-menu/README.md +366 -5
  49. package/context-menu/fesm2022/context-menu.mjs +9 -9
  50. package/date-picker/README.md +436 -34
  51. package/date-picker/fesm2022/date-picker.mjs +79 -68
  52. package/date-picker/types/date-picker.d.ts +8 -4
  53. package/dialog/README.md +419 -34
  54. package/dialog/fesm2022/dialog.mjs +48 -48
  55. package/drawer/README.md +395 -5
  56. package/drawer/fesm2022/drawer.mjs +45 -45
  57. package/dropdown-menu/README.md +417 -5
  58. package/dropdown-menu/fesm2022/dropdown-menu.mjs +85 -73
  59. package/dropdown-menu/types/dropdown-menu.d.ts +4 -0
  60. package/empty/README.md +329 -5
  61. package/empty/fesm2022/empty.mjs +31 -31
  62. package/field/README.md +385 -5
  63. package/field/fesm2022/field.mjs +59 -59
  64. package/field/types/field.d.ts +1 -1
  65. package/form-checkbox/README.md +283 -34
  66. package/form-checkbox/fesm2022/form-checkbox.mjs +37 -19
  67. package/form-checkbox/types/form-checkbox.d.ts +7 -1
  68. package/form-date-picker/README.md +293 -34
  69. package/form-date-picker/fesm2022/form-date-picker.mjs +59 -24
  70. package/form-date-picker/types/form-date-picker.d.ts +7 -1
  71. package/form-field/README.md +327 -34
  72. package/form-field/fesm2022/form-field.mjs +30 -16
  73. package/form-field/types/form-field.d.ts +28 -20
  74. package/form-field-simple/README.md +311 -34
  75. package/form-field-simple/fesm2022/form-field-simple.mjs +4 -4
  76. package/form-searchable-multiselect/README.md +332 -34
  77. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +41 -21
  78. package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +8 -2
  79. package/form-select/README.md +321 -34
  80. package/form-select/fesm2022/form-select.mjs +62 -29
  81. package/form-select/types/form-select.d.ts +7 -1
  82. package/form-text-input/README.md +342 -34
  83. package/form-text-input/fesm2022/form-text-input.mjs +43 -55
  84. package/form-text-input/types/form-text-input.d.ts +9 -12
  85. package/form-textarea/README.md +318 -34
  86. package/form-textarea/fesm2022/form-textarea.mjs +42 -23
  87. package/form-textarea/types/form-textarea.d.ts +8 -1
  88. package/hover-card/README.md +256 -5
  89. package/hover-card/fesm2022/hover-card.mjs +19 -19
  90. package/icon/README.md +210 -34
  91. package/icon/fesm2022/icon.mjs +8 -8
  92. package/input/README.md +240 -34
  93. package/input/fesm2022/input.mjs +17 -12
  94. package/input/types/input.d.ts +2 -1
  95. package/input-group/README.md +335 -5
  96. package/input-group/fesm2022/input-group.mjs +37 -37
  97. package/input-group/types/input-group.d.ts +3 -3
  98. package/input-otp/README.md +375 -5
  99. package/input-otp/fesm2022/input-otp.mjs +27 -27
  100. package/item/README.md +385 -5
  101. package/item/fesm2022/item.mjs +54 -54
  102. package/kbd/README.md +291 -5
  103. package/kbd/fesm2022/kbd.mjs +13 -13
  104. package/label/README.md +243 -34
  105. package/label/fesm2022/label.mjs +9 -9
  106. package/label/types/label.d.ts +1 -1
  107. package/layout-simple/README.md +174 -44
  108. package/layout-simple/fesm2022/layout-simple.mjs +917 -398
  109. package/layout-simple/types/layout-simple.d.ts +180 -129
  110. package/menu/README.md +418 -0
  111. package/menu/fesm2022/menu.mjs +461 -0
  112. package/menu/package.json +24 -0
  113. package/menu/types/menu.d.ts +137 -0
  114. package/menubar/README.md +343 -5
  115. package/menubar/fesm2022/menubar.mjs +13 -13
  116. package/native-select/README.md +323 -5
  117. package/native-select/fesm2022/native-select.mjs +19 -19
  118. package/navigation-menu/README.md +369 -5
  119. package/navigation-menu/fesm2022/navigation-menu.mjs +37 -37
  120. package/package.json +183 -154
  121. package/pagination/README.md +388 -5
  122. package/pagination/fesm2022/pagination.mjs +63 -63
  123. package/popover/README.md +302 -34
  124. package/popover/fesm2022/popover.mjs +30 -30
  125. package/progress/README.md +311 -5
  126. package/progress/fesm2022/progress.mjs +13 -13
  127. package/radio-group/README.md +335 -34
  128. package/radio-group/fesm2022/radio-group.mjs +26 -19
  129. package/resizable/README.md +269 -5
  130. package/resizable/fesm2022/resizable.mjs +19 -19
  131. package/scroll-area/README.md +233 -5
  132. package/scroll-area/fesm2022/scroll-area.mjs +9 -9
  133. package/searchable-multiselect/README.md +294 -34
  134. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +63 -16
  135. package/searchable-multiselect/types/searchable-multiselect.d.ts +8 -2
  136. package/select/README.md +408 -34
  137. package/select/fesm2022/select.mjs +80 -72
  138. package/select/types/select.d.ts +3 -1
  139. package/separator/README.md +193 -34
  140. package/separator/fesm2022/separator.mjs +9 -9
  141. package/separator/types/separator.d.ts +1 -1
  142. package/sheet/README.md +282 -34
  143. package/sheet/fesm2022/sheet.mjs +30 -30
  144. package/sidebar/README.md +457 -5
  145. package/sidebar/fesm2022/sidebar.mjs +136 -134
  146. package/sidebar/types/sidebar.d.ts +3 -3
  147. package/skeleton/README.md +217 -5
  148. package/skeleton/fesm2022/skeleton.mjs +9 -9
  149. package/slider/README.md +273 -5
  150. package/slider/fesm2022/slider.mjs +29 -25
  151. package/sonner/README.md +317 -34
  152. package/sonner/fesm2022/sonner.mjs +9 -9
  153. package/spinner/README.md +255 -34
  154. package/spinner/fesm2022/spinner.mjs +8 -8
  155. package/switch/README.md +281 -34
  156. package/switch/fesm2022/switch.mjs +12 -14
  157. package/table/README.md +423 -5
  158. package/table/fesm2022/table.mjs +41 -41
  159. package/tabs/README.md +382 -34
  160. package/tabs/fesm2022/tabs.mjs +48 -38
  161. package/textarea/README.md +282 -5
  162. package/textarea/fesm2022/textarea.mjs +9 -9
  163. package/toggle/README.md +270 -5
  164. package/toggle/fesm2022/toggle.mjs +14 -14
  165. package/toggle-group/README.md +340 -5
  166. package/toggle-group/fesm2022/toggle-group.mjs +13 -13
  167. package/toggle-group/types/toggle-group.d.ts +13 -7
  168. package/tooltip/README.md +240 -34
  169. package/tooltip/fesm2022/tooltip.mjs +14 -14
  170. package/typography/README.md +271 -5
  171. package/typography/fesm2022/typography.mjs +53 -53
  172. package/typography/types/typography.d.ts +12 -12
  173. package/utils/README.md +274 -34
  174. package/utils/fesm2022/utils.mjs +68 -44
  175. package/accordion/fesm2022/accordion.mjs.map +0 -1
  176. package/alert/fesm2022/alert.mjs.map +0 -1
  177. package/alert-dialog/fesm2022/alert-dialog.mjs.map +0 -1
  178. package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +0 -1
  179. package/autocomplete/fesm2022/autocomplete.mjs.map +0 -1
  180. package/avatar/fesm2022/avatar.mjs.map +0 -1
  181. package/badge/fesm2022/badge.mjs.map +0 -1
  182. package/basic-alert/fesm2022/basic-alert.mjs.map +0 -1
  183. package/breadcrumb/fesm2022/breadcrumb.mjs.map +0 -1
  184. package/button/fesm2022/button.mjs.map +0 -1
  185. package/button-group/fesm2022/button-group.mjs.map +0 -1
  186. package/calendar/fesm2022/calendar.mjs.map +0 -1
  187. package/card/fesm2022/card.mjs.map +0 -1
  188. package/carousel/fesm2022/carousel.mjs.map +0 -1
  189. package/checkbox/fesm2022/checkbox.mjs.map +0 -1
  190. package/collapsible/fesm2022/collapsible.mjs.map +0 -1
  191. package/combobox/fesm2022/combobox.mjs.map +0 -1
  192. package/command/fesm2022/command.mjs.map +0 -1
  193. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +0 -1
  194. package/context-menu/fesm2022/context-menu.mjs.map +0 -1
  195. package/date-picker/fesm2022/date-picker.mjs.map +0 -1
  196. package/dialog/fesm2022/dialog.mjs.map +0 -1
  197. package/drawer/fesm2022/drawer.mjs.map +0 -1
  198. package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +0 -1
  199. package/empty/fesm2022/empty.mjs.map +0 -1
  200. package/field/fesm2022/field.mjs.map +0 -1
  201. package/form-checkbox/fesm2022/form-checkbox.mjs.map +0 -1
  202. package/form-date-picker/fesm2022/form-date-picker.mjs.map +0 -1
  203. package/form-field/fesm2022/form-field.mjs.map +0 -1
  204. package/form-field-simple/fesm2022/form-field-simple.mjs.map +0 -1
  205. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +0 -1
  206. package/form-select/fesm2022/form-select.mjs.map +0 -1
  207. package/form-text-input/fesm2022/form-text-input.mjs.map +0 -1
  208. package/form-textarea/fesm2022/form-textarea.mjs.map +0 -1
  209. package/hover-card/fesm2022/hover-card.mjs.map +0 -1
  210. package/icon/fesm2022/icon.mjs.map +0 -1
  211. package/input/fesm2022/input.mjs.map +0 -1
  212. package/input-group/fesm2022/input-group.mjs.map +0 -1
  213. package/input-otp/fesm2022/input-otp.mjs.map +0 -1
  214. package/item/fesm2022/item.mjs.map +0 -1
  215. package/kbd/fesm2022/kbd.mjs.map +0 -1
  216. package/label/fesm2022/label.mjs.map +0 -1
  217. package/layout-simple/fesm2022/layout-simple.mjs.map +0 -1
  218. package/menubar/fesm2022/menubar.mjs.map +0 -1
  219. package/native-select/fesm2022/native-select.mjs.map +0 -1
  220. package/navigation-menu/fesm2022/navigation-menu.mjs.map +0 -1
  221. package/pagination/fesm2022/pagination.mjs.map +0 -1
  222. package/popover/fesm2022/popover.mjs.map +0 -1
  223. package/progress/fesm2022/progress.mjs.map +0 -1
  224. package/radio-group/fesm2022/radio-group.mjs.map +0 -1
  225. package/resizable/fesm2022/resizable.mjs.map +0 -1
  226. package/scroll-area/fesm2022/scroll-area.mjs.map +0 -1
  227. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +0 -1
  228. package/select/fesm2022/select.mjs.map +0 -1
  229. package/separator/fesm2022/separator.mjs.map +0 -1
  230. package/sheet/fesm2022/sheet.mjs.map +0 -1
  231. package/sidebar/fesm2022/sidebar.mjs.map +0 -1
  232. package/skeleton/fesm2022/skeleton.mjs.map +0 -1
  233. package/slider/fesm2022/slider.mjs.map +0 -1
  234. package/sonner/fesm2022/sonner.mjs.map +0 -1
  235. package/spinner/fesm2022/spinner.mjs.map +0 -1
  236. package/switch/fesm2022/switch.mjs.map +0 -1
  237. package/table/fesm2022/table.mjs.map +0 -1
  238. package/tabs/fesm2022/tabs.mjs.map +0 -1
  239. package/textarea/fesm2022/textarea.mjs.map +0 -1
  240. package/toggle/fesm2022/toggle.mjs.map +0 -1
  241. package/toggle-group/fesm2022/toggle-group.mjs.map +0 -1
  242. package/tooltip/fesm2022/tooltip.mjs.map +0 -1
  243. package/typography/fesm2022/typography.mjs.map +0 -1
  244. package/utils/fesm2022/utils.mjs.map +0 -1
@@ -1,11 +1,275 @@
1
- # Resizable
1
+ # Resizable (`@egose/shadcn-theme-ng/resizable`)
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli).
3
+ A shadcn/ui-style **Resizable** panel layout — draggable split views (side-by-side or stacked) with collapsible panels. This is the Angular equivalent of shadcn/ui `ResizablePanelGroup` / `ResizablePanel` / `ResizableHandle`.
4
4
 
5
- ## Building
5
+ The behavior comes from **spartan-ng/brain** (`BrnResizableGroup`, `BrnResizablePanel`, `BrnResizableHandle`): pointer-drag resizing, panel size constraints, and layout events. This package is a thin styling/directive layer — a flex group container, constraint-forwarding panel directive with a `setSize` helper, and a handle with an optional grip pill.
6
6
 
7
- To build the library, run:
7
+ > **Ships as:** `@egose/shadcn-theme-ng/resizable` and `@egose/shadcn-theme-ng-tw/resizable` (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
- ng build resizable
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
18
+ ```
19
+
20
+ ```ts
21
+ import { HlmResizableImports } from '@egose/shadcn-theme-ng/resizable';
22
+ // tw variant:
23
+ // import { HlmResizableImports } from '@egose/shadcn-theme-ng-tw/resizable';
24
+ ```
25
+
26
+ Peer dependencies (see [package README](../../README.md) for versions): `@angular/core`, `@angular/common`, `@spartan-ng/brain`.
27
+
28
+ ## Imports
29
+
30
+ Real exported symbols (from `src/public-api.ts`):
31
+
32
+ | Symbol | Kind | Description |
33
+ | --------------------- | ------------- | ------------------------------------------------------------------------------------- |
34
+ | `HlmResizableGroup` | Directive | Flex row/column container; forwards `BrnResizableGroup` |
35
+ | `HlmResizablePanel` | Directive | Size-constrained panel; forwards `BrnResizablePanel`, `exportAs: 'hlmResizablePanel'` |
36
+ | `HlmResizableHandle` | Component | Drag handle with optional grip pill; `exportAs: 'hlmResizableHandle'` |
37
+ | `HlmResizableImports` | `const` array | `[HlmResizableGroup, HlmResizablePanel, HlmResizableHandle]` standalone imports |
38
+ | `HlmResizableModule` | `NgModule` | NgModule wrapper re-exporting the three above |
39
+
40
+ Standalone usage:
41
+
42
+ ```ts
43
+ import { Component } from '@angular/core';
44
+ import { HlmResizableImports } from '@egose/shadcn-theme-ng/resizable';
45
+
46
+ @Component({
47
+ selector: 'app-demo',
48
+ standalone: true,
49
+ imports: [HlmResizableImports],
50
+ template: `...`,
51
+ })
52
+ export class DemoComponent {}
53
+ ```
54
+
55
+ NgModule usage:
56
+
57
+ ```ts
58
+ import { NgModule } from '@angular/core';
59
+ import { HlmResizableModule } from '@egose/shadcn-theme-ng/resizable';
60
+
61
+ @NgModule({ imports: [HlmResizableModule] })
62
+ export class DemoModule {}
63
+ ```
64
+
65
+ ## Anatomy / Structure
66
+
67
+ ```html
68
+ <div hlmResizableGroup direction="horizontal">
69
+ <div hlmResizablePanel defaultSize="25">Sidebar</div>
70
+
71
+ <hlm-resizable-handle withHandle />
72
+
73
+ <div hlmResizablePanel defaultSize="75">Main content</div>
74
+ </div>
75
+ ```
76
+
77
+ Real selectors:
78
+
79
+ | Selector | Class | Notes |
80
+ | -------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------ |
81
+ | `[hlmResizableGroup]`, `hlm-resizable-group` | `HlmResizableGroup` | `data-slot="resizable-group"`; row by default, column when the panel-group direction is vertical |
82
+ | `[hlmResizablePanel]`, `hlm-resizable-panel` | `HlmResizablePanel` | `data-slot="resizable-panel"` |
83
+ | `hlm-resizable-handle` | `HlmResizableHandle` | `data-slot="resizable-handle"`; renders a grip `<div>` only when `withHandle` is true |
84
+
85
+ ## API reference
86
+
87
+ ### HlmResizableGroup (directive)
88
+
89
+ Thin directive wrapper — no own inputs. Forwarded `BrnResizableGroup` bindings:
90
+
91
+ | Binding | Kind | Description |
92
+ | -------------- | ------ | --------------------------------------------- |
93
+ | `direction` | input | `'horizontal' \| 'vertical'` layout direction |
94
+ | `layout` | input | Controlled panel layout (sizes) |
95
+ | `dragStart` | output | Emitted when a drag resize starts |
96
+ | `dragEnd` | output | Emitted when a drag resize ends |
97
+ | `layoutChange` | output | Emitted when the panel layout changes |
98
+
99
+ ### HlmResizablePanel (directive)
100
+
101
+ Thin directive wrapper plus one helper method. No own inputs. Forwarded `BrnResizablePanel` inputs:
102
+
103
+ | Input | Description |
104
+ | ------------- | ------------------------------------------------ |
105
+ | `defaultSize` | Initial size (percentage of the group) |
106
+ | `id` | Panel id (used for persisted/controlled layouts) |
107
+ | `collapsible` | Whether the panel can collapse to zero |
108
+ | `minSize` | Minimum size (percentage) |
109
+ | `maxSize` | Maximum size (percentage) |
110
+
111
+ | Method | Signature | Description |
112
+ | --------- | ----------------------------- | --------------------------------------------------------------------------- |
113
+ | `setSize` | `setSize(size: number): void` | Programmatically resize the panel; delegates to `BrnResizablePanel.setSize` |
114
+
115
+ Because the directive is `exportAs: 'hlmResizablePanel'`, grab it with a template reference: `<div hlmResizablePanel #panel="hlmResizablePanel">` then call `panel.setSize(50)`.
116
+
117
+ ### HlmResizableHandle (component)
118
+
119
+ | Input (forwarded to `BrnResizableHandle`) | Description |
120
+ | ----------------------------------------- | ------------------------------------ |
121
+ | `withHandle` | Show the grip pill inside the handle |
122
+ | `disabled` | Disable dragging on this handle |
123
+
124
+ When `withHandle` is true the component renders a short rounded pill (`<div class="...">`) centered in the handle; otherwise the handle is just the thin hover/drag strip. Hover cursors adapt to direction (`ew-resize` horizontal, `ns-resize` vertical).
125
+
126
+ ## Examples
127
+
128
+ ### 1. Basic horizontal split
129
+
130
+ ```ts
131
+ import { Component } from '@angular/core';
132
+ import { HlmResizableImports } from '@egose/shadcn-theme-ng/resizable';
133
+
134
+ @Component({
135
+ selector: 'app-basic-resizable',
136
+ standalone: true,
137
+ imports: [HlmResizableImports],
138
+ template: `
139
+ <div hlmResizableGroup direction="horizontal" class="tw:h-64 tw:rounded-lg tw:border">
140
+ <div hlmResizablePanel defaultSize="30" class="tw:p-4">Nav</div>
141
+ <hlm-resizable-handle />
142
+ <div hlmResizablePanel defaultSize="70" class="tw:p-4">Content</div>
143
+ </div>
144
+ `,
145
+ })
146
+ export class BasicResizableComponent {}
147
+ ```
148
+
149
+ ### 2. Handle with grip pill
150
+
151
+ ```html
152
+ <div hlmResizableGroup direction="horizontal" class="tw:h-64 tw:rounded-lg tw:border">
153
+ <div hlmResizablePanel defaultSize="25" class="tw:p-4">Files</div>
154
+
155
+ <hlm-resizable-handle withHandle />
156
+
157
+ <div hlmResizablePanel defaultSize="75" class="tw:p-4">Editor</div>
158
+ </div>
159
+ ```
160
+
161
+ ### 3. Vertical stacking
162
+
163
+ ```ts
164
+ import { Component } from '@angular/core';
165
+ import { HlmResizableImports } from '@egose/shadcn-theme-ng/resizable';
166
+
167
+ @Component({
168
+ selector: 'app-vertical-resizable',
169
+ standalone: true,
170
+ imports: [HlmResizableImports],
171
+ template: `
172
+ <div hlmResizableGroup direction="vertical" class="tw:h-96 tw:rounded-lg tw:border">
173
+ <div hlmResizablePanel defaultSize="40" class="tw:p-4">Preview</div>
174
+ <hlm-resizable-handle withHandle />
175
+ <div hlmResizablePanel defaultSize="60" class="tw:p-4">Console</div>
176
+ </div>
177
+ `,
178
+ })
179
+ export class VerticalResizableComponent {}
180
+ ```
181
+
182
+ The group flips to `flex-col` automatically for vertical direction, and the handle renders horizontally with an `ns-resize` cursor.
183
+
184
+ ### 4. Constrained + collapsible panels
185
+
186
+ ```html
187
+ <div hlmResizableGroup direction="horizontal" class="tw:h-64 tw:rounded-lg tw:border">
188
+ <div hlmResizablePanel defaultSize="20" minSize="10" maxSize="40" collapsible class="tw:p-4">
189
+ Collapsible sidebar (10–40%)
190
+ </div>
191
+ <hlm-resizable-handle withHandle />
192
+ <div hlmResizablePanel defaultSize="80" minSize="30" class="tw:p-4">Main (≥30%)</div>
193
+ </div>
11
194
  ```
195
+
196
+ ### 5. Programmatic control via `setSize`
197
+
198
+ ```ts
199
+ import { Component } from '@angular/core';
200
+ import { HlmResizableImports } from '@egose/shadcn-theme-ng/resizable';
201
+
202
+ @Component({
203
+ selector: 'app-controlled-resizable',
204
+ standalone: true,
205
+ imports: [HlmResizableImports],
206
+ template: `
207
+ <div class="tw:mb-2 tw:flex tw:gap-2">
208
+ <button type="button" (click)="left.setSize(20)">Sidebar 20%</button>
209
+ <button type="button" (click)="left.setSize(50)">Split 50/50</button>
210
+ </div>
211
+ <div hlmResizableGroup direction="horizontal" class="tw:h-64 tw:rounded-lg tw:border">
212
+ <div hlmResizablePanel #left="hlmResizablePanel" defaultSize="30" class="tw:p-4">Nav</div>
213
+ <hlm-resizable-handle withHandle />
214
+ <div hlmResizablePanel defaultSize="70" class="tw:p-4">Content</div>
215
+ </div>
216
+ `,
217
+ })
218
+ export class ControlledResizableComponent {}
219
+ ```
220
+
221
+ ### 6. Layout events + three-pane IDE layout
222
+
223
+ ```ts
224
+ import { Component, signal } from '@angular/core';
225
+ import { HlmResizableImports } from '@egose/shadcn-theme-ng/resizable';
226
+
227
+ @Component({
228
+ selector: 'app-ide-resizable',
229
+ standalone: true,
230
+ imports: [HlmResizableImports],
231
+ template: `
232
+ <div
233
+ hlmResizableGroup
234
+ direction="horizontal"
235
+ class="tw:h-96 tw:rounded-lg tw:border"
236
+ (dragStart)="dragging.set(true)"
237
+ (dragEnd)="dragging.set(false)"
238
+ (layoutChange)="onLayout($event)"
239
+ >
240
+ <div hlmResizablePanel defaultSize="20" minSize="12" collapsible class="tw:p-4">Explorer</div>
241
+ <hlm-resizable-handle withHandle />
242
+ <div hlmResizablePanel defaultSize="55" minSize="30" class="tw:p-4">Editor</div>
243
+ <hlm-resizable-handle />
244
+ <div hlmResizablePanel defaultSize="25" minSize="15" collapsible class="tw:p-4">Outline</div>
245
+ </div>
246
+ @if (dragging()) {
247
+ <p class="tw:text-muted-foreground tw:text-sm">Resizing…</p>
248
+ }
249
+ `,
250
+ })
251
+ export class IdeResizableComponent {
252
+ readonly dragging = signal(false);
253
+
254
+ onLayout(layout: unknown): void {
255
+ console.log('panel layout:', layout);
256
+ }
257
+ }
258
+ ```
259
+
260
+ ## Accessibility notes
261
+
262
+ - The drag handle is keyboard-focusable via the underlying `BrnResizableHandle` — ensure handles remain in the tab order (do not set `tabindex="-1"` on them).
263
+ - A handle without `withHandle` is only a 1px strip visually; prefer `withHandle` when pointer users need a bigger grab target, and keep `disabled` handles out of confusing layouts (they still occupy space).
264
+ - Give each region a landmark or label (`role="region"` + `aria-label`, or headings) so screen-reader users understand the pane structure, since drag-to-resize itself is pointer/keyboard driven on the handle.
265
+
266
+ ## Theming / CSS variables
267
+
268
+ Class-driven only (flex direction, borders, cursors). Size the group with your own height/width utilities — panels size themselves as percentages of it.
269
+
270
+ ## Related subpaths
271
+
272
+ - `@egose/shadcn-theme-ng/card` — paneled content inside resizable regions
273
+ - `@egose/shadcn-theme-ng/scroll-area` — scrollable overflow inside fixed-size panels
274
+ - `@egose/shadcn-theme-ng/sidebar` — app-level collapsible navigation (alternative to a resizable nav pane)
275
+ - `@egose/shadcn-theme-ng/separator` — static visual dividers where resizing is not needed
@@ -6,12 +6,12 @@ import { classes } from '@egose/shadcn-theme-ng-tw/utils';
6
6
 
7
7
  class HlmResizableGroup {
8
8
  constructor() {
9
- classes(() => 'group flex h-full w-full data-[panel-group-direction=vertical]:flex-col');
9
+ classes(() => 'tw:group tw:flex tw:h-full tw:w-full tw:data-[panel-group-direction=vertical]:flex-col');
10
10
  }
11
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
12
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmResizableGroup, isStandalone: true, selector: "[hlmResizableGroup],hlm-resizable-group", host: { attributes: { "data-slot": "resizable-group" } }, hostDirectives: [{ directive: i1.BrnResizableGroup, inputs: ["direction", "direction", "layout", "layout"], outputs: ["dragEnd", "dragEnd", "dragStart", "dragStart", "layoutChange", "layoutChange"] }], ngImport: i0 });
11
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
12
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmResizableGroup, isStandalone: true, selector: "[hlmResizableGroup],hlm-resizable-group", host: { attributes: { "data-slot": "resizable-group" } }, hostDirectives: [{ directive: i1.BrnResizableGroup, inputs: ["direction", "direction", "layout", "layout"], outputs: ["dragEnd", "dragEnd", "dragStart", "dragStart", "layoutChange", "layoutChange"] }], ngImport: i0 });
13
13
  }
14
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableGroup, decorators: [{
14
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableGroup, decorators: [{
15
15
  type: Directive,
16
16
  args: [{
17
17
  selector: '[hlmResizableGroup],hlm-resizable-group',
@@ -32,18 +32,18 @@ class HlmResizableHandle {
32
32
  _brnResizableHandle = inject(BrnResizableHandle);
33
33
  constructor() {
34
34
  classes(() => [
35
- 'bg-border ring-offset-background focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90',
36
- 'data-[panel-group-direction=horizontal]:hover:cursor-ew-resize data-[panel-group-direction=vertical]:hover:cursor-ns-resize',
35
+ 'tw:bg-border tw:ring-offset-background tw:focus-visible:ring-ring tw:relative tw:flex tw:w-px tw:items-center tw:justify-center tw:after:absolute tw:after:inset-y-0 tw:after:left-1/2 tw:after:w-1 tw:after:-translate-x-1/2 tw:focus-visible:ring-1 tw:focus-visible:outline-hidden tw:data-[panel-group-direction=vertical]:h-px tw:data-[panel-group-direction=vertical]:w-full tw:data-[panel-group-direction=vertical]:after:left-0 tw:data-[panel-group-direction=vertical]:after:h-1 tw:data-[panel-group-direction=vertical]:after:w-full tw:data-[panel-group-direction=vertical]:after:translate-x-0 tw:data-[panel-group-direction=vertical]:after:-translate-y-1/2 tw:[&[data-panel-group-direction=vertical]>div]:rotate-90',
36
+ 'tw:data-[panel-group-direction=horizontal]:hover:cursor-ew-resize tw:data-[panel-group-direction=vertical]:hover:cursor-ns-resize',
37
37
  ]);
38
38
  }
39
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableHandle, deps: [], target: i0.ɵɵFactoryTarget.Component });
40
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: HlmResizableHandle, isStandalone: true, selector: "hlm-resizable-handle", host: { attributes: { "data-slot": "resizable-handle" } }, exportAs: ["hlmResizableHandle"], hostDirectives: [{ directive: i1.BrnResizableHandle, inputs: ["withHandle", "withHandle", "disabled", "disabled"] }], ngImport: i0, template: `
39
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableHandle, deps: [], target: i0.ɵɵFactoryTarget.Component });
40
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: HlmResizableHandle, isStandalone: true, selector: "hlm-resizable-handle", host: { attributes: { "data-slot": "resizable-handle" } }, exportAs: ["hlmResizableHandle"], hostDirectives: [{ directive: i1.BrnResizableHandle, inputs: ["withHandle", "withHandle", "disabled", "disabled"] }], ngImport: i0, template: `
41
41
  @if (_brnResizableHandle.withHandle()) {
42
- <div class="bg-border h-6 w-1 rounded-lg z-10 flex shrink-0"></div>
42
+ <div class="tw:bg-border tw:h-6 tw:w-1 tw:rounded-lg tw:z-10 tw:flex tw:shrink-0"></div>
43
43
  }
44
44
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
45
45
  }
46
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableHandle, decorators: [{
46
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableHandle, decorators: [{
47
47
  type: Component,
48
48
  args: [{
49
49
  selector: 'hlm-resizable-handle',
@@ -55,7 +55,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
55
55
  },
56
56
  template: `
57
57
  @if (_brnResizableHandle.withHandle()) {
58
- <div class="bg-border h-6 w-1 rounded-lg z-10 flex shrink-0"></div>
58
+ <div class="tw:bg-border tw:h-6 tw:w-1 tw:rounded-lg tw:z-10 tw:flex tw:shrink-0"></div>
59
59
  }
60
60
  `,
61
61
  }]
@@ -66,10 +66,10 @@ class HlmResizablePanel {
66
66
  setSize(size) {
67
67
  this._resizablePanel.setSize(size);
68
68
  }
69
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizablePanel, deps: [], target: i0.ɵɵFactoryTarget.Directive });
70
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmResizablePanel, isStandalone: true, selector: "[hlmResizablePanel],hlm-resizable-panel", host: { attributes: { "data-slot": "resizable-panel" } }, exportAs: ["hlmResizablePanel"], hostDirectives: [{ directive: i1.BrnResizablePanel, inputs: ["defaultSize", "defaultSize", "id", "id", "collapsible", "collapsible", "maxSize", "maxSize", "minSize", "minSize"] }], ngImport: i0 });
69
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizablePanel, deps: [], target: i0.ɵɵFactoryTarget.Directive });
70
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmResizablePanel, isStandalone: true, selector: "[hlmResizablePanel],hlm-resizable-panel", host: { attributes: { "data-slot": "resizable-panel" } }, exportAs: ["hlmResizablePanel"], hostDirectives: [{ directive: i1.BrnResizablePanel, inputs: ["defaultSize", "defaultSize", "id", "id", "collapsible", "collapsible", "maxSize", "maxSize", "minSize", "minSize"] }], ngImport: i0 });
71
71
  }
72
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizablePanel, decorators: [{
72
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizablePanel, decorators: [{
73
73
  type: Directive,
74
74
  args: [{
75
75
  selector: '[hlmResizablePanel],hlm-resizable-panel',
@@ -91,11 +91,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
91
91
  */
92
92
  const HlmResizableImports = [HlmResizableGroup, HlmResizablePanel, HlmResizableHandle];
93
93
  class HlmResizableModule {
94
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
95
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableModule, imports: [HlmResizableGroup, HlmResizablePanel, HlmResizableHandle], exports: [HlmResizableGroup, HlmResizablePanel, HlmResizableHandle] });
96
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableModule });
94
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
95
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableModule, imports: [HlmResizableGroup, HlmResizablePanel, HlmResizableHandle], exports: [HlmResizableGroup, HlmResizablePanel, HlmResizableHandle] });
96
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableModule });
97
97
  }
98
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmResizableModule, decorators: [{
98
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmResizableModule, decorators: [{
99
99
  type: NgModule,
100
100
  args: [{
101
101
  imports: [...HlmResizableImports],
@@ -108,4 +108,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
108
108
  */
109
109
 
110
110
  export { HlmResizableGroup, HlmResizableHandle, HlmResizableImports, HlmResizableModule, HlmResizablePanel };
111
- //# sourceMappingURL=resizable.mjs.map
111
+
@@ -1,11 +1,239 @@
1
- # ScrollArea
1
+ # Scroll Area (`@egose/shadcn-theme-ng/scroll-area`)
2
2
 
3
- This project was generated using [Angular CLI](https://github.com/angular/angular-cli).
3
+ A shadcn/ui-style **Scroll Area** — a themed scrollable container with hover-reveal scrollbars. This is the Angular equivalent of shadcn/ui `ScrollArea`.
4
4
 
5
- ## Building
5
+ Unlike most subpaths in this library it is **not** built on spartan-ng/brain: it is a thin directive wrapper over `NgScrollbar` from **ngx-scrollbar**. The directive matches `ng-scrollbar[hlm]` (or `ng-scrollbar[hlmScrollbar]`), forces `visibility: 'hover'` scrollbar options, and pins the shadcn scrollbar CSS variables (thumb color, track color/thickness) so every scroll area looks consistent with the theme.
6
6
 
7
- To build the library, run:
7
+ > **Ships as:** `@egose/shadcn-theme-ng/scroll-area` and `@egose/shadcn-theme-ng-tw/scroll-area` (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
- ng build scroll-area
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
18
+ ```
19
+
20
+ ```ts
21
+ import { HlmScrollAreaImports } from '@egose/shadcn-theme-ng/scroll-area';
22
+ // tw variant:
23
+ // import { HlmScrollAreaImports } from '@egose/shadcn-theme-ng-tw/scroll-area';
11
24
  ```
25
+
26
+ Peer dependencies (see [package README](../../README.md) for versions): `@angular/core`, `@angular/common`, `@spartan-ng/brain`. Runtime `ngx-scrollbar` is installed transitively — but note you must import `NgScrollbar` itself (from `ngx-scrollbar`) wherever you use the directive, since this package only provides the `hlm` styling layer.
27
+
28
+ ## Imports
29
+
30
+ Real exported symbols (from `src/public-api.ts`):
31
+
32
+ | Symbol | Kind | Description |
33
+ | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------- |
34
+ | `HlmScrollArea` | Directive | Styling/behavior layer for `NgScrollbar`; selector `ng-scrollbar[hlm],ng-scrollbar[hlmScrollbar]` |
35
+ | `HlmScrollAreaImports` | `const` array | `[HlmScrollArea]` standalone imports |
36
+ | `HlmScrollAreaModule` | `NgModule` | NgModule wrapper re-exporting `HlmScrollArea` |
37
+
38
+ Standalone usage (you almost always pair it with `NgScrollbar`):
39
+
40
+ ```ts
41
+ import { Component } from '@angular/core';
42
+ import { NgScrollbar } from 'ngx-scrollbar';
43
+ import { HlmScrollAreaImports } from '@egose/shadcn-theme-ng/scroll-area';
44
+
45
+ @Component({
46
+ selector: 'app-demo',
47
+ standalone: true,
48
+ imports: [NgScrollbar, HlmScrollAreaImports],
49
+ template: ` <ng-scrollbar hlm class="tw:h-64"> ... </ng-scrollbar> `,
50
+ })
51
+ export class DemoComponent {}
52
+ ```
53
+
54
+ NgModule usage:
55
+
56
+ ```ts
57
+ import { NgModule } from '@angular/core';
58
+ import { NgScrollbar } from 'ngx-scrollbar';
59
+ import { HlmScrollAreaModule } from '@egose/shadcn-theme-ng/scroll-area';
60
+
61
+ @NgModule({ imports: [NgScrollbar, HlmScrollAreaModule] })
62
+ export class DemoModule {}
63
+ ```
64
+
65
+ ## Anatomy / Structure
66
+
67
+ ```html
68
+ <ng-scrollbar hlm class="tw:h-72 tw:w-80 tw:rounded-md tw:border">
69
+ <div class="tw:p-4">
70
+ <h4>Title</h4>
71
+ <p>Scrollable content…</p>
72
+ </div>
73
+ </ng-scrollbar>
74
+ ```
75
+
76
+ Real selectors:
77
+
78
+ | Selector | Class | Notes |
79
+ | ------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------- |
80
+ | `ng-scrollbar[hlm]`, `ng-scrollbar[hlmScrollbar]` | `HlmScrollArea` | `data-slot="scroll-area"`; requires the `NgScrollbar` component from `ngx-scrollbar` as the host element |
81
+
82
+ The directive sets these host bindings: `--scrollbar-thumb-color` and `--scrollbar-thumb-hover-color` to `var(--border)`, `--scrollbar-track-color: transparent`, `--scrollbar-track-thickness: 0.625rem`, `--scrollbar-track-offset: 1.5px`, plus a rounded/pill thumb shape and block layout classes. Scrollbars appear on hover (`visibility: 'hover'`).
83
+
84
+ ## API reference
85
+
86
+ `HlmScrollArea` declares **no inputs, outputs, or methods of its own** — it is a pure styling directive. All scrolling behavior/inputs (e.g. `orientation`, `visibility` overrides, viewport access) come from the host `NgScrollbar` component itself; consult the `ngx-scrollbar` API for those.
87
+
88
+ | Host CSS variables set by the directive | Value |
89
+ | --------------------------------------- | -------------------- |
90
+ | `--scrollbar-thumb-color` | `var(--border)` |
91
+ | `--scrollbar-thumb-hover-color` | `var(--border)` |
92
+ | `--scrollbar-track-color` | `transparent` |
93
+ | `--scrollbar-track-thickness` | `0.625rem` |
94
+ | `--scrollbar-track-offset` | `1.5px` |
95
+ | `--scrollbar-thumb-shape` | `9999px` (via class) |
96
+
97
+ ## Examples
98
+
99
+ ### 1. Basic vertical scroll area
100
+
101
+ ```ts
102
+ import { Component } from '@angular/core';
103
+ import { NgScrollbar } from 'ngx-scrollbar';
104
+ import { HlmScrollAreaImports } from '@egose/shadcn-theme-ng/scroll-area';
105
+
106
+ @Component({
107
+ selector: 'app-basic-scroll',
108
+ standalone: true,
109
+ imports: [NgScrollbar, HlmScrollAreaImports],
110
+ template: `
111
+ <ng-scrollbar hlm class="tw:h-64 tw:w-80 tw:rounded-md tw:border">
112
+ <div class="tw:p-4 tw:space-y-2">
113
+ @for (item of items; track item) {
114
+ <p class="tw:text-sm">{{ item }}</p>
115
+ }
116
+ </div>
117
+ </ng-scrollbar>
118
+ `,
119
+ })
120
+ export class BasicScrollComponent {
121
+ readonly items = Array.from({ length: 50 }, (_, i) => `Item ${i + 1}`);
122
+ }
123
+ ```
124
+
125
+ ### 2. Fixed-height log / chat window
126
+
127
+ ```ts
128
+ import { Component, signal } from '@angular/core';
129
+ import { NgScrollbar } from 'ngx-scrollbar';
130
+ import { HlmScrollAreaImports } from '@egose/shadcn-theme-ng/scroll-area';
131
+
132
+ @Component({
133
+ selector: 'app-log-scroll',
134
+ standalone: true,
135
+ imports: [NgScrollbar, HlmScrollAreaImports],
136
+ template: `
137
+ <ng-scrollbar hlm class="tw:h-72 tw:rounded-md tw:border tw:bg-muted/30">
138
+ <div class="tw:p-4 tw:font-mono tw:text-xs tw:space-y-1">
139
+ @for (line of lines(); track $index) {
140
+ <div>{{ line }}</div>
141
+ }
142
+ </div>
143
+ </ng-scrollbar>
144
+ <button type="button" (click)="addLine()">Add line</button>
145
+ `,
146
+ })
147
+ export class LogScrollComponent {
148
+ readonly lines = signal(['[ok] booted', '[ok] connected']);
149
+
150
+ addLine(): void {
151
+ this.lines.update((ls) => [...ls, `[log] event ${ls.length}`]);
152
+ }
153
+ }
154
+ ```
155
+
156
+ ### 3. Horizontal scrolling row
157
+
158
+ `NgScrollbar` supports horizontal viewports — the `hlm` styling applies the same way:
159
+
160
+ ```html
161
+ <ng-scrollbar hlm orientation="horizontal" class="tw:w-full tw:max-w-xl tw:rounded-md tw:border">
162
+ <div class="tw:flex tw:gap-3 tw:p-4 tw:w-max">
163
+ @for (card of cards; track card) {
164
+ <div class="tw:h-24 tw:w-40 tw:shrink-0 tw:rounded-md tw:bg-muted tw:p-2">{{ card }}</div>
165
+ }
166
+ </div>
167
+ </ng-scrollbar>
168
+ ```
169
+
170
+ ### 4. Scroll area inside a card
171
+
172
+ ```html
173
+ <div class="tw:rounded-lg tw:border tw:p-4">
174
+ <h3 class="tw:mb-2 tw:font-semibold">Recent activity</h3>
175
+ <ng-scrollbar hlm class="tw:h-48">
176
+ <ul class="tw:space-y-2 tw:pe-4">
177
+ @for (event of activity; track event.id) {
178
+ <li class="tw:flex tw:justify-between tw:text-sm">
179
+ <span>{{ event.label }}</span>
180
+ <span class="tw:text-muted-foreground">{{ event.at }}</span>
181
+ </li>
182
+ }
183
+ </ul>
184
+ </ng-scrollbar>
185
+ </div>
186
+ ```
187
+
188
+ Leave end-padding (`pe-4`) so text never slides under the hover scrollbar.
189
+
190
+ ### 5. Long select/popover content
191
+
192
+ Scrollable dropdown content with the themed thumb:
193
+
194
+ ```html
195
+ <ng-scrollbar hlm class="tw:max-h-60 tw:w-64 tw:rounded-md tw:border">
196
+ <div class="tw:p-1">
197
+ @for (option of options; track option.value) {
198
+ <button
199
+ type="button"
200
+ (click)="pick(option)"
201
+ class="tw:w-full tw:rounded-sm tw:px-2 tw:py-1.5 tw:text-left tw:text-sm tw:hover:bg-accent"
202
+ >
203
+ {{ option.label }}
204
+ </button>
205
+ }
206
+ </div>
207
+ </ng-scrollbar>
208
+ ```
209
+
210
+ ### 6. Overriding thumb color per instance
211
+
212
+ The colors are CSS variables, so any instance can be re-themed inline:
213
+
214
+ ```html
215
+ <ng-scrollbar
216
+ hlm
217
+ class="tw:h-64 tw:rounded-md tw:border"
218
+ style="--scrollbar-thumb-color: var(--primary); --scrollbar-thumb-hover-color: var(--primary);"
219
+ >
220
+ <div class="tw:p-4">Brand-colored scrollbar…</div>
221
+ </ng-scrollbar>
222
+ ```
223
+
224
+ ## Accessibility notes
225
+
226
+ - `NgScrollbar` keeps native scroll semantics; keyboard users can scroll the region with arrows/PageUp/PageDown when it has focus — make sure scrollable regions with important content are focusable (`tabindex="0"`) and labelled (`aria-label`/`role="region"`).
227
+ - Hover-only scrollbars can be hard to discover for pointer users and invisible to some low-vision users — for primary page-level scrolling prefer native overflow; reserve this component for secondary panes (sidebars, dropdowns, logs).
228
+ - Do not nest scroll areas with competing orientations unless each has a clear label; nested scroll traps confuse both keyboard and screen-reader users.
229
+
230
+ ## Theming / CSS variables
231
+
232
+ The component is driven by `--scrollbar-*` variables (see table above) plus the theme's `--border` token. Override per instance with inline `style` as shown in example 6; dark mode follows automatically through the theme tokens.
233
+
234
+ ## Related subpaths
235
+
236
+ - `@egose/shadcn-theme-ng/resizable` — fixed-size panes that pair well with internal scroll areas
237
+ - `@egose/shadcn-theme-ng/select` — its dropdown content scrolls internally for long option lists
238
+ - `@egose/shadcn-theme-ng/sidebar` — sidebar content areas that often need themed scrolling
239
+ - `@egose/shadcn-theme-ng/card` — bordered containers frequently wrapped around scroll areas
@@ -5,12 +5,12 @@ import { provideScrollbarOptions } from 'ngx-scrollbar';
5
5
 
6
6
  class HlmScrollArea {
7
7
  constructor() {
8
- classes(() => 'rounded-md [--scrollbar-thumb-shape:9999px] block');
8
+ classes(() => 'tw:rounded-md tw:[--scrollbar-thumb-shape:9999px] tw:block');
9
9
  }
10
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmScrollArea, deps: [], target: i0.ɵɵFactoryTarget.Directive });
11
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.7", type: HlmScrollArea, isStandalone: true, selector: "ng-scrollbar[hlm],ng-scrollbar[hlmScrollbar]", host: { attributes: { "data-slot": "scroll-area" }, properties: { "style.--scrollbar-thumb-color": "\"var(--border)\"", "style.--scrollbar-thumb-hover-color": "\"var(--border)\"", "style.--scrollbar-track-color": "\"transparent\"", "style.--scrollbar-track-thickness": "\"0.625rem\"", "style.--scrollbar-track-offset": "\"1.5px\"" } }, providers: [provideScrollbarOptions({ visibility: 'hover' })], ngImport: i0 });
10
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmScrollArea, deps: [], target: i0.ɵɵFactoryTarget.Directive });
11
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmScrollArea, isStandalone: true, selector: "ng-scrollbar[hlm],ng-scrollbar[hlmScrollbar]", host: { attributes: { "data-slot": "scroll-area" }, properties: { "style.--scrollbar-thumb-color": "\"var(--border)\"", "style.--scrollbar-thumb-hover-color": "\"var(--border)\"", "style.--scrollbar-track-color": "\"transparent\"", "style.--scrollbar-track-thickness": "\"0.625rem\"", "style.--scrollbar-track-offset": "\"1.5px\"" } }, providers: [provideScrollbarOptions({ visibility: 'hover' })], ngImport: i0 });
12
12
  }
13
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmScrollArea, decorators: [{
13
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmScrollArea, decorators: [{
14
14
  type: Directive,
15
15
  args: [{
16
16
  selector: 'ng-scrollbar[hlm],ng-scrollbar[hlmScrollbar]',
@@ -31,11 +31,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
31
31
  */
32
32
  const HlmScrollAreaImports = [HlmScrollArea];
33
33
  class HlmScrollAreaModule {
34
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmScrollAreaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
35
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.7", ngImport: i0, type: HlmScrollAreaModule, imports: [HlmScrollArea], exports: [HlmScrollArea] });
36
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmScrollAreaModule });
34
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmScrollAreaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
35
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.1.3", ngImport: i0, type: HlmScrollAreaModule, imports: [HlmScrollArea], exports: [HlmScrollArea] });
36
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmScrollAreaModule });
37
37
  }
38
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: HlmScrollAreaModule, decorators: [{
38
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmScrollAreaModule, decorators: [{
39
39
  type: NgModule,
40
40
  args: [{
41
41
  imports: [...HlmScrollAreaImports],
@@ -48,4 +48,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
48
48
  */
49
49
 
50
50
  export { HlmScrollArea, HlmScrollAreaImports, HlmScrollAreaModule };
51
- //# sourceMappingURL=scroll-area.mjs.map
51
+