@raintonic/formaui 0.2.0 → 0.3.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 (186) hide show
  1. package/CHANGELOG.md +104 -7
  2. package/LICENSE +21 -0
  3. package/README.md +199 -145
  4. package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs.map +1 -1
  5. package/fesm2022/raintonic-formaui-cdk-form-field.mjs.map +1 -1
  6. package/fesm2022/raintonic-formaui-cdk-overlay.mjs +0 -26
  7. package/fesm2022/raintonic-formaui-cdk-overlay.mjs.map +1 -1
  8. package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs +2 -2
  9. package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs.map +1 -1
  10. package/fesm2022/raintonic-formaui-components-accordion.mjs +2 -2
  11. package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -1
  12. package/fesm2022/raintonic-formaui-components-alert.mjs +24 -5
  13. package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -1
  14. package/fesm2022/raintonic-formaui-components-autocomplete.mjs +38 -9
  15. package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -1
  16. package/fesm2022/raintonic-formaui-components-avatar.mjs.map +1 -1
  17. package/fesm2022/raintonic-formaui-components-badge.mjs +45 -31
  18. package/fesm2022/raintonic-formaui-components-badge.mjs.map +1 -1
  19. package/fesm2022/raintonic-formaui-components-big-menu.mjs +23 -5
  20. package/fesm2022/raintonic-formaui-components-big-menu.mjs.map +1 -1
  21. package/fesm2022/raintonic-formaui-components-breadcrumb.mjs +24 -7
  22. package/fesm2022/raintonic-formaui-components-breadcrumb.mjs.map +1 -1
  23. package/fesm2022/raintonic-formaui-components-button-group.mjs +6 -6
  24. package/fesm2022/raintonic-formaui-components-button-group.mjs.map +1 -1
  25. package/fesm2022/raintonic-formaui-components-button.mjs +63 -17
  26. package/fesm2022/raintonic-formaui-components-button.mjs.map +1 -1
  27. package/fesm2022/raintonic-formaui-components-card.mjs +8 -8
  28. package/fesm2022/raintonic-formaui-components-card.mjs.map +1 -1
  29. package/fesm2022/raintonic-formaui-components-checkbox.mjs +2 -2
  30. package/fesm2022/raintonic-formaui-components-checkbox.mjs.map +1 -1
  31. package/fesm2022/raintonic-formaui-components-data-table.mjs +67 -9
  32. package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -1
  33. package/fesm2022/raintonic-formaui-components-date-picker.mjs +63 -16
  34. package/fesm2022/raintonic-formaui-components-date-picker.mjs.map +1 -1
  35. package/fesm2022/raintonic-formaui-components-divider.mjs +2 -2
  36. package/fesm2022/raintonic-formaui-components-divider.mjs.map +1 -1
  37. package/fesm2022/raintonic-formaui-components-drawer.mjs +19 -4
  38. package/fesm2022/raintonic-formaui-components-drawer.mjs.map +1 -1
  39. package/fesm2022/raintonic-formaui-components-empty-state.mjs +2 -2
  40. package/fesm2022/raintonic-formaui-components-empty-state.mjs.map +1 -1
  41. package/fesm2022/raintonic-formaui-components-file-upload.mjs +25 -5
  42. package/fesm2022/raintonic-formaui-components-file-upload.mjs.map +1 -1
  43. package/fesm2022/raintonic-formaui-components-form-field.mjs +21 -6
  44. package/fesm2022/raintonic-formaui-components-form-field.mjs.map +1 -1
  45. package/fesm2022/raintonic-formaui-components-icon.mjs +2 -2
  46. package/fesm2022/raintonic-formaui-components-icon.mjs.map +1 -1
  47. package/fesm2022/raintonic-formaui-components-input.mjs +1 -1
  48. package/fesm2022/raintonic-formaui-components-input.mjs.map +1 -1
  49. package/fesm2022/raintonic-formaui-components-list.mjs +4 -4
  50. package/fesm2022/raintonic-formaui-components-list.mjs.map +1 -1
  51. package/fesm2022/raintonic-formaui-components-menu.mjs +4 -4
  52. package/fesm2022/raintonic-formaui-components-menu.mjs.map +1 -1
  53. package/fesm2022/raintonic-formaui-components-number-input.mjs +20 -5
  54. package/fesm2022/raintonic-formaui-components-number-input.mjs.map +1 -1
  55. package/fesm2022/raintonic-formaui-components-paginator.mjs +27 -7
  56. package/fesm2022/raintonic-formaui-components-paginator.mjs.map +1 -1
  57. package/fesm2022/raintonic-formaui-components-password-input.mjs +23 -5
  58. package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -1
  59. package/fesm2022/raintonic-formaui-components-popover.mjs +2 -2
  60. package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -1
  61. package/fesm2022/raintonic-formaui-components-progressbar.mjs +32 -7
  62. package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -1
  63. package/fesm2022/raintonic-formaui-components-radio.mjs +4 -4
  64. package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -1
  65. package/fesm2022/raintonic-formaui-components-select.mjs +41 -26
  66. package/fesm2022/raintonic-formaui-components-select.mjs.map +1 -1
  67. package/fesm2022/raintonic-formaui-components-side-panel.mjs +19 -4
  68. package/fesm2022/raintonic-formaui-components-side-panel.mjs.map +1 -1
  69. package/fesm2022/raintonic-formaui-components-sidebar.mjs +23 -5
  70. package/fesm2022/raintonic-formaui-components-sidebar.mjs.map +1 -1
  71. package/fesm2022/raintonic-formaui-components-skeleton.mjs +2 -2
  72. package/fesm2022/raintonic-formaui-components-skeleton.mjs.map +1 -1
  73. package/fesm2022/raintonic-formaui-components-slider.mjs +23 -5
  74. package/fesm2022/raintonic-formaui-components-slider.mjs.map +1 -1
  75. package/fesm2022/raintonic-formaui-components-spinner.mjs +24 -7
  76. package/fesm2022/raintonic-formaui-components-spinner.mjs.map +1 -1
  77. package/fesm2022/raintonic-formaui-components-stepper.mjs +2 -2
  78. package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -1
  79. package/fesm2022/raintonic-formaui-components-tab.mjs +10 -10
  80. package/fesm2022/raintonic-formaui-components-tab.mjs.map +1 -1
  81. package/fesm2022/raintonic-formaui-components-tag.mjs +21 -4
  82. package/fesm2022/raintonic-formaui-components-tag.mjs.map +1 -1
  83. package/fesm2022/raintonic-formaui-components-time-picker.mjs +26 -7
  84. package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -1
  85. package/fesm2022/raintonic-formaui-components-toggle.mjs +2 -2
  86. package/fesm2022/raintonic-formaui-components-toggle.mjs.map +1 -1
  87. package/fesm2022/raintonic-formaui-components-toolbar.mjs +41 -7
  88. package/fesm2022/raintonic-formaui-components-toolbar.mjs.map +1 -1
  89. package/fesm2022/raintonic-formaui-components-tooltip.mjs +2 -2
  90. package/fesm2022/raintonic-formaui-components-tooltip.mjs.map +1 -1
  91. package/fesm2022/raintonic-formaui-components-tree-select.mjs +2 -2
  92. package/fesm2022/raintonic-formaui-components-tree-select.mjs.map +1 -1
  93. package/fesm2022/raintonic-formaui-components-tree-table.mjs +35 -6
  94. package/fesm2022/raintonic-formaui-components-tree-table.mjs.map +1 -1
  95. package/fesm2022/raintonic-formaui-components-tree.mjs +25 -7
  96. package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -1
  97. package/fesm2022/raintonic-formaui-core.mjs +25 -1
  98. package/fesm2022/raintonic-formaui-core.mjs.map +1 -1
  99. package/fesm2022/raintonic-formaui-services-dialog.mjs +37 -37
  100. package/fesm2022/raintonic-formaui-services-dialog.mjs.map +1 -1
  101. package/fesm2022/raintonic-formaui-services-notification.mjs +2 -2
  102. package/fesm2022/raintonic-formaui-services-notification.mjs.map +1 -1
  103. package/fesm2022/raintonic-formaui-services-theme.mjs +3 -3
  104. package/fesm2022/raintonic-formaui-services-theme.mjs.map +1 -1
  105. package/fesm2022/raintonic-formaui-test-utils.mjs +21 -16
  106. package/fesm2022/raintonic-formaui-test-utils.mjs.map +1 -1
  107. package/fesm2022/raintonic-formaui.mjs +1 -1
  108. package/fesm2022/raintonic-formaui.mjs.map +1 -1
  109. package/llms-full.txt +36 -122
  110. package/llms.txt +4 -5
  111. package/package.json +1 -5
  112. package/styles/index.scss +5 -5
  113. package/styles/partials/_motion.scss +25 -0
  114. package/styles/partials/_theme.scss +6 -5
  115. package/styles/partials/components/_button.scss +361 -0
  116. package/styles/partials/components/_dialog.scss +180 -0
  117. package/styles/partials/components/_overlay.scss +87 -0
  118. package/styles/partials/themes/_dark.scss +14 -0
  119. package/styles/partials/themes/_light.scss +14 -0
  120. package/types/raintonic-formaui-cdk-overlay.d.ts +0 -1
  121. package/types/raintonic-formaui-cdk-overlay.d.ts.map +1 -1
  122. package/types/raintonic-formaui-components-alert.d.ts +11 -1
  123. package/types/raintonic-formaui-components-alert.d.ts.map +1 -1
  124. package/types/raintonic-formaui-components-autocomplete.d.ts +25 -7
  125. package/types/raintonic-formaui-components-autocomplete.d.ts.map +1 -1
  126. package/types/raintonic-formaui-components-badge.d.ts +20 -9
  127. package/types/raintonic-formaui-components-badge.d.ts.map +1 -1
  128. package/types/raintonic-formaui-components-big-menu.d.ts +12 -1
  129. package/types/raintonic-formaui-components-big-menu.d.ts.map +1 -1
  130. package/types/raintonic-formaui-components-breadcrumb.d.ts +11 -2
  131. package/types/raintonic-formaui-components-breadcrumb.d.ts.map +1 -1
  132. package/types/raintonic-formaui-components-button-group.d.ts +6 -6
  133. package/types/raintonic-formaui-components-button.d.ts +9 -7
  134. package/types/raintonic-formaui-components-button.d.ts.map +1 -1
  135. package/types/raintonic-formaui-components-card.d.ts +4 -4
  136. package/types/raintonic-formaui-components-checkbox.d.ts +1 -1
  137. package/types/raintonic-formaui-components-data-table.d.ts +56 -16
  138. package/types/raintonic-formaui-components-data-table.d.ts.map +1 -1
  139. package/types/raintonic-formaui-components-date-picker.d.ts +32 -4
  140. package/types/raintonic-formaui-components-date-picker.d.ts.map +1 -1
  141. package/types/raintonic-formaui-components-drawer.d.ts +10 -1
  142. package/types/raintonic-formaui-components-drawer.d.ts.map +1 -1
  143. package/types/raintonic-formaui-components-file-upload.d.ts +12 -1
  144. package/types/raintonic-formaui-components-file-upload.d.ts.map +1 -1
  145. package/types/raintonic-formaui-components-form-field.d.ts +12 -2
  146. package/types/raintonic-formaui-components-form-field.d.ts.map +1 -1
  147. package/types/raintonic-formaui-components-input.d.ts +1 -1
  148. package/types/raintonic-formaui-components-number-input.d.ts +11 -2
  149. package/types/raintonic-formaui-components-number-input.d.ts.map +1 -1
  150. package/types/raintonic-formaui-components-paginator.d.ts +13 -1
  151. package/types/raintonic-formaui-components-paginator.d.ts.map +1 -1
  152. package/types/raintonic-formaui-components-password-input.d.ts +12 -2
  153. package/types/raintonic-formaui-components-password-input.d.ts.map +1 -1
  154. package/types/raintonic-formaui-components-progressbar.d.ts +14 -1
  155. package/types/raintonic-formaui-components-progressbar.d.ts.map +1 -1
  156. package/types/raintonic-formaui-components-select.d.ts.map +1 -1
  157. package/types/raintonic-formaui-components-side-panel.d.ts +10 -1
  158. package/types/raintonic-formaui-components-side-panel.d.ts.map +1 -1
  159. package/types/raintonic-formaui-components-sidebar.d.ts +12 -1
  160. package/types/raintonic-formaui-components-sidebar.d.ts.map +1 -1
  161. package/types/raintonic-formaui-components-slider.d.ts +12 -1
  162. package/types/raintonic-formaui-components-slider.d.ts.map +1 -1
  163. package/types/raintonic-formaui-components-spinner.d.ts +12 -2
  164. package/types/raintonic-formaui-components-spinner.d.ts.map +1 -1
  165. package/types/raintonic-formaui-components-tag.d.ts +10 -1
  166. package/types/raintonic-formaui-components-tag.d.ts.map +1 -1
  167. package/types/raintonic-formaui-components-time-picker.d.ts +14 -2
  168. package/types/raintonic-formaui-components-time-picker.d.ts.map +1 -1
  169. package/types/raintonic-formaui-components-toggle.d.ts +1 -1
  170. package/types/raintonic-formaui-components-toolbar.d.ts +22 -4
  171. package/types/raintonic-formaui-components-toolbar.d.ts.map +1 -1
  172. package/types/raintonic-formaui-components-tree-table.d.ts +29 -4
  173. package/types/raintonic-formaui-components-tree-table.d.ts.map +1 -1
  174. package/types/raintonic-formaui-components-tree.d.ts +12 -1
  175. package/types/raintonic-formaui-components-tree.d.ts.map +1 -1
  176. package/types/raintonic-formaui-core.d.ts +19 -2
  177. package/types/raintonic-formaui-core.d.ts.map +1 -1
  178. package/types/raintonic-formaui-services-dialog.d.ts +1 -1
  179. package/types/raintonic-formaui-services-theme.d.ts +3 -3
  180. package/types/raintonic-formaui-test-utils.d.ts +15 -2
  181. package/types/raintonic-formaui-test-utils.d.ts.map +1 -1
  182. package/types/raintonic-formaui.d.ts +1 -1
  183. package/fesm2022/raintonic-formaui-components-dynamic-form.mjs +0 -266
  184. package/fesm2022/raintonic-formaui-components-dynamic-form.mjs.map +0 -1
  185. package/types/raintonic-formaui-components-dynamic-form.d.ts +0 -412
  186. package/types/raintonic-formaui-components-dynamic-form.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-services-notification.mjs","sources":["../../../lib/services/notification/notification-ref.ts","../../../lib/services/notification/notification-container.component.ts","../../../lib/services/notification/notification-container.component.html","../../../lib/services/notification/notification.service.ts","../../../lib/services/notification/raintonic-formaui-services-notification.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\nimport { FuiNotificationConfig } from '@raintonic/formaui/components/alert';\n\n/**\n * Reference to a notification instance.\n * Provides control over the notification and observables for lifecycle events.\n */\nexport class FuiNotificationRef {\n private readonly _afterClosed = new Subject<void>();\n private readonly _afterDismissed = new Subject<void>();\n\n /**\n * Observable that emits when the notification is closed\n */\n readonly afterClosed: Observable<void> = this._afterClosed.asObservable();\n\n /**\n * Observable that emits when the notification is dismissed (after animation)\n */\n readonly afterDismissed: Observable<void> = this._afterDismissed.asObservable();\n\n constructor(\n public readonly id: string,\n public readonly config: FuiNotificationConfig,\n ) {}\n\n /**\n * Close the notification\n */\n close(): void {\n this._afterClosed.next();\n this._afterClosed.complete();\n }\n\n /**\n * Called internally when the notification is fully dismissed\n * @internal\n */\n _dismiss(): void {\n this._afterDismissed.next();\n this._afterDismissed.complete();\n }\n}\n","import { ChangeDetectionStrategy, Component, effect, signal, ViewEncapsulation } from '@angular/core';\nimport { FuiAlertComponent } from '@raintonic/formaui/components/alert';\nimport { FuiNotificationRef } from './notification-ref';\n\n/**\n * Container component for displaying stacked notifications.\n * This component is created by the notification service and managed internally.\n * @internal\n */\n@Component({\n selector: 'fui-notification-container',\n standalone: true,\n imports: [FuiAlertComponent],\n templateUrl: './notification-container.component.html',\n styleUrls: ['./notification-container.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'fui-notification-container',\n role: 'log',\n 'aria-live': 'polite',\n 'aria-atomic': 'false',\n },\n})\nexport class FuiNotificationContainerComponent {\n /**\n * List of active notifications\n */\n readonly notifications = signal<FuiNotificationRef[]>([]);\n\n /**\n * Progress values for each notification (0-100)\n */\n readonly progressValues = signal(new Map());\n\n /**\n * Timers for auto-dismiss\n */\n private readonly timers = new Map<\n string,\n { interval: ReturnType<typeof setInterval>; timeout: ReturnType<typeof setTimeout> }\n >();\n\n constructor() {\n // Set up effect to manage timers when notifications change\n effect(() => {\n this.notifications();\n // This will react to changes in the notifications signal\n });\n }\n\n /**\n * Add a notification to the container\n */\n addNotification(notification: FuiNotificationRef): void {\n this.notifications.update((notifications) => [...notifications, notification]);\n\n // Set up auto-dismiss if duration is specified\n const duration = notification.config.duration ?? 5000;\n if (duration > 0) {\n this._setupAutoDismiss(notification, duration);\n }\n\n // Listen for manual close\n notification.afterClosed.subscribe(() => {\n this._removeNotification(notification);\n });\n }\n\n /**\n * Remove a notification from the container\n */\n removeNotification(notificationId: string): void {\n const notification = this.notifications().find((n) => n.id === notificationId);\n if (notification) {\n this._removeNotification(notification);\n }\n }\n\n /**\n * Handle notification close button click\n */\n onNotificationClose(notification: FuiNotificationRef): void {\n notification.close();\n }\n\n /**\n * Get the progress value for a notification\n */\n getProgress(notificationId: string): number {\n return this.progressValues().get(notificationId) ?? 100;\n }\n\n /**\n * Check if notification should show progress bar\n */\n shouldShowProgress(notification: FuiNotificationRef): boolean {\n const duration = notification.config.duration ?? 5000;\n return duration > 0;\n }\n\n private _setupAutoDismiss(notification: FuiNotificationRef, duration: number): void {\n const startTime = Date.now();\n const updateInterval = 50; // Update progress every 50ms for smooth animation\n\n // Update progress bar\n const interval = setInterval(() => {\n const elapsed = Date.now() - startTime;\n const progress = Math.max(0, 100 - (elapsed / duration) * 100);\n\n this.progressValues.update((values) => {\n const newValues = new Map(values);\n newValues.set(notification.id, progress);\n return newValues;\n });\n\n if (progress <= 0) {\n clearInterval(interval);\n }\n }, updateInterval);\n\n // Auto-dismiss after duration\n const timeout = setTimeout(() => {\n notification.close();\n }, duration);\n\n this.timers.set(notification.id, { interval, timeout });\n }\n\n private _removeNotification(notification: FuiNotificationRef): void {\n // Clear timers\n const timers = this.timers.get(notification.id);\n if (timers) {\n clearInterval(timers.interval);\n clearTimeout(timers.timeout);\n this.timers.delete(notification.id);\n }\n\n // Remove from progress map\n this.progressValues.update((values) => {\n const newValues = new Map(values);\n newValues.delete(notification.id);\n return newValues;\n });\n\n // Remove from notifications list\n this.notifications.update((notifications) => notifications.filter((n) => n.id !== notification.id));\n\n // Notify that notification is dismissed\n notification._dismiss();\n }\n}\n","<div class=\"fui-notification-container__stack\">\n @for (notification of notifications(); track notification.id) {\n <div class=\"fui-notification-container__item\" role=\"alert\" aria-atomic=\"true\">\n <fui-alert\n [variant]=\"notification.config.variant\"\n [title]=\"notification.config.title\"\n [description]=\"notification.config.description ?? null\"\n [closeable]=\"notification.config.closeable ?? true\"\n [icon]=\"notification.config.icon ?? null\"\n [progress]=\"shouldShowProgress(notification) ? getProgress(notification.id) : -1\"\n (closed)=\"onNotificationClose(notification)\"\n />\n </div>\n }\n</div>\n","import {\n Injectable,\n Renderer2,\n RendererFactory2,\n ComponentRef,\n createComponent,\n EnvironmentInjector,\n inject,\n ApplicationRef,\n} from '@angular/core';\nimport { DOCUMENT } from '@angular/common';\nimport { FuiNotificationConfig, FuiNotificationPosition } from '@raintonic/formaui/components/alert';\nimport { FuiNotificationRef } from './notification-ref';\nimport { FuiNotificationContainerComponent } from './notification-container.component';\n\n/**\n * # FuiNotificationService\n *\n * Service for displaying toast-style notifications using overlays.\n * Notifications can be displayed at various positions on the screen and will\n * auto-dismiss after a configurable duration with a visual countdown.\n *\n * ## Features\n * - Multiple notification variants (success, info, warning, error, primary, generic)\n * - Configurable positioning (top-left, top-center, top-right, bottom-left, bottom-center, bottom-right)\n * - Auto-dismiss with progress bar countdown\n * - Manual dismiss via close button\n * - Stack multiple notifications\n * - Convenient shorthand methods for common variants\n *\n * ## Usage\n *\n * ### Success Notification\n * ```typescript\n * this.notificationService.success('Changes saved successfully!');\n * ```\n *\n * ### Error Notification with Description\n * ```typescript\n * this.notificationService.error('Failed to save', {\n * description: 'Please check your connection and try again.'\n * });\n * ```\n *\n * ### Custom Duration and Position\n * ```typescript\n * this.notificationService.info('New message received', {\n * description: 'Click to view',\n * duration: 10000,\n * position: 'bottom-right'\n * });\n * ```\n *\n * ### No Auto-Dismiss\n * ```typescript\n * this.notificationService.warning('Important notice', {\n * duration: 0, // Won't auto-dismiss\n * closeable: true\n * });\n * ```\n *\n * ### Full Configuration\n * ```typescript\n * const ref = this.notificationService.show({\n * variant: 'success',\n * title: 'Success!',\n * description: 'Your operation completed successfully.',\n * duration: 5000,\n * closeable: true,\n * icon: 'custom-icon',\n * position: 'top-center'\n * });\n *\n * // Programmatically close\n * ref.close();\n * ```\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class FuiNotificationService {\n private readonly _document = inject(DOCUMENT);\n private readonly _rendererFactory = inject(RendererFactory2);\n private readonly _environmentInjector = inject(EnvironmentInjector);\n private readonly _applicationRef = inject(ApplicationRef);\n private readonly _renderer: Renderer2;\n\n /**\n * Map of container components by position\n */\n private readonly _containers = new Map<FuiNotificationPosition, ComponentRef<FuiNotificationContainerComponent>>();\n\n /**\n * Default position for notifications\n */\n private _defaultPosition: FuiNotificationPosition = 'bottom-right';\n\n /**\n * Next unique notification ID\n */\n private _nextId = 0;\n\n constructor() {\n this._renderer = this._rendererFactory.createRenderer(null, null);\n }\n\n /**\n * Set the default position for notifications\n */\n setDefaultPosition(position: FuiNotificationPosition): void {\n this._defaultPosition = position;\n }\n\n /**\n * Show a success notification\n */\n success(\n title: string,\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\n position?: FuiNotificationPosition;\n },\n ): FuiNotificationRef {\n return this.show({\n variant: 'success',\n title,\n ...options,\n });\n }\n\n /**\n * Show an info notification\n */\n info(\n title: string,\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\n position?: FuiNotificationPosition;\n },\n ): FuiNotificationRef {\n return this.show({\n variant: 'info',\n title,\n ...options,\n });\n }\n\n /**\n * Show a warning notification\n */\n warning(\n title: string,\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\n position?: FuiNotificationPosition;\n },\n ): FuiNotificationRef {\n return this.show({\n variant: 'warning',\n title,\n ...options,\n });\n }\n\n /**\n * Show an error notification\n */\n error(\n title: string,\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\n position?: FuiNotificationPosition;\n },\n ): FuiNotificationRef {\n return this.show({\n variant: 'error',\n title,\n ...options,\n });\n }\n\n /**\n * Show a primary notification\n */\n primary(\n title: string,\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\n position?: FuiNotificationPosition;\n },\n ): FuiNotificationRef {\n return this.show({\n variant: 'primary',\n title,\n ...options,\n });\n }\n\n /**\n * Show a generic notification\n */\n generic(\n title: string,\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\n position?: FuiNotificationPosition;\n },\n ): FuiNotificationRef {\n return this.show({\n variant: 'generic',\n title,\n ...options,\n });\n }\n\n /**\n * Show a notification with full configuration\n */\n show(config: FuiNotificationConfig & { position?: FuiNotificationPosition }): FuiNotificationRef {\n const position = config.position ?? this._defaultPosition;\n const container = this._getOrCreateContainer(position);\n\n // Create notification reference\n const notificationId = `fui-notification-${this._nextId++}`;\n const notificationRef = new FuiNotificationRef(notificationId, config);\n\n // Add to container\n container.instance.addNotification(notificationRef);\n\n return notificationRef;\n }\n\n /**\n * Clear all notifications at a specific position\n */\n clearPosition(position: FuiNotificationPosition): void {\n const container = this._containers.get(position);\n if (container) {\n // Clear all notifications\n const notifications = container.instance.notifications();\n notifications.forEach((notification) => {\n container.instance.removeNotification(notification.id);\n });\n }\n }\n\n /**\n * Clear all notifications\n */\n clearAll(): void {\n this._containers.forEach((container) => {\n const notifications = container.instance.notifications();\n notifications.forEach((notification) => {\n container.instance.removeNotification(notification.id);\n });\n });\n }\n\n private _getOrCreateContainer(position: FuiNotificationPosition): ComponentRef<FuiNotificationContainerComponent> {\n let container = this._containers.get(position);\n\n if (!container) {\n container = this._createContainer(position);\n this._containers.set(position, container);\n }\n\n return container;\n }\n\n private _createContainer(position: FuiNotificationPosition): ComponentRef<FuiNotificationContainerComponent> {\n // Create the container component\n const containerRef = createComponent(FuiNotificationContainerComponent, {\n environmentInjector: this._environmentInjector,\n });\n\n // Add position class\n const positionClass = `fui-notification-container--${position}`;\n this._renderer.addClass(containerRef.location.nativeElement, positionClass);\n\n // Attach to the application\n this._applicationRef.attachView(containerRef.hostView);\n\n // Append to document body\n const containerElement = containerRef.location.nativeElement;\n this._renderer.appendChild(this._document.body, containerElement);\n\n return containerRef;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"raintonic-formaui-services-notification.mjs","sources":["../../../lib/services/notification/notification-ref.ts","../../../lib/services/notification/notification-container.component.ts","../../../lib/services/notification/notification-container.component.html","../../../lib/services/notification/notification.service.ts","../../../lib/services/notification/raintonic-formaui-services-notification.ts"],"sourcesContent":["import { Observable, Subject } from 'rxjs';\r\nimport { FuiNotificationConfig } from '@raintonic/formaui/components/alert';\r\n\r\n/**\r\n * Reference to a notification instance.\r\n * Provides control over the notification and observables for lifecycle events.\r\n */\r\nexport class FuiNotificationRef {\r\n private readonly _afterClosed = new Subject<void>();\r\n private readonly _afterDismissed = new Subject<void>();\r\n\r\n /**\r\n * Observable that emits when the notification is closed\r\n */\r\n readonly afterClosed: Observable<void> = this._afterClosed.asObservable();\r\n\r\n /**\r\n * Observable that emits when the notification is dismissed (after animation)\r\n */\r\n readonly afterDismissed: Observable<void> = this._afterDismissed.asObservable();\r\n\r\n constructor(\r\n public readonly id: string,\r\n public readonly config: FuiNotificationConfig,\r\n ) {}\r\n\r\n /**\r\n * Close the notification\r\n */\r\n close(): void {\r\n this._afterClosed.next();\r\n this._afterClosed.complete();\r\n }\r\n\r\n /**\r\n * Called internally when the notification is fully dismissed\r\n * @internal\r\n */\r\n _dismiss(): void {\r\n this._afterDismissed.next();\r\n this._afterDismissed.complete();\r\n }\r\n}\r\n","import { ChangeDetectionStrategy, Component, effect, signal, ViewEncapsulation } from '@angular/core';\r\nimport { FuiAlertComponent } from '@raintonic/formaui/components/alert';\r\nimport { FuiNotificationRef } from './notification-ref';\r\n\r\n/**\r\n * Container component for displaying stacked notifications.\r\n * This component is created by the notification service and managed internally.\r\n * @internal\r\n */\r\n@Component({\r\n selector: 'fui-notification-container',\r\n standalone: true,\r\n imports: [FuiAlertComponent],\r\n templateUrl: './notification-container.component.html',\r\n styleUrls: ['./notification-container.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-notification-container',\r\n role: 'log',\r\n 'aria-live': 'polite',\r\n 'aria-atomic': 'false',\r\n },\r\n})\r\nexport class FuiNotificationContainerComponent {\r\n /**\r\n * List of active notifications\r\n */\r\n readonly notifications = signal<FuiNotificationRef[]>([]);\r\n\r\n /**\r\n * Progress values for each notification (0-100)\r\n */\r\n readonly progressValues = signal(new Map());\r\n\r\n /**\r\n * Timers for auto-dismiss\r\n */\r\n private readonly timers = new Map<\r\n string,\r\n { interval: ReturnType<typeof setInterval>; timeout: ReturnType<typeof setTimeout> }\r\n >();\r\n\r\n constructor() {\r\n // Set up effect to manage timers when notifications change\r\n effect(() => {\r\n this.notifications();\r\n // This will react to changes in the notifications signal\r\n });\r\n }\r\n\r\n /**\r\n * Add a notification to the container\r\n */\r\n addNotification(notification: FuiNotificationRef): void {\r\n this.notifications.update((notifications) => [...notifications, notification]);\r\n\r\n // Set up auto-dismiss if duration is specified\r\n const duration = notification.config.duration ?? 5000;\r\n if (duration > 0) {\r\n this._setupAutoDismiss(notification, duration);\r\n }\r\n\r\n // Listen for manual close\r\n notification.afterClosed.subscribe(() => {\r\n this._removeNotification(notification);\r\n });\r\n }\r\n\r\n /**\r\n * Remove a notification from the container\r\n */\r\n removeNotification(notificationId: string): void {\r\n const notification = this.notifications().find((n) => n.id === notificationId);\r\n if (notification) {\r\n this._removeNotification(notification);\r\n }\r\n }\r\n\r\n /**\r\n * Handle notification close button click\r\n */\r\n onNotificationClose(notification: FuiNotificationRef): void {\r\n notification.close();\r\n }\r\n\r\n /**\r\n * Get the progress value for a notification\r\n */\r\n getProgress(notificationId: string): number {\r\n return this.progressValues().get(notificationId) ?? 100;\r\n }\r\n\r\n /**\r\n * Check if notification should show progress bar\r\n */\r\n shouldShowProgress(notification: FuiNotificationRef): boolean {\r\n const duration = notification.config.duration ?? 5000;\r\n return duration > 0;\r\n }\r\n\r\n private _setupAutoDismiss(notification: FuiNotificationRef, duration: number): void {\r\n const startTime = Date.now();\r\n const updateInterval = 50; // Update progress every 50ms for smooth animation\r\n\r\n // Update progress bar\r\n const interval = setInterval(() => {\r\n const elapsed = Date.now() - startTime;\r\n const progress = Math.max(0, 100 - (elapsed / duration) * 100);\r\n\r\n this.progressValues.update((values) => {\r\n const newValues = new Map(values);\r\n newValues.set(notification.id, progress);\r\n return newValues;\r\n });\r\n\r\n if (progress <= 0) {\r\n clearInterval(interval);\r\n }\r\n }, updateInterval);\r\n\r\n // Auto-dismiss after duration\r\n const timeout = setTimeout(() => {\r\n notification.close();\r\n }, duration);\r\n\r\n this.timers.set(notification.id, { interval, timeout });\r\n }\r\n\r\n private _removeNotification(notification: FuiNotificationRef): void {\r\n // Clear timers\r\n const timers = this.timers.get(notification.id);\r\n if (timers) {\r\n clearInterval(timers.interval);\r\n clearTimeout(timers.timeout);\r\n this.timers.delete(notification.id);\r\n }\r\n\r\n // Remove from progress map\r\n this.progressValues.update((values) => {\r\n const newValues = new Map(values);\r\n newValues.delete(notification.id);\r\n return newValues;\r\n });\r\n\r\n // Remove from notifications list\r\n this.notifications.update((notifications) => notifications.filter((n) => n.id !== notification.id));\r\n\r\n // Notify that notification is dismissed\r\n notification._dismiss();\r\n }\r\n}\r\n","<div class=\"fui-notification-container__stack\">\r\n @for (notification of notifications(); track notification.id) {\r\n <div class=\"fui-notification-container__item\" role=\"alert\" aria-atomic=\"true\">\r\n <fui-alert\r\n [variant]=\"notification.config.variant\"\r\n [title]=\"notification.config.title\"\r\n [description]=\"notification.config.description ?? null\"\r\n [closeable]=\"notification.config.closeable ?? true\"\r\n [icon]=\"notification.config.icon ?? null\"\r\n [progress]=\"shouldShowProgress(notification) ? getProgress(notification.id) : -1\"\r\n (closed)=\"onNotificationClose(notification)\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n","import {\r\n Injectable,\r\n Renderer2,\r\n RendererFactory2,\r\n ComponentRef,\r\n createComponent,\r\n EnvironmentInjector,\r\n inject,\r\n ApplicationRef,\r\n} from '@angular/core';\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { FuiNotificationConfig, FuiNotificationPosition } from '@raintonic/formaui/components/alert';\r\nimport { FuiNotificationRef } from './notification-ref';\r\nimport { FuiNotificationContainerComponent } from './notification-container.component';\r\n\r\n/**\r\n * # FuiNotificationService\r\n *\r\n * Service for displaying toast-style notifications using overlays.\r\n * Notifications can be displayed at various positions on the screen and will\r\n * auto-dismiss after a configurable duration with a visual countdown.\r\n *\r\n * ## Features\r\n * - Multiple notification variants (success, info, warning, error, primary, generic)\r\n * - Configurable positioning (top-left, top-center, top-right, bottom-left, bottom-center, bottom-right)\r\n * - Auto-dismiss with progress bar countdown\r\n * - Manual dismiss via close button\r\n * - Stack multiple notifications\r\n * - Convenient shorthand methods for common variants\r\n *\r\n * ## Usage\r\n *\r\n * ### Success Notification\r\n * ```typescript\r\n * this.notificationService.success('Changes saved successfully!');\r\n * ```\r\n *\r\n * ### Error Notification with Description\r\n * ```typescript\r\n * this.notificationService.error('Failed to save', {\r\n * description: 'Please check your connection and try again.'\r\n * });\r\n * ```\r\n *\r\n * ### Custom Duration and Position\r\n * ```typescript\r\n * this.notificationService.info('New message received', {\r\n * description: 'Click to view',\r\n * duration: 10000,\r\n * position: 'bottom-right'\r\n * });\r\n * ```\r\n *\r\n * ### No Auto-Dismiss\r\n * ```typescript\r\n * this.notificationService.warning('Important notice', {\r\n * duration: 0, // Won't auto-dismiss\r\n * closeable: true\r\n * });\r\n * ```\r\n *\r\n * ### Full Configuration\r\n * ```typescript\r\n * const ref = this.notificationService.show({\r\n * variant: 'success',\r\n * title: 'Success!',\r\n * description: 'Your operation completed successfully.',\r\n * duration: 5000,\r\n * closeable: true,\r\n * icon: 'custom-icon',\r\n * position: 'top-center'\r\n * });\r\n *\r\n * // Programmatically close\r\n * ref.close();\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class FuiNotificationService {\r\n private readonly _document = inject(DOCUMENT);\r\n private readonly _rendererFactory = inject(RendererFactory2);\r\n private readonly _environmentInjector = inject(EnvironmentInjector);\r\n private readonly _applicationRef = inject(ApplicationRef);\r\n private readonly _renderer: Renderer2;\r\n\r\n /**\r\n * Map of container components by position\r\n */\r\n private readonly _containers = new Map<FuiNotificationPosition, ComponentRef<FuiNotificationContainerComponent>>();\r\n\r\n /**\r\n * Default position for notifications\r\n */\r\n private _defaultPosition: FuiNotificationPosition = 'bottom-right';\r\n\r\n /**\r\n * Next unique notification ID\r\n */\r\n private _nextId = 0;\r\n\r\n constructor() {\r\n this._renderer = this._rendererFactory.createRenderer(null, null);\r\n }\r\n\r\n /**\r\n * Set the default position for notifications\r\n */\r\n setDefaultPosition(position: FuiNotificationPosition): void {\r\n this._defaultPosition = position;\r\n }\r\n\r\n /**\r\n * Show a success notification\r\n */\r\n success(\r\n title: string,\r\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\r\n position?: FuiNotificationPosition;\r\n },\r\n ): FuiNotificationRef {\r\n return this.show({\r\n variant: 'success',\r\n title,\r\n ...options,\r\n });\r\n }\r\n\r\n /**\r\n * Show an info notification\r\n */\r\n info(\r\n title: string,\r\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\r\n position?: FuiNotificationPosition;\r\n },\r\n ): FuiNotificationRef {\r\n return this.show({\r\n variant: 'info',\r\n title,\r\n ...options,\r\n });\r\n }\r\n\r\n /**\r\n * Show a warning notification\r\n */\r\n warning(\r\n title: string,\r\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\r\n position?: FuiNotificationPosition;\r\n },\r\n ): FuiNotificationRef {\r\n return this.show({\r\n variant: 'warning',\r\n title,\r\n ...options,\r\n });\r\n }\r\n\r\n /**\r\n * Show an error notification\r\n */\r\n error(\r\n title: string,\r\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\r\n position?: FuiNotificationPosition;\r\n },\r\n ): FuiNotificationRef {\r\n return this.show({\r\n variant: 'error',\r\n title,\r\n ...options,\r\n });\r\n }\r\n\r\n /**\r\n * Show a primary notification\r\n */\r\n primary(\r\n title: string,\r\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\r\n position?: FuiNotificationPosition;\r\n },\r\n ): FuiNotificationRef {\r\n return this.show({\r\n variant: 'primary',\r\n title,\r\n ...options,\r\n });\r\n }\r\n\r\n /**\r\n * Show a generic notification\r\n */\r\n generic(\r\n title: string,\r\n options?: Partial<Omit<FuiNotificationConfig, 'variant' | 'title'>> & {\r\n position?: FuiNotificationPosition;\r\n },\r\n ): FuiNotificationRef {\r\n return this.show({\r\n variant: 'generic',\r\n title,\r\n ...options,\r\n });\r\n }\r\n\r\n /**\r\n * Show a notification with full configuration\r\n */\r\n show(config: FuiNotificationConfig & { position?: FuiNotificationPosition }): FuiNotificationRef {\r\n const position = config.position ?? this._defaultPosition;\r\n const container = this._getOrCreateContainer(position);\r\n\r\n // Create notification reference\r\n const notificationId = `fui-notification-${this._nextId++}`;\r\n const notificationRef = new FuiNotificationRef(notificationId, config);\r\n\r\n // Add to container\r\n container.instance.addNotification(notificationRef);\r\n\r\n return notificationRef;\r\n }\r\n\r\n /**\r\n * Clear all notifications at a specific position\r\n */\r\n clearPosition(position: FuiNotificationPosition): void {\r\n const container = this._containers.get(position);\r\n if (container) {\r\n // Clear all notifications\r\n const notifications = container.instance.notifications();\r\n notifications.forEach((notification) => {\r\n container.instance.removeNotification(notification.id);\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Clear all notifications\r\n */\r\n clearAll(): void {\r\n this._containers.forEach((container) => {\r\n const notifications = container.instance.notifications();\r\n notifications.forEach((notification) => {\r\n container.instance.removeNotification(notification.id);\r\n });\r\n });\r\n }\r\n\r\n private _getOrCreateContainer(position: FuiNotificationPosition): ComponentRef<FuiNotificationContainerComponent> {\r\n let container = this._containers.get(position);\r\n\r\n if (!container) {\r\n container = this._createContainer(position);\r\n this._containers.set(position, container);\r\n }\r\n\r\n return container;\r\n }\r\n\r\n private _createContainer(position: FuiNotificationPosition): ComponentRef<FuiNotificationContainerComponent> {\r\n // Create the container component\r\n const containerRef = createComponent(FuiNotificationContainerComponent, {\r\n environmentInjector: this._environmentInjector,\r\n });\r\n\r\n // Add position class\r\n const positionClass = `fui-notification-container--${position}`;\r\n this._renderer.addClass(containerRef.location.nativeElement, positionClass);\r\n\r\n // Attach to the application\r\n this._applicationRef.attachView(containerRef.hostView);\r\n\r\n // Append to document body\r\n const containerElement = containerRef.location.nativeElement;\r\n this._renderer.appendChild(this._document.body, containerElement);\r\n\r\n return containerRef;\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -53,9 +53,9 @@ import { DOCUMENT, isPlatformBrowser } from '@angular/common';
53
53
  * @Component({
54
54
  * template: `
55
55
  * <div class="theme-controls">
56
- * <button rtButton (click)="setLightMode()">Light</button>
57
- * <button rtButton (click)="setDarkMode()">Dark</button>
58
- * <button rtButton (click)="setAutoMode()">Auto</button>
56
+ * <button fuiButton (click)="setLightMode()">Light</button>
57
+ * <button fuiButton (click)="setDarkMode()">Dark</button>
58
+ * <button fuiButton (click)="setAutoMode()">Auto</button>
59
59
  * </div>
60
60
  * `
61
61
  * })
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-services-theme.mjs","sources":["../../../lib/services/theme/theme.service.ts","../../../lib/services/theme/raintonic-formaui-services-theme.ts"],"sourcesContent":["import { DestroyRef, inject, Injectable, PLATFORM_ID, signal, Signal, WritableSignal } from '@angular/core';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\n\n/**\n * Configuration interface for theme customization\n */\nexport interface FuiThemeConfig {\n /** Primary color for the theme (hex, rgb, hsl) */\n primary?: string;\n /** Secondary color for the theme (hex, rgb, hsl) */\n secondary?: string;\n /** Tertiary color for the theme (hex, rgb, hsl) */\n tertiary?: string;\n}\n\n/**\n * Available theme modes\n */\nexport type FuiThemeMode = 'light' | 'dark' | 'auto';\n\n/**\n * # FuiTheme Service\n *\n * Central service for managing theme configuration and mode switching.\n * Provides runtime theme customization with CSS variables and automatic palette generation.\n *\n * ## Features\n * - Runtime theme customization\n * - Light/dark/auto mode switching\n * - Automatic color palette generation\n * - CSS variables-based theming\n * - Persistent theme preferences\n * - System theme detection\n *\n * ## Usage\n *\n * ### Basic Theme Setup\n * ```typescript\n * import { FuiThemeService } from '@raintonic/formaui/services/theme';\n *\n * constructor(private themeService: FuiThemeService) {\n * // Set custom theme colors\n * this.themeService.setTheme({\n * primary: '#007bff',\n * secondary: '#6c757d',\n * tertiary: '#28a745'\n * });\n * }\n * ```\n *\n * ### Theme Mode Switching\n * ```typescript\n * // Switch to dark mode\n * this.themeService.setMode('dark');\n *\n * // Switch to auto (follows system preference)\n * this.themeService.setMode('auto');\n *\n * // Get current mode\n * const currentMode = this.themeService.currentMode();\n * const isDark = this.themeService.isDark();\n * ```\n *\n * @example\n * ```typescript\n * import { Component, effect } from '@angular/core';\n * import { FuiThemeService } from '@raintonic/formaui/services/theme';\n *\n * @Component({\n * template: `\n * <div class=\"theme-controls\">\n * <button rtButton (click)=\"setLightMode()\">Light</button>\n * <button rtButton (click)=\"setDarkMode()\">Dark</button>\n * <button rtButton (click)=\"setAutoMode()\">Auto</button>\n * </div>\n * `\n * })\n * export class ThemeControlsComponent {\n * constructor(public themeService: FuiThemeService) {}\n *\n * setLightMode() { this.themeService.setMode('light'); }\n * setDarkMode() { this.themeService.setMode('dark'); }\n * setAutoMode() { this.themeService.setMode('auto'); }\n * }\n * ```\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class FuiThemeService {\n private readonly _destroyRef = inject(DestroyRef);\n private readonly _document = inject(DOCUMENT);\n private readonly _platformId = inject(PLATFORM_ID);\n private readonly _currentMode: WritableSignal<FuiThemeMode> = signal<FuiThemeMode>('dark');\n private readonly _isDark: WritableSignal<boolean> = signal(false);\n\n readonly currentMode: Signal<FuiThemeMode> = this._currentMode.asReadonly();\n readonly isDark: Signal<boolean> = this._isDark.asReadonly();\n\n constructor() {\n this._initializeTheme();\n this._setupMediaQueryListener();\n }\n\n /**\n * Initialize theme with custom colors\n */\n initTheme(config: FuiThemeConfig = {}): void {\n this.setTheme(config);\n }\n\n /**\n * Set theme colors dynamically\n */\n setTheme(config: FuiThemeConfig = {}): void {\n const root: HTMLElement = this._document.documentElement;\n\n if (config.primary) {\n this._setColorPalette(root, 'primary', config.primary);\n }\n\n if (config.secondary) {\n this._setColorPalette(root, 'secondary', config.secondary);\n }\n\n if (config.tertiary) {\n this._setColorPalette(root, 'tertiary', config.tertiary);\n }\n }\n\n /**\n * Set theme mode\n */\n setThemeMode(mode: FuiThemeMode): void {\n this.setMode(mode);\n }\n\n /**\n * Set theme mode (preferred method)\n */\n setMode(mode: FuiThemeMode): void {\n this._currentMode.set(mode);\n this._applyThemeMode(mode);\n }\n\n /**\n * Toggle between light and dark themes\n */\n toggleTheme(): void {\n const newMode: FuiThemeMode = this._isDark() ? 'light' : 'dark';\n this.setMode(newMode);\n }\n\n private _initializeTheme(): void {\n if (!isPlatformBrowser(this._platformId)) {\n return;\n }\n\n const win = this._document.defaultView;\n try {\n const savedMode: FuiThemeMode | null = win?.localStorage.getItem('fui-theme-mode') as FuiThemeMode;\n if (savedMode && ['light', 'dark', 'auto'].includes(savedMode)) {\n this.setMode(savedMode);\n return;\n }\n } catch {\n // localStorage may be unavailable (e.g., privacy mode)\n }\n\n const mediaQuery: MediaQueryList | undefined = win?.matchMedia('(prefers-color-scheme: dark)');\n this._updateDarkMode(mediaQuery?.matches ?? false);\n }\n\n private _setupMediaQueryListener(): void {\n if (!isPlatformBrowser(this._platformId)) {\n return;\n }\n\n const win = this._document.defaultView;\n if (!win) {\n return;\n }\n\n const mediaQuery: MediaQueryList = win.matchMedia('(prefers-color-scheme: dark)');\n\n const handleChange = (e: MediaQueryListEvent): void => {\n if (this._currentMode() === 'auto') {\n this._updateDarkMode(e.matches);\n }\n };\n\n mediaQuery.addEventListener('change', handleChange);\n\n // Clean up listener when service is destroyed\n this._destroyRef.onDestroy(() => {\n mediaQuery.removeEventListener('change', handleChange);\n });\n\n // Initial check\n if (this._currentMode() === 'auto') {\n this._updateDarkMode(mediaQuery.matches);\n }\n }\n\n private _applyThemeMode(mode: FuiThemeMode): void {\n const root: HTMLElement = this._document.documentElement;\n\n // Save to localStorage\n try {\n this._document.defaultView?.localStorage.setItem('fui-theme-mode', mode);\n } catch {\n // localStorage may be unavailable\n }\n\n // Remove existing theme classes\n root.classList.remove('fui-theme-light', 'fui-theme-dark');\n\n switch (mode) {\n case 'light':\n root.classList.add('fui-theme-light');\n this._updateDarkMode(false);\n break;\n case 'dark':\n root.classList.add('fui-theme-dark');\n this._updateDarkMode(true);\n break;\n case 'auto': {\n const win = this._document.defaultView;\n const _isDarkPreferred: boolean = win?.matchMedia('(prefers-color-scheme: dark)').matches ?? false;\n this._updateDarkMode(_isDarkPreferred);\n break;\n }\n }\n }\n\n private _updateDarkMode(isDark: boolean): void {\n this._isDark.set(isDark);\n this._document.documentElement.classList.toggle('fui-theme-dark', isDark);\n }\n\n private _setColorPalette(root: HTMLElement, colorName: string, baseColor: string): void {\n const palette: Record<string, string> = this._generateColorPalette(baseColor);\n\n Object.entries(palette).forEach(([shade, color]) => {\n root.style.setProperty(`--fui-${colorName}-${shade}`, color);\n });\n\n // Update semantic color\n root.style.setProperty(`--fui-${colorName}-color`, `var(--fui-${colorName}-60)`);\n }\n\n private _generateColorPalette(baseColor: string): Record<string, string> {\n // Convert hex to RGB\n const hex: string = baseColor.replace('#', '');\n const r: number = parseInt(hex.substr(0, 2), 16);\n const g: number = parseInt(hex.substr(2, 2), 16);\n const b: number = parseInt(hex.substr(4, 2), 16);\n\n const palette: Record<string, string> = {};\n\n // Generate lighter shades (10-50)\n for (let i = 10; i <= 50; i += 10) {\n const factor: number = (60 - i) / 60; // More white for lower numbers\n const newR: number = Math.round(r + (255 - r) * (1 - factor));\n const newG: number = Math.round(g + (255 - g) * (1 - factor));\n const newB: number = Math.round(b + (255 - b) * (1 - factor));\n palette[i.toString()] = `rgb(${newR}, ${newG}, ${newB})`;\n }\n\n // Base color (60)\n palette['60'] = baseColor;\n\n // Generate darker shades (70-100)\n for (let i = 70; i <= 100; i += 10) {\n const factor: number = (i - 60) / 40; // More black for higher numbers\n const newR: number = Math.round(r * (1 - factor));\n const newG: number = Math.round(g * (1 - factor));\n const newB: number = Math.round(b * (1 - factor));\n palette[i.toString()] = `rgb(${newR}, ${newG}, ${newB})`;\n }\n\n return palette;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"raintonic-formaui-services-theme.mjs","sources":["../../../lib/services/theme/theme.service.ts","../../../lib/services/theme/raintonic-formaui-services-theme.ts"],"sourcesContent":["import { DestroyRef, inject, Injectable, PLATFORM_ID, signal, Signal, WritableSignal } from '@angular/core';\r\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\r\n\r\n/**\r\n * Configuration interface for theme customization\r\n */\r\nexport interface FuiThemeConfig {\r\n /** Primary color for the theme (hex, rgb, hsl) */\r\n primary?: string;\r\n /** Secondary color for the theme (hex, rgb, hsl) */\r\n secondary?: string;\r\n /** Tertiary color for the theme (hex, rgb, hsl) */\r\n tertiary?: string;\r\n}\r\n\r\n/**\r\n * Available theme modes\r\n */\r\nexport type FuiThemeMode = 'light' | 'dark' | 'auto';\r\n\r\n/**\r\n * # FuiTheme Service\r\n *\r\n * Central service for managing theme configuration and mode switching.\r\n * Provides runtime theme customization with CSS variables and automatic palette generation.\r\n *\r\n * ## Features\r\n * - Runtime theme customization\r\n * - Light/dark/auto mode switching\r\n * - Automatic color palette generation\r\n * - CSS variables-based theming\r\n * - Persistent theme preferences\r\n * - System theme detection\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Theme Setup\r\n * ```typescript\r\n * import { FuiThemeService } from '@raintonic/formaui/services/theme';\r\n *\r\n * constructor(private themeService: FuiThemeService) {\r\n * // Set custom theme colors\r\n * this.themeService.setTheme({\r\n * primary: '#007bff',\r\n * secondary: '#6c757d',\r\n * tertiary: '#28a745'\r\n * });\r\n * }\r\n * ```\r\n *\r\n * ### Theme Mode Switching\r\n * ```typescript\r\n * // Switch to dark mode\r\n * this.themeService.setMode('dark');\r\n *\r\n * // Switch to auto (follows system preference)\r\n * this.themeService.setMode('auto');\r\n *\r\n * // Get current mode\r\n * const currentMode = this.themeService.currentMode();\r\n * const isDark = this.themeService.isDark();\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { Component, effect } from '@angular/core';\r\n * import { FuiThemeService } from '@raintonic/formaui/services/theme';\r\n *\r\n * @Component({\r\n * template: `\r\n * <div class=\"theme-controls\">\r\n * <button fuiButton (click)=\"setLightMode()\">Light</button>\r\n * <button fuiButton (click)=\"setDarkMode()\">Dark</button>\r\n * <button fuiButton (click)=\"setAutoMode()\">Auto</button>\r\n * </div>\r\n * `\r\n * })\r\n * export class ThemeControlsComponent {\r\n * constructor(public themeService: FuiThemeService) {}\r\n *\r\n * setLightMode() { this.themeService.setMode('light'); }\r\n * setDarkMode() { this.themeService.setMode('dark'); }\r\n * setAutoMode() { this.themeService.setMode('auto'); }\r\n * }\r\n * ```\r\n */\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class FuiThemeService {\r\n private readonly _destroyRef = inject(DestroyRef);\r\n private readonly _document = inject(DOCUMENT);\r\n private readonly _platformId = inject(PLATFORM_ID);\r\n private readonly _currentMode: WritableSignal<FuiThemeMode> = signal<FuiThemeMode>('dark');\r\n private readonly _isDark: WritableSignal<boolean> = signal(false);\r\n\r\n readonly currentMode: Signal<FuiThemeMode> = this._currentMode.asReadonly();\r\n readonly isDark: Signal<boolean> = this._isDark.asReadonly();\r\n\r\n constructor() {\r\n this._initializeTheme();\r\n this._setupMediaQueryListener();\r\n }\r\n\r\n /**\r\n * Initialize theme with custom colors\r\n */\r\n initTheme(config: FuiThemeConfig = {}): void {\r\n this.setTheme(config);\r\n }\r\n\r\n /**\r\n * Set theme colors dynamically\r\n */\r\n setTheme(config: FuiThemeConfig = {}): void {\r\n const root: HTMLElement = this._document.documentElement;\r\n\r\n if (config.primary) {\r\n this._setColorPalette(root, 'primary', config.primary);\r\n }\r\n\r\n if (config.secondary) {\r\n this._setColorPalette(root, 'secondary', config.secondary);\r\n }\r\n\r\n if (config.tertiary) {\r\n this._setColorPalette(root, 'tertiary', config.tertiary);\r\n }\r\n }\r\n\r\n /**\r\n * Set theme mode\r\n */\r\n setThemeMode(mode: FuiThemeMode): void {\r\n this.setMode(mode);\r\n }\r\n\r\n /**\r\n * Set theme mode (preferred method)\r\n */\r\n setMode(mode: FuiThemeMode): void {\r\n this._currentMode.set(mode);\r\n this._applyThemeMode(mode);\r\n }\r\n\r\n /**\r\n * Toggle between light and dark themes\r\n */\r\n toggleTheme(): void {\r\n const newMode: FuiThemeMode = this._isDark() ? 'light' : 'dark';\r\n this.setMode(newMode);\r\n }\r\n\r\n private _initializeTheme(): void {\r\n if (!isPlatformBrowser(this._platformId)) {\r\n return;\r\n }\r\n\r\n const win = this._document.defaultView;\r\n try {\r\n const savedMode: FuiThemeMode | null = win?.localStorage.getItem('fui-theme-mode') as FuiThemeMode;\r\n if (savedMode && ['light', 'dark', 'auto'].includes(savedMode)) {\r\n this.setMode(savedMode);\r\n return;\r\n }\r\n } catch {\r\n // localStorage may be unavailable (e.g., privacy mode)\r\n }\r\n\r\n const mediaQuery: MediaQueryList | undefined = win?.matchMedia('(prefers-color-scheme: dark)');\r\n this._updateDarkMode(mediaQuery?.matches ?? false);\r\n }\r\n\r\n private _setupMediaQueryListener(): void {\r\n if (!isPlatformBrowser(this._platformId)) {\r\n return;\r\n }\r\n\r\n const win = this._document.defaultView;\r\n if (!win) {\r\n return;\r\n }\r\n\r\n const mediaQuery: MediaQueryList = win.matchMedia('(prefers-color-scheme: dark)');\r\n\r\n const handleChange = (e: MediaQueryListEvent): void => {\r\n if (this._currentMode() === 'auto') {\r\n this._updateDarkMode(e.matches);\r\n }\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n\r\n // Clean up listener when service is destroyed\r\n this._destroyRef.onDestroy(() => {\r\n mediaQuery.removeEventListener('change', handleChange);\r\n });\r\n\r\n // Initial check\r\n if (this._currentMode() === 'auto') {\r\n this._updateDarkMode(mediaQuery.matches);\r\n }\r\n }\r\n\r\n private _applyThemeMode(mode: FuiThemeMode): void {\r\n const root: HTMLElement = this._document.documentElement;\r\n\r\n // Save to localStorage\r\n try {\r\n this._document.defaultView?.localStorage.setItem('fui-theme-mode', mode);\r\n } catch {\r\n // localStorage may be unavailable\r\n }\r\n\r\n // Remove existing theme classes\r\n root.classList.remove('fui-theme-light', 'fui-theme-dark');\r\n\r\n switch (mode) {\r\n case 'light':\r\n root.classList.add('fui-theme-light');\r\n this._updateDarkMode(false);\r\n break;\r\n case 'dark':\r\n root.classList.add('fui-theme-dark');\r\n this._updateDarkMode(true);\r\n break;\r\n case 'auto': {\r\n const win = this._document.defaultView;\r\n const _isDarkPreferred: boolean = win?.matchMedia('(prefers-color-scheme: dark)').matches ?? false;\r\n this._updateDarkMode(_isDarkPreferred);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n private _updateDarkMode(isDark: boolean): void {\r\n this._isDark.set(isDark);\r\n this._document.documentElement.classList.toggle('fui-theme-dark', isDark);\r\n }\r\n\r\n private _setColorPalette(root: HTMLElement, colorName: string, baseColor: string): void {\r\n const palette: Record<string, string> = this._generateColorPalette(baseColor);\r\n\r\n Object.entries(palette).forEach(([shade, color]) => {\r\n root.style.setProperty(`--fui-${colorName}-${shade}`, color);\r\n });\r\n\r\n // Update semantic color\r\n root.style.setProperty(`--fui-${colorName}-color`, `var(--fui-${colorName}-60)`);\r\n }\r\n\r\n private _generateColorPalette(baseColor: string): Record<string, string> {\r\n // Convert hex to RGB\r\n const hex: string = baseColor.replace('#', '');\r\n const r: number = parseInt(hex.substr(0, 2), 16);\r\n const g: number = parseInt(hex.substr(2, 2), 16);\r\n const b: number = parseInt(hex.substr(4, 2), 16);\r\n\r\n const palette: Record<string, string> = {};\r\n\r\n // Generate lighter shades (10-50)\r\n for (let i = 10; i <= 50; i += 10) {\r\n const factor: number = (60 - i) / 60; // More white for lower numbers\r\n const newR: number = Math.round(r + (255 - r) * (1 - factor));\r\n const newG: number = Math.round(g + (255 - g) * (1 - factor));\r\n const newB: number = Math.round(b + (255 - b) * (1 - factor));\r\n palette[i.toString()] = `rgb(${newR}, ${newG}, ${newB})`;\r\n }\r\n\r\n // Base color (60)\r\n palette['60'] = baseColor;\r\n\r\n // Generate darker shades (70-100)\r\n for (let i = 70; i <= 100; i += 10) {\r\n const factor: number = (i - 60) / 40; // More black for higher numbers\r\n const newR: number = Math.round(r * (1 - factor));\r\n const newG: number = Math.round(g * (1 - factor));\r\n const newB: number = Math.round(b * (1 - factor));\r\n palette[i.toString()] = `rgb(${newR}, ${newG}, ${newB})`;\r\n }\r\n\r\n return palette;\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -2,23 +2,28 @@ import axe from 'axe-core';
2
2
 
3
3
  /**
4
4
  * Runs axe-core accessibility audit on the given element.
5
- * Returns violations array. Empty array means no violations.
5
+ * Returns the violations array. Empty array means no violations.
6
+ *
7
+ * `color-contrast` is disabled by default because JSDOM does not compute
8
+ * real styles, so color-contrast checks produce unreliable results.
6
9
  */
7
- async function runA11yAudit(element) {
8
- const results = await axe.run(element, {
9
- rules: {
10
- 'color-contrast': { enabled: true },
11
- 'keyboard-access': { enabled: true },
12
- 'aria-roles': { enabled: true },
13
- 'aria-required-attr': { enabled: true },
14
- 'aria-valid-attr': { enabled: true },
15
- 'aria-valid-attr-value': { enabled: true },
16
- 'button-name': { enabled: true },
17
- 'image-alt': { enabled: true },
18
- label: { enabled: true },
19
- 'link-name': { enabled: true },
20
- },
21
- });
10
+ async function runA11yAudit(element, options = {}) {
11
+ const rules = {
12
+ 'color-contrast': { enabled: false },
13
+ 'aria-roles': { enabled: true },
14
+ 'aria-required-attr': { enabled: true },
15
+ 'aria-valid-attr': { enabled: true },
16
+ 'aria-valid-attr-value': { enabled: true },
17
+ 'aria-allowed-attr': { enabled: true },
18
+ 'button-name': { enabled: true },
19
+ 'image-alt': { enabled: true },
20
+ label: { enabled: true },
21
+ 'link-name': { enabled: true },
22
+ };
23
+ for (const id of options.disableRules ?? []) {
24
+ rules[id] = { enabled: false };
25
+ }
26
+ const results = await axe.run(element, { rules });
22
27
  return results.violations;
23
28
  }
24
29
 
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-test-utils.mjs","sources":["../../../lib/test-utils/a11y-test.util.ts","../../../lib/test-utils/keyboard-test.util.ts","../../../lib/test-utils/raintonic-formaui-test-utils.ts"],"sourcesContent":["import axe from 'axe-core';\n\n/**\n * Runs axe-core accessibility audit on the given element.\n * Returns violations array. Empty array means no violations.\n */\nexport async function runA11yAudit(element: HTMLElement): Promise<axe.Result[]> {\n const results = await axe.run(element, {\n rules: {\n 'color-contrast': { enabled: true },\n 'keyboard-access': { enabled: true },\n 'aria-roles': { enabled: true },\n 'aria-required-attr': { enabled: true },\n 'aria-valid-attr': { enabled: true },\n 'aria-valid-attr-value': { enabled: true },\n 'button-name': { enabled: true },\n 'image-alt': { enabled: true },\n label: { enabled: true },\n 'link-name': { enabled: true },\n },\n });\n return results.violations;\n}\n","export function pressKey(\n element: HTMLElement,\n key: string,\n modifiers?: { shift?: boolean; ctrl?: boolean; alt?: boolean },\n): void {\n const event = new KeyboardEvent('keydown', {\n key,\n bubbles: true,\n cancelable: true,\n shiftKey: modifiers?.shift ?? false,\n ctrlKey: modifiers?.ctrl ?? false,\n altKey: modifiers?.alt ?? false,\n });\n element.dispatchEvent(event);\n}\n\nexport function pressTab(element: HTMLElement, shift = false): void {\n pressKey(element, 'Tab', { shift });\n}\n\nexport function pressArrowDown(element: HTMLElement): void {\n pressKey(element, 'ArrowDown');\n}\n\nexport function pressArrowUp(element: HTMLElement): void {\n pressKey(element, 'ArrowUp');\n}\n\nexport function pressEnter(element: HTMLElement): void {\n pressKey(element, 'Enter');\n}\n\nexport function pressSpace(element: HTMLElement): void {\n pressKey(element, ' ');\n}\n\nexport function pressEscape(element: HTMLElement): void {\n pressKey(element, 'Escape');\n}\n\nexport function pressHome(element: HTMLElement): void {\n pressKey(element, 'Home');\n}\n\nexport function pressEnd(element: HTMLElement): void {\n pressKey(element, 'End');\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAEA;;;AAGG;AACI,eAAe,YAAY,CAAC,OAAoB,EAAA;IACrD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE;AACrC,QAAA,KAAK,EAAE;AACL,YAAA,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACnC,YAAA,iBAAiB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACpC,YAAA,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC/B,YAAA,oBAAoB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACvC,YAAA,iBAAiB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACpC,YAAA,uBAAuB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC1C,YAAA,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAChC,YAAA,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC9B,YAAA,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACxB,YAAA,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC/B,SAAA;AACF,KAAA,CAAC;IACF,OAAO,OAAO,CAAC,UAAU;AAC3B;;SCtBgB,QAAQ,CACtB,OAAoB,EACpB,GAAW,EACX,SAA8D,EAAA;AAE9D,IAAA,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,SAAS,EAAE;QACzC,GAAG;AACH,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,UAAU,EAAE,IAAI;AAChB,QAAA,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,KAAK;AACnC,QAAA,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,KAAK;AACjC,QAAA,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,KAAK;AAChC,KAAA,CAAC;AACF,IAAA,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC;AAC9B;SAEgB,QAAQ,CAAC,OAAoB,EAAE,KAAK,GAAG,KAAK,EAAA;IAC1D,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AACrC;AAEM,SAAU,cAAc,CAAC,OAAoB,EAAA;AACjD,IAAA,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;AAChC;AAEM,SAAU,YAAY,CAAC,OAAoB,EAAA;AAC/C,IAAA,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;AAC9B;AAEM,SAAU,UAAU,CAAC,OAAoB,EAAA;AAC7C,IAAA,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;AAC5B;AAEM,SAAU,UAAU,CAAC,OAAoB,EAAA;AAC7C,IAAA,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC;AACxB;AAEM,SAAU,WAAW,CAAC,OAAoB,EAAA;AAC9C,IAAA,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;AAC7B;AAEM,SAAU,SAAS,CAAC,OAAoB,EAAA;AAC5C,IAAA,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;AAC3B;AAEM,SAAU,QAAQ,CAAC,OAAoB,EAAA;AAC3C,IAAA,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;AAC1B;;AC9CA;;AAEG;;;;"}
1
+ {"version":3,"file":"raintonic-formaui-test-utils.mjs","sources":["../../../lib/test-utils/a11y-test.util.ts","../../../lib/test-utils/keyboard-test.util.ts","../../../lib/test-utils/raintonic-formaui-test-utils.ts"],"sourcesContent":["import axe from 'axe-core';\r\n\r\nexport interface RunA11yAuditOptions {\r\n /**\r\n * IDs of axe rules to disable for this audit (merged on top of defaults).\r\n * Useful when a component legitimately fails a rule because of a\r\n * JSDOM limitation or host-element wrapping (e.g. `listitem` on\r\n * component hosts between `<ol>` and `<li>`).\r\n */\r\n disableRules?: string[];\r\n}\r\n\r\n/**\r\n * Runs axe-core accessibility audit on the given element.\r\n * Returns the violations array. Empty array means no violations.\r\n *\r\n * `color-contrast` is disabled by default because JSDOM does not compute\r\n * real styles, so color-contrast checks produce unreliable results.\r\n */\r\nexport async function runA11yAudit(\r\n element: HTMLElement,\r\n options: RunA11yAuditOptions = {},\r\n): Promise<axe.Result[]> {\r\n const rules: Record<string, { enabled: boolean }> = {\r\n 'color-contrast': { enabled: false },\r\n 'aria-roles': { enabled: true },\r\n 'aria-required-attr': { enabled: true },\r\n 'aria-valid-attr': { enabled: true },\r\n 'aria-valid-attr-value': { enabled: true },\r\n 'aria-allowed-attr': { enabled: true },\r\n 'button-name': { enabled: true },\r\n 'image-alt': { enabled: true },\r\n label: { enabled: true },\r\n 'link-name': { enabled: true },\r\n };\r\n for (const id of options.disableRules ?? []) {\r\n rules[id] = { enabled: false };\r\n }\r\n const results = await axe.run(element, { rules });\r\n return results.violations;\r\n}\r\n","export function pressKey(\r\n element: HTMLElement,\r\n key: string,\r\n modifiers?: { shift?: boolean; ctrl?: boolean; alt?: boolean },\r\n): void {\r\n const event = new KeyboardEvent('keydown', {\r\n key,\r\n bubbles: true,\r\n cancelable: true,\r\n shiftKey: modifiers?.shift ?? false,\r\n ctrlKey: modifiers?.ctrl ?? false,\r\n altKey: modifiers?.alt ?? false,\r\n });\r\n element.dispatchEvent(event);\r\n}\r\n\r\nexport function pressTab(element: HTMLElement, shift = false): void {\r\n pressKey(element, 'Tab', { shift });\r\n}\r\n\r\nexport function pressArrowDown(element: HTMLElement): void {\r\n pressKey(element, 'ArrowDown');\r\n}\r\n\r\nexport function pressArrowUp(element: HTMLElement): void {\r\n pressKey(element, 'ArrowUp');\r\n}\r\n\r\nexport function pressEnter(element: HTMLElement): void {\r\n pressKey(element, 'Enter');\r\n}\r\n\r\nexport function pressSpace(element: HTMLElement): void {\r\n pressKey(element, ' ');\r\n}\r\n\r\nexport function pressEscape(element: HTMLElement): void {\r\n pressKey(element, 'Escape');\r\n}\r\n\r\nexport function pressHome(element: HTMLElement): void {\r\n pressKey(element, 'Home');\r\n}\r\n\r\nexport function pressEnd(element: HTMLElement): void {\r\n pressKey(element, 'End');\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAYA;;;;;;AAMG;AACI,eAAe,YAAY,CAChC,OAAoB,EACpB,UAA+B,EAAE,EAAA;AAEjC,IAAA,MAAM,KAAK,GAAyC;AAClD,QAAA,gBAAgB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;AACpC,QAAA,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC/B,QAAA,oBAAoB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACvC,QAAA,iBAAiB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACpC,QAAA,uBAAuB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC1C,QAAA,mBAAmB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACtC,QAAA,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAChC,QAAA,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AAC9B,QAAA,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;AACxB,QAAA,WAAW,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;KAC/B;IACD,KAAK,MAAM,EAAE,IAAI,OAAO,CAAC,YAAY,IAAI,EAAE,EAAE;QAC3C,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE;IAChC;AACA,IAAA,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC;IACjD,OAAO,OAAO,CAAC,UAAU;AAC3B;;SCxCgB,QAAQ,CACtB,OAAoB,EACpB,GAAW,EACX,SAA8D,EAAA;AAE9D,IAAA,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,SAAS,EAAE;QACzC,GAAG;AACH,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,UAAU,EAAE,IAAI;AAChB,QAAA,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,KAAK;AACnC,QAAA,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,KAAK;AACjC,QAAA,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,KAAK;AAChC,KAAA,CAAC;AACF,IAAA,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC;AAC9B;SAEgB,QAAQ,CAAC,OAAoB,EAAE,KAAK,GAAG,KAAK,EAAA;IAC1D,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC;AACrC;AAEM,SAAU,cAAc,CAAC,OAAoB,EAAA;AACjD,IAAA,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;AAChC;AAEM,SAAU,YAAY,CAAC,OAAoB,EAAA;AAC/C,IAAA,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;AAC9B;AAEM,SAAU,UAAU,CAAC,OAAoB,EAAA;AAC7C,IAAA,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;AAC5B;AAEM,SAAU,UAAU,CAAC,OAAoB,EAAA;AAC7C,IAAA,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC;AACxB;AAEM,SAAU,WAAW,CAAC,OAAoB,EAAA;AAC9C,IAAA,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;AAC7B;AAEM,SAAU,SAAS,CAAC,OAAoB,EAAA;AAC5C,IAAA,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;AAC3B;AAEM,SAAU,QAAQ,CAAC,OAAoB,EAAA;AAC3C,IAAA,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;AAC1B;;AC9CA;;AAEG;;;;"}
@@ -1,4 +1,4 @@
1
- const FORMAUI_VERSION = '0.1.0';
1
+ const FORMAUI_VERSION = '0.3.0';
2
2
  // FormaUI - Primary entry point
3
3
  // Secondary entry points are imported directly, e.g.:
4
4
  // import { FuiButtonDirective } from '@raintonic/formaui/components/button';
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui.mjs","sources":["../../../lib/src/public-api.ts","../../../lib/src/raintonic-formaui.ts"],"sourcesContent":["export const FORMAUI_VERSION = '0.1.0';\n\n// FormaUI - Primary entry point\n// Secondary entry points are imported directly, e.g.:\n// import { FuiButtonDirective } from '@raintonic/formaui/components/button';\n// import { FuiIconComponent } from '@raintonic/formaui/components/icon';\n// import { ThemeService } from '@raintonic/formaui/services/theme';\n// import { FuiOverlayService } from '@raintonic/formaui/cdk/overlay';\n// import { FuiCoreModule } from '@raintonic/formaui/core';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAO,MAAM,eAAe,GAAG;AAE/B;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;;AAEG;;;;"}
1
+ {"version":3,"file":"raintonic-formaui.mjs","sources":["../../../lib/src/public-api.ts","../../../lib/src/raintonic-formaui.ts"],"sourcesContent":["export const FORMAUI_VERSION = '0.3.0';\r\n\r\n// FormaUI - Primary entry point\r\n// Secondary entry points are imported directly, e.g.:\r\n// import { FuiButtonDirective } from '@raintonic/formaui/components/button';\r\n// import { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\n// import { ThemeService } from '@raintonic/formaui/services/theme';\r\n// import { FuiOverlayService } from '@raintonic/formaui/cdk/overlay';\r\n// import { FuiCoreModule } from '@raintonic/formaui/core';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAO,MAAM,eAAe,GAAG;AAE/B;AACA;AACA;AACA;AACA;AACA;AACA;;ACRA;;AAEG;;;;"}
package/llms-full.txt CHANGED
@@ -79,6 +79,10 @@ An autocomplete component designed to work seamlessly with fui-form-field. Simil
79
79
 
80
80
  | Name | Type | Default | Required |
81
81
  |------|------|---------|----------|
82
+ | addButtonLabel | string | undefined | undefined | no |
83
+ | refreshButtonLabel | string | undefined | undefined | no |
84
+ | noOptionsText | string | undefined | undefined | no |
85
+ | searchPlaceholder | string | undefined | undefined | no |
82
86
  | errorStateMatcher | ErrorStateMatcher | null | null | no |
83
87
 
84
88
  #### Outputs
@@ -127,7 +131,7 @@ An autocomplete component designed to work seamlessly with fui-form-field. Simil
127
131
  | Name | Type | Default | Required |
128
132
  |------|------|---------|----------|
129
133
  | icon | string | null | null | no |
130
- | customColor | string | null | null | no |
134
+ | customColor | FuiBadgeCustomColor | null | null | no |
131
135
  | size | FuiBadgeSize | 'md' | no |
132
136
  | variant | FuiBadgeVariant | 'primary' | no |
133
137
  | ariaLabel | string | null | null | no |
@@ -159,7 +163,11 @@ An autocomplete component designed to work seamlessly with fui-form-field. Simil
159
163
  - **Import**: `import { FuiBreadcrumbComponent } from 'formaui/components/breadcrumb'`
160
164
  - **Selector**: `fui-breadcrumb`
161
165
 
162
- No public inputs or outputs.
166
+ #### Inputs
167
+
168
+ | Name | Type | Default | Required |
169
+ |------|------|---------|----------|
170
+ | aria-label | string | undefined | undefined | no |
163
171
 
164
172
  ### Sub-components
165
173
 
@@ -178,7 +186,7 @@ No public inputs or outputs.
178
186
 
179
187
  ## button
180
188
 
181
- A versatile button directive for triggering user actions. Supports multiple visual variants, sizes, loading states, and icon-only mode. Works on both `<button>` and `<a>` elements.
189
+ A versatile button directive that can be applied to both `<button>` and `<a>` elements. Follows Carbon Design System patterns with full accessibility support.
182
190
 
183
191
  - **Import**: `import { FuiButtonDirective } from 'formaui/components/button'`
184
192
  - **Selector**: `button[fuiButton], a[fuiButton]`
@@ -196,40 +204,6 @@ A versatile button directive for triggering user actions. Supports multiple visu
196
204
  | aria-label | string | null | null | no |
197
205
  | type | ButtonType | 'button' | no |
198
206
 
199
- ### Usage
200
-
201
- ```html
202
- <!-- Primary button -->
203
- <button fuiButton>Click me</button>
204
-
205
- <!-- Button with variant and size -->
206
- <button fuiButton variant="secondary" size="lg">Large Secondary</button>
207
-
208
- <!-- Danger button for destructive actions -->
209
- <button fuiButton variant="danger">Delete</button>
210
-
211
- <!-- Loading state -->
212
- <button fuiButton [loading]="isLoading">Save</button>
213
-
214
- <!-- Icon-only button -->
215
- <button fuiButton variant="icon" iconOnly aria-label="Settings">
216
- <fui-icon name="settings" />
217
- </button>
218
-
219
- <!-- Link button -->
220
- <a fuiButton variant="link" href="/dashboard">Go to Dashboard</a>
221
-
222
- <!-- Full-width button -->
223
- <button fuiButton fullWidth>Full Width Action</button>
224
- ```
225
-
226
- ### Notes
227
-
228
- - Use `variant="danger"` only for destructive actions (delete, remove, etc.)
229
- - Always provide `aria-label` on icon-only buttons for accessibility
230
- - The `loading` state automatically disables the button and shows a spinner
231
- - On `<a>` elements, the `disabled` state removes the `href` attribute
232
-
233
207
  ---
234
208
 
235
209
  ## button-group
@@ -329,6 +303,8 @@ A checkbox component with full Angular Reactive Forms support. Compatible with A
329
303
  | Name | Type | Default | Required |
330
304
  |------|------|---------|----------|
331
305
  | data | T[] | [] | no |
306
+ | tableAriaLabel | string | undefined | undefined | no |
307
+ | emptyMessage | string | undefined | undefined | no |
332
308
  | sort | { field: string; direction: 'ASC' | 'DESC' } | null | null | no |
333
309
  | filters | ColumnFilter[] | [] | no |
334
310
  | config | AdvancedDataTableConfig | - | yes |
@@ -410,29 +386,6 @@ A checkbox component with full Angular Reactive Forms support. Compatible with A
410
386
 
411
387
  ---
412
388
 
413
- ## dynamic-form
414
-
415
- A component that automatically renders forms based on a JSON configuration. It takes a FormGroup and a configuration object that specifies the form structure.
416
-
417
- - **Import**: `import { FuiDynamicFormRendererComponent } from 'formaui/components/dynamic-form'`
418
- - **Selector**: `fui-dynamic-form-renderer`
419
-
420
- #### Inputs
421
-
422
- | Name | Type | Default | Required |
423
- |------|------|---------|----------|
424
- | formGroup | FormGroup | - | yes |
425
- | config | DynamicFormConfig | - | yes |
426
-
427
- #### Outputs
428
-
429
- | Name | Type |
430
- |------|------|
431
- | autocompleteAction | DynamicFormAutocompleteEvent |
432
- | fileChange | DynamicFormFileEvent |
433
-
434
- ---
435
-
436
389
  ## empty-state
437
390
 
438
391
  - **Import**: `import { FuiEmptyStateComponent } from 'formaui/components/empty-state'`
@@ -477,7 +430,7 @@ A file upload component with drag-and-drop support, file previews, and validatio
477
430
 
478
431
  ## form-field
479
432
 
480
- A wrapper component that provides consistent layout, labeling, validation, and accessibility for form controls. Works with any component implementing the `FuiFormFieldControl` interface (select, input, date-picker, etc.).
433
+ A form field wrapper component that provides consistent styling and behavior for form controls. Follows Angular Material patterns with Carbon Design System styling.
481
434
 
482
435
  - **Import**: `import { FuiFormFieldComponent } from 'formaui/components/form-field'`
483
436
  - **Selector**: `fui-form-field`
@@ -488,33 +441,6 @@ A wrapper component that provides consistent layout, labeling, validation, and a
488
441
  |------|------|---------|----------|
489
442
  | appearance | FormFieldAppearance | 'outline' | no |
490
443
 
491
- ### Usage
492
-
493
- ```html
494
- <!-- Basic form field with input -->
495
- <fui-form-field>
496
- <fui-label>Email</fui-label>
497
- <input fuiInput type="email" [formControl]="emailControl" />
498
- <fui-hint>We'll never share your email</fui-hint>
499
- <fui-error>Please enter a valid email</fui-error>
500
- </fui-form-field>
501
-
502
- <!-- Form field with prefix and suffix -->
503
- <fui-form-field>
504
- <fui-label>Price</fui-label>
505
- <span fuiPrefix>$</span>
506
- <input fuiInput type="number" [formControl]="priceControl" />
507
- <span fuiSuffix>.00</span>
508
- </fui-form-field>
509
- ```
510
-
511
- ### Notes
512
-
513
- - `fui-error` is shown only when the form control is in an error state
514
- - `fui-hint` is hidden when an error is displayed
515
- - Use `fuiPrefix` and `fuiSuffix` directives on any element for adornments
516
- - The form field automatically associates the label with the control for accessibility
517
-
518
444
  ### Sub-components
519
445
 
520
446
  #### FuiErrorComponent
@@ -855,7 +781,7 @@ A progress bar component compatible with Angular Material's mat-progress-bar int
855
781
 
856
782
  ## select
857
783
 
858
- A dropdown select component for single or multiple selection. Designed to work inside `fui-form-field` with full Reactive Forms support, keyboard navigation, and type-ahead search.
784
+ A select component designed to work seamlessly with fui-form-field. Similar to Angular Material's mat-select integration with mat-form-field. Provides full Reactive Forms support with validation and error handling.
859
785
 
860
786
  - **Import**: `import { FuiSelectComponent } from 'formaui/components/select'`
861
787
  - **Selector**: `fui-select`
@@ -874,39 +800,6 @@ A dropdown select component for single or multiple selection. Designed to work i
874
800
  | selectionChange | FuiSelectChange |
875
801
  | openedChange | boolean |
876
802
 
877
- ### Usage
878
-
879
- ```html
880
- <!-- Basic select inside form-field -->
881
- <fui-form-field>
882
- <fui-label>Country</fui-label>
883
- <fui-select placeholder="Choose a country" [formControl]="countryControl">
884
- <fui-option value="us">United States</fui-option>
885
- <fui-option value="uk">United Kingdom</fui-option>
886
- <fui-option value="de">Germany</fui-option>
887
- </fui-select>
888
- <fui-error>Country is required</fui-error>
889
- </fui-form-field>
890
-
891
- <!-- Multiple selection -->
892
- <fui-form-field>
893
- <fui-label>Tags</fui-label>
894
- <fui-select multiple [formControl]="tagsControl">
895
- <fui-option value="angular">Angular</fui-option>
896
- <fui-option value="react">React</fui-option>
897
- <fui-option value="vue">Vue</fui-option>
898
- </fui-select>
899
- </fui-form-field>
900
- ```
901
-
902
- ### Notes
903
-
904
- - Always wrap in `fui-form-field` for label, error, and hint support
905
- - Options are projected as `<fui-option>` child elements
906
- - Supports keyboard navigation: Arrow keys, Home/End, Enter/Space, Escape
907
- - Type-ahead search: start typing to jump to matching options
908
- - Use `compareWith` input for custom object comparison
909
-
910
803
  ### Sub-components
911
804
 
912
805
  #### FuiOptionComponent
@@ -1031,6 +924,7 @@ A slider (range input) component with single and dual-thumb (range) support. Int
1031
924
  | value | number | 0 | no |
1032
925
  | size | FuiSpinnerSize | 'md' | no |
1033
926
  | color | string | null | null | no |
927
+ | aria-label | string | undefined | undefined | no |
1034
928
 
1035
929
  ---
1036
930
 
@@ -1204,6 +1098,8 @@ A top navigation toolbar following Carbon Design System principles. Provides spa
1204
1098
  | menuItems | FuiToolbarMenuItem[] | [] | no |
1205
1099
  | userProfile | FuiToolbarUserProfile | null | null | no |
1206
1100
  | activeMenuItemId | string | number | '' | no |
1101
+ | ariaLabel | string | undefined | undefined | no |
1102
+ | userAriaLabel | string | undefined | undefined | no |
1207
1103
 
1208
1104
  #### Outputs
1209
1105
 
@@ -1319,6 +1215,7 @@ A top navigation toolbar following Carbon Design System principles. Provides spa
1319
1215
  |------|------|---------|----------|
1320
1216
  | sort | { field: string; direction: 'ASC' | 'DESC' } | null | null | no |
1321
1217
  | filters | FuiTreeTableColumnFilter[] | [] | no |
1218
+ | emptyMessage | string | undefined | undefined | no |
1322
1219
  | config | FuiTreeTableConfig | - | yes |
1323
1220
 
1324
1221
  #### Outputs
@@ -1585,6 +1482,23 @@ A top navigation toolbar following Carbon Design System principles. Provides spa
1585
1482
  | --fui-state-info-bg | var(--fui-info-30) |
1586
1483
  | --fui-state-info-hover | var(--fui-info-110) |
1587
1484
 
1485
+ ### Destructive
1486
+
1487
+ | Token | Value |
1488
+ |-------|-------|
1489
+ | --fui-destructive-default | var(--fui-danger-90) |
1490
+ | --fui-destructive-hover | var(--fui-danger-100) |
1491
+ | --fui-destructive-text | white |
1492
+
1493
+ ### Tertiary
1494
+
1495
+ | Token | Value |
1496
+ |-------|-------|
1497
+ | --fui-tertiary-text | var(--fui-text-primary) |
1498
+ | --fui-tertiary-hover-bg | var(--fui-surface-03) |
1499
+ | --fui-tertiary-violet-text | var(--fui-primary) |
1500
+ | --fui-tertiary-violet-hover-bg | var(--fui-primary-bg) |
1501
+
1588
1502
  ### Field
1589
1503
 
1590
1504
  | Token | Value |
package/llms.txt CHANGED
@@ -15,7 +15,7 @@ npm install formaui
15
15
  - badge: No description available. `import { FuiBadgeComponent } from 'formaui/components/badge'`
16
16
  - big-menu: No description available. `import { FuiBigMenuComponent } from 'formaui/components/big-menu'`
17
17
  - breadcrumb: No description available. `import { FuiBreadcrumbComponent } from 'formaui/components/breadcrumb'`
18
- - button: A versatile button directive for triggering user actions. Supports multiple visual variants, sizes, loading states, and `import { FuiButtonDirective } from 'formaui/components/button'`
18
+ - button: A versatile button directive that can be applied to both `<button>` and `<a>` elements. Follows Carbon Design System pat `import { FuiButtonDirective } from 'formaui/components/button'`
19
19
  - button-group: A container component that groups multiple buttons together, creating a unified visual element with connected borders. F `import { FuiButtonGroupComponent } from 'formaui/components/button-group'`
20
20
  - card: A flexible container component following Carbon Design System patterns. Provides a structured layout with optional heade `import { FuiCardComponent } from 'formaui/components/card'`
21
21
  - checkbox: A checkbox component with full Angular Reactive Forms support. Compatible with Angular Material's mat-checkbox interface `import { FuiCheckboxComponent } from 'formaui/components/checkbox'`
@@ -23,10 +23,9 @@ npm install formaui
23
23
  - date-picker: No description available. `import { FuiDatePickerComponent } from 'formaui/components/date-picker'`
24
24
  - divider: No description available. `import { FuiDividerComponent } from 'formaui/components/divider'`
25
25
  - drawer: No description available. `import { FuiDrawerComponent } from 'formaui/components/drawer'`
26
- - dynamic-form: A component that automatically renders forms based on a JSON configuration. It takes a FormGroup and a configuration obj `import { FuiDynamicFormRendererComponent } from 'formaui/components/dynamic-form'`
27
26
  - empty-state: No description available. `import { FuiEmptyStateComponent } from 'formaui/components/empty-state'`
28
27
  - file-upload: A file upload component with drag-and-drop support, file previews, and validation. `import { FuiFileUploadComponent } from 'formaui/components/file-upload'`
29
- - form-field: A wrapper component that provides consistent layout, labeling, validation, and accessibility for form controls. Works wi `import { FuiFormFieldComponent } from 'formaui/components/form-field'`
28
+ - form-field: A form field wrapper component that provides consistent styling and behavior for form controls. Follows Angular Material `import { FuiFormFieldComponent } from 'formaui/components/form-field'`
30
29
  - icon: A wrapper component for Phosphor Icons with consistent sizing and styling. Provides easy access to the complete Phosphor `import { FuiIconComponent } from 'formaui/components/icon'`
31
30
  - input: An input directive that integrates seamlessly with fui-form-field and Angular Forms. Follows Angular Material patterns w `import { FuiInputDirective } from 'formaui/components/input'`
32
31
  - list: No description available. `import { FuiListComponent } from 'formaui/components/list'`
@@ -37,7 +36,7 @@ npm install formaui
37
36
  - popover: Internal popover container component rendered inside the overlay. Provides a styled panel with optional arrow indicator. `import { FuiPopoverComponent } from 'formaui/components/popover'`
38
37
  - progressbar: A progress bar component compatible with Angular Material's mat-progress-bar interface. `import { FuiProgressbarComponent } from 'formaui/components/progressbar'`
39
38
  - radio: No description available. `import { FuiRadioButtonComponent } from 'formaui/components/radio'`
40
- - select: A dropdown select component for single or multiple selection. Designed to work inside `fui-form-field` with full Reactiv `import { FuiSelectComponent } from 'formaui/components/select'`
39
+ - select: A select component designed to work seamlessly with fui-form-field. Similar to Angular Material's mat-select integration `import { FuiSelectComponent } from 'formaui/components/select'`
41
40
  - side-panel: No description available. `import { FuiSidePanelComponent } from 'formaui/components/side-panel'`
42
41
  - sidebar: A flexible sidebar component following Carbon Design System principles. Provides navigation with Angular Material-like A `import { FuiSidebarComponent } from 'formaui/components/sidebar'`
43
42
  - skeleton: No description available. `import { FuiSkeletonComponent } from 'formaui/components/skeleton'`
@@ -57,4 +56,4 @@ npm install formaui
57
56
  ## Design Tokens
58
57
 
59
58
  CSS custom properties prefixed with `--fui-*`. Themes: light (default), dark.
60
- Key token groups: primary, secondary, danger, success, warning, info, pink, orange, tomato, white, black, text, border, surface, bg, state, field, icon, background, error, card.
59
+ Key token groups: primary, secondary, danger, success, warning, info, pink, orange, tomato, white, black, text, border, surface, bg, state, destructive, tertiary, field, icon, background, error, card.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raintonic/formaui",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "A modern Angular UI component library with theming support",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -103,10 +103,6 @@
103
103
  "types": "./types/raintonic-formaui-components-drawer.d.ts",
104
104
  "default": "./fesm2022/raintonic-formaui-components-drawer.mjs"
105
105
  },
106
- "./components/dynamic-form": {
107
- "types": "./types/raintonic-formaui-components-dynamic-form.d.ts",
108
- "default": "./fesm2022/raintonic-formaui-components-dynamic-form.mjs"
109
- },
110
106
  "./components/empty-state": {
111
107
  "types": "./types/raintonic-formaui-components-empty-state.d.ts",
112
108
  "default": "./fesm2022/raintonic-formaui-components-empty-state.mjs"