@tacdaed/fragments 1.0.0-beta.0 → 1.0.0-beta.2

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 (248) hide show
  1. package/README.md +2 -18
  2. package/ng-package.json +25 -0
  3. package/package.json +22 -29
  4. package/src/lib/components/accordion/accordion.component.html +103 -0
  5. package/src/lib/components/accordion/accordion.component.scss +382 -0
  6. package/src/lib/components/accordion/accordion.component.spec.ts +147 -0
  7. package/src/lib/components/accordion/accordion.component.ts +211 -0
  8. package/src/lib/components/accordion/accordion.type.ts +82 -0
  9. package/src/lib/components/breadcrumb/breadcrumb.component.html +43 -0
  10. package/src/lib/components/breadcrumb/breadcrumb.component.scss +112 -0
  11. package/src/lib/components/breadcrumb/breadcrumb.component.spec.ts +33 -0
  12. package/src/lib/components/breadcrumb/breadcrumb.component.ts +103 -0
  13. package/src/lib/components/breadcrumb/breadcrumb.interface.ts +7 -0
  14. package/src/lib/components/button/button.component.html +57 -0
  15. package/src/lib/components/button/button.component.scss +445 -0
  16. package/src/lib/components/button/button.component.spec.ts +99 -0
  17. package/src/lib/components/button/button.component.ts +143 -0
  18. package/src/lib/components/button/button.type.ts +7 -0
  19. package/src/lib/components/card/card.component.html +44 -0
  20. package/src/lib/components/card/card.component.scss +114 -0
  21. package/src/lib/components/card/card.component.spec.ts +65 -0
  22. package/src/lib/components/card/card.component.ts +21 -0
  23. package/src/lib/components/card/card.type.ts +3 -0
  24. package/src/lib/components/code-block/code-block.component.html +55 -0
  25. package/src/lib/components/code-block/code-block.component.scss +122 -0
  26. package/src/lib/components/code-block/code-block.component.spec.ts +81 -0
  27. package/src/lib/components/code-block/code-block.component.ts +302 -0
  28. package/src/lib/components/code-block/code-block.interface.ts +28 -0
  29. package/src/lib/components/code-block/code-block.type.ts +73 -0
  30. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.html +14 -0
  31. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.scss +20 -0
  32. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.spec.ts +38 -0
  33. package/src/lib/components/decorative/sparkle-field/sparkle-field.component.ts +181 -0
  34. package/src/lib/components/input/input-base.ts +187 -0
  35. package/src/lib/components/input/input-calendar/input-calendar.component.html +76 -0
  36. package/src/lib/components/input/input-calendar/input-calendar.component.scss +179 -0
  37. package/src/lib/components/input/input-calendar/input-calendar.component.spec.ts +44 -0
  38. package/src/lib/components/input/input-calendar/input-calendar.component.ts +299 -0
  39. package/src/lib/components/input/input-checkbox/input-checkbox.component.html +37 -0
  40. package/src/lib/components/input/input-checkbox/input-checkbox.component.scss +128 -0
  41. package/src/lib/components/input/input-checkbox/input-checkbox.component.spec.ts +43 -0
  42. package/src/lib/components/input/input-checkbox/input-checkbox.component.ts +112 -0
  43. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.html +43 -0
  44. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.scss +140 -0
  45. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.spec.ts +62 -0
  46. package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.ts +136 -0
  47. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.html +81 -0
  48. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.scss +228 -0
  49. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.spec.ts +62 -0
  50. package/src/lib/components/input/input-clock-picker/input-clock-picker.component.ts +178 -0
  51. package/src/lib/components/input/input-consts.ts +132 -0
  52. package/src/lib/components/input/input-date/input-date-validators.ts +41 -0
  53. package/src/lib/components/input/input-date/input-date.component.html +41 -0
  54. package/src/lib/components/input/input-date/input-date.component.scss +95 -0
  55. package/src/lib/components/input/input-date/input-date.component.spec.ts +43 -0
  56. package/src/lib/components/input/input-date/input-date.component.ts +359 -0
  57. package/src/lib/components/input/input-date-time/input-date-time.component.html +70 -0
  58. package/src/lib/components/input/input-date-time/input-date-time.component.scss +133 -0
  59. package/src/lib/components/input/input-date-time/input-date-time.component.spec.ts +36 -0
  60. package/src/lib/components/input/input-date-time/input-date-time.component.ts +387 -0
  61. package/src/lib/components/input/input-file-upload/input-file-upload.component.html +89 -0
  62. package/src/lib/components/input/input-file-upload/input-file-upload.component.scss +171 -0
  63. package/src/lib/components/input/input-file-upload/input-file-upload.component.spec.ts +43 -0
  64. package/src/lib/components/input/input-file-upload/input-file-upload.component.ts +351 -0
  65. package/src/lib/components/input/input-interface.ts +8 -0
  66. package/src/lib/components/input/input-number/input-number-validators.ts +0 -0
  67. package/src/lib/components/input/input-number/input-number.component.html +51 -0
  68. package/src/lib/components/input/input-number/input-number.component.scss +140 -0
  69. package/src/lib/components/input/input-number/input-number.component.spec.ts +44 -0
  70. package/src/lib/components/input/input-number/input-number.component.ts +343 -0
  71. package/src/lib/components/input/input-radio-group/input-radio-group.component.html +44 -0
  72. package/src/lib/components/input/input-radio-group/input-radio-group.component.scss +139 -0
  73. package/src/lib/components/input/input-radio-group/input-radio-group.component.spec.ts +58 -0
  74. package/src/lib/components/input/input-radio-group/input-radio-group.component.ts +132 -0
  75. package/src/lib/components/input/input-slider/input-slider.component.html +111 -0
  76. package/src/lib/components/input/input-slider/input-slider.component.scss +203 -0
  77. package/src/lib/components/input/input-slider/input-slider.component.spec.ts +46 -0
  78. package/src/lib/components/input/input-slider/input-slider.component.ts +410 -0
  79. package/src/lib/components/input/input-text/input-text-validators.ts +67 -0
  80. package/src/lib/components/input/input-text/input-text.component.html +71 -0
  81. package/src/lib/components/input/input-text/input-text.component.scss +118 -0
  82. package/src/lib/components/input/input-text/input-text.component.spec.ts +55 -0
  83. package/src/lib/components/input/input-text/input-text.component.ts +215 -0
  84. package/src/lib/components/input/input-time/input-time-validators.ts +42 -0
  85. package/src/lib/components/input/input-time/input-time.component.html +92 -0
  86. package/src/lib/components/input/input-time/input-time.component.scss +191 -0
  87. package/src/lib/components/input/input-time/input-time.component.spec.ts +39 -0
  88. package/src/lib/components/input/input-time/input-time.component.ts +691 -0
  89. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.html +36 -0
  90. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.scss +121 -0
  91. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.spec.ts +54 -0
  92. package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.ts +117 -0
  93. package/src/lib/components/input/input-type.ts +18 -0
  94. package/src/lib/components/input/input-validation/input-validation.component.html +19 -0
  95. package/src/lib/components/input/input-validation/input-validation.component.scss +39 -0
  96. package/src/lib/components/input/input-validation/input-validation.component.spec.ts +45 -0
  97. package/src/lib/components/input/input-validation/input-validation.component.ts +13 -0
  98. package/src/lib/components/input/input.pipe.ts +14 -0
  99. package/src/lib/components/layout/container/container.component.html +1 -0
  100. package/src/lib/components/layout/container/container.component.scss +33 -0
  101. package/src/lib/components/layout/container/container.component.ts +32 -0
  102. package/src/lib/components/layout/container/container.type.ts +1 -0
  103. package/src/lib/components/layout/divider/divider.component.html +1 -0
  104. package/src/lib/components/layout/divider/divider.component.scss +60 -0
  105. package/src/lib/components/layout/divider/divider.component.ts +38 -0
  106. package/src/lib/components/layout/divider/divider.type.ts +2 -0
  107. package/src/lib/components/layout/section/section.component.html +21 -0
  108. package/src/lib/components/layout/section/section.component.scss +43 -0
  109. package/src/lib/components/layout/section/section.component.ts +33 -0
  110. package/src/lib/components/layout/section/section.type.ts +2 -0
  111. package/src/lib/components/layout/separator/separator.component.html +9 -0
  112. package/src/lib/components/layout/separator/separator.component.scss +52 -0
  113. package/src/lib/components/layout/separator/separator.component.ts +25 -0
  114. package/src/lib/components/layout/separator/separator.type.ts +1 -0
  115. package/src/lib/components/loader/content-blur/content-blur.component.html +13 -0
  116. package/src/lib/components/loader/content-blur/content-blur.component.scss +43 -0
  117. package/src/lib/components/loader/content-blur/content-blur.component.spec.ts +42 -0
  118. package/src/lib/components/loader/content-blur/content-blur.component.ts +34 -0
  119. package/src/lib/components/loader/loader.type.ts +2 -0
  120. package/src/lib/components/loader/progress-bar/progress-bar.component.html +26 -0
  121. package/src/lib/components/loader/progress-bar/progress-bar.component.scss +151 -0
  122. package/src/lib/components/loader/progress-bar/progress-bar.component.spec.ts +47 -0
  123. package/src/lib/components/loader/progress-bar/progress-bar.component.ts +28 -0
  124. package/src/lib/components/loader/progress-bar/progress-bar.type.ts +8 -0
  125. package/src/lib/components/loader/pulse-loader/pulse-loader.component.html +12 -0
  126. package/src/lib/components/loader/pulse-loader/pulse-loader.component.scss +202 -0
  127. package/src/lib/components/loader/pulse-loader/pulse-loader.component.spec.ts +55 -0
  128. package/src/lib/components/loader/pulse-loader/pulse-loader.component.ts +73 -0
  129. package/src/lib/components/loader/pulse-loader/pulse-loader.type.ts +6 -0
  130. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.html +13 -0
  131. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.scss +113 -0
  132. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.spec.ts +37 -0
  133. package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.ts +51 -0
  134. package/src/lib/components/loader/skeleton-loader/skeleton-loader.type.ts +6 -0
  135. package/src/lib/components/loader/spinner/spinner.component.html +20 -0
  136. package/src/lib/components/loader/spinner/spinner.component.scss +137 -0
  137. package/src/lib/components/loader/spinner/spinner.component.spec.ts +43 -0
  138. package/src/lib/components/loader/spinner/spinner.component.ts +32 -0
  139. package/src/lib/components/loader/spinner/spinner.type.ts +6 -0
  140. package/src/lib/components/modal/modal.component.html +47 -0
  141. package/src/lib/components/modal/modal.component.scss +139 -0
  142. package/src/lib/components/modal/modal.component.spec.ts +60 -0
  143. package/src/lib/components/modal/modal.component.ts +83 -0
  144. package/src/lib/components/modal/modal.type.ts +9 -0
  145. package/src/lib/components/morph/blob-moph/blob-moprh.component.spec.ts +79 -0
  146. package/src/lib/components/morph/blob-moph/blob-moprh.component.ts +96 -0
  147. package/src/lib/components/morph/blob-moph/blob-morph.component.html +34 -0
  148. package/src/lib/components/morph/blob-moph/blob-morph.component.scss +7 -0
  149. package/src/lib/components/morph/morph.abstract.ts +13 -0
  150. package/src/lib/components/pagination/pagination.interface.ts +4 -0
  151. package/src/lib/components/pagination/small-pagination/small-pagination.component.html +61 -0
  152. package/src/lib/components/pagination/small-pagination/small-pagination.component.scss +187 -0
  153. package/src/lib/components/pagination/small-pagination/small-pagination.component.spec.ts +88 -0
  154. package/src/lib/components/pagination/small-pagination/small-pagination.component.ts +177 -0
  155. package/src/lib/components/selection-lists/multi-select/multi-select.component.html +170 -0
  156. package/src/lib/components/selection-lists/multi-select/multi-select.component.scss +312 -0
  157. package/src/lib/components/selection-lists/multi-select/multi-select.component.spec.ts +61 -0
  158. package/src/lib/components/selection-lists/multi-select/multi-select.component.ts +372 -0
  159. package/src/lib/components/selection-lists/selection-list/selection-list.component.html +125 -0
  160. package/src/lib/components/selection-lists/selection-list/selection-list.component.scss +267 -0
  161. package/src/lib/components/selection-lists/selection-list/selection-list.component.spec.ts +66 -0
  162. package/src/lib/components/selection-lists/selection-list/selection-list.component.ts +315 -0
  163. package/src/lib/components/selection-lists/selection-lists-base.ts +35 -0
  164. package/src/lib/components/selection-lists/selection-lists-const.ts +17 -0
  165. package/src/lib/components/selection-lists/selection-lists-interface.ts +7 -0
  166. package/src/lib/components/selection-lists/selection-lists.type.ts +1 -0
  167. package/src/lib/components/side-nav/side-nav.component.html +101 -0
  168. package/src/lib/components/side-nav/side-nav.component.scss +295 -0
  169. package/src/lib/components/side-nav/side-nav.component.spec.ts +0 -0
  170. package/src/lib/components/side-nav/side-nav.component.ts +18 -0
  171. package/src/lib/components/side-nav/side-nav.type.ts +28 -0
  172. package/src/lib/components/snackbar/snackbar.component.html +33 -0
  173. package/src/lib/components/snackbar/snackbar.component.scss +195 -0
  174. package/src/lib/components/snackbar/snackbar.component.ts +112 -0
  175. package/src/lib/components/snackbar/snackbar.type.ts +27 -0
  176. package/src/lib/components/status/chip/chip.component.html +51 -0
  177. package/src/lib/components/status/chip/chip.component.scss +149 -0
  178. package/src/lib/components/status/chip/chip.component.spec.ts +62 -0
  179. package/src/lib/components/status/chip/chip.component.ts +83 -0
  180. package/src/lib/components/status/chip/chip.type.ts +42 -0
  181. package/src/lib/components/status/directives/badge/badge.directive.spec.ts +60 -0
  182. package/src/lib/components/status/directives/badge/badge.directive.ts +190 -0
  183. package/src/lib/components/status/directives/badge/badge.interface.ts +19 -0
  184. package/src/lib/components/status/pill/pill.component.html +40 -0
  185. package/src/lib/components/status/pill/pill.component.scss +113 -0
  186. package/src/lib/components/status/pill/pill.component.spec.ts +47 -0
  187. package/src/lib/components/status/pill/pill.component.ts +83 -0
  188. package/src/lib/components/status/pill/pill.type.ts +42 -0
  189. package/src/lib/components/status/status.interface.ts +57 -0
  190. package/src/lib/components/status/status.type.ts +62 -0
  191. package/src/lib/components/status/tag/tag.component.html +39 -0
  192. package/src/lib/components/status/tag/tag.component.scss +140 -0
  193. package/src/lib/components/status/tag/tag.component.spec.ts +47 -0
  194. package/src/lib/components/status/tag/tag.component.ts +83 -0
  195. package/src/lib/components/status/tag/tag.type.ts +42 -0
  196. package/src/lib/components/stepper/stepper.component.html +83 -0
  197. package/src/lib/components/stepper/stepper.component.scss +196 -0
  198. package/src/lib/components/stepper/stepper.component.ts +482 -0
  199. package/src/lib/components/stepper/stepper.type.ts +60 -0
  200. package/src/lib/components/table/table.component.html +438 -0
  201. package/src/lib/components/table/table.component.scss +259 -0
  202. package/src/lib/components/table/table.component.spec.ts +117 -0
  203. package/src/lib/components/table/table.component.ts +215 -0
  204. package/src/lib/components/table/table.enum.ts +4 -0
  205. package/src/lib/components/table/table.function.ts +47 -0
  206. package/src/lib/components/table/table.interface.ts +143 -0
  207. package/src/lib/components/table/table.pipe.ts +62 -0
  208. package/src/lib/components/table/table.type.ts +15 -0
  209. package/src/lib/components/tabs/tabs.component.html +88 -0
  210. package/src/lib/components/tabs/tabs.component.scss +305 -0
  211. package/src/lib/components/tabs/tabs.component.spec.ts +94 -0
  212. package/src/lib/components/tabs/tabs.component.ts +282 -0
  213. package/src/lib/components/tabs/tabs.type.ts +81 -0
  214. package/src/lib/components/title-bar/title-bar.component.html +21 -0
  215. package/src/lib/components/title-bar/title-bar.component.scss +139 -0
  216. package/src/lib/components/title-bar/title-bar.component.spec.ts +44 -0
  217. package/src/lib/components/title-bar/title-bar.component.ts +13 -0
  218. package/src/lib/components/toast/toast.component.html +36 -0
  219. package/src/lib/components/toast/toast.component.scss +241 -0
  220. package/src/lib/components/toast/toast.component.ts +165 -0
  221. package/src/lib/components/toast/toast.type.ts +37 -0
  222. package/src/lib/components/toast-stack/toast-stack.component.html +30 -0
  223. package/src/lib/components/toast-stack/toast-stack.component.scss +35 -0
  224. package/src/lib/components/toast-stack/toast-stack.component.ts +51 -0
  225. package/src/lib/consts/country-prefix.ts +244 -0
  226. package/src/lib/directives/tooltip/popover.directive.ts +274 -0
  227. package/src/lib/directives/tooltip/tooltip.directive.spec.ts +86 -0
  228. package/src/lib/directives/tooltip/tooltip.directive.ts +234 -0
  229. package/src/lib/directives/tooltip/tooltip.interface.ts +29 -0
  230. package/src/lib/directives/tooltip/tooltip.type.ts +9 -0
  231. package/src/lib/interfaces/common.interfaces.ts +4 -0
  232. package/src/lib/pipes/chunk.pipe.ts +16 -0
  233. package/src/lib/pipes/safe-html.pipe.ts +14 -0
  234. package/src/lib/pipes/sanitize-html.pipe.ts +23 -0
  235. package/src/lib/types/base.types.ts +23 -0
  236. package/src/lib/types/common.types.ts +98 -0
  237. package/src/lib/types/form.types.ts +5 -0
  238. package/src/lib/utils/common.utils.ts +53 -0
  239. package/src/lib/utils/date.utils.ts +474 -0
  240. package/src/lib/utils/number.utils.ts +16 -0
  241. package/src/lib/utils/uuid.utils.ts +39 -0
  242. package/src/public-api.ts +114 -0
  243. package/tsconfig.lib.json +17 -0
  244. package/tsconfig.lib.prod.json +10 -0
  245. package/tsconfig.spec.json +9 -0
  246. package/fesm2022/fragments.mjs +0 -8928
  247. package/fesm2022/fragments.mjs.map +0 -1
  248. package/index.d.ts +0 -3929
@@ -0,0 +1,190 @@
1
+ import {
2
+ Directive,
3
+ ElementRef,
4
+ inject,
5
+ Input,
6
+ OnChanges,
7
+ OnDestroy,
8
+ Renderer2,
9
+ SimpleChanges,
10
+ } from '@angular/core';
11
+ import { Badge } from './badge.interface';
12
+
13
+ @Directive({
14
+ selector: '[frgBadge]',
15
+ standalone: true,
16
+ host: {
17
+ class: 'frg-has-badge',
18
+ },
19
+ })
20
+ export class FrgBadgeDirective implements OnChanges, OnDestroy {
21
+ private readonly host = inject(ElementRef<HTMLElement>);
22
+ private readonly renderer = inject(Renderer2);
23
+
24
+ /**
25
+ * Badge configuration object.
26
+ */
27
+ @Input() badge!: Badge;
28
+
29
+ /**
30
+ * Reference to the badge HTML element.
31
+ */
32
+ private badgeEl?: HTMLElement;
33
+
34
+ ngOnChanges(changes: SimpleChanges): void {
35
+ if (changes['badge']) {
36
+ this.updateBadge();
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Cleans up the badge element when the directive is destroyed.
42
+ */
43
+ ngOnDestroy(): void {
44
+ this.removeBadge();
45
+ }
46
+
47
+ /**
48
+ * Updates the badge element based on the current badge configuration.
49
+ * Creates, updates, or removes the badge as necessary.
50
+ */
51
+ private updateBadge(): void {
52
+ if (this.shouldHide()) {
53
+ this.removeBadge();
54
+ return;
55
+ }
56
+
57
+ if (!this.badgeEl) {
58
+ this.createBadge();
59
+ }
60
+
61
+ this.updateBadgeContent();
62
+ this.updateBadgeClasses();
63
+ }
64
+
65
+ /**
66
+ * Creates the badge HTML element and appends it to the host element.
67
+ * Initializes the badge with the base class.
68
+ */
69
+ private createBadge(): void {
70
+ this.badgeEl = this.renderer.createElement('span');
71
+ this.renderer.addClass(this.badgeEl, 'frg-badge');
72
+
73
+ this.renderer.appendChild(this.host.nativeElement, this.badgeEl);
74
+ }
75
+
76
+ /**
77
+ * Updates the content of the badge element based on the badge configuration.
78
+ * Handles dot mode, icon placement, and value display.
79
+ */
80
+ private updateBadgeContent(): void {
81
+ if (!this.badgeEl || this.badge.dot) {
82
+ this.badgeEl!.innerHTML = '';
83
+ return;
84
+ }
85
+
86
+ this.badgeEl.innerHTML = '';
87
+
88
+ const hasIcon = !!this.badge.icon;
89
+ const hasValue = this.badge.value != null && this.badge.value !== '';
90
+
91
+ if (hasIcon) {
92
+ const iconEl = this.createIconElement(this.badge.icon || '');
93
+
94
+ if (this.badge.iconPosition === 'start') {
95
+ this.appendIconThenValue(iconEl, hasValue);
96
+ } else {
97
+ this.appendValueThenIcon(hasValue, iconEl);
98
+ }
99
+ } else if (hasValue) {
100
+ this.badgeEl.innerText = String(this.badge.value);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * Creates the icon element with all classes
106
+ */
107
+ private createIconElement(iconClass: string): HTMLElement {
108
+ const iconEl = this.renderer.createElement('i');
109
+ for (const cls of iconClass.split(' ')) {
110
+ this.renderer.addClass(iconEl, cls);
111
+ }
112
+ this.renderer.addClass(iconEl, 'frg-badge__icon');
113
+ return iconEl;
114
+ }
115
+
116
+ /**
117
+ * Append value first, then icon
118
+ */
119
+ private appendValueThenIcon(hasValue: boolean, iconEl: HTMLElement): void {
120
+ if (hasValue) {
121
+ const textNode = this.renderer.createText(String(this.badge.value));
122
+ this.renderer.appendChild(this.badgeEl!, textNode);
123
+ }
124
+ this.renderer.appendChild(this.badgeEl!, iconEl);
125
+ }
126
+
127
+ /**
128
+ * Append icon first, then value
129
+ */
130
+ private appendIconThenValue(iconEl: HTMLElement, hasValue: boolean): void {
131
+ this.renderer.appendChild(this.badgeEl!, iconEl);
132
+ if (hasValue) {
133
+ const textNode = this.renderer.createText(String(this.badge.value));
134
+ this.renderer.appendChild(this.badgeEl!, textNode);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Updates the CSS classes of the badge element based on the badge configuration.
140
+ * Applies size, style, and dot mode classes.
141
+ */
142
+ private updateBadgeClasses(): void {
143
+ if (!this.badgeEl) return;
144
+
145
+ this.renderer.setAttribute(this.badgeEl, 'class', 'frg-badge');
146
+
147
+ if (this.badge.size) {
148
+ this.renderer.addClass(this.badgeEl, `frg-badge--${this.badge.size}`);
149
+ }
150
+
151
+ if (this.badge.style) {
152
+ this.renderer.addClass(this.badgeEl, `frg-badge--${this.badge.style}`);
153
+ }
154
+
155
+ if (this.badge.dot) {
156
+ this.renderer.addClass(this.badgeEl, 'frg-badge--dot');
157
+ }
158
+
159
+ if (this.badge.disabled) {
160
+ this.renderer.addClass(this.badgeEl, 'frg-badge--disabled');
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Removes the badge element from the host element and clears the reference.
166
+ * Used when the badge should be hidden.
167
+ */
168
+ private removeBadge(): void {
169
+ if (this.badgeEl) {
170
+ this.renderer.removeChild(this.host.nativeElement, this.badgeEl);
171
+ this.badgeEl = undefined;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Determines whether the badge should be hidden based on its configuration.
177
+ * Returns true if the badge is marked as hidden or has no value in non-dot mode.
178
+ */
179
+ private shouldHide(): boolean {
180
+ if (this.badge.hidden) return true;
181
+
182
+ if (this.badge.dot) return false;
183
+
184
+ return (
185
+ this.badge.value === null ||
186
+ this.badge.value === undefined ||
187
+ this.badge.value === ''
188
+ );
189
+ }
190
+ }
@@ -0,0 +1,19 @@
1
+ import { StatusIndicator } from "../../status.interface";
2
+
3
+ export interface Badge extends Partial<StatusIndicator> {
4
+ /**
5
+ * Badge numeric or string value.
6
+ * If null or undefined and `dot` is false → badge is hidden.
7
+ */
8
+ value?: string | number | null;
9
+
10
+ /**
11
+ * Dot mode: shows only a small circular indicator.
12
+ */
13
+ dot?: boolean;
14
+
15
+ /**
16
+ * Determines whether the badge is hidden.
17
+ */
18
+ hidden?: boolean;
19
+ }
@@ -0,0 +1,40 @@
1
+ <span
2
+ class="frg-pill"
3
+ [class.frg-pill--disabled]="disabled"
4
+ [class.removable]="removable"
5
+ [ngClass]="[
6
+ 'frg-pill--' + style,
7
+ 'frg-pill--' + size,
8
+ iconPosition === 'end' ? 'frg-pill--icon-end' : 'frg-pill--icon-start'
9
+ ]"
10
+ >
11
+
12
+ @if(icon && iconPosition === 'start') {
13
+ <span class="frg-pill__icon">
14
+ <i [class]="icon"></i>
15
+ </span>
16
+ }
17
+
18
+ @if(label) {
19
+ <span class="frg-pill__label">
20
+ {{ label }}
21
+ </span>
22
+ }
23
+
24
+ @if(icon && iconPosition === 'end') {
25
+ <span class="frg-pill__icon">
26
+ <i [class]="icon"></i>
27
+ </span>
28
+ }
29
+
30
+ @if(removable) {
31
+ <button
32
+ class="frg-pill__remove"
33
+ type="button"
34
+ aria-label="Remove pill"
35
+ (click)="onRemove()"
36
+ >
37
+ ×
38
+ </button>
39
+ }
40
+ </span>
@@ -0,0 +1,113 @@
1
+ @use 'sass:color';
2
+ @use './../../../../../assets/styles/scss/variables' as *;
3
+
4
+ :host {
5
+ .frg-pill {
6
+ display: inline-flex;
7
+ align-items: center;
8
+ border-radius: 9999px; // pill shape
9
+ font-family: $base-font;
10
+ font-weight: 500;
11
+ line-height: 1.2;
12
+ cursor: default;
13
+ user-select: none;
14
+
15
+ padding: 0.25rem 0.75rem;
16
+ font-size: $font-size-sm;
17
+
18
+ &.frg-pill--sm {
19
+ padding: 0.125rem 0.5rem;
20
+ font-size: $font-size-xs;
21
+ }
22
+
23
+ &.frg-pill--md {
24
+ padding: 0.25rem 0.75rem;
25
+ font-size: $font-size-sm;
26
+ }
27
+
28
+ &.frg-pill--lg {
29
+ padding: 0.375rem 1rem;
30
+ font-size: $font-size-md;
31
+ }
32
+
33
+ // Style variants
34
+ &.frg-pill--primary {
35
+ background-color: $color-primary;
36
+ color: $color-light;
37
+ }
38
+ &.frg-pill--secondary {
39
+ background-color: $color-secondary;
40
+ color: $color-dark;
41
+ }
42
+ &.frg-pill--tertiary {
43
+ background-color: $color-tertiary;
44
+ color: $color-light;
45
+ }
46
+ &.frg-pill--success {
47
+ background-color: $color-success;
48
+ color: $color-light;
49
+ }
50
+ &.frg-pill--warning {
51
+ background-color: $color-warning;
52
+ color: $color-dark;
53
+ }
54
+ &.frg-pill--danger {
55
+ background-color: $color-danger;
56
+ color: $color-light;
57
+ }
58
+ &.frg-pill--info {
59
+ background-color: $color-info;
60
+ color: $color-light;
61
+ }
62
+ &.frg-pill--dark {
63
+ background-color: $color-dark;
64
+ color: $color-light;
65
+ }
66
+ &.frg-pill--light {
67
+ background-color: $color-light;
68
+ color: $color-dark;
69
+ }
70
+
71
+ // Disabled state
72
+ &.frg-pill--disabled {
73
+ background-color: $color-light-neutral;
74
+ color: $color-disabled-text;
75
+ pointer-events: none;
76
+ opacity: 0.6;
77
+ }
78
+
79
+ .frg-pill__icon {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ margin: 0;
83
+
84
+ & + .frg-pill__label {
85
+ margin-left: 0.5rem;
86
+ }
87
+ }
88
+
89
+ .frg-pill--icon-end .frg-pill__icon {
90
+ margin-left: 0.5rem;
91
+ margin-right: 0;
92
+ }
93
+
94
+ .frg-pill__label {
95
+ display: inline-block;
96
+ }
97
+
98
+ .frg-pill__remove {
99
+ background: transparent;
100
+ border: none;
101
+ cursor: pointer;
102
+ margin-left: 0.5rem;
103
+ font-size: 1rem;
104
+ line-height: 1;
105
+ padding: 0;
106
+ color: inherit;
107
+
108
+ &:hover {
109
+ opacity: 0.8;
110
+ }
111
+ }
112
+ }
113
+ }
@@ -0,0 +1,47 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { By } from '@angular/platform-browser';
3
+ import { PillComponent } from './pill.component';
4
+
5
+ describe('PillComponent', () => {
6
+ let fixture: ComponentFixture<PillComponent>;
7
+ let component: PillComponent;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [PillComponent]
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(PillComponent);
15
+ component = fixture.componentInstance;
16
+ });
17
+
18
+ it('renders the label', () => {
19
+ component.label = 'New';
20
+
21
+ fixture.detectChanges();
22
+
23
+ const label = fixture.debugElement.query(By.css('.frg-pill__label'));
24
+ expect(label.nativeElement.textContent).toContain('New');
25
+ });
26
+
27
+ it('applies disabled class when disabled', () => {
28
+ component.disabled = true;
29
+
30
+ fixture.detectChanges();
31
+
32
+ const host = fixture.debugElement.query(By.css('.frg-pill'));
33
+ expect(host.nativeElement.classList).toContain('frg-pill--disabled');
34
+ });
35
+
36
+ it('emits removed when removable and not disabled', () => {
37
+ const emitSpy = spyOn(component.removed, 'emit');
38
+ component.removable = true;
39
+
40
+ fixture.detectChanges();
41
+
42
+ const removeButton = fixture.debugElement.query(By.css('.frg-pill__remove'));
43
+ removeButton.nativeElement.click();
44
+
45
+ expect(emitSpy).toHaveBeenCalledWith(component.id);
46
+ });
47
+ });
@@ -0,0 +1,83 @@
1
+ import { NgClass } from '@angular/common';
2
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
3
+ import { generateUUID } from '../../../utils/uuid.utils';
4
+ import { Pill, TPillIconPosition, TPillSize, TPillType } from './pill.type';
5
+
6
+ /**
7
+ * TagComponent
8
+ *
9
+ * A small UI element used to display labeled statuses, metadata, or categories.
10
+ * Supports icons, removable behavior, disabled state, and standardized design-
11
+ * system styles and sizes. Implements the shared `Tag` interface to ensure
12
+ * consistency across all status-driven UI components (Tag, Badge, Chip, etc.).
13
+ */
14
+ @Component({
15
+ selector: 'frg-pill',
16
+ templateUrl: './pill.component.html',
17
+ styleUrls: ['./pill.component.scss'],
18
+ imports: [NgClass]
19
+ })
20
+ export class PillComponent implements Pill {
21
+
22
+ /**
23
+ * Unique identifier for the tag.
24
+ * Automatically generated if not provided by the parent.
25
+ * Used primarily for tracking and removal events.
26
+ */
27
+ @Input() id: string = generateUUID();
28
+
29
+ /**
30
+ * Text content displayed inside the tag.
31
+ */
32
+ @Input() label?: string = '';
33
+
34
+ /**
35
+ * Visual style of the pill.
36
+ * Corresponds to design-system status color tokens.
37
+ * Example: 'primary', 'secondary', 'success', 'warning', etc.
38
+ */
39
+ @Input() style: TPillType = 'primary';
40
+
41
+ /**
42
+ * Size variant of the pill.
43
+ * Options follow the standardized sizing tokens: 'sm', 'md', or 'lg'.
44
+ */
45
+ @Input() size: TPillSize = 'md';
46
+
47
+ /**
48
+ * Optional icon class displayed before the label.
49
+ * Example: 'frg-icon-info', 'frg-icon-alert'.
50
+ */
51
+ @Input() icon: string | undefined = undefined;
52
+
53
+ /**
54
+ * Position of the icon
55
+ */
56
+ @Input() iconPosition: TPillIconPosition = 'end';
57
+
58
+ /**
59
+ * Whether the pill is disabled.
60
+ * Disables interactions and applies the disabled visual style.
61
+ */
62
+ @Input() disabled = false;
63
+
64
+ /**
65
+ * If true, displays a remove button allowing the pill to be dismissed.
66
+ */
67
+ @Input() removable = false;
68
+
69
+ /**
70
+ * Emits the ID of the pill when it is removed.
71
+ */
72
+ @Output() removed = new EventEmitter<string>();
73
+
74
+ /**
75
+ * Emits the `removed` event when the remove button is clicked,
76
+ * provided the tag is not disabled and removal is allowed.
77
+ */
78
+ onRemove(): void {
79
+ if (!this.disabled && this.removable) {
80
+ this.removed.emit(this.id);
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,42 @@
1
+ import { StatusIndicator } from "../status.interface";
2
+ import { TBaseStatusIconPosition, TBaseStatusSize, TBaseStatusStyle } from "../status.type";
3
+
4
+ /**
5
+ * TagType
6
+ *
7
+ * Alias for `TBaseStatusStyle`.
8
+ * Represents the visual style of a tag according to the design system.
9
+ * Example: 'primary', 'secondary', 'success', etc.
10
+ */
11
+ export type TPillType = TBaseStatusStyle;
12
+
13
+ /**
14
+ * PillSize
15
+ *
16
+ * Alias for `TBaseStatusSize`.
17
+ * Defines the size of the pill. Options: 'sm', 'md', 'lg'.
18
+ */
19
+ export type TPillSize = TBaseStatusSize;
20
+
21
+ /**
22
+ * PillIconPosition
23
+ *
24
+ * Alias for `TBaseStatusIconPosition`.
25
+ * Defines the icon position of the icon in the pill. Options: 'start' or 'end'.
26
+ */
27
+ export type TPillIconPosition = TBaseStatusIconPosition;
28
+ /**
29
+ * Pill
30
+ *
31
+ * A UI element that extends the shared `StatusIndicator` interface.
32
+ * Represents a labeled status, optionally removable.
33
+ *
34
+ * @extends StatusIndicator
35
+ */
36
+ export interface Pill extends StatusIndicator {
37
+ /**
38
+ * If true, the pill can be removed by the user.
39
+ * Triggers the `removed` event in the component.
40
+ */
41
+ removable?: boolean;
42
+ }
@@ -0,0 +1,57 @@
1
+ import { TBaseStatusIconPosition, TBaseStatusSize, TBaseStatusStyle } from "./status.type";
2
+
3
+ /**
4
+ * StatusIndicator
5
+ *
6
+ * Base interface for all UI components that represent a status or state.
7
+ * Provides standardized properties for label, visual style, size, icon, and
8
+ * interaction state. This interface is intended to be extended by components
9
+ * such as Tag, Badge, Chip, etc.
10
+ */
11
+ export interface StatusIndicator {
12
+ /**
13
+ * Unique identifier for the status element.
14
+ * Used for tracking, removal, or other programmatic operations.
15
+ */
16
+ id: string;
17
+ /**
18
+ * Text label displayed within the UI element.
19
+ */
20
+ label?: string;
21
+ /**
22
+ * Visual style of the element.
23
+ * Corresponds to the design system status colors.
24
+ * Example: 'primary', 'secondary', 'success', 'warning', etc.
25
+ *
26
+ * @see TBaseStatusStyle
27
+ */
28
+ style: TBaseStatusStyle;
29
+ /**
30
+ * Optional size of the element.
31
+ * Should conform to design-system sizing tokens.
32
+ * Example: 'sm', 'md', 'lg'.
33
+ *
34
+ * @see TBaseStatusSize
35
+ */
36
+ size?: TBaseStatusSize;
37
+ /**
38
+ * Optional icon class displayed before the label.
39
+ * Example: 'frg-icon-info', 'frg-icon-alert'.
40
+ */
41
+ icon?: string;
42
+ /**
43
+ * Determines the position of the icon relative to the label in a status-based component
44
+ * such as a tag, badge, or chip.
45
+ *
46
+ * Available options:
47
+ * - 'start' — icon appears before the label (default)
48
+ * - 'end' — icon appears after the label
49
+ *
50
+ * @see TBaseStatusIconPosition
51
+ */
52
+ iconPosition?: TBaseStatusIconPosition
53
+ /**
54
+ * If true, the element is disabled and user interactions are blocked.
55
+ */
56
+ disabled?: boolean;
57
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * TBaseStatusStyle
3
+ *
4
+ * Represents the allowed visual styles for status-based UI components.
5
+ * Typically maps to the design system color palette for components like
6
+ * tags, badges, or chips.
7
+ *
8
+ * Available options:
9
+ * - 'primary'
10
+ * - 'secondary'
11
+ * - 'tertiary'
12
+ * - 'info'
13
+ * - 'success'
14
+ * - 'warning'
15
+ * - 'danger'
16
+ * - 'dark'
17
+ * - 'light'
18
+ */
19
+ export type TBaseStatusStyle =
20
+ 'primary'
21
+ | 'secondary'
22
+ | 'tertiary'
23
+ | 'info'
24
+ | 'warning'
25
+ | 'danger'
26
+ | 'success'
27
+ | 'dark'
28
+ | 'light';
29
+
30
+ /**
31
+ * TBaseStatusSize
32
+ *
33
+ * Represents the allowed sizes for status-based UI components.
34
+ * Used to adjust the dimensions and spacing of elements like tags, badges,
35
+ * or chips.
36
+ *
37
+ * Available options:
38
+ * - 'sm' (small)
39
+ * - 'md' (medium, default)
40
+ * - 'lg' (large)
41
+ */
42
+ export type TBaseStatusSize =
43
+ 'sm'
44
+ | 'md'
45
+ | 'lg';
46
+
47
+ /**
48
+ * TBaseStatusIconPosition
49
+ *
50
+ * Represents the allowed positions for an icon inside a status-based UI component
51
+ * such as a tag, badge, or chip.
52
+ *
53
+ * Determines whether the icon appears before (start) or after (end) the label.
54
+ *
55
+ * Available options:
56
+ * - 'start' (default) — icon appears before the label
57
+ * - 'end' — icon appears after the label
58
+ */
59
+ export type TBaseStatusIconPosition =
60
+ 'start'
61
+ | 'end';
62
+
@@ -0,0 +1,39 @@
1
+ <span
2
+ class="frg-tag"
3
+ [class.frg-tag--disabled]="disabled"
4
+ [class.removable]="removable"
5
+ [ngClass]="[
6
+ 'frg-tag--' + style,
7
+ 'frg-tag--' + size,
8
+ iconPosition === 'end' ? 'frg-tag--icon-end' : ''
9
+ ]"
10
+ >
11
+ @if(icon && iconPosition === 'start') {
12
+ <span class="frg-tag__icon">
13
+ <i [class]="icon"></i>
14
+ </span>
15
+ }
16
+
17
+ @if(label) {
18
+ <span class="frg-tag__label">
19
+ {{ label }}
20
+ </span>
21
+ }
22
+
23
+ @if(icon && iconPosition === 'end') {
24
+ <span class="frg-tag__icon">
25
+ <i [class]="icon"></i>
26
+ </span>
27
+ }
28
+
29
+ @if(removable) {
30
+ <button
31
+ class="frg-tag__remove"
32
+ type="button"
33
+ aria-label="Remove tag"
34
+ (click)="onRemove()"
35
+ >
36
+ ×
37
+ </button>
38
+ }
39
+ </span>