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

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 (333) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +107 -2
  3. package/accordion/fesm2022/accordion.mjs +42 -37
  4. package/accordion/fesm2022/accordion.mjs.map +1 -1
  5. package/accordion/package.json +25 -0
  6. package/accordion/{index.d.ts → types/accordion.d.ts} +1 -1
  7. package/alert/fesm2022/alert.mjs +32 -27
  8. package/alert/fesm2022/alert.mjs.map +1 -1
  9. package/alert/package.json +25 -0
  10. package/alert-dialog/README.md +11 -0
  11. package/alert-dialog/fesm2022/alert-dialog.mjs +287 -0
  12. package/alert-dialog/fesm2022/alert-dialog.mjs.map +1 -0
  13. package/alert-dialog/package.json +25 -0
  14. package/alert-dialog/types/alert-dialog.d.ts +90 -0
  15. package/aspect-ratio/README.md +11 -0
  16. package/aspect-ratio/fesm2022/aspect-ratio.mjs +62 -0
  17. package/aspect-ratio/fesm2022/aspect-ratio.mjs.map +1 -0
  18. package/aspect-ratio/package.json +25 -0
  19. package/aspect-ratio/types/aspect-ratio.d.ts +21 -0
  20. package/autocomplete/fesm2022/autocomplete.mjs +323 -457
  21. package/autocomplete/fesm2022/autocomplete.mjs.map +1 -1
  22. package/autocomplete/package.json +24 -0
  23. package/autocomplete/types/autocomplete.d.ts +96 -0
  24. package/avatar/README.md +11 -0
  25. package/avatar/fesm2022/avatar.mjs +178 -0
  26. package/avatar/fesm2022/avatar.mjs.map +1 -0
  27. package/avatar/package.json +25 -0
  28. package/avatar/types/avatar.d.ts +50 -0
  29. package/badge/fesm2022/badge.mjs +16 -10
  30. package/badge/fesm2022/badge.mjs.map +1 -1
  31. package/badge/package.json +25 -0
  32. package/basic-alert/fesm2022/basic-alert.mjs +12 -8
  33. package/basic-alert/fesm2022/basic-alert.mjs.map +1 -1
  34. package/basic-alert/package.json +24 -0
  35. package/breadcrumb/README.md +11 -0
  36. package/breadcrumb/fesm2022/breadcrumb.mjs +224 -0
  37. package/breadcrumb/fesm2022/breadcrumb.mjs.map +1 -0
  38. package/breadcrumb/package.json +25 -0
  39. package/breadcrumb/types/breadcrumb.d.ts +57 -0
  40. package/button/fesm2022/button.mjs +100 -26
  41. package/button/fesm2022/button.mjs.map +1 -1
  42. package/button/package.json +25 -0
  43. package/button/{index.d.ts → types/button.d.ts} +30 -9
  44. package/button-group/README.md +11 -0
  45. package/button-group/fesm2022/button-group.mjs +102 -0
  46. package/button-group/fesm2022/button-group.mjs.map +1 -0
  47. package/button-group/package.json +25 -0
  48. package/button-group/types/button-group.d.ts +30 -0
  49. package/calendar/fesm2022/calendar.mjs +868 -546
  50. package/calendar/fesm2022/calendar.mjs.map +1 -1
  51. package/calendar/package.json +24 -0
  52. package/calendar/types/calendar.d.ts +94 -0
  53. package/card/README.md +11 -0
  54. package/card/fesm2022/card.mjs +169 -0
  55. package/card/fesm2022/card.mjs.map +1 -0
  56. package/card/package.json +25 -0
  57. package/card/types/card.d.ts +54 -0
  58. package/carousel/README.md +11 -0
  59. package/carousel/fesm2022/carousel.mjs +309 -0
  60. package/carousel/fesm2022/carousel.mjs.map +1 -0
  61. package/carousel/package.json +25 -0
  62. package/carousel/types/carousel.d.ts +84 -0
  63. package/checkbox/fesm2022/checkbox.mjs +25 -20
  64. package/checkbox/fesm2022/checkbox.mjs.map +1 -1
  65. package/checkbox/package.json +24 -0
  66. package/collapsible/README.md +11 -0
  67. package/collapsible/fesm2022/collapsible.mjs +77 -0
  68. package/collapsible/fesm2022/collapsible.mjs.map +1 -0
  69. package/collapsible/package.json +25 -0
  70. package/collapsible/types/collapsible.d.ts +27 -0
  71. package/combobox/README.md +11 -0
  72. package/combobox/fesm2022/combobox.mjs +683 -0
  73. package/combobox/fesm2022/combobox.mjs.map +1 -0
  74. package/combobox/package.json +25 -0
  75. package/combobox/types/combobox.d.ts +151 -0
  76. package/command/README.md +11 -0
  77. package/command/fesm2022/command.mjs +361 -0
  78. package/command/fesm2022/command.mjs.map +1 -0
  79. package/command/package.json +25 -0
  80. package/command/types/command.d.ts +89 -0
  81. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs +19 -8
  82. package/confirmation-dialog/fesm2022/confirmation-dialog.mjs.map +1 -1
  83. package/confirmation-dialog/package.json +24 -0
  84. package/context-menu/README.md +11 -0
  85. package/context-menu/fesm2022/context-menu.mjs +89 -0
  86. package/context-menu/fesm2022/context-menu.mjs.map +1 -0
  87. package/context-menu/package.json +25 -0
  88. package/context-menu/types/context-menu.d.ts +34 -0
  89. package/date-picker/fesm2022/date-picker.mjs +1262 -307
  90. package/date-picker/fesm2022/date-picker.mjs.map +1 -1
  91. package/date-picker/package.json +24 -0
  92. package/date-picker/types/date-picker.d.ts +551 -0
  93. package/dialog/fesm2022/dialog.mjs +137 -108
  94. package/dialog/fesm2022/dialog.mjs.map +1 -1
  95. package/dialog/package.json +24 -0
  96. package/dialog/types/dialog.d.ts +95 -0
  97. package/drawer/README.md +11 -0
  98. package/drawer/fesm2022/drawer.mjs +271 -0
  99. package/drawer/fesm2022/drawer.mjs.map +1 -0
  100. package/drawer/package.json +25 -0
  101. package/drawer/types/drawer.d.ts +76 -0
  102. package/dropdown-menu/README.md +11 -0
  103. package/dropdown-menu/fesm2022/dropdown-menu.mjs +542 -0
  104. package/dropdown-menu/fesm2022/dropdown-menu.mjs.map +1 -0
  105. package/dropdown-menu/package.json +25 -0
  106. package/dropdown-menu/types/dropdown-menu.d.ts +176 -0
  107. package/empty/README.md +11 -0
  108. package/empty/fesm2022/empty.mjs +151 -0
  109. package/empty/fesm2022/empty.mjs.map +1 -0
  110. package/empty/package.json +25 -0
  111. package/empty/types/empty.d.ts +54 -0
  112. package/field/README.md +11 -0
  113. package/field/fesm2022/field.mjs +367 -0
  114. package/field/fesm2022/field.mjs.map +1 -0
  115. package/field/package.json +25 -0
  116. package/field/types/field.d.ts +107 -0
  117. package/form-checkbox/fesm2022/form-checkbox.mjs +39 -22
  118. package/form-checkbox/fesm2022/form-checkbox.mjs.map +1 -1
  119. package/form-checkbox/package.json +24 -0
  120. package/form-date-picker/fesm2022/form-date-picker.mjs +58 -51
  121. package/form-date-picker/fesm2022/form-date-picker.mjs.map +1 -1
  122. package/form-date-picker/package.json +24 -0
  123. package/form-field/fesm2022/form-field.mjs +39 -27
  124. package/form-field/fesm2022/form-field.mjs.map +1 -1
  125. package/form-field/package.json +25 -0
  126. package/form-field/{index.d.ts → types/form-field.d.ts} +4 -3
  127. package/form-field-simple/fesm2022/form-field-simple.mjs +15 -10
  128. package/form-field-simple/fesm2022/form-field-simple.mjs.map +1 -1
  129. package/form-field-simple/package.json +24 -0
  130. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +44 -25
  131. package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs.map +1 -1
  132. package/form-searchable-multiselect/package.json +24 -0
  133. package/form-select/fesm2022/form-select.mjs +132 -71
  134. package/form-select/fesm2022/form-select.mjs.map +1 -1
  135. package/form-select/package.json +24 -0
  136. package/form-text-input/fesm2022/form-text-input.mjs +68 -39
  137. package/form-text-input/fesm2022/form-text-input.mjs.map +1 -1
  138. package/form-text-input/package.json +24 -0
  139. package/form-textarea/fesm2022/form-textarea.mjs +54 -30
  140. package/form-textarea/fesm2022/form-textarea.mjs.map +1 -1
  141. package/form-textarea/package.json +24 -0
  142. package/hover-card/README.md +11 -0
  143. package/hover-card/fesm2022/hover-card.mjs +123 -0
  144. package/hover-card/fesm2022/hover-card.mjs.map +1 -0
  145. package/hover-card/package.json +25 -0
  146. package/hover-card/types/hover-card.d.ts +36 -0
  147. package/icon/fesm2022/icon.mjs +12 -10
  148. package/icon/fesm2022/icon.mjs.map +1 -1
  149. package/icon/package.json +25 -0
  150. package/input/fesm2022/input.mjs +20 -70
  151. package/input/fesm2022/input.mjs.map +1 -1
  152. package/input/package.json +25 -0
  153. package/input/types/input.d.ts +18 -0
  154. package/input-group/README.md +11 -0
  155. package/input-group/fesm2022/input-group.mjs +199 -0
  156. package/input-group/fesm2022/input-group.mjs.map +1 -0
  157. package/input-group/package.json +25 -0
  158. package/input-group/types/input-group.d.ts +52 -0
  159. package/input-otp/README.md +11 -0
  160. package/input-otp/fesm2022/input-otp.mjs +141 -0
  161. package/input-otp/fesm2022/input-otp.mjs.map +1 -0
  162. package/input-otp/package.json +25 -0
  163. package/input-otp/types/input-otp.d.ts +43 -0
  164. package/item/README.md +11 -0
  165. package/item/fesm2022/item.mjs +278 -0
  166. package/item/fesm2022/item.mjs.map +1 -0
  167. package/item/package.json +25 -0
  168. package/item/types/item.d.ts +101 -0
  169. package/kbd/README.md +11 -0
  170. package/kbd/fesm2022/kbd.mjs +61 -0
  171. package/kbd/fesm2022/kbd.mjs.map +1 -0
  172. package/kbd/package.json +25 -0
  173. package/kbd/types/kbd.d.ts +22 -0
  174. package/label/fesm2022/label.mjs +11 -10
  175. package/label/fesm2022/label.mjs.map +1 -1
  176. package/label/package.json +25 -0
  177. package/layout-simple/fesm2022/layout-simple.mjs +438 -325
  178. package/layout-simple/fesm2022/layout-simple.mjs.map +1 -1
  179. package/layout-simple/package.json +24 -0
  180. package/layout-simple/{index.d.ts → types/layout-simple.d.ts} +28 -17
  181. package/menubar/README.md +11 -0
  182. package/menubar/fesm2022/menubar.mjs +108 -0
  183. package/menubar/fesm2022/menubar.mjs.map +1 -0
  184. package/menubar/package.json +25 -0
  185. package/menubar/types/menubar.d.ts +40 -0
  186. package/native-select/README.md +11 -0
  187. package/native-select/fesm2022/native-select.mjs +207 -0
  188. package/native-select/fesm2022/native-select.mjs.map +1 -0
  189. package/native-select/package.json +25 -0
  190. package/native-select/types/native-select.d.ts +70 -0
  191. package/navigation-menu/README.md +11 -0
  192. package/navigation-menu/fesm2022/navigation-menu.mjs +206 -0
  193. package/navigation-menu/fesm2022/navigation-menu.mjs.map +1 -0
  194. package/navigation-menu/package.json +25 -0
  195. package/navigation-menu/types/navigation-menu.d.ts +54 -0
  196. package/package.json +223 -81
  197. package/pagination/README.md +11 -0
  198. package/pagination/fesm2022/pagination.mjs +808 -0
  199. package/pagination/fesm2022/pagination.mjs.map +1 -0
  200. package/pagination/package.json +25 -0
  201. package/pagination/types/pagination.d.ts +192 -0
  202. package/popover/fesm2022/popover.mjs +121 -27
  203. package/popover/fesm2022/popover.mjs.map +1 -1
  204. package/popover/package.json +24 -0
  205. package/popover/types/popover.d.ts +54 -0
  206. package/progress/README.md +11 -0
  207. package/progress/fesm2022/progress.mjs +77 -0
  208. package/progress/fesm2022/progress.mjs.map +1 -0
  209. package/progress/package.json +25 -0
  210. package/progress/types/progress.d.ts +27 -0
  211. package/radio-group/fesm2022/radio-group.mjs +97 -63
  212. package/radio-group/fesm2022/radio-group.mjs.map +1 -1
  213. package/radio-group/package.json +25 -0
  214. package/radio-group/{index.d.ts → types/radio-group.d.ts} +22 -14
  215. package/resizable/README.md +11 -0
  216. package/resizable/fesm2022/resizable.mjs +111 -0
  217. package/resizable/fesm2022/resizable.mjs.map +1 -0
  218. package/resizable/package.json +25 -0
  219. package/resizable/types/resizable.d.ts +32 -0
  220. package/scroll-area/README.md +11 -0
  221. package/scroll-area/fesm2022/scroll-area.mjs +51 -0
  222. package/scroll-area/fesm2022/scroll-area.mjs.map +1 -0
  223. package/scroll-area/package.json +25 -0
  224. package/scroll-area/types/scroll-area.d.ts +16 -0
  225. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +92 -88
  226. package/searchable-multiselect/fesm2022/searchable-multiselect.mjs.map +1 -1
  227. package/searchable-multiselect/package.json +24 -0
  228. package/searchable-multiselect/{index.d.ts → types/searchable-multiselect.d.ts} +13 -24
  229. package/select/fesm2022/select.mjs +371 -189
  230. package/select/fesm2022/select.mjs.map +1 -1
  231. package/select/package.json +25 -0
  232. package/select/types/select.d.ts +119 -0
  233. package/separator/fesm2022/separator.mjs +16 -14
  234. package/separator/fesm2022/separator.mjs.map +1 -1
  235. package/separator/package.json +24 -0
  236. package/separator/{index.d.ts → types/separator.d.ts} +4 -5
  237. package/sheet/fesm2022/sheet.mjs +57 -51
  238. package/sheet/fesm2022/sheet.mjs.map +1 -1
  239. package/sheet/package.json +24 -0
  240. package/sidebar/README.md +11 -0
  241. package/sidebar/fesm2022/sidebar.mjs +948 -0
  242. package/sidebar/fesm2022/sidebar.mjs.map +1 -0
  243. package/sidebar/package.json +25 -0
  244. package/sidebar/types/sidebar.d.ts +237 -0
  245. package/skeleton/README.md +11 -0
  246. package/skeleton/fesm2022/skeleton.mjs +44 -0
  247. package/skeleton/fesm2022/skeleton.mjs.map +1 -0
  248. package/skeleton/package.json +25 -0
  249. package/skeleton/types/skeleton.d.ts +16 -0
  250. package/slider/README.md +11 -0
  251. package/slider/fesm2022/slider.mjs +144 -0
  252. package/slider/fesm2022/slider.mjs.map +1 -0
  253. package/slider/package.json +25 -0
  254. package/slider/types/slider.d.ts +19 -0
  255. package/sonner/fesm2022/sonner.mjs +30 -35
  256. package/sonner/fesm2022/sonner.mjs.map +1 -1
  257. package/sonner/package.json +25 -0
  258. package/spinner/fesm2022/spinner.mjs +18 -14
  259. package/spinner/fesm2022/spinner.mjs.map +1 -1
  260. package/spinner/package.json +25 -0
  261. package/switch/fesm2022/switch.mjs +29 -26
  262. package/switch/fesm2022/switch.mjs.map +1 -1
  263. package/switch/package.json +25 -0
  264. package/table/README.md +11 -0
  265. package/table/fesm2022/table.mjs +211 -0
  266. package/table/fesm2022/table.mjs.map +1 -0
  267. package/table/package.json +25 -0
  268. package/table/types/table.d.ts +87 -0
  269. package/tabs/fesm2022/tabs.mjs +133 -105
  270. package/tabs/fesm2022/tabs.mjs.map +1 -1
  271. package/tabs/package.json +25 -0
  272. package/tabs/types/tabs.d.ts +71 -0
  273. package/textarea/README.md +11 -0
  274. package/textarea/fesm2022/textarea.mjs +47 -0
  275. package/textarea/fesm2022/textarea.mjs.map +1 -0
  276. package/textarea/package.json +25 -0
  277. package/textarea/types/textarea.d.ts +18 -0
  278. package/toggle/README.md +11 -0
  279. package/toggle/fesm2022/toggle.mjs +78 -0
  280. package/toggle/fesm2022/toggle.mjs.map +1 -0
  281. package/toggle/package.json +25 -0
  282. package/toggle/types/toggle.d.ts +27 -0
  283. package/toggle-group/README.md +11 -0
  284. package/toggle-group/fesm2022/toggle-group.mjs +117 -0
  285. package/toggle-group/fesm2022/toggle-group.mjs.map +1 -0
  286. package/toggle-group/package.json +25 -0
  287. package/toggle-group/types/toggle-group.d.ts +39 -0
  288. package/tooltip/fesm2022/tooltip.mjs +33 -54
  289. package/tooltip/fesm2022/tooltip.mjs.map +1 -1
  290. package/tooltip/package.json +25 -0
  291. package/tooltip/types/tooltip.d.ts +22 -0
  292. package/typography/README.md +11 -0
  293. package/typography/fesm2022/typography.mjs +242 -0
  294. package/typography/fesm2022/typography.mjs.map +1 -0
  295. package/typography/package.json +25 -0
  296. package/typography/types/typography.d.ts +94 -0
  297. package/utils/fesm2022/utils.mjs +184 -1
  298. package/utils/fesm2022/utils.mjs.map +1 -1
  299. package/utils/package.json +25 -0
  300. package/utils/types/utils.d.ts +13 -0
  301. package/autocomplete/index.d.ts +0 -162
  302. package/calendar/index.d.ts +0 -111
  303. package/date-picker/index.d.ts +0 -227
  304. package/dialog/index.d.ts +0 -89
  305. package/exports.json +0 -1
  306. package/input/index.d.ts +0 -41
  307. package/menu/README.md +0 -64
  308. package/menu/fesm2022/menu.mjs +0 -449
  309. package/menu/fesm2022/menu.mjs.map +0 -1
  310. package/menu/index.d.ts +0 -137
  311. package/popover/index.d.ts +0 -30
  312. package/select/index.d.ts +0 -92
  313. package/tabs/index.d.ts +0 -71
  314. package/tooltip/index.d.ts +0 -21
  315. package/utils/index.d.ts +0 -5
  316. /package/alert/{index.d.ts → types/alert.d.ts} +0 -0
  317. /package/badge/{index.d.ts → types/badge.d.ts} +0 -0
  318. /package/basic-alert/{index.d.ts → types/basic-alert.d.ts} +0 -0
  319. /package/checkbox/{index.d.ts → types/checkbox.d.ts} +0 -0
  320. /package/confirmation-dialog/{index.d.ts → types/confirmation-dialog.d.ts} +0 -0
  321. /package/form-checkbox/{index.d.ts → types/form-checkbox.d.ts} +0 -0
  322. /package/form-date-picker/{index.d.ts → types/form-date-picker.d.ts} +0 -0
  323. /package/form-field-simple/{index.d.ts → types/form-field-simple.d.ts} +0 -0
  324. /package/form-searchable-multiselect/{index.d.ts → types/form-searchable-multiselect.d.ts} +0 -0
  325. /package/form-select/{index.d.ts → types/form-select.d.ts} +0 -0
  326. /package/form-text-input/{index.d.ts → types/form-text-input.d.ts} +0 -0
  327. /package/form-textarea/{index.d.ts → types/form-textarea.d.ts} +0 -0
  328. /package/icon/{index.d.ts → types/icon.d.ts} +0 -0
  329. /package/label/{index.d.ts → types/label.d.ts} +0 -0
  330. /package/sheet/{index.d.ts → types/sheet.d.ts} +0 -0
  331. /package/sonner/{index.d.ts → types/sonner.d.ts} +0 -0
  332. /package/spinner/{index.d.ts → types/spinner.d.ts} +0 -0
  333. /package/switch/{index.d.ts → types/switch.d.ts} +0 -0
@@ -1,76 +1,56 @@
1
1
  import * as i0 from '@angular/core';
2
- import { viewChild, input, output, signal, computed, effect, forwardRef, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { input, output, signal, computed, forwardRef, ChangeDetectionStrategy, Component } from '@angular/core';
3
3
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
- import { HlmAutocomplete } from '@egose/shadcn-theme-ng-tw/autocomplete';
4
+ import { HlmPopover, HlmPopoverTrigger, HlmPopoverContent } from '@egose/shadcn-theme-ng-tw/popover';
5
+ import { HlmButton } from '@egose/shadcn-theme-ng-tw/button';
6
+ import { HlmCheckbox } from '@egose/shadcn-theme-ng-tw/checkbox';
7
+ import { hlm } from '@egose/shadcn-theme-ng-tw/utils';
5
8
 
6
9
  class EgSearchableMultiselect {
7
- autoComplete = viewChild(HlmAutocomplete, ...(ngDevMode ? [{ debugName: "autoComplete" }] : []));
8
10
  /** Full option list with labels/values */
9
- options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
10
- placeholder = input('Start typing to add…', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
11
+ options = input([], /* @ts-ignore */
12
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
13
+ placeholder = input('Start typing to add…', /* @ts-ignore */
14
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
15
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
11
16
  /** Value: array of selected values (string[]) */
12
- value = input([], ...(ngDevMode ? [{ debugName: "value" }] : []));
13
- valueChange = output(); // emits string[] of values
14
- /** Internal state */
15
- search = signal('', ...(ngDevMode ? [{ debugName: "search" }] : []));
16
- selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : [])); // full objects for display
17
+ value = input([], /* @ts-ignore */
18
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
19
+ valueChange = output();
20
+ selectedItems = signal([], /* @ts-ignore */
21
+ ...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
17
22
  isDisabled = false;
18
23
  isFormBound = false;
19
- /** Filtered **labels** for hlm-autocomplete */
20
- filteredOptionLabels = computed(() => (this.options() || [])
21
- .filter((opt) => opt.label.toLowerCase().includes(this.search().toLowerCase()) &&
22
- !this.selectedItems().some((sel) => sel.value === opt.value))
23
- .map((opt) => opt.label), ...(ngDevMode ? [{ debugName: "filteredOptionLabels" }] : []));
24
- /** Form callbacks */
25
- onChange = () => { };
26
- onTouched = () => { };
27
- constructor() {
28
- // Sync `value` input to selectedItems for standalone usage
29
- effect(() => {
30
- if (!this.isFormBound) {
31
- this.updateSelectedFromValues(this.value() || []);
32
- }
33
- });
24
+ _hostClass = computed(() => hlm(this.userClass()), /* @ts-ignore */
25
+ ...(ngDevMode ? [{ debugName: "_hostClass" }] : /* istanbul ignore next */ []));
26
+ isSelected(value) {
27
+ return this.selectedItems().some((s) => s.value === value);
34
28
  }
35
- /** Add by label string (from autocomplete) */
36
- addItemByLabel(label) {
37
- const opt = this.options()?.find((o) => o.label === label);
38
- if (opt) {
39
- this.addItem(opt.value);
29
+ toggle(value, checked) {
30
+ if (checked) {
31
+ this.addItem(value);
32
+ }
33
+ else {
34
+ this.removeItem(value);
40
35
  }
41
36
  }
42
- /** Add by value string */
43
37
  addItem(value) {
44
- if (!this.selectedItems().some((sel) => sel.value === value)) {
38
+ if (!this.selectedItems().some((s) => s.value === value)) {
45
39
  const opt = this.options()?.find((o) => o.value === value);
46
40
  if (!opt)
47
41
  return;
48
- const updatedItems = [...this.selectedItems(), opt];
49
- this.updateValueFromSelected(updatedItems);
42
+ const updated = [...this.selectedItems(), opt];
43
+ this.updateValueFromSelected(updated);
50
44
  }
51
45
  }
52
- /** Remove by value string */
53
46
  removeItem(value) {
54
- const updatedItems = this.selectedItems().filter((i) => i.value !== value);
55
- this.updateValueFromSelected(updatedItems);
47
+ const updated = this.selectedItems().filter((i) => i.value !== value);
48
+ this.updateValueFromSelected(updated);
56
49
  }
57
- /** Clear autocomplete text */
58
- clearAutocompleteText() {
59
- this.autoComplete()?.clearText();
60
- if (this.options().length === this.selectedItems().length) {
61
- this.autoComplete()?.setPopoverState('closed');
62
- }
63
- }
64
- handleSelect(label) {
65
- this.clearAutocompleteText();
66
- }
67
- /** Map string[] values → full objects */
68
50
  updateSelectedFromValues(values) {
69
51
  const opts = this.options() || [];
70
- const matched = opts.filter((o) => values.includes(o.value));
71
- this.selectedItems.set(matched);
52
+ this.selectedItems.set(opts.filter((o) => values.includes(o.value)));
72
53
  }
73
- /** Map full objects → string[] values and emit */
74
54
  updateValueFromSelected(items) {
75
55
  this.selectedItems.set(items);
76
56
  const values = items.map((i) => i.value);
@@ -78,7 +58,12 @@ class EgSearchableMultiselect {
78
58
  this.onChange(values);
79
59
  this.onTouched();
80
60
  }
61
+ constructor() {
62
+ // No effect needed; we read `value` input directly via writeValue for form-bound usage.
63
+ }
81
64
  // --- ControlValueAccessor ---
65
+ onChange = () => { };
66
+ onTouched = () => { };
82
67
  writeValue(values) {
83
68
  this.isFormBound = true;
84
69
  this.updateSelectedFromValues(values || []);
@@ -92,21 +77,17 @@ class EgSearchableMultiselect {
92
77
  setDisabledState(isDisabled) {
93
78
  this.isDisabled = isDisabled;
94
79
  }
95
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgSearchableMultiselect, deps: [], target: i0.ɵɵFactoryTarget.Component });
96
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.1", type: EgSearchableMultiselect, isStandalone: true, selector: "eg-searchable-multiselect", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, providers: [
80
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: EgSearchableMultiselect, deps: [], target: i0.ɵɵFactoryTarget.Component });
81
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: EgSearchableMultiselect, isStandalone: true, selector: "eg-searchable-multiselect", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "class": "_hostClass()" } }, providers: [
97
82
  {
98
83
  provide: NG_VALUE_ACCESSOR,
99
84
  useExisting: forwardRef(() => EgSearchableMultiselect),
100
85
  multi: true,
101
86
  },
102
- ], viewQueries: [{ propertyName: "autoComplete", first: true, predicate: HlmAutocomplete, descendants: true, isSignal: true }], ngImport: i0, template: `
87
+ ], ngImport: i0, template: `
103
88
  <div class="tw:flex tw:flex-col tw:gap-2 tw:w-full">
104
- <!-- Selected items -->
105
- <div
106
- class="tw:flex tw:gap-2 tw:overflow-x-auto tw:whitespace-nowrap
107
- tw:[scrollbar-width:none] tw:[-ms-overflow-style:none]
108
- tw:[&::-webkit-scrollbar]:hidden"
109
- >
89
+ <!-- Selected chips -->
90
+ <div class="tw:flex tw:flex-wrap tw:gap-2">
110
91
  @if (selectedItems().length === 0) {
111
92
  <span
112
93
  class="tw:bg-gray-100 tw:text-gray-400 tw:rounded-full
@@ -134,24 +115,36 @@ class EgSearchableMultiselect {
134
115
  }
135
116
  </div>
136
117
 
137
- <!-- Autocomplete -->
138
- <hlm-autocomplete
139
- [filteredOptions]="filteredOptionLabels()"
140
- [(search)]="search"
141
- (valueChange)="addItemByLabel($event)"
142
- [searchPlaceholderText]="this.selectedItems().length.toString() + ' of ' + this.options().length + ' selected'"
143
- [onSelect]="handleSelect.bind(this)"
144
- [disabled]="isDisabled"
145
- />
118
+ <!-- Trigger -->
119
+ <hlm-popover>
120
+ <button hlmPopoverTrigger hlmButton variant="secondary" appearance="outline" type="button">
121
+ {{ selectedItems().length }} selected
122
+ </button>
123
+
124
+ <hlm-popover-content class="tw:w-64 tw:p-2">
125
+ <div class="tw:max-h-60 tw:overflow-auto tw:flex tw:flex-col tw:gap-1">
126
+ @for (option of options(); track option.value) {
127
+ <label
128
+ class="tw:flex tw:items-center tw:gap-2 tw:cursor-pointer tw:px-2 tw:py-1 tw:rounded-sm tw:hover:bg-secondary"
129
+ >
130
+ <hlm-checkbox [checked]="isSelected(option.value)" (changed)="toggle(option.value, $event)" />
131
+ <span class="tw:text-sm">{{ option.label }}</span>
132
+ </label>
133
+ } @empty {
134
+ <span class="tw:text-xs tw:text-muted-foreground tw:px-2 tw:py-1">No options</span>
135
+ }
136
+ </div>
137
+ </hlm-popover-content>
138
+ </hlm-popover>
146
139
  </div>
147
- `, isInline: true, dependencies: [{ kind: "component", type: HlmAutocomplete, selector: "hlm-autocomplete", inputs: ["onSelect", "class", "autocompleteListClass", "autocompleteEmptyClass", "filteredOptions", "value", "search", "transformValueToSearch", "optionTemplate", "loading", "searchPlaceholderText", "loadingText", "emptyText", "ariaLabelToggleButton", "inputId", "disabled"], outputs: ["valueChange", "searchChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
140
+ `, isInline: true, dependencies: [{ kind: "directive", type: HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: HlmPopoverTrigger, selector: "button[hlmPopoverTrigger],button[hlmPopoverTriggerFor]" }, { kind: "directive", type: HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "component", type: HlmButton, selector: "button[hlmButton], a[hlmButton]", inputs: ["variant", "size", "appearance", "loading", "icon", "iconPosition", "class", "spinnerUserClass", "disabled", "type"] }, { kind: "component", type: HlmCheckbox, selector: "hlm-checkbox", inputs: ["class", "id", "aria-label", "aria-labelledby", "aria-describedby", "checked", "name", "required", "disabled"], outputs: ["checkedChange", "changed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
148
141
  }
149
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: EgSearchableMultiselect, decorators: [{
142
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: EgSearchableMultiselect, decorators: [{
150
143
  type: Component,
151
144
  args: [{
152
145
  selector: 'eg-searchable-multiselect',
153
146
  standalone: true,
154
- imports: [HlmAutocomplete],
147
+ imports: [HlmPopover, HlmPopoverTrigger, HlmPopoverContent, HlmButton, HlmCheckbox],
155
148
  changeDetection: ChangeDetectionStrategy.OnPush,
156
149
  providers: [
157
150
  {
@@ -160,14 +153,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImpor
160
153
  multi: true,
161
154
  },
162
155
  ],
156
+ host: {
157
+ '[class]': '_hostClass()',
158
+ },
163
159
  template: `
164
160
  <div class="tw:flex tw:flex-col tw:gap-2 tw:w-full">
165
- <!-- Selected items -->
166
- <div
167
- class="tw:flex tw:gap-2 tw:overflow-x-auto tw:whitespace-nowrap
168
- tw:[scrollbar-width:none] tw:[-ms-overflow-style:none]
169
- tw:[&::-webkit-scrollbar]:hidden"
170
- >
161
+ <!-- Selected chips -->
162
+ <div class="tw:flex tw:flex-wrap tw:gap-2">
171
163
  @if (selectedItems().length === 0) {
172
164
  <span
173
165
  class="tw:bg-gray-100 tw:text-gray-400 tw:rounded-full
@@ -195,19 +187,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImpor
195
187
  }
196
188
  </div>
197
189
 
198
- <!-- Autocomplete -->
199
- <hlm-autocomplete
200
- [filteredOptions]="filteredOptionLabels()"
201
- [(search)]="search"
202
- (valueChange)="addItemByLabel($event)"
203
- [searchPlaceholderText]="this.selectedItems().length.toString() + ' of ' + this.options().length + ' selected'"
204
- [onSelect]="handleSelect.bind(this)"
205
- [disabled]="isDisabled"
206
- />
190
+ <!-- Trigger -->
191
+ <hlm-popover>
192
+ <button hlmPopoverTrigger hlmButton variant="secondary" appearance="outline" type="button">
193
+ {{ selectedItems().length }} selected
194
+ </button>
195
+
196
+ <hlm-popover-content class="tw:w-64 tw:p-2">
197
+ <div class="tw:max-h-60 tw:overflow-auto tw:flex tw:flex-col tw:gap-1">
198
+ @for (option of options(); track option.value) {
199
+ <label
200
+ class="tw:flex tw:items-center tw:gap-2 tw:cursor-pointer tw:px-2 tw:py-1 tw:rounded-sm tw:hover:bg-secondary"
201
+ >
202
+ <hlm-checkbox [checked]="isSelected(option.value)" (changed)="toggle(option.value, $event)" />
203
+ <span class="tw:text-sm">{{ option.label }}</span>
204
+ </label>
205
+ } @empty {
206
+ <span class="tw:text-xs tw:text-muted-foreground tw:px-2 tw:py-1">No options</span>
207
+ }
208
+ </div>
209
+ </hlm-popover-content>
210
+ </hlm-popover>
207
211
  </div>
208
212
  `,
209
213
  }]
210
- }], ctorParameters: () => [] });
214
+ }], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
211
215
 
212
216
  /*
213
217
  * Public API Surface of searchable-multiselect
@@ -1 +1 @@
1
- {"version":3,"file":"searchable-multiselect.mjs","sources":["../../../projects/searchable-multiselect/src/lib/searchable-multiselect.ts","../../../projects/searchable-multiselect/src/public-api.ts","../../../projects/searchable-multiselect/src/searchable-multiselect.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n signal,\n input,\n output,\n viewChild,\n effect,\n forwardRef,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { HlmAutocomplete } from '@egose/shadcn-theme-ng/autocomplete';\n\nexport interface SelectOption {\n label: string;\n value: string;\n}\n\n@Component({\n selector: 'eg-searchable-multiselect',\n standalone: true,\n imports: [HlmAutocomplete],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => EgSearchableMultiselect),\n multi: true,\n },\n ],\n template: `\n <div class=\"tw:flex tw:flex-col tw:gap-2 tw:w-full\">\n <!-- Selected items -->\n <div\n class=\"tw:flex tw:gap-2 tw:overflow-x-auto tw:whitespace-nowrap\n tw:[scrollbar-width:none] tw:[-ms-overflow-style:none]\n tw:[&::-webkit-scrollbar]:hidden\"\n >\n @if (selectedItems().length === 0) {\n <span\n class=\"tw:bg-gray-100 tw:text-gray-400 tw:rounded-full\n tw:px-2 tw:py-1 tw:inline-flex tw:items-center tw:text-xs\"\n >\n {{ placeholder() }}\n </span>\n } @else {\n @for (item of selectedItems(); track item.value) {\n <span\n class=\"tw:bg-gray-200 tw:rounded-full tw:px-2 tw:py-1\n tw:inline-flex tw:items-center tw:gap-2 tw:text-xs\"\n >\n {{ item.label }}\n <button\n type=\"button\"\n (click)=\"removeItem(item.value)\"\n class=\"tw:bg-transparent tw:border-0 tw:text-gray-600\n tw:hover:text-red-500 tw:cursor-pointer\"\n >\n ✕\n </button>\n </span>\n }\n }\n </div>\n\n <!-- Autocomplete -->\n <hlm-autocomplete\n [filteredOptions]=\"filteredOptionLabels()\"\n [(search)]=\"search\"\n (valueChange)=\"addItemByLabel($event)\"\n [searchPlaceholderText]=\"this.selectedItems().length.toString() + ' of ' + this.options().length + ' selected'\"\n [onSelect]=\"handleSelect.bind(this)\"\n [disabled]=\"isDisabled\"\n />\n </div>\n `,\n})\nexport class EgSearchableMultiselect implements ControlValueAccessor {\n autoComplete = viewChild(HlmAutocomplete);\n\n /** Full option list with labels/values */\n options = input<SelectOption[]>([]);\n placeholder = input<string>('Start typing to add…');\n\n /** Value: array of selected values (string[]) */\n value = input<string[]>([]);\n valueChange = output<string[]>(); // emits string[] of values\n\n /** Internal state */\n search = signal<string>('');\n selectedItems = signal<SelectOption[]>([]); // full objects for display\n isDisabled = false;\n private isFormBound = false;\n\n /** Filtered **labels** for hlm-autocomplete */\n filteredOptionLabels = computed(\n () =>\n (this.options() || [])\n .filter(\n (opt) =>\n opt.label.toLowerCase().includes(this.search().toLowerCase()) &&\n !this.selectedItems().some((sel) => sel.value === opt.value),\n )\n .map((opt) => opt.label), // convert to string[] for hlm-autocomplete\n );\n\n /** Form callbacks */\n private onChange: (value: string[]) => void = () => {};\n private onTouched: () => void = () => {};\n\n constructor() {\n // Sync `value` input to selectedItems for standalone usage\n effect(() => {\n if (!this.isFormBound) {\n this.updateSelectedFromValues(this.value() || []);\n }\n });\n }\n\n /** Add by label string (from autocomplete) */\n addItemByLabel(label: string) {\n const opt = this.options()?.find((o) => o.label === label);\n if (opt) {\n this.addItem(opt.value);\n }\n }\n\n /** Add by value string */\n addItem(value: string) {\n if (!this.selectedItems().some((sel) => sel.value === value)) {\n const opt = this.options()?.find((o) => o.value === value);\n if (!opt) return;\n const updatedItems = [...this.selectedItems(), opt];\n this.updateValueFromSelected(updatedItems);\n }\n }\n\n /** Remove by value string */\n removeItem(value: string) {\n const updatedItems = this.selectedItems().filter((i) => i.value !== value);\n this.updateValueFromSelected(updatedItems);\n }\n\n /** Clear autocomplete text */\n clearAutocompleteText() {\n this.autoComplete()?.clearText();\n\n if (this.options().length === this.selectedItems().length) {\n this.autoComplete()?.setPopoverState('closed');\n }\n }\n\n handleSelect(label: string) {\n this.clearAutocompleteText();\n }\n\n /** Map string[] values → full objects */\n private updateSelectedFromValues(values: string[]) {\n const opts = this.options() || [];\n const matched = opts.filter((o) => values.includes(o.value));\n this.selectedItems.set(matched);\n }\n\n /** Map full objects → string[] values and emit */\n private updateValueFromSelected(items: SelectOption[]) {\n this.selectedItems.set(items);\n const values = items.map((i) => i.value);\n this.valueChange.emit(values);\n this.onChange(values);\n this.onTouched();\n }\n\n // --- ControlValueAccessor ---\n writeValue(values: string[] | null): void {\n this.isFormBound = true;\n this.updateSelectedFromValues(values || []);\n }\n\n registerOnChange(fn: (value: string[]) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.isDisabled = isDisabled;\n }\n}\n","/*\n * Public API Surface of searchable-multiselect\n */\n\nexport * from './lib/searchable-multiselect';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"searchable-multiselect.mjs","sources":["../../../projects/searchable-multiselect/src/lib/searchable-multiselect.ts","../../../projects/searchable-multiselect/src/public-api.ts","../../../projects/searchable-multiselect/src/searchable-multiselect.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, forwardRef, input, output, signal } from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\nimport { HlmPopover, HlmPopoverContent, HlmPopoverTrigger } from '@egose/shadcn-theme-ng/popover';\nimport { HlmButton } from '@egose/shadcn-theme-ng/button';\nimport { HlmCheckbox } from '@egose/shadcn-theme-ng/checkbox';\nimport { hlm } from '@egose/shadcn-theme-ng/utils';\nimport { ClassValue } from 'clsx';\n\nexport interface SelectOption {\n label: string;\n value: string;\n}\n\n@Component({\n selector: 'eg-searchable-multiselect',\n standalone: true,\n imports: [HlmPopover, HlmPopoverTrigger, HlmPopoverContent, HlmButton, HlmCheckbox],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => EgSearchableMultiselect),\n multi: true,\n },\n ],\n host: {\n '[class]': '_hostClass()',\n },\n template: `\n <div class=\"tw:flex tw:flex-col tw:gap-2 tw:w-full\">\n <!-- Selected chips -->\n <div class=\"tw:flex tw:flex-wrap tw:gap-2\">\n @if (selectedItems().length === 0) {\n <span\n class=\"tw:bg-gray-100 tw:text-gray-400 tw:rounded-full\n tw:px-2 tw:py-1 tw:inline-flex tw:items-center tw:text-xs\"\n >\n {{ placeholder() }}\n </span>\n } @else {\n @for (item of selectedItems(); track item.value) {\n <span\n class=\"tw:bg-gray-200 tw:rounded-full tw:px-2 tw:py-1\n tw:inline-flex tw:items-center tw:gap-2 tw:text-xs\"\n >\n {{ item.label }}\n <button\n type=\"button\"\n (click)=\"removeItem(item.value)\"\n class=\"tw:bg-transparent tw:border-0 tw:text-gray-600\n tw:hover:text-red-500 tw:cursor-pointer\"\n >\n ✕\n </button>\n </span>\n }\n }\n </div>\n\n <!-- Trigger -->\n <hlm-popover>\n <button hlmPopoverTrigger hlmButton variant=\"secondary\" appearance=\"outline\" type=\"button\">\n {{ selectedItems().length }} selected\n </button>\n\n <hlm-popover-content class=\"tw:w-64 tw:p-2\">\n <div class=\"tw:max-h-60 tw:overflow-auto tw:flex tw:flex-col tw:gap-1\">\n @for (option of options(); track option.value) {\n <label\n class=\"tw:flex tw:items-center tw:gap-2 tw:cursor-pointer tw:px-2 tw:py-1 tw:rounded-sm tw:hover:bg-secondary\"\n >\n <hlm-checkbox [checked]=\"isSelected(option.value)\" (changed)=\"toggle(option.value, $event)\" />\n <span class=\"tw:text-sm\">{{ option.label }}</span>\n </label>\n } @empty {\n <span class=\"tw:text-xs tw:text-muted-foreground tw:px-2 tw:py-1\">No options</span>\n }\n </div>\n </hlm-popover-content>\n </hlm-popover>\n </div>\n `,\n})\nexport class EgSearchableMultiselect implements ControlValueAccessor {\n /** Full option list with labels/values */\n options = input<SelectOption[]>([]);\n placeholder = input<string>('Start typing to add…');\n\n userClass = input<ClassValue>('', { alias: 'class' });\n\n /** Value: array of selected values (string[]) */\n value = input<string[]>([]);\n valueChange = output<string[]>();\n\n protected readonly selectedItems = signal<SelectOption[]>([]);\n protected isDisabled = false;\n private isFormBound = false;\n\n protected readonly _hostClass = computed(() => hlm(this.userClass()));\n\n protected isSelected(value: string): boolean {\n return this.selectedItems().some((s) => s.value === value);\n }\n\n protected toggle(value: string, checked: boolean): void {\n if (checked) {\n this.addItem(value);\n } else {\n this.removeItem(value);\n }\n }\n\n protected addItem(value: string): void {\n if (!this.selectedItems().some((s) => s.value === value)) {\n const opt = this.options()?.find((o) => o.value === value);\n if (!opt) return;\n const updated = [...this.selectedItems(), opt];\n this.updateValueFromSelected(updated);\n }\n }\n\n protected removeItem(value: string): void {\n const updated = this.selectedItems().filter((i) => i.value !== value);\n this.updateValueFromSelected(updated);\n }\n\n private updateSelectedFromValues(values: string[]): void {\n const opts = this.options() || [];\n this.selectedItems.set(opts.filter((o) => values.includes(o.value)));\n }\n\n private updateValueFromSelected(items: SelectOption[]): void {\n this.selectedItems.set(items);\n const values = items.map((i) => i.value);\n this.valueChange.emit(values);\n this.onChange(values);\n this.onTouched();\n }\n\n constructor() {\n // No effect needed; we read `value` input directly via writeValue for form-bound usage.\n }\n\n // --- ControlValueAccessor ---\n private onChange: (value: string[]) => void = () => {};\n private onTouched: () => void = () => {};\n\n writeValue(values: string[] | null): void {\n this.isFormBound = true;\n this.updateSelectedFromValues(values || []);\n }\n\n registerOnChange(fn: (value: string[]) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.isDisabled = isDisabled;\n }\n}\n","/*\n * Public API Surface of searchable-multiselect\n */\n\nexport * from './lib/searchable-multiselect';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "searchable-multiselect",
3
+ "version": "0.0.1",
4
+ "peerDependencies": {
5
+ "@angular/common": "^20.3.0 || ^22.0.0",
6
+ "@angular/core": "^20.3.0 || ^22.0.0"
7
+ },
8
+ "dependencies": {
9
+ "tslib": "^2.3.0"
10
+ },
11
+ "sideEffects": false,
12
+ "module": "fesm2022/searchable-multiselect.mjs",
13
+ "typings": "types/searchable-multiselect.d.ts",
14
+ "exports": {
15
+ "./package.json": {
16
+ "default": "./package.json"
17
+ },
18
+ ".": {
19
+ "types": "./types/searchable-multiselect.d.ts",
20
+ "default": "./fesm2022/searchable-multiselect.mjs"
21
+ }
22
+ },
23
+ "type": "module"
24
+ }
@@ -1,49 +1,38 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { ControlValueAccessor } from '@angular/forms';
3
- import { HlmAutocomplete } from '@egose/shadcn-theme-ng/autocomplete';
3
+ import { ClassValue } from 'clsx';
4
4
 
5
5
  interface SelectOption {
6
6
  label: string;
7
7
  value: string;
8
8
  }
9
9
  declare class EgSearchableMultiselect implements ControlValueAccessor {
10
- autoComplete: _angular_core.Signal<HlmAutocomplete<any> | undefined>;
11
10
  /** Full option list with labels/values */
12
11
  options: _angular_core.InputSignal<SelectOption[]>;
13
12
  placeholder: _angular_core.InputSignal<string>;
13
+ userClass: _angular_core.InputSignal<ClassValue>;
14
14
  /** Value: array of selected values (string[]) */
15
15
  value: _angular_core.InputSignal<string[]>;
16
16
  valueChange: _angular_core.OutputEmitterRef<string[]>;
17
- /** Internal state */
18
- search: _angular_core.WritableSignal<string>;
19
- selectedItems: _angular_core.WritableSignal<SelectOption[]>;
20
- isDisabled: boolean;
17
+ protected readonly selectedItems: _angular_core.WritableSignal<SelectOption[]>;
18
+ protected isDisabled: boolean;
21
19
  private isFormBound;
22
- /** Filtered **labels** for hlm-autocomplete */
23
- filteredOptionLabels: _angular_core.Signal<string[]>;
24
- /** Form callbacks */
25
- private onChange;
26
- private onTouched;
27
- constructor();
28
- /** Add by label string (from autocomplete) */
29
- addItemByLabel(label: string): void;
30
- /** Add by value string */
31
- addItem(value: string): void;
32
- /** Remove by value string */
33
- removeItem(value: string): void;
34
- /** Clear autocomplete text */
35
- clearAutocompleteText(): void;
36
- handleSelect(label: string): void;
37
- /** Map string[] values → full objects */
20
+ protected readonly _hostClass: _angular_core.Signal<string>;
21
+ protected isSelected(value: string): boolean;
22
+ protected toggle(value: string, checked: boolean): void;
23
+ protected addItem(value: string): void;
24
+ protected removeItem(value: string): void;
38
25
  private updateSelectedFromValues;
39
- /** Map full objects → string[] values and emit */
40
26
  private updateValueFromSelected;
27
+ constructor();
28
+ private onChange;
29
+ private onTouched;
41
30
  writeValue(values: string[] | null): void;
42
31
  registerOnChange(fn: (value: string[]) => void): void;
43
32
  registerOnTouched(fn: () => void): void;
44
33
  setDisabledState(isDisabled: boolean): void;
45
34
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgSearchableMultiselect, never>;
46
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgSearchableMultiselect, "eg-searchable-multiselect", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
35
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgSearchableMultiselect, "eg-searchable-multiselect", never, { "options": { "alias": "options"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, never, true, never>;
47
36
  }
48
37
 
49
38
  export { EgSearchableMultiselect };