@radix-ng/primitives 0.11.0 → 0.12.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 (445) hide show
  1. package/.compodocrc.json +12 -0
  2. package/CHANGELOG.md +182 -0
  3. package/LICENSE +21 -0
  4. package/accordion/__tests__/accordion-content.directive.spec.ts +8 -0
  5. package/accordion/__tests__/accordion-header.directive.spec.ts +8 -0
  6. package/accordion/__tests__/accordion-item.directive.spec.ts +8 -0
  7. package/accordion/__tests__/accordion-root.directive.spec.ts +8 -0
  8. package/accordion/__tests__/accordion-trigger.directive.spec.ts +8 -0
  9. package/accordion/ng-package.json +5 -0
  10. package/accordion/src/accordion-content.directive.ts +46 -0
  11. package/accordion/src/accordion-header.directive.ts +15 -0
  12. package/accordion/src/accordion-item.directive.ts +216 -0
  13. package/accordion/src/accordion-root.directive.ts +205 -0
  14. package/accordion/src/accordion-trigger.directive.ts +37 -0
  15. package/accordion/stories/accordion.docs.mdx +77 -0
  16. package/accordion/stories/accordion.stories.ts +340 -0
  17. package/alert-dialog/{index.d.ts → index.ts} +1 -0
  18. package/alert-dialog/ng-package.json +5 -0
  19. package/alert-dialog/src/alert-dialog-cancel.directive.ts +17 -0
  20. package/alert-dialog/src/alert-dialog-content.directive.ts +24 -0
  21. package/alert-dialog/src/alert-dialog-root.directive.ts +15 -0
  22. package/alert-dialog/src/alert-dialog-title.directive.ts +7 -0
  23. package/alert-dialog/src/alert-dialog-trigger.directive.ts +17 -0
  24. package/alert-dialog/src/alert-dialog.service.ts +51 -0
  25. package/alert-dialog/stories/alert-dialog.stories.ts +139 -0
  26. package/avatar/__tests__/avatar-fallback.directive.spec.ts +31 -0
  27. package/avatar/__tests__/avatar-image.directive.spec.ts +36 -0
  28. package/avatar/ng-package.json +5 -0
  29. package/avatar/src/avatar-fallback.directive.ts +62 -0
  30. package/avatar/src/avatar-image.directive.ts +55 -0
  31. package/avatar/src/avatar-root.directive.ts +35 -0
  32. package/avatar/src/avatar.config.ts +29 -0
  33. package/avatar/stories/avatar.docs.mdx +37 -0
  34. package/avatar/stories/avatar.stories.ts +87 -0
  35. package/button/__tests__/.gitkeep +0 -0
  36. package/button/src/button-abstract.directive.ts +46 -0
  37. package/checkbox/ng-package.json +5 -0
  38. package/checkbox/src/checkbox-button.directive.ts +26 -0
  39. package/checkbox/src/checkbox-indicator.directive.ts +16 -0
  40. package/checkbox/src/checkbox-input.directive.ts +36 -0
  41. package/checkbox/src/checkbox.directive.ts +146 -0
  42. package/checkbox/src/checkbox.token.ts +8 -0
  43. package/checkbox/stories/checkbox-group.component.ts +87 -0
  44. package/checkbox/stories/checkbox-group.styles.scss +49 -0
  45. package/checkbox/stories/checkbox-indeterminate.component.ts +52 -0
  46. package/checkbox/stories/checkbox.docs.mdx +58 -0
  47. package/checkbox/stories/checkbox.stories.ts +105 -0
  48. package/collapsible/__tests__/collapsible-content.directive.spec.ts +30 -0
  49. package/collapsible/__tests__/collapsible-root.directive.spec.ts +27 -0
  50. package/collapsible/__tests__/collapsible-trigger.directive.spec.ts +30 -0
  51. package/collapsible/ng-package.json +5 -0
  52. package/collapsible/src/collapsible-content.directive.ts +34 -0
  53. package/collapsible/src/collapsible-content.token.ts +6 -0
  54. package/collapsible/src/collapsible-root.directive.ts +120 -0
  55. package/collapsible/src/collapsible-trigger.directive.ts +44 -0
  56. package/collapsible/stories/collapsible-animation.component.ts +116 -0
  57. package/collapsible/stories/collapsible-external-triggering.component.ts +86 -0
  58. package/collapsible/stories/collapsible.docs.mdx +53 -0
  59. package/collapsible/stories/collapsible.stories.ts +151 -0
  60. package/context-menu/README.md +1 -0
  61. package/context-menu/index.ts +10 -0
  62. package/context-menu/ng-package.json +5 -0
  63. package/context-menu/src/context-menu-content.directive.ts +47 -0
  64. package/context-menu/src/context-menu-item-checkbox.directive.ts +30 -0
  65. package/context-menu/src/context-menu-item-indicator.directive.ts +14 -0
  66. package/context-menu/src/context-menu-item-radio-group.directive.ts +31 -0
  67. package/context-menu/src/context-menu-item-radio.directive.ts +69 -0
  68. package/context-menu/src/context-menu-item-selectable.ts +18 -0
  69. package/context-menu/src/context-menu-item.directive.ts +65 -0
  70. package/context-menu/src/context-menu-label.directive.ts +7 -0
  71. package/context-menu/src/context-menu-separator.directive.ts +13 -0
  72. package/context-menu/src/context-menu-trigger.directive.ts +82 -0
  73. package/context-menu/stories/context-menu.docs.mdx +23 -0
  74. package/context-menu/stories/context-menu.stories.ts +253 -0
  75. package/core/index.ts +3 -0
  76. package/core/src/accessor/provide-value-accessor.ts +20 -0
  77. package/core/src/auto-focus.directive.ts +81 -0
  78. package/core/src/inject-ng-control.ts +28 -0
  79. package/core/src/mount.ts +27 -0
  80. package/dialog/README.md +1 -0
  81. package/dialog/__tests__/dialog-content.directive.spec.ts +77 -0
  82. package/dialog/__tests__/dialog-trigger.directive.spec.ts +85 -0
  83. package/dialog/index.ts +31 -0
  84. package/dialog/ng-package.json +5 -0
  85. package/dialog/src/dialog-close.directive.ts +18 -0
  86. package/dialog/src/dialog-content.directive.ts +45 -0
  87. package/dialog/src/dialog-description.directive.ts +7 -0
  88. package/dialog/src/dialog-dismiss.directive.ts +18 -0
  89. package/dialog/src/dialog-ref.ts +70 -0
  90. package/dialog/src/dialog-title.directive.ts +7 -0
  91. package/dialog/src/dialog-trigger.directive.ts +52 -0
  92. package/dialog/src/dialog.config.ts +55 -0
  93. package/dialog/src/dialog.injectors.ts +12 -0
  94. package/dialog/src/dialog.providers.ts +27 -0
  95. package/dialog/src/dialog.service.ts +94 -0
  96. package/dialog/stories/dialog.docs.mdx +32 -0
  97. package/dialog/stories/dialog.stories.ts +233 -0
  98. package/dropdown-menu/ng-package.json +5 -0
  99. package/dropdown-menu/src/dropdown-menu-content.directive.ts +47 -0
  100. package/dropdown-menu/src/dropdown-menu-item-checkbox.directive.ts +30 -0
  101. package/dropdown-menu/src/dropdown-menu-item-indicator.directive.ts +14 -0
  102. package/dropdown-menu/src/dropdown-menu-item-radio-group.directive.ts +31 -0
  103. package/dropdown-menu/src/dropdown-menu-item-radio.directive.ts +72 -0
  104. package/dropdown-menu/src/dropdown-menu-item-selectable.ts +18 -0
  105. package/dropdown-menu/src/dropdown-menu-item.directive.ts +66 -0
  106. package/dropdown-menu/src/dropdown-menu-label.directive.ts +7 -0
  107. package/dropdown-menu/src/dropdown-menu-separator.directive.ts +13 -0
  108. package/dropdown-menu/src/dropdown-menu-trigger.directive.ts +185 -0
  109. package/dropdown-menu/stories/dropdown-menu-item-checkbox.component.ts +104 -0
  110. package/dropdown-menu/stories/dropdown-menu-item-checkbox.styles.scss +106 -0
  111. package/dropdown-menu/stories/dropdown-menu-item-radio.component.ts +95 -0
  112. package/dropdown-menu/stories/dropdown-menu-item-radio.styles.scss +106 -0
  113. package/dropdown-menu/stories/dropdown.docs.mdx +27 -0
  114. package/dropdown-menu/stories/dropdown.stories.ts +212 -0
  115. package/form-field/index.ts +1 -0
  116. package/form-field/src/.gitkeep +0 -0
  117. package/jest.config.ts +21 -0
  118. package/label/__tests__/label-root.directive.spec.ts +99 -0
  119. package/label/ng-package.json +5 -0
  120. package/label/src/label.directive.ts +58 -0
  121. package/label/stories/label.docs.mdx +40 -0
  122. package/label/stories/label.stories.ts +76 -0
  123. package/menu/index.ts +29 -0
  124. package/menu/ng-package.json +5 -0
  125. package/menu/src/menu-content.directive.ts +9 -0
  126. package/menu/src/menu-directive.ts +10 -0
  127. package/menu/src/menu-group.directive.ts +12 -0
  128. package/menu/src/menu-item.directive.ts +44 -0
  129. package/menu/src/menu-label.directive.ts +7 -0
  130. package/menu/src/menu-separator.directive.ts +13 -0
  131. package/menubar/index.ts +38 -0
  132. package/menubar/ng-package.json +5 -0
  133. package/menubar/src/menubar-content.directive.ts +9 -0
  134. package/menubar/src/menubar-item-checkbox.directive.ts +32 -0
  135. package/menubar/src/menubar-item-indicator.directive.ts +10 -0
  136. package/menubar/src/menubar-item-radio.directive.ts +33 -0
  137. package/menubar/src/menubar-item.directive.ts +12 -0
  138. package/menubar/src/menubar-radio-group.directive.ts +9 -0
  139. package/menubar/src/menubar-root.directive.ts +15 -0
  140. package/menubar/src/menubar-separator.directive.ts +9 -0
  141. package/menubar/src/menubar-trigger.directive.ts +40 -0
  142. package/menubar/stories/menubar.stories.ts +229 -0
  143. package/ng-package.json +8 -0
  144. package/package.json +4 -112
  145. package/portal/stories/portal.docs.mdx +85 -0
  146. package/presence/__test__/presence-test.component.ts +51 -0
  147. package/presence/__test__/presence.spec.ts +50 -0
  148. package/presence/index.ts +4 -0
  149. package/presence/src/presence.ts +119 -0
  150. package/presence/src/transitions/transition.collapse.ts +99 -0
  151. package/presence/src/transitions/transition.toast.ts +27 -0
  152. package/presence/src/types.ts +20 -0
  153. package/presence/src/utils.ts +63 -0
  154. package/presence/stories/presence-story.componen.ts +69 -0
  155. package/presence/stories/presence.docs.mdx +40 -0
  156. package/presence/stories/presence.stories.ts +29 -0
  157. package/progress/__test__/progress.spec.ts +55 -0
  158. package/progress/{index.d.ts → index.ts} +1 -0
  159. package/progress/ng-package.json +5 -0
  160. package/progress/src/progress-indicator.directive.ts +26 -0
  161. package/progress/src/progress-root.directive.ts +134 -0
  162. package/progress/stories/progress.docs.mdx +65 -0
  163. package/progress/stories/progress.stories.ts +66 -0
  164. package/project.json +39 -0
  165. package/radio/{index.d.ts → index.ts} +1 -0
  166. package/radio/ng-package.json +5 -0
  167. package/radio/src/radio-indicator.directive.ts +17 -0
  168. package/radio/src/radio-item.directive.ts +68 -0
  169. package/radio/src/radio-root.directive.ts +207 -0
  170. package/radio/src/{radio-tokens.d.ts → radio-tokens.ts} +5 -1
  171. package/radio/stories/radio-group.component.ts +39 -0
  172. package/radio/stories/radio-group.styles.scss +70 -0
  173. package/radio/stories/radio.docs.mdx +68 -0
  174. package/radio/stories/radio.stories.ts +155 -0
  175. package/separator/__tests__/separator.directive.spec.ts +58 -0
  176. package/separator/ng-package.json +5 -0
  177. package/separator/src/separator.directive.ts +35 -0
  178. package/separator/stories/separator.docs.mdx +37 -0
  179. package/separator/stories/separator.stories.ts +82 -0
  180. package/slider/src/slider-input.directive.ts +0 -0
  181. package/slider/src/slider-thumb.directives.ts +60 -0
  182. package/slider/src/slider-track.directive.ts +11 -0
  183. package/slider/src/slider.directive.ts +59 -0
  184. package/slider/src/slider.types.ts +4 -0
  185. package/switch/index.ts +22 -0
  186. package/switch/ng-package.json +5 -0
  187. package/switch/src/switch-input.directive.ts +24 -0
  188. package/switch/src/switch-root.directive.ts +127 -0
  189. package/switch/src/switch-thumb.directive.ts +15 -0
  190. package/switch/stories/switch.docs.mdx +83 -0
  191. package/switch/stories/switch.stories.ts +149 -0
  192. package/tabs/__tests__/tabs-context.service.spec.ts +35 -0
  193. package/tabs/index.ts +26 -0
  194. package/tabs/ng-package.json +5 -0
  195. package/tabs/src/tabs-content.directive.ts +23 -0
  196. package/tabs/src/tabs-context.service.ts +43 -0
  197. package/tabs/src/tabs-list.directive.ts +21 -0
  198. package/tabs/src/tabs-root.directive.ts +70 -0
  199. package/tabs/src/tabs-trigger.directive.ts +55 -0
  200. package/tabs/stories/tabs.stories.ts +213 -0
  201. package/test-setup.ts +1 -0
  202. package/toggle/__tests__/toggle.directive.spec.ts +87 -0
  203. package/toggle/ng-package.json +5 -0
  204. package/toggle/src/toggle.directive.ts +49 -0
  205. package/toggle/stories/toggle.docs.mdx +60 -0
  206. package/toggle/stories/toggle.stories.ts +84 -0
  207. package/toggle-group/ng-package.json +5 -0
  208. package/toggle-group/src/toggle-group-button.directive.ts +73 -0
  209. package/toggle-group/src/toggle-group-button.token.ts +8 -0
  210. package/toggle-group/src/toggle-group-multi.directive.ts +158 -0
  211. package/toggle-group/src/toggle-group.directive.ts +148 -0
  212. package/toggle-group/src/toggle-group.token.ts +11 -0
  213. package/toggle-group/stories/toggle-group.docs.mdx +87 -0
  214. package/toggle-group/stories/toggle-group.stories.ts +95 -0
  215. package/tsconfig.doc.json +11 -0
  216. package/tsconfig.json +29 -0
  217. package/tsconfig.lib.json +19 -0
  218. package/tsconfig.lib.prod.json +12 -0
  219. package/tsconfig.spec.json +11 -0
  220. package/visually-hidden/README.md +3 -0
  221. package/visually-hidden/stories/visually-hidden.docs.mdx +36 -0
  222. package/accordion/src/accordion-content.directive.d.ts +0 -16
  223. package/accordion/src/accordion-header.directive.d.ts +0 -7
  224. package/accordion/src/accordion-item.directive.d.ts +0 -62
  225. package/accordion/src/accordion-root.directive.d.ts +0 -78
  226. package/accordion/src/accordion-trigger.directive.d.ts +0 -15
  227. package/alert-dialog/src/alert-dialog-cancel.directive.d.ts +0 -7
  228. package/alert-dialog/src/alert-dialog-content.directive.d.ts +0 -9
  229. package/alert-dialog/src/alert-dialog-root.directive.d.ts +0 -9
  230. package/alert-dialog/src/alert-dialog-title.directive.d.ts +0 -5
  231. package/alert-dialog/src/alert-dialog-trigger.directive.d.ts +0 -7
  232. package/alert-dialog/src/alert-dialog.service.d.ts +0 -14
  233. package/avatar/src/avatar-fallback.directive.d.ts +0 -27
  234. package/avatar/src/avatar-image.directive.d.ts +0 -16
  235. package/avatar/src/avatar-root.directive.d.ts +0 -21
  236. package/avatar/src/avatar.config.d.ts +0 -13
  237. package/checkbox/src/checkbox-button.directive.d.ts +0 -8
  238. package/checkbox/src/checkbox-indicator.directive.d.ts +0 -6
  239. package/checkbox/src/checkbox-input.directive.d.ts +0 -9
  240. package/checkbox/src/checkbox.directive.d.ts +0 -75
  241. package/checkbox/src/checkbox.token.d.ts +0 -4
  242. package/collapsible/src/collapsible-content.directive.d.ts +0 -17
  243. package/collapsible/src/collapsible-content.token.d.ts +0 -3
  244. package/collapsible/src/collapsible-root.directive.d.ts +0 -55
  245. package/collapsible/src/collapsible-trigger.directive.d.ts +0 -26
  246. package/compodoc/documentation.json +0 -11395
  247. package/dropdown-menu/src/dropdown-menu-content.directive.d.ts +0 -15
  248. package/dropdown-menu/src/dropdown-menu-item-checkbox.directive.d.ts +0 -9
  249. package/dropdown-menu/src/dropdown-menu-item-indicator.directive.d.ts +0 -7
  250. package/dropdown-menu/src/dropdown-menu-item-radio-group.directive.d.ts +0 -12
  251. package/dropdown-menu/src/dropdown-menu-item-radio.directive.d.ts +0 -19
  252. package/dropdown-menu/src/dropdown-menu-item-selectable.d.ts +0 -12
  253. package/dropdown-menu/src/dropdown-menu-item.directive.d.ts +0 -17
  254. package/dropdown-menu/src/dropdown-menu-label.directive.d.ts +0 -5
  255. package/dropdown-menu/src/dropdown-menu-separator.directive.d.ts +0 -6
  256. package/dropdown-menu/src/dropdown-menu-trigger.directive.d.ts +0 -43
  257. package/esm2022/accordion/index.mjs +0 -6
  258. package/esm2022/accordion/radix-ng-primitives-accordion.mjs +0 -5
  259. package/esm2022/accordion/src/accordion-content.directive.mjs +0 -36
  260. package/esm2022/accordion/src/accordion-header.directive.mjs +0 -23
  261. package/esm2022/accordion/src/accordion-item.directive.mjs +0 -170
  262. package/esm2022/accordion/src/accordion-root.directive.mjs +0 -157
  263. package/esm2022/accordion/src/accordion-trigger.directive.mjs +0 -42
  264. package/esm2022/alert-dialog/index.mjs +0 -7
  265. package/esm2022/alert-dialog/radix-ng-primitives-alert-dialog.mjs +0 -5
  266. package/esm2022/alert-dialog/src/alert-dialog-cancel.directive.mjs +0 -24
  267. package/esm2022/alert-dialog/src/alert-dialog-content.directive.mjs +0 -34
  268. package/esm2022/alert-dialog/src/alert-dialog-root.directive.mjs +0 -25
  269. package/esm2022/alert-dialog/src/alert-dialog-title.directive.mjs +0 -14
  270. package/esm2022/alert-dialog/src/alert-dialog-trigger.directive.mjs +0 -24
  271. package/esm2022/alert-dialog/src/alert-dialog.service.mjs +0 -47
  272. package/esm2022/avatar/index.mjs +0 -5
  273. package/esm2022/avatar/radix-ng-primitives-avatar.mjs +0 -5
  274. package/esm2022/avatar/src/avatar-fallback.directive.mjs +0 -54
  275. package/esm2022/avatar/src/avatar-image.directive.mjs +0 -48
  276. package/esm2022/avatar/src/avatar-root.directive.mjs +0 -38
  277. package/esm2022/avatar/src/avatar.config.mjs +0 -17
  278. package/esm2022/checkbox/index.mjs +0 -6
  279. package/esm2022/checkbox/radix-ng-primitives-checkbox.mjs +0 -5
  280. package/esm2022/checkbox/src/checkbox-button.directive.mjs +0 -33
  281. package/esm2022/checkbox/src/checkbox-indicator.directive.mjs +0 -24
  282. package/esm2022/checkbox/src/checkbox-input.directive.mjs +0 -41
  283. package/esm2022/checkbox/src/checkbox.directive.mjs +0 -141
  284. package/esm2022/checkbox/src/checkbox.token.mjs +0 -6
  285. package/esm2022/collapsible/index.mjs +0 -4
  286. package/esm2022/collapsible/radix-ng-primitives-collapsible.mjs +0 -5
  287. package/esm2022/collapsible/src/collapsible-content.directive.mjs +0 -45
  288. package/esm2022/collapsible/src/collapsible-content.token.mjs +0 -3
  289. package/esm2022/collapsible/src/collapsible-root.directive.mjs +0 -118
  290. package/esm2022/collapsible/src/collapsible-trigger.directive.mjs +0 -49
  291. package/esm2022/dropdown-menu/index.mjs +0 -11
  292. package/esm2022/dropdown-menu/radix-ng-primitives-dropdown-menu.mjs +0 -5
  293. package/esm2022/dropdown-menu/src/dropdown-menu-content.directive.mjs +0 -56
  294. package/esm2022/dropdown-menu/src/dropdown-menu-item-checkbox.directive.mjs +0 -36
  295. package/esm2022/dropdown-menu/src/dropdown-menu-item-indicator.directive.mjs +0 -22
  296. package/esm2022/dropdown-menu/src/dropdown-menu-item-radio-group.directive.mjs +0 -37
  297. package/esm2022/dropdown-menu/src/dropdown-menu-item-radio.directive.mjs +0 -64
  298. package/esm2022/dropdown-menu/src/dropdown-menu-item-selectable.mjs +0 -31
  299. package/esm2022/dropdown-menu/src/dropdown-menu-item.directive.mjs +0 -71
  300. package/esm2022/dropdown-menu/src/dropdown-menu-label.directive.mjs +0 -14
  301. package/esm2022/dropdown-menu/src/dropdown-menu-separator.directive.mjs +0 -21
  302. package/esm2022/dropdown-menu/src/dropdown-menu-trigger.directive.mjs +0 -176
  303. package/esm2022/index.mjs +0 -2
  304. package/esm2022/label/index.mjs +0 -2
  305. package/esm2022/label/radix-ng-primitives-label.mjs +0 -5
  306. package/esm2022/label/src/label.directive.mjs +0 -59
  307. package/esm2022/menu/index.mjs +0 -45
  308. package/esm2022/menu/radix-ng-primitives-menu.mjs +0 -5
  309. package/esm2022/menu/src/menu-content.directive.mjs +0 -17
  310. package/esm2022/menu/src/menu-directive.mjs +0 -18
  311. package/esm2022/menu/src/menu-group.directive.mjs +0 -20
  312. package/esm2022/menu/src/menu-item.directive.mjs +0 -46
  313. package/esm2022/menu/src/menu-label.directive.mjs +0 -14
  314. package/esm2022/menu/src/menu-separator.directive.mjs +0 -21
  315. package/esm2022/menubar/index.mjs +0 -60
  316. package/esm2022/menubar/radix-ng-primitives-menubar.mjs +0 -5
  317. package/esm2022/menubar/src/menubar-content.directive.mjs +0 -17
  318. package/esm2022/menubar/src/menubar-item-checkbox.directive.mjs +0 -34
  319. package/esm2022/menubar/src/menubar-item-indicator.directive.mjs +0 -17
  320. package/esm2022/menubar/src/menubar-item-radio.directive.mjs +0 -35
  321. package/esm2022/menubar/src/menubar-item.directive.mjs +0 -20
  322. package/esm2022/menubar/src/menubar-radio-group.directive.mjs +0 -17
  323. package/esm2022/menubar/src/menubar-root.directive.mjs +0 -24
  324. package/esm2022/menubar/src/menubar-separator.directive.mjs +0 -17
  325. package/esm2022/menubar/src/menubar-trigger.directive.mjs +0 -45
  326. package/esm2022/progress/index.mjs +0 -3
  327. package/esm2022/progress/radix-ng-primitives-progress.mjs +0 -5
  328. package/esm2022/progress/src/progress-indicator.directive.mjs +0 -34
  329. package/esm2022/progress/src/progress-root.directive.mjs +0 -127
  330. package/esm2022/radio/index.mjs +0 -4
  331. package/esm2022/radio/radix-ng-primitives-radio.mjs +0 -5
  332. package/esm2022/radio/src/radio-indicator.directive.mjs +0 -25
  333. package/esm2022/radio/src/radio-item.directive.mjs +0 -70
  334. package/esm2022/radio/src/radio-root.directive.mjs +0 -194
  335. package/esm2022/radio/src/radio-tokens.mjs +0 -3
  336. package/esm2022/radix-ng-primitives.mjs +0 -5
  337. package/esm2022/separator/index.mjs +0 -2
  338. package/esm2022/separator/radix-ng-primitives-separator.mjs +0 -5
  339. package/esm2022/separator/src/separator.directive.mjs +0 -31
  340. package/esm2022/switch/index.mjs +0 -30
  341. package/esm2022/switch/radix-ng-primitives-switch.mjs +0 -5
  342. package/esm2022/switch/src/switch-input.directive.mjs +0 -32
  343. package/esm2022/switch/src/switch-root.directive.mjs +0 -95
  344. package/esm2022/switch/src/switch-thumb.directive.mjs +0 -23
  345. package/esm2022/tabs/index.mjs +0 -38
  346. package/esm2022/tabs/radix-ng-primitives-tabs.mjs +0 -5
  347. package/esm2022/tabs/src/tabs-content.directive.mjs +0 -29
  348. package/esm2022/tabs/src/tabs-context.service.mjs +0 -43
  349. package/esm2022/tabs/src/tabs-list.directive.mjs +0 -23
  350. package/esm2022/tabs/src/tabs-root.directive.mjs +0 -54
  351. package/esm2022/tabs/src/tabs-trigger.directive.mjs +0 -52
  352. package/esm2022/toggle/index.mjs +0 -2
  353. package/esm2022/toggle/radix-ng-primitives-toggle.mjs +0 -5
  354. package/esm2022/toggle/src/toggle.directive.mjs +0 -39
  355. package/esm2022/toggle-group/index.mjs +0 -6
  356. package/esm2022/toggle-group/radix-ng-primitives-toggle-group.mjs +0 -5
  357. package/esm2022/toggle-group/src/toggle-group-button.directive.mjs +0 -75
  358. package/esm2022/toggle-group/src/toggle-group-button.token.mjs +0 -6
  359. package/esm2022/toggle-group/src/toggle-group-multi.directive.mjs +0 -143
  360. package/esm2022/toggle-group/src/toggle-group.directive.mjs +0 -134
  361. package/esm2022/toggle-group/src/toggle-group.token.mjs +0 -6
  362. package/fesm2022/radix-ng-primitives-accordion.mjs +0 -418
  363. package/fesm2022/radix-ng-primitives-accordion.mjs.map +0 -1
  364. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +0 -161
  365. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +0 -1
  366. package/fesm2022/radix-ng-primitives-avatar.mjs +0 -156
  367. package/fesm2022/radix-ng-primitives-avatar.mjs.map +0 -1
  368. package/fesm2022/radix-ng-primitives-checkbox.mjs +0 -241
  369. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +0 -1
  370. package/fesm2022/radix-ng-primitives-collapsible.mjs +0 -213
  371. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +0 -1
  372. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs +0 -502
  373. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs.map +0 -1
  374. package/fesm2022/radix-ng-primitives-label.mjs +0 -66
  375. package/fesm2022/radix-ng-primitives-label.mjs.map +0 -1
  376. package/fesm2022/radix-ng-primitives-menu.mjs +0 -158
  377. package/fesm2022/radix-ng-primitives-menu.mjs.map +0 -1
  378. package/fesm2022/radix-ng-primitives-menubar.mjs +0 -245
  379. package/fesm2022/radix-ng-primitives-menubar.mjs.map +0 -1
  380. package/fesm2022/radix-ng-primitives-progress.mjs +0 -165
  381. package/fesm2022/radix-ng-primitives-progress.mjs.map +0 -1
  382. package/fesm2022/radix-ng-primitives-radio.mjs +0 -289
  383. package/fesm2022/radix-ng-primitives-radio.mjs.map +0 -1
  384. package/fesm2022/radix-ng-primitives-separator.mjs +0 -38
  385. package/fesm2022/radix-ng-primitives-separator.mjs.map +0 -1
  386. package/fesm2022/radix-ng-primitives-switch.mjs +0 -173
  387. package/fesm2022/radix-ng-primitives-switch.mjs.map +0 -1
  388. package/fesm2022/radix-ng-primitives-tabs.mjs +0 -222
  389. package/fesm2022/radix-ng-primitives-tabs.mjs.map +0 -1
  390. package/fesm2022/radix-ng-primitives-toggle-group.mjs +0 -358
  391. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +0 -1
  392. package/fesm2022/radix-ng-primitives-toggle.mjs +0 -46
  393. package/fesm2022/radix-ng-primitives-toggle.mjs.map +0 -1
  394. package/fesm2022/radix-ng-primitives.mjs +0 -4
  395. package/fesm2022/radix-ng-primitives.mjs.map +0 -1
  396. package/label/src/label.directive.d.ts +0 -29
  397. package/menu/index.d.ts +0 -18
  398. package/menu/src/menu-content.directive.d.ts +0 -6
  399. package/menu/src/menu-directive.d.ts +0 -6
  400. package/menu/src/menu-group.directive.d.ts +0 -6
  401. package/menu/src/menu-item.directive.d.ts +0 -12
  402. package/menu/src/menu-label.directive.d.ts +0 -5
  403. package/menu/src/menu-separator.directive.d.ts +0 -6
  404. package/menubar/index.d.ts +0 -24
  405. package/menubar/src/menubar-content.directive.d.ts +0 -6
  406. package/menubar/src/menubar-item-checkbox.directive.d.ts +0 -14
  407. package/menubar/src/menubar-item-indicator.directive.d.ts +0 -5
  408. package/menubar/src/menubar-item-radio.directive.d.ts +0 -14
  409. package/menubar/src/menubar-item.directive.d.ts +0 -8
  410. package/menubar/src/menubar-radio-group.directive.d.ts +0 -6
  411. package/menubar/src/menubar-root.directive.d.ts +0 -7
  412. package/menubar/src/menubar-separator.directive.d.ts +0 -6
  413. package/menubar/src/menubar-trigger.directive.d.ts +0 -11
  414. package/progress/src/progress-indicator.directive.d.ts +0 -16
  415. package/progress/src/progress-root.directive.d.ts +0 -63
  416. package/radio/src/radio-indicator.directive.d.ts +0 -9
  417. package/radio/src/radio-item.directive.d.ts +0 -21
  418. package/radio/src/radio-root.directive.d.ts +0 -72
  419. package/separator/src/separator.directive.d.ts +0 -22
  420. package/switch/index.d.ts +0 -13
  421. package/switch/src/switch-input.directive.d.ts +0 -6
  422. package/switch/src/switch-root.directive.d.ts +0 -51
  423. package/switch/src/switch-thumb.directive.d.ts +0 -6
  424. package/tabs/index.d.ts +0 -15
  425. package/tabs/src/tabs-content.directive.d.ts +0 -8
  426. package/tabs/src/tabs-context.service.d.ts +0 -22
  427. package/tabs/src/tabs-list.directive.d.ts +0 -6
  428. package/tabs/src/tabs-root.directive.d.ts +0 -37
  429. package/tabs/src/tabs-trigger.directive.d.ts +0 -19
  430. package/toggle/src/toggle.directive.d.ts +0 -30
  431. package/toggle-group/src/toggle-group-button.directive.d.ts +0 -39
  432. package/toggle-group/src/toggle-group-button.token.d.ts +0 -4
  433. package/toggle-group/src/toggle-group-multi.directive.d.ts +0 -93
  434. package/toggle-group/src/toggle-group.directive.d.ts +0 -84
  435. package/toggle-group/src/toggle-group.token.d.ts +0 -5
  436. /package/accordion/{index.d.ts → index.ts} +0 -0
  437. /package/avatar/{index.d.ts → index.ts} +0 -0
  438. /package/checkbox/{index.d.ts → index.ts} +0 -0
  439. /package/collapsible/{index.d.ts → index.ts} +0 -0
  440. /package/dropdown-menu/{index.d.ts → index.ts} +0 -0
  441. /package/{index.d.ts → index.ts} +0 -0
  442. /package/label/{index.d.ts → index.ts} +0 -0
  443. /package/separator/{index.d.ts → index.ts} +0 -0
  444. /package/toggle/{index.d.ts → index.ts} +0 -0
  445. /package/toggle-group/{index.d.ts → index.ts} +0 -0
@@ -0,0 +1,51 @@
1
+ import { Component, ElementRef, NgZone, OnInit } from '@angular/core';
2
+ import { usePresence } from '../src/presence';
3
+ import { CollapseContext, transitionCollapsing } from '../src/transitions/transition.collapse';
4
+
5
+ @Component({
6
+ selector: 'app-presence',
7
+ template: `
8
+ <div #element>Presence Component</div>
9
+ `,
10
+ styles: [
11
+ `
12
+ .collapse {
13
+ transition: height 0.5s ease-in-out;
14
+ }
15
+ .collapsing {
16
+ height: 0px;
17
+ }
18
+ .show {
19
+ height: auto;
20
+ }
21
+ `
22
+
23
+ ]
24
+ })
25
+ export class PresenceComponent implements OnInit {
26
+ private context: CollapseContext = {
27
+ direction: 'show',
28
+ dimension: 'height'
29
+ };
30
+ private element!: HTMLElement;
31
+
32
+ constructor(
33
+ private zone: NgZone,
34
+ private elRef: ElementRef
35
+ ) {}
36
+
37
+ ngOnInit(): void {
38
+ this.element = this.elRef.nativeElement.querySelector('div');
39
+ const options = {
40
+ context: this.context,
41
+ animation: true,
42
+ state: 'stop' as const
43
+ };
44
+
45
+ usePresence(this.zone, this.element, transitionCollapsing, options).subscribe();
46
+ }
47
+
48
+ getContext(): CollapseContext {
49
+ return this.context;
50
+ }
51
+ }
@@ -0,0 +1,50 @@
1
+ import { NgZone } from '@angular/core';
2
+ import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
3
+ import { By } from '@angular/platform-browser';
4
+ import { PresenceComponent } from './presence-test.component';
5
+
6
+ describe('presence', () => {
7
+ let component: PresenceComponent;
8
+ let fixture: ComponentFixture<PresenceComponent>;
9
+ let zone: NgZone;
10
+
11
+ beforeEach(async () => {
12
+ await TestBed.configureTestingModule({
13
+ declarations: [PresenceComponent],
14
+ providers: [{ provide: NgZone, useValue: new NgZone({ enableLongStackTrace: false }) }]
15
+ }).compileComponents();
16
+
17
+ fixture = TestBed.createComponent(PresenceComponent);
18
+ component = fixture.componentInstance;
19
+ zone = TestBed.inject(NgZone);
20
+
21
+ fixture.detectChanges(); // triggers ngOnInit
22
+ });
23
+
24
+ it('should create', () => {
25
+ expect(component).toBeTruthy();
26
+ });
27
+
28
+ it('should initialize element and context correctly', () => {
29
+ const element = fixture.debugElement.query(By.css('div')).nativeElement;
30
+
31
+ const context = component.getContext();
32
+
33
+ expect(component['element']).toBe(element);
34
+ expect(context).toEqual({ direction: 'show', dimension: 'height', maxSize: '0px' });
35
+ });
36
+
37
+ it('should complete animation correctly', fakeAsync(() => {
38
+ const element = fixture.debugElement.query(By.css('div')).nativeElement;
39
+
40
+ zone.runOutsideAngular(() => {
41
+ element.dispatchEvent(new Event('transitionend'));
42
+ });
43
+
44
+ tick(600);
45
+ fixture.detectChanges();
46
+
47
+ expect(element.classList.contains('collapsing')).toBe(false);
48
+ expect(element.classList.contains('show')).toBe(true);
49
+ }));
50
+ });
@@ -0,0 +1,4 @@
1
+ export * from './src/presence';
2
+ export * from './src/transitions/transition.collapse';
3
+ export * from './src/transitions/transition.toast';
4
+ export * from './src/types';
@@ -0,0 +1,119 @@
1
+ import { NgZone } from '@angular/core';
2
+ import { EMPTY, endWith, filter, fromEvent, Observable, of, race, Subject, takeUntil, timer } from 'rxjs';
3
+ import { TransitionContext, TransitionEndFn, TransitionOptions, TransitionStartFn } from './types';
4
+ import { getTransitionDurationMs, runInZone } from './utils';
5
+
6
+ const noopFn: TransitionEndFn = () => {
7
+ /* Noop */
8
+ };
9
+ const TransitionsMap = new Map<HTMLElement, TransitionContext<any>>();
10
+
11
+ /**
12
+ * Manages the presence of an element with optional transition animation.
13
+ *
14
+ * @template T - The type of the context object used in the transition.
15
+ * @param {NgZone} zone - The Angular zone to control the change detection context.
16
+ * @param {HTMLElement} element - The target HTML element to apply the transition.
17
+ * @param {TransitionOptions<T>} options - Options for controlling the transition behavior.
18
+ * @param {T} [options.context] - An optional context object to pass through the transition.
19
+ * @param {boolean} options.animation - A flag indicating if the transition should be animated.
20
+ * @param {'start' | 'continue' | 'stop'} options.state - The desired state of the transition.
21
+ * @param {TransitionStartFn<T>} startFn - A function to start the transition.
22
+ * @returns {Observable<void>} - An observable that emits when the transition completes.
23
+ *
24
+ * The `usePresence` function is designed to manage the presence and visibility of an HTML element,
25
+ * optionally applying a transition animation. It utilizes Angular's NgZone for efficient change
26
+ * detection management and allows for different states of transitions ('start', 'continue', 'stop').
27
+ * The function takes a start function to handle the beginning of the transition and returns an
28
+ * observable that completes when the transition ends.
29
+ *
30
+ * Example usage:
31
+ *
32
+ * const options: TransitionOptions<MyContext> = {
33
+ * context: {}, // your context object
34
+ * animation: true,
35
+ * state: 'start'
36
+ * };
37
+ *
38
+ * const startFn: TransitionStartFn<MyContext> = (el, animation, context) => {
39
+ * el.classList.add('active');
40
+ * return () => el.classList.remove('active');
41
+ * };
42
+ *
43
+ * usePresence(zone, element, startFn, options).subscribe(() => {
44
+ * console.log('Transition completed');
45
+ * });
46
+ */
47
+ const usePresence = <T>(
48
+ zone: NgZone,
49
+ element: HTMLElement,
50
+ startFn: TransitionStartFn<T>,
51
+ options: TransitionOptions<T>
52
+ ): Observable<void> => {
53
+ let context = options.context || <T>{};
54
+
55
+ const transitionTimerDelayMs = options.transitionTimerDelayMs ?? 5;
56
+ const state = options.state ?? 'stop';
57
+
58
+ const running = TransitionsMap.get(element);
59
+
60
+ if (running) {
61
+ switch (state) {
62
+ case 'continue':
63
+ return EMPTY;
64
+ case 'stop':
65
+ zone.run(() => running.transition$.complete());
66
+ context = { ...running.context, ...context };
67
+ TransitionsMap.delete(element);
68
+ break;
69
+ }
70
+ }
71
+ const endFn = startFn(element, options.animation, context) || noopFn;
72
+
73
+ if (!options.animation || window.getComputedStyle(element).transitionProperty === 'none') {
74
+ zone.run(() => endFn());
75
+ return of(undefined).pipe(runInZone(zone));
76
+ }
77
+
78
+ const transition$ = new Subject<void>();
79
+ const finishTransition$ = new Subject<void>();
80
+ const stop$ = transition$.pipe(endWith(true));
81
+
82
+ TransitionsMap.set(element, {
83
+ transition$,
84
+ complete: () => {
85
+ finishTransition$.next();
86
+ finishTransition$.complete();
87
+ },
88
+ context
89
+ });
90
+
91
+ const transitionDurationMs = getTransitionDurationMs(element);
92
+
93
+ zone.runOutsideAngular(() => {
94
+ const transitionEnd$ = fromEvent<TransitionEvent>(element, 'transitionend').pipe(
95
+ filter(({ target }) => target === element),
96
+ takeUntil(stop$)
97
+ );
98
+ const timer$ = timer(transitionDurationMs + transitionTimerDelayMs).pipe(takeUntil(stop$));
99
+
100
+ race(timer$, transitionEnd$, finishTransition$)
101
+ .pipe(takeUntil(stop$))
102
+ .subscribe(() => {
103
+ TransitionsMap.delete(element);
104
+ zone.run(() => {
105
+ endFn();
106
+ transition$.next();
107
+ transition$.complete();
108
+ });
109
+ });
110
+ });
111
+
112
+ return transition$.asObservable();
113
+ };
114
+
115
+ const completeTransition = (element: HTMLElement) => {
116
+ TransitionsMap.get(element)?.complete();
117
+ };
118
+
119
+ export { completeTransition, usePresence };
@@ -0,0 +1,99 @@
1
+ import { TransitionStartFn } from '../types';
2
+ import { triggerReflow } from '../utils';
3
+
4
+ export type CollapseContext = {
5
+ direction: 'show' | 'hide';
6
+ dimension: 'width' | 'height';
7
+ maxSize?: string;
8
+ };
9
+
10
+ // Define constants for class names
11
+ const COLLAPSE_CLASS = 'collapse';
12
+ const COLLAPSING_CLASS = 'collapsing';
13
+ const SHOW_CLASS = 'show';
14
+ /**
15
+ * Function to handle the start of a collapsing transition.
16
+ *
17
+ * @param element - The HTML element to animate.
18
+ * @param animation - Whether to use animation or not.
19
+ * @param context - The context containing direction and dimension information.
20
+ * @returns A function to clean up the animation.
21
+ */
22
+ export const transitionCollapsing: TransitionStartFn<CollapseContext> = (
23
+ element: HTMLElement,
24
+ animation: boolean,
25
+ context: CollapseContext
26
+ ) => {
27
+ const { direction, dimension } = context;
28
+ let { maxSize } = context;
29
+ const { classList } = element;
30
+
31
+ /**
32
+ * Sets initial classes based on the direction.
33
+ */
34
+ function setInitialClasses() {
35
+ classList.add(COLLAPSE_CLASS);
36
+ if (direction === 'show') {
37
+ classList.add(SHOW_CLASS);
38
+ } else {
39
+ classList.remove(SHOW_CLASS);
40
+ }
41
+ }
42
+
43
+ if (!animation) {
44
+ setInitialClasses();
45
+ return;
46
+ }
47
+
48
+ if (!maxSize) {
49
+ maxSize = measureCollapsingElementDimensionPx(element, dimension);
50
+ context.maxSize = maxSize;
51
+
52
+ // Fix the height before starting the animation
53
+ element.style[dimension] = direction !== 'show' ? maxSize : '0px';
54
+
55
+ classList.remove(COLLAPSE_CLASS, COLLAPSING_CLASS, 'show');
56
+
57
+ triggerReflow(element);
58
+
59
+ // Start the animation
60
+ classList.add(COLLAPSING_CLASS);
61
+ }
62
+
63
+ element.style[dimension] = direction === 'show' ? maxSize : '0px';
64
+
65
+ return () => {
66
+ setInitialClasses();
67
+ classList.remove(COLLAPSING_CLASS);
68
+ element.style[dimension] = '';
69
+ };
70
+ };
71
+
72
+ /**
73
+ * Measures the dimension of the collapsing element in pixels.
74
+ *
75
+ * @param element - The HTML element to measure.
76
+ * @param dimension - The dimension ('width' or 'height') to measure.
77
+ * @returns The size of the dimension in pixels.
78
+ */
79
+ function measureCollapsingElementDimensionPx(element: HTMLElement, dimension: 'width' | 'height'): string {
80
+ // SSR fix
81
+ if (typeof navigator === 'undefined') {
82
+ return '0px';
83
+ }
84
+
85
+ const { classList } = element;
86
+ const hasShownClass = classList.contains(SHOW_CLASS);
87
+ if (!hasShownClass) {
88
+ classList.add(SHOW_CLASS);
89
+ }
90
+
91
+ element.style[dimension] = '';
92
+ const dimensionSize = element.getBoundingClientRect()[dimension] + 'px';
93
+
94
+ if (!hasShownClass) {
95
+ classList.remove(SHOW_CLASS);
96
+ }
97
+
98
+ return dimensionSize;
99
+ }
@@ -0,0 +1,27 @@
1
+ import { TransitionStartFn } from '../types';
2
+ import { triggerReflow } from '../utils';
3
+
4
+ export const toastFadeInTransition: TransitionStartFn = (element: HTMLElement, animation: boolean) => {
5
+ const { classList } = element;
6
+
7
+ if (animation) {
8
+ classList.add('fade');
9
+ } else {
10
+ classList.add('show');
11
+ return;
12
+ }
13
+
14
+ triggerReflow(element);
15
+ classList.add('show', 'showing');
16
+
17
+ return () => {
18
+ classList.remove('showing');
19
+ };
20
+ };
21
+
22
+ export const toastFadeOutTransition: TransitionStartFn = ({ classList }: HTMLElement) => {
23
+ classList.add('showing');
24
+ return () => {
25
+ classList.remove('show', 'showing');
26
+ };
27
+ };
@@ -0,0 +1,20 @@
1
+ import { Subject } from 'rxjs';
2
+
3
+ type TransitionOptions<T> = {
4
+ context?: T;
5
+ animation: boolean;
6
+ state?: 'continue' | 'stop';
7
+ transitionTimerDelayMs?: number;
8
+ };
9
+
10
+ type TransitionContext<T> = {
11
+ transition$: Subject<any>;
12
+ complete: () => void;
13
+ context: T;
14
+ };
15
+
16
+ type TransitionStartFn<T = any> = (element: HTMLElement, animation: boolean, context: T) => TransitionEndFn | void;
17
+
18
+ type TransitionEndFn = () => void;
19
+
20
+ export { TransitionContext, TransitionEndFn, TransitionOptions, TransitionStartFn };
@@ -0,0 +1,63 @@
1
+ import { NgZone } from '@angular/core';
2
+ import { Observable } from 'rxjs';
3
+
4
+ /**
5
+ * Ensures that the observable stream runs inside Angular's NgZone.
6
+ *
7
+ * This function is a higher-order function that takes an observable stream as input and ensures
8
+ * that all emissions, errors, and completion notifications are run inside Angular's NgZone. This
9
+ * is particularly useful for ensuring that change detection is triggered properly in Angular
10
+ * applications.
11
+ *
12
+ * @template T - The type of the items emitted by the observable.
13
+ * @param {NgZone} zone - The Angular zone to control the change detection context.
14
+ * @returns {(source: Observable<T>) => Observable<T>} - A function that takes an observable as input
15
+ * and returns an observable that runs inside Angular's NgZone.
16
+ *
17
+ * Example usage:
18
+ *
19
+ * const source$ = of('some value');
20
+ * const zoned$ = source$.pipe(runInZone(zone));
21
+ * zoned$.subscribe(value => {
22
+ * console.log('Value:', value);
23
+ * });
24
+ */
25
+ function runInZone<T>(zone: NgZone): (source: Observable<T>) => Observable<T> {
26
+ return (source: Observable<T>) =>
27
+ new Observable((observer) =>
28
+ source.subscribe({
29
+ next: (value) => zone.run(() => observer.next(value)),
30
+ error: (err) => zone.run(() => observer.error(err)),
31
+ complete: () => zone.run(() => observer.complete())
32
+ })
33
+ );
34
+ }
35
+
36
+ /**
37
+ * Calculates the total transition duration in milliseconds for a given HTML element.
38
+ *
39
+ * This function retrieves the computed style of the specified element and extracts the
40
+ * transition duration and delay properties. It then converts these values from seconds
41
+ * to milliseconds and returns their sum, representing the total transition duration.
42
+ *
43
+ * @param {HTMLElement} element - The HTML element for which to calculate the transition duration.
44
+ * @returns {number} - The total transition duration in milliseconds.
45
+ *
46
+ * Example usage:
47
+ *
48
+ * const durationMs = getTransitionDurationMs(element);
49
+ * console.log(`Transition duration: ${durationMs} ms`);
50
+ */
51
+ function getTransitionDurationMs(element: HTMLElement): number {
52
+ const { transitionDelay, transitionDuration } = window.getComputedStyle(element);
53
+ const transitionDelaySec = parseFloat(transitionDelay);
54
+ const transitionDurationSec = parseFloat(transitionDuration);
55
+
56
+ return (transitionDelaySec + transitionDurationSec) * 1000;
57
+ }
58
+
59
+ export { getTransitionDurationMs, runInZone };
60
+
61
+ export function triggerReflow(element: HTMLElement) {
62
+ return (element || document.body).getBoundingClientRect();
63
+ }
@@ -0,0 +1,69 @@
1
+ import { Component, ElementRef, inject, NgZone, OnInit } from '@angular/core';
2
+ import { usePresence } from '../src/presence';
3
+ import { CollapseContext, transitionCollapsing } from '../src/transitions/transition.collapse';
4
+
5
+ @Component({
6
+ selector: 'app-presence',
7
+ standalone: true,
8
+ template: `
9
+ <div>
10
+ <button (click)="toggle()">Toggle</button>
11
+ <div class="collapse-content" #collapseContent>Content to be collapsed</div>
12
+ </div>
13
+ `,
14
+ styles: [
15
+ `
16
+ .collapse-content {
17
+ overflow: hidden;
18
+ transition: height 0.5s ease-in-out;
19
+ }
20
+ .collapse:not(.show) {
21
+ display: none;
22
+ }
23
+ .show {
24
+ height: auto;
25
+ }
26
+ `
27
+
28
+ ]
29
+ })
30
+ export class PresenceStoryComponent implements OnInit {
31
+ private elRef = inject(ElementRef);
32
+ private zone = inject(NgZone);
33
+
34
+ private element!: HTMLElement;
35
+
36
+ private _isCollapsed = false;
37
+ private afterInit = false;
38
+
39
+ set collapsed(isCollapsed: boolean) {
40
+ if (this._isCollapsed !== isCollapsed) {
41
+ this._isCollapsed = isCollapsed;
42
+ if (this.afterInit) {
43
+ this.initCollapse(this._isCollapsed, true);
44
+ }
45
+ }
46
+ }
47
+
48
+ ngOnInit(): void {
49
+ this.element = this.elRef.nativeElement.querySelector('.collapse-content');
50
+ this.initCollapse(this._isCollapsed, false);
51
+ this.afterInit = true;
52
+ }
53
+
54
+ toggle(open: boolean = this._isCollapsed) {
55
+ this.collapsed = !open;
56
+ }
57
+
58
+ private initCollapse(collapsed: boolean, animation: boolean): void {
59
+ const options = {
60
+ context: {
61
+ direction: collapsed ? 'hide' : 'show',
62
+ dimension: 'height'
63
+ } as CollapseContext,
64
+ animation
65
+ };
66
+
67
+ usePresence(this.zone, this.element, transitionCollapsing, options).subscribe();
68
+ }
69
+ }
@@ -0,0 +1,40 @@
1
+ import { ArgTypes, Canvas, Markdown, Meta } from '@storybook/blocks';
2
+
3
+ <Meta title="Primitives/Presence" />
4
+
5
+ # Presence
6
+
7
+ The `usePresence` function is a utility designed to manage transitions and animations
8
+ for DOM elements in an Angular application.
9
+ It provides a consistent way to handle animations, ensuring that they run correctly within Angular's zone.
10
+
11
+ By using `usePresence`, developers can manage transitions and animations in a consistent and performant manner, ensuring that their Angular applications remain responsive and efficient.
12
+
13
+ ## Function Signature
14
+
15
+ ```typescript
16
+ export const usePresence = <T>(
17
+ zone: NgZone,
18
+ element: HTMLElement,
19
+ startFn: TransitionStartFn<T>,
20
+ options: TransitionOptions<T>
21
+ ): Observable<void> => { ... }
22
+
23
+ ```
24
+
25
+ ### Parameters
26
+
27
+ - `zone` (NgZone): Angular's NgZone service, which is used to manage change detection and ensure that transitions and animations are run outside of Angular's zone, avoiding unnecessary change detection cycles.
28
+ - `element` (HTMLElement): The DOM element that the transition will be applied to.
29
+ - startFn (`TransitionStartFn<T>`): A function that initiates the transition. It takes the element, the animation flag, and the context as parameters, and returns a cleanup function (TransitionEndFn) to be called when the transition ends.
30
+ - options (`TransitionOptions<T>`): An object containing options for the transition.
31
+ - context (T): A context object that provides additional information needed for the transition.
32
+ - animation (boolean): A boolean indicating whether the transition should include animation.
33
+ - state ('stop' | 'continue'): Specifies whether to stop any running transition ('stop') or continue with the current one ('continue'). The default value is 'stop'.
34
+ - transitionTimerDelayMs (number, optional): An optional delay (in milliseconds) to be added to the transition timer. Default value is 5.
35
+
36
+ ## Notes
37
+
38
+ - Transition Context: The context object can hold any additional data required for the transition. It allows for flexible and reusable transition logic.
39
+ - Zone Management: Running transition logic outside Angular's zone prevents unnecessary change detection cycles, improving performance.
40
+ - Customizable Delay: The optional transitionTimerDelayMs allows for fine-tuning the transition timing.
@@ -0,0 +1,29 @@
1
+ import { componentWrapperDecorator, Meta, moduleMetadata, StoryObj } from '@storybook/angular';
2
+ import { PresenceStoryComponent } from './presence-story.componen';
3
+
4
+ export default {
5
+ title: 'Primitives/Presence',
6
+ decorators: [
7
+ moduleMetadata({
8
+ imports: [PresenceStoryComponent]
9
+ }),
10
+ componentWrapperDecorator(
11
+ (story) =>
12
+ `<div class="radix-themes light light-theme"
13
+ data-radius="medium"
14
+ data-scaling="100%">${story}</div>`
15
+ )
16
+ ]
17
+ } as Meta;
18
+
19
+ type Story = StoryObj;
20
+
21
+ export const Default: Story = {
22
+ render: (args) => ({
23
+ props: args,
24
+ template: `
25
+ <app-presence></app-presence>
26
+
27
+ `
28
+ })
29
+ };
@@ -0,0 +1,55 @@
1
+ import { Component } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+ import { RdxProgressIndicatorDirective } from '../src/progress-indicator.directive';
4
+ import { RdxProgressRootDirective } from '../src/progress-root.directive';
5
+
6
+ @Component({
7
+ template: `
8
+ <div [rdxValue]="value" [rdxMax]="max" [id]="id" rdxProgressRoot>
9
+ <div rdxProgressIndicator></div>
10
+ </div>
11
+ `
12
+ })
13
+ class TestHostComponent {
14
+ value: number | null | undefined = 50;
15
+ max = 100;
16
+ id = 'test-progress';
17
+ }
18
+
19
+ describe('RdxProgress', () => {
20
+ let component: TestHostComponent;
21
+ let fixture: ComponentFixture<TestHostComponent>;
22
+
23
+ beforeEach(async () => {
24
+ await TestBed.configureTestingModule({
25
+ imports: [RdxProgressRootDirective, RdxProgressIndicatorDirective],
26
+ declarations: [TestHostComponent]
27
+ }).compileComponents();
28
+
29
+ fixture = TestBed.createComponent(TestHostComponent);
30
+ component = fixture.componentInstance;
31
+ fixture.detectChanges();
32
+ });
33
+
34
+ it('should set the correct aria attributes and data attributes', () => {
35
+ const progressElement: HTMLElement = fixture.nativeElement.querySelector('div[role="progressbar"]');
36
+
37
+ expect(progressElement.getAttribute('aria-valuemax')).toBe('100');
38
+ expect(progressElement.getAttribute('aria-valuemin')).toBe('0');
39
+ expect(progressElement.getAttribute('aria-valuenow')).toBe('50');
40
+ expect(progressElement.getAttribute('aria-valuetext')).toBe('50%');
41
+ expect(progressElement.getAttribute('data-state')).toBe('loading');
42
+ expect(progressElement.getAttribute('data-value')).toBe('50');
43
+ expect(progressElement.getAttribute('data-max')).toBe('100');
44
+ expect(progressElement.id).toBe('test-progress');
45
+ });
46
+
47
+ it('should show complete state when value equals max', () => {
48
+ component.value = 100;
49
+ fixture.detectChanges();
50
+
51
+ const progressElement: HTMLElement = fixture.nativeElement.querySelector('div[role="progressbar"]');
52
+
53
+ expect(progressElement.getAttribute('data-state')).toBe('complete');
54
+ });
55
+ });
@@ -1,3 +1,4 @@
1
1
  export * from './src/progress-indicator.directive';
2
2
  export * from './src/progress-root.directive';
3
+
3
4
  export type { ProgressProps } from './src/progress-root.directive';
@@ -0,0 +1,5 @@
1
+ {
2
+ "lib": {
3
+ "entryFile": "index.ts"
4
+ }
5
+ }
@@ -0,0 +1,26 @@
1
+ import { Directive } from '@angular/core';
2
+ import { injectProgress } from './progress-root.directive';
3
+
4
+ /**
5
+ * Directive to manage progress indicator state and attributes.
6
+ *
7
+ * This directive is used to display the progress indicator inside the progress bar.
8
+ * It inherits the state and value from the `RdxProgressRootDirective`.
9
+ */
10
+ @Directive({
11
+ selector: 'div[rdxProgressIndicator]',
12
+ exportAs: 'ProgressIndicator',
13
+ standalone: true,
14
+ host: {
15
+ '[attr.data-state]': 'progress.state',
16
+ '[attr.data-value]': 'progress.value',
17
+ '[attr.data-max]': 'progress.max'
18
+ }
19
+ })
20
+ export class RdxProgressIndicatorDirective {
21
+ /**
22
+ *
23
+ * This allows the directive to access the progress bar state and values.
24
+ */
25
+ protected readonly progress = injectProgress();
26
+ }