@raintonic/formaui 0.3.1 → 0.9.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.
- package/CHANGELOG.md +80 -35
- package/README.md +22 -26
- package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs +39 -41
- package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-cdk-form-field.mjs +207 -3
- package/fesm2022/raintonic-formaui-cdk-form-field.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-cdk-overlay.mjs +27 -2
- package/fesm2022/raintonic-formaui-cdk-overlay.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs +5 -12
- package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-accordion.mjs +8 -5
- package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-alert.mjs +16 -2
- package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs +255 -462
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-avatar.mjs +34 -59
- package/fesm2022/raintonic-formaui-components-avatar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-badge.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-badge.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-breadcrumb.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-breadcrumb.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-button-group.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-button-group.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-button.mjs +15 -20
- package/fesm2022/raintonic-formaui-components-button.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-card.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-card.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-checkbox.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-checkbox.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-chip.mjs +97 -0
- package/fesm2022/raintonic-formaui-components-chip.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-data-table.mjs +69 -29
- package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-date-picker.mjs +223 -144
- package/fesm2022/raintonic-formaui-components-date-picker.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-divider.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-divider.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-drawer.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-drawer.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-dropdown-menu.mjs +888 -0
- package/fesm2022/raintonic-formaui-components-dropdown-menu.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-dual-tier-navigation.mjs +774 -0
- package/fesm2022/raintonic-formaui-components-dual-tier-navigation.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-empty-state.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-empty-state.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-file-upload.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-file-upload.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-form-field.mjs +81 -50
- package/fesm2022/raintonic-formaui-components-form-field.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-icon.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-icon.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-input.mjs +47 -12
- package/fesm2022/raintonic-formaui-components-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-list.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-list.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-number-input.mjs +20 -12
- package/fesm2022/raintonic-formaui-components-number-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-paginator.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-paginator.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-password-input.mjs +35 -110
- package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-popover.mjs +3 -2
- package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-progressbar.mjs +3 -2
- package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-radio.mjs +5 -6
- package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-select.mjs +257 -412
- package/fesm2022/raintonic-formaui-components-select.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-side-panel.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-side-panel.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-sidebar-nav-menu.mjs +525 -0
- package/fesm2022/raintonic-formaui-components-sidebar-nav-menu.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-skeleton.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-skeleton.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-slider.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-slider.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-spinner.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-spinner.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-stepper.mjs +50 -45
- package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-strength-meter.mjs +149 -0
- package/fesm2022/raintonic-formaui-components-strength-meter.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tab.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-tab.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-time-picker.mjs +194 -154
- package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-toggle-group.mjs +302 -0
- package/fesm2022/raintonic-formaui-components-toggle-group.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-toggle.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-toggle.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-toolbar.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-toolbar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tooltip.mjs +10 -4
- package/fesm2022/raintonic-formaui-components-tooltip.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-topbar.mjs +60 -0
- package/fesm2022/raintonic-formaui-components-topbar.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-components-tree-select.mjs +59 -69
- package/fesm2022/raintonic-formaui-components-tree-select.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tree-table.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-tree-table.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tree.mjs +31 -5
- package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-core.mjs +279 -1
- package/fesm2022/raintonic-formaui-core.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-services-breakpoint.mjs +93 -0
- package/fesm2022/raintonic-formaui-services-breakpoint.mjs.map +1 -0
- package/fesm2022/raintonic-formaui-services-dialog.mjs +314 -16
- package/fesm2022/raintonic-formaui-services-dialog.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-services-notification.mjs +93 -29
- package/fesm2022/raintonic-formaui-services-notification.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-services-theme.mjs +46 -196
- package/fesm2022/raintonic-formaui-services-theme.mjs.map +1 -1
- package/fesm2022/raintonic-formaui.mjs +1 -1
- package/fesm2022/raintonic-formaui.mjs.map +1 -1
- package/llms-full.txt +2329 -450
- package/llms.txt +36 -33
- package/package.json +42 -19
- package/styles/fonts/Geist-Bold.woff2 +0 -0
- package/styles/fonts/Geist-Italic.woff2 +0 -0
- package/styles/fonts/Geist-Light.woff2 +0 -0
- package/styles/fonts/Geist-Medium.woff2 +0 -0
- package/styles/fonts/Geist-Regular.woff2 +0 -0
- package/styles/fonts/Geist-SemiBold.woff2 +0 -0
- package/styles/fonts/GeistMono-Regular.woff2 +0 -0
- package/styles/generated/_tokens.scss +906 -0
- package/styles/index.scss +11 -10
- package/styles/partials/_brand.scss +46 -0
- package/styles/partials/_constants.scss +22 -20
- package/styles/partials/_fonts.scss +54 -10
- package/styles/partials/_grid.scss +29 -18
- package/styles/partials/_mixins.scss +69 -27
- package/styles/partials/_motion.scss +28 -33
- package/styles/partials/_theme.scss +28 -255
- package/styles/partials/_type.scss +117 -0
- package/styles/partials/_typography.scss +45 -45
- package/styles/partials/_utilities.scss +198 -98
- package/styles/partials/components/_button.scss +144 -75
- package/styles/partials/components/_dialog.scss +181 -180
- package/styles/partials/components/_overlay.scss +87 -87
- package/styles/partials/themes/_dark.scss +3 -268
- package/styles/partials/themes/_light.scss +4 -268
- package/styles/styles.css +7744 -0
- package/styles/styles.entry.scss +3 -0
- package/styles/utilities.css +4802 -0
- package/styles/utilities.entry.scss +3 -0
- package/types/raintonic-formaui-cdk-drag-drop.d.ts +0 -1
- package/types/raintonic-formaui-cdk-drag-drop.d.ts.map +1 -1
- package/types/raintonic-formaui-cdk-form-field.d.ts +118 -2
- package/types/raintonic-formaui-cdk-form-field.d.ts.map +1 -1
- package/types/raintonic-formaui-cdk-overlay.d.ts +2 -0
- package/types/raintonic-formaui-cdk-overlay.d.ts.map +1 -1
- package/types/raintonic-formaui-cdk-virtual-scroll.d.ts +0 -1
- package/types/raintonic-formaui-cdk-virtual-scroll.d.ts.map +1 -1
- package/types/raintonic-formaui-components-accordion.d.ts +1 -1
- package/types/raintonic-formaui-components-accordion.d.ts.map +1 -1
- package/types/raintonic-formaui-components-alert.d.ts +6 -1
- package/types/raintonic-formaui-components-alert.d.ts.map +1 -1
- package/types/raintonic-formaui-components-autocomplete.d.ts +73 -116
- package/types/raintonic-formaui-components-autocomplete.d.ts.map +1 -1
- package/types/raintonic-formaui-components-avatar.d.ts +13 -31
- package/types/raintonic-formaui-components-avatar.d.ts.map +1 -1
- package/types/raintonic-formaui-components-button.d.ts +4 -10
- package/types/raintonic-formaui-components-button.d.ts.map +1 -1
- package/types/raintonic-formaui-components-chip.d.ts +43 -0
- package/types/raintonic-formaui-components-chip.d.ts.map +1 -0
- package/types/raintonic-formaui-components-data-table.d.ts +48 -11
- package/types/raintonic-formaui-components-data-table.d.ts.map +1 -1
- package/types/raintonic-formaui-components-date-picker.d.ts +59 -23
- package/types/raintonic-formaui-components-date-picker.d.ts.map +1 -1
- package/types/raintonic-formaui-components-dropdown-menu.d.ts +394 -0
- package/types/raintonic-formaui-components-dropdown-menu.d.ts.map +1 -0
- package/types/raintonic-formaui-components-dual-tier-navigation.d.ts +87 -0
- package/types/raintonic-formaui-components-dual-tier-navigation.d.ts.map +1 -0
- package/types/raintonic-formaui-components-form-field.d.ts +51 -21
- package/types/raintonic-formaui-components-form-field.d.ts.map +1 -1
- package/types/raintonic-formaui-components-input.d.ts +20 -11
- package/types/raintonic-formaui-components-input.d.ts.map +1 -1
- package/types/raintonic-formaui-components-number-input.d.ts +5 -3
- package/types/raintonic-formaui-components-number-input.d.ts.map +1 -1
- package/types/raintonic-formaui-components-password-input.d.ts +18 -32
- package/types/raintonic-formaui-components-password-input.d.ts.map +1 -1
- package/types/raintonic-formaui-components-popover.d.ts.map +1 -1
- package/types/raintonic-formaui-components-progressbar.d.ts +1 -1
- package/types/raintonic-formaui-components-progressbar.d.ts.map +1 -1
- package/types/raintonic-formaui-components-radio.d.ts +1 -2
- package/types/raintonic-formaui-components-radio.d.ts.map +1 -1
- package/types/raintonic-formaui-components-select.d.ts +107 -76
- package/types/raintonic-formaui-components-select.d.ts.map +1 -1
- package/types/raintonic-formaui-components-sidebar-nav-menu.d.ts +223 -0
- package/types/raintonic-formaui-components-sidebar-nav-menu.d.ts.map +1 -0
- package/types/raintonic-formaui-components-stepper.d.ts +4 -2
- package/types/raintonic-formaui-components-stepper.d.ts.map +1 -1
- package/types/raintonic-formaui-components-strength-meter.d.ts +78 -0
- package/types/raintonic-formaui-components-strength-meter.d.ts.map +1 -0
- package/types/raintonic-formaui-components-time-picker.d.ts +44 -24
- package/types/raintonic-formaui-components-time-picker.d.ts.map +1 -1
- package/types/raintonic-formaui-components-toggle-group.d.ts +100 -0
- package/types/raintonic-formaui-components-toggle-group.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tooltip.d.ts +2 -1
- package/types/raintonic-formaui-components-tooltip.d.ts.map +1 -1
- package/types/raintonic-formaui-components-topbar.d.ts +48 -0
- package/types/raintonic-formaui-components-topbar.d.ts.map +1 -0
- package/types/raintonic-formaui-components-tree-select.d.ts +25 -9
- package/types/raintonic-formaui-components-tree-select.d.ts.map +1 -1
- package/types/raintonic-formaui-components-tree.d.ts +12 -1
- package/types/raintonic-formaui-components-tree.d.ts.map +1 -1
- package/types/raintonic-formaui-core.d.ts +243 -5
- package/types/raintonic-formaui-core.d.ts.map +1 -1
- package/types/raintonic-formaui-services-breakpoint.d.ts +44 -0
- package/types/raintonic-formaui-services-breakpoint.d.ts.map +1 -0
- package/types/raintonic-formaui-services-dialog.d.ts +141 -2
- package/types/raintonic-formaui-services-dialog.d.ts.map +1 -1
- package/types/raintonic-formaui-services-notification.d.ts +24 -2
- package/types/raintonic-formaui-services-notification.d.ts.map +1 -1
- package/types/raintonic-formaui-services-theme.d.ts +13 -103
- package/types/raintonic-formaui-services-theme.d.ts.map +1 -1
- package/types/raintonic-formaui.d.ts +1 -1
- package/fesm2022/raintonic-formaui-components-big-menu.mjs +0 -86
- package/fesm2022/raintonic-formaui-components-big-menu.mjs.map +0 -1
- package/fesm2022/raintonic-formaui-components-menu.mjs +0 -896
- package/fesm2022/raintonic-formaui-components-menu.mjs.map +0 -1
- package/fesm2022/raintonic-formaui-components-sidebar.mjs +0 -275
- package/fesm2022/raintonic-formaui-components-sidebar.mjs.map +0 -1
- package/fesm2022/raintonic-formaui-components-tag.mjs +0 -95
- package/fesm2022/raintonic-formaui-components-tag.mjs.map +0 -1
- package/styles/_fonts-entry.scss +0 -3
- package/styles/fonts/inter-tight-latin-italic.woff2 +0 -0
- package/styles/fonts/inter-tight-latin.woff2 +0 -0
- package/types/raintonic-formaui-components-big-menu.d.ts +0 -73
- package/types/raintonic-formaui-components-big-menu.d.ts.map +0 -1
- package/types/raintonic-formaui-components-menu.d.ts +0 -403
- package/types/raintonic-formaui-components-menu.d.ts.map +0 -1
- package/types/raintonic-formaui-components-sidebar.d.ts +0 -185
- package/types/raintonic-formaui-components-sidebar.d.ts.map +0 -1
- package/types/raintonic-formaui-components-tag.d.ts +0 -43
- package/types/raintonic-formaui-components-tag.d.ts.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-menu.mjs","sources":["../../../lib/components/menu/menu-item.component.ts","../../../lib/components/menu/menu-item.component.html","../../../lib/components/menu/menu.component.ts","../../../lib/components/menu/menu.component.html","../../../lib/components/menu/menu-trigger.directive.ts","../../../lib/components/menu/index.ts","../../../lib/components/menu/raintonic-formaui-components-menu.ts"],"sourcesContent":["import {\r\n Component,\r\n ElementRef,\r\n HostListener,\r\n Renderer2,\r\n computed,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n booleanAttribute,\r\n} from '@angular/core';\r\n\r\n/**\r\n * Available menu item variants\r\n */\r\nexport type MenuItemVariant = 'default' | 'danger';\r\n\r\nexport const MENU_ITEM_VARIANTS = ['default', 'danger'] as const;\r\n\r\n/**\r\n * # FuiMenuItem Component\r\n *\r\n * A menu item component designed to be used within fui-menu.\r\n * Provides consistent styling and behavior for menu options.\r\n *\r\n * ## Features\r\n * - Default and danger variants\r\n * - Full accessibility support (ARIA attributes, keyboard navigation)\r\n * - Icon support with proper spacing\r\n * - Disabled state support\r\n * - Hover and focus states\r\n * - Keyboard activation (Enter and Space)\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Menu Item\r\n * ```html\r\n * <fui-menu-item>Profile</fui-menu-item>\r\n * ```\r\n *\r\n * ### Menu Item with Icon\r\n * ```html\r\n * <fui-menu-item>\r\n * <fui-icon name=\"user\" fuiPrefix></fui-icon>\r\n * Profile\r\n * </fui-menu-item>\r\n * ```\r\n *\r\n * ### Danger Menu Item\r\n * ```html\r\n * <fui-menu-item variant=\"danger\">\r\n * <fui-icon name=\"trash\" fuiPrefix></fui-icon>\r\n * Delete Account\r\n * </fui-menu-item>\r\n * ```\r\n *\r\n * ### Disabled Menu Item\r\n * ```html\r\n * <fui-menu-item [disabled]=\"true\">\r\n * Unavailable Option\r\n * </fui-menu-item>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiMenuItemComponent } from '@raintonic/formaui/components/menu';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiMenuItemComponent],\r\n * templateUrl: './my-component.component.html',\r\n * styleUrl: './my-component.component.scss'\r\n * })\r\n * export class MyComponent {\r\n * onItemClick(event: Event) {\r\n * console.log('Menu item clicked:', event);\r\n * }\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-menu-item',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './menu-item.component.html',\r\n styleUrl: './menu-item.component.scss',\r\n host: {\r\n '[class]': 'computedClasses()',\r\n '[attr.role]': '\"menuitem\"',\r\n '[attr.tabindex]': 'disabled() ? \"-1\" : tabIndex()',\r\n '[attr.aria-disabled]': 'disabled() ? \"true\" : null',\r\n },\r\n})\r\nexport class FuiMenuItemComponent {\r\n /**\r\n * Menu item variant that determines the visual style\r\n * @default 'default'\r\n */\r\n readonly variant = input<MenuItemVariant, MenuItemVariant | string>('default', {\r\n transform: (v) => ((MENU_ITEM_VARIANTS as readonly string[]).includes(v) ? (v as MenuItemVariant) : 'default'),\r\n });\r\n\r\n /**\r\n * Whether the menu item is disabled\r\n * @default false\r\n */\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n\r\n /**\r\n * Emitted when the menu item is clicked or activated\r\n */\r\n readonly selected = output<Event>();\r\n\r\n /**\r\n * Internal tabindex for roving tabindex pattern.\r\n * Managed by the parent FuiMenuComponent.\r\n * @internal\r\n */\r\n readonly tabIndex = signal('-1');\r\n\r\n // Computed properties\r\n readonly computedClasses = computed(() => {\r\n const classes: string[] = ['fui-menu-item', `fui-menu-item--${this.variant()}`];\r\n\r\n if (this.disabled()) {\r\n classes.push('fui-menu-item--disabled');\r\n }\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n /** @internal */ readonly _elementRef: ElementRef<HTMLElement> = inject(ElementRef);\r\n private readonly _renderer: Renderer2 = inject(Renderer2);\r\n\r\n @HostListener('click', ['$event'])\r\n onClick(event: Event): void {\r\n if (this.disabled()) {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n return;\r\n }\r\n\r\n this.selected.emit(event);\r\n }\r\n\r\n @HostListener('keydown', ['$event'])\r\n onKeydown(event: KeyboardEvent): void {\r\n if (this.disabled()) {\r\n return;\r\n }\r\n\r\n switch (event.key) {\r\n case 'Enter':\r\n case ' ':\r\n event.preventDefault();\r\n // Dispatch a synthetic click so the parent menu's click handler\r\n // can detect the activation and close the menu.\r\n this._elementRef.nativeElement.click();\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Focuses the menu item\r\n */\r\n focus(): void {\r\n this._elementRef.nativeElement.focus();\r\n }\r\n}\r\n","<ng-content></ng-content>\r\n","import {\r\n booleanAttribute,\r\n Component,\r\n computed,\r\n contentChildren,\r\n effect,\r\n ElementRef,\r\n HostListener,\r\n inject,\r\n NgZone,\r\n input,\r\n OnDestroy,\r\n output,\r\n signal,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport { FuiMenuItemComponent } from './menu-item.component';\r\n\r\nimport { DOCUMENT } from '@angular/common';\r\nimport { fromEvent, Subscription } from 'rxjs';\r\nimport { filter } from 'rxjs/operators';\r\nimport { FuiConnectedPosition, FuiOverlayRef, FuiOverlayService } from '@raintonic/formaui/cdk/overlay';\r\n\r\n/**\r\n * Available menu positions relative to the trigger element\r\n */\r\nexport type FuiMenuPosition =\r\n | 'top-start'\r\n | 'top'\r\n | 'top-end'\r\n | 'bottom-start'\r\n | 'bottom'\r\n | 'bottom-end'\r\n | 'left-start'\r\n | 'left'\r\n | 'left-end'\r\n | 'right-start'\r\n | 'right'\r\n | 'right-end';\r\n\r\nexport const RT_MENU_POSITIONS = [\r\n 'top-start',\r\n 'top',\r\n 'top-end',\r\n 'bottom-start',\r\n 'bottom',\r\n 'bottom-end',\r\n 'left-start',\r\n 'left',\r\n 'left-end',\r\n 'right-start',\r\n 'right',\r\n 'right-end',\r\n] as const;\r\n\r\n/**\r\n * Available menu sizes\r\n */\r\nexport type FuiMenuSize = 'sm' | 'md' | 'lg';\r\n\r\nexport const RT_MENU_SIZES = ['sm', 'md', 'lg'] as const;\r\n\r\n/**\r\n * # FuiMenu Component\r\n *\r\n * A dropdown menu component that provides a list of options or actions.\r\n * Designed to work with external triggers using the fuiMenuTrigger directive.\r\n *\r\n * ## Features\r\n * - Multiple positioning options relative to trigger\r\n * - Keyboard navigation (Arrow keys, Enter, Escape)\r\n * - Click outside to close\r\n * - Full accessibility support (ARIA attributes, focus management)\r\n * - Customizable size variants\r\n * - Auto-positioning with collision detection\r\n * - Portal attachment to document body to avoid clipping issues\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Menu with External Trigger\r\n * ```html\r\n * <button fuiButton fuiMenuTrigger [fuiMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-menu #menu>\r\n * <fui-menu-item>Option 1</fui-menu-item>\r\n * <fui-menu-item>Option 2</fui-menu-item>\r\n * </fui-menu>\r\n * ```\r\n *\r\n * ### Menu with Custom Position\r\n * ```html\r\n * <button fuiButton fuiMenuTrigger [fuiMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-menu #menu position=\"top-start\" size=\"lg\">\r\n * <fui-menu-item>Profile</fui-menu-item>\r\n * <fui-menu-item variant=\"danger\">Logout</fui-menu-item>\r\n * </fui-menu>\r\n * ```\r\n *\r\n * ### Menu without Portal (for special cases)\r\n * ```html\r\n * <button fuiButton fuiMenuTrigger [fuiMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-menu #menu [attachToBody]=\"false\">\r\n * <fui-menu-item>Option 1</fui-menu-item>\r\n * <fui-menu-item>Option 2</fui-menu-item>\r\n * </fui-menu>\r\n * ```\r\n *\r\n * ### Menu with Data Passed from Trigger\r\n * ```html\r\n * <button fuiButton fuiMenuTrigger\r\n * [fuiMenuTriggerFor]=\"dynamicMenu\"\r\n * [menuTriggerData]=\"{ user: currentUser, items: menuItems }\">\r\n * Open Menu\r\n * </button>\r\n * <fui-menu #dynamicMenu>\r\n * <!-- Access data in component using menu.menuData() -->\r\n * </fui-menu>\r\n * ```\r\n *\r\n * ```typescript\r\n * @Component({\r\n * template: `\r\n * <fui-menu #menu>\r\n * <fui-menu-item *ngFor=\"let item of menu.menuData()?.items\">\r\n * {{ item.label }}\r\n * </fui-menu-item>\r\n * </fui-menu>\r\n * `\r\n * })\r\n * export class MyComponent { }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-menu',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './menu.component.html',\r\n styleUrl: './menu.component.scss',\r\n host: {\r\n '[class]': 'computedClasses()',\r\n '[attr.data-open]': 'isOpen() ? \"true\" : null',\r\n },\r\n})\r\nexport class FuiMenuComponent implements OnDestroy {\r\n /**\r\n * Menu position relative to the trigger element\r\n * @default 'bottom-start'\r\n */\r\n readonly position = input<FuiMenuPosition>('bottom-start');\r\n\r\n /**\r\n * Menu size variant\r\n * @default 'md'\r\n */\r\n readonly size = input<FuiMenuSize>('md');\r\n\r\n /**\r\n * Whether the menu should close when clicking outside\r\n * @default true\r\n */\r\n readonly closeOnClickOutside = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n /**\r\n * Whether the menu should close when pressing Escape\r\n * @default true\r\n */\r\n readonly closeOnEscape = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n /**\r\n * Whether the menu is disabled\r\n * @default false\r\n */\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n\r\n /**\r\n * Whether to attach the menu panel to the document body to avoid clipping issues\r\n * @default true\r\n */\r\n readonly attachToBody = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n /**\r\n * Emitted when the menu open state changes\r\n */\r\n readonly openChange = output<boolean>();\r\n\r\n /**\r\n * Emitted when a menu item is selected\r\n */\r\n readonly itemSelected = output<Event>();\r\n\r\n // Internal state\r\n protected readonly _isOpen = signal(false);\r\n protected readonly _animationState = signal<'void' | 'enter' | 'leave'>('void');\r\n private readonly _triggerElement = signal<HTMLElement | null>(null);\r\n private readonly _menuData = signal<unknown>(null);\r\n private _previousFocusedElement: HTMLElement | null = null;\r\n private _overlayRef: FuiOverlayRef | null = null;\r\n private _overlaySubscriptions = new Subscription();\r\n private _closeAnimationTimeout: number | null = null;\r\n\r\n // Computed properties\r\n readonly computedClasses = computed(() => {\r\n const classes: string[] = ['fui-menu', `fui-menu--${this.position()}`, `fui-menu--${this.size()}`];\r\n\r\n if (this.disabled()) {\r\n classes.push('fui-menu--disabled');\r\n }\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n // Injected dependencies\r\n private readonly _elementRef: ElementRef<HTMLElement> = inject(ElementRef);\r\n private readonly _overlayService: FuiOverlayService = inject(FuiOverlayService);\r\n private readonly _document = inject(DOCUMENT);\r\n private readonly _ngZone = inject(NgZone);\r\n private _outsideClickSub?: Subscription;\r\n\r\n // View references\r\n @ViewChild('menuPanel', { static: false }) menuPanel?: ElementRef<HTMLElement>;\r\n\r\n // Content children for roving tabindex management\r\n private readonly _menuItems = contentChildren(FuiMenuItemComponent, { descendants: true });\r\n\r\n constructor() {\r\n // Handle open state changes with animation\r\n effect(() => {\r\n if (this._isOpen()) {\r\n requestAnimationFrame(() => {\r\n this._animationState.set('enter');\r\n this._openMenu();\r\n });\r\n } else {\r\n this._startCloseAnimation();\r\n }\r\n });\r\n\r\n // Emit open change events\r\n effect(() => {\r\n this.openChange.emit(this._isOpen());\r\n });\r\n }\r\n\r\n /**\r\n * Whether the menu is currently open\r\n */\r\n isOpen(): boolean {\r\n return this._isOpen();\r\n }\r\n\r\n /**\r\n * Opens the menu\r\n */\r\n open(): void {\r\n if (this.disabled()) return;\r\n this._isOpen.set(true);\r\n }\r\n\r\n /**\r\n * Closes the menu\r\n */\r\n close(): void {\r\n this._isOpen.set(false);\r\n }\r\n\r\n /**\r\n * Toggles the menu open/closed state\r\n */\r\n toggle(): void {\r\n if (this._isOpen()) {\r\n this.close();\r\n } else {\r\n this.open();\r\n }\r\n }\r\n\r\n /**\r\n * Sets the trigger element for positioning (called by trigger directive)\r\n */\r\n setTriggerElement(element: HTMLElement): void {\r\n this._triggerElement.set(element);\r\n }\r\n\r\n /**\r\n * Gets the menu data passed from the trigger\r\n * Returns a signal containing the data\r\n */\r\n menuData(): unknown {\r\n return this._menuData();\r\n }\r\n\r\n /**\r\n * Sets the menu data (called by trigger directive)\r\n * @param data The data to pass to the menu\r\n */\r\n setMenuData(data: unknown): void {\r\n this._menuData.set(data);\r\n }\r\n\r\n // Start listening for outside clicks when menu opens\r\n private _listenForOutsideClicks(): void {\r\n this._outsideClickSub?.unsubscribe();\r\n\r\n if (!this.closeOnClickOutside()) return;\r\n\r\n this._ngZone.runOutsideAngular(() => {\r\n setTimeout(() => {\r\n this._outsideClickSub = fromEvent<MouseEvent>(this._document, 'click')\r\n .pipe(\r\n filter(() => this._isOpen()),\r\n filter((event) => {\r\n const target = event.target as HTMLElement;\r\n const menuElement = this._elementRef.nativeElement;\r\n const triggerElement = this._triggerElement();\r\n return !menuElement.contains(target) && !triggerElement?.contains(target);\r\n }),\r\n )\r\n .subscribe(() => {\r\n this._ngZone.run(() => {\r\n this.close();\r\n });\r\n });\r\n });\r\n });\r\n }\r\n\r\n @HostListener('document:keydown', ['$event'])\r\n onDocumentKeydown(event: KeyboardEvent): void {\r\n if (!this._isOpen() || !this._isTopmostOverlay()) {\r\n return;\r\n }\r\n\r\n switch (event.key) {\r\n case 'Escape':\r\n if (this.closeOnEscape()) {\r\n event.preventDefault();\r\n this.close();\r\n }\r\n break;\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this._focusNextItem();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this._focusPreviousItem();\r\n break;\r\n case 'Home':\r\n event.preventDefault();\r\n this._focusFirstItem();\r\n break;\r\n case 'End':\r\n event.preventDefault();\r\n this._focusLastItem();\r\n break;\r\n }\r\n }\r\n\r\n @HostListener('click', ['$event'])\r\n onMenuClick(event: Event): void {\r\n // Check if the click was on a menu item\r\n const target = event.target as HTMLElement;\r\n const menuItem = target.closest('fui-menu-item');\r\n\r\n if (menuItem && this._isOpen()) {\r\n // Emit the itemSelected event and close the menu\r\n this.itemSelected.emit(event);\r\n this.close();\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this._clearCloseTimeout();\r\n this._outsideClickSub?.unsubscribe();\r\n this._restoreFocus();\r\n this._disposeOverlay();\r\n }\r\n\r\n private _openMenu(): void {\r\n // Create overlay after the view updates\r\n requestAnimationFrame(() => {\r\n this._createOverlay();\r\n this._listenForOutsideClicks();\r\n\r\n const triggerElement = this._triggerElement();\r\n if (triggerElement) {\r\n triggerElement.setAttribute('aria-expanded', 'true');\r\n this._previousFocusedElement = document.activeElement as HTMLElement;\r\n }\r\n });\r\n }\r\n\r\n private _closeMenu(): void {\r\n this._outsideClickSub?.unsubscribe();\r\n const triggerElement = this._triggerElement();\r\n if (triggerElement) {\r\n triggerElement.setAttribute('aria-expanded', 'false');\r\n }\r\n\r\n // Reset roving tabindex on all items\r\n this._resetRovingTabindex();\r\n\r\n this._disposeOverlay();\r\n this._restoreFocus();\r\n }\r\n\r\n private _createOverlay(): void {\r\n if (this._overlayRef || !this.menuPanel) {\r\n return;\r\n }\r\n\r\n const triggerElement = this._triggerElement();\r\n if (!triggerElement) {\r\n return;\r\n }\r\n\r\n // Create overlay with positioning strategy\r\n const positions = this._getPositionsForMenuPosition(this.position());\r\n const positionStrategy = this._overlayService\r\n .position()\r\n .connectedTo(triggerElement, positions)\r\n .withPush(true)\r\n .withViewportMargin(8);\r\n\r\n // Create overlay\r\n this._overlayRef = this._overlayService.create({\r\n positionStrategy,\r\n scrollStrategy: this.closeOnClickOutside()\r\n ? this._overlayService.scrollStrategies.close()\r\n : this._overlayService.scrollStrategies.reposition(),\r\n hasBackdrop: this.closeOnClickOutside(),\r\n backdropClass: 'fui-menu-backdrop',\r\n backdropClickBehavior: 'close',\r\n panelClass: ['fui-menu-panel', `fui-menu-panel--${this.size()}`],\r\n });\r\n\r\n // Track overlay subscriptions for proper cleanup\r\n this._overlaySubscriptions.unsubscribe();\r\n this._overlaySubscriptions = new Subscription();\r\n\r\n if (this.closeOnClickOutside()) {\r\n this._overlaySubscriptions.add(\r\n this._overlayRef.backdropClick.subscribe(() => {\r\n this.close();\r\n }),\r\n );\r\n }\r\n\r\n if (this.closeOnEscape()) {\r\n this._overlaySubscriptions.add(\r\n this._overlayRef.keydownEvents.subscribe((event) => {\r\n if (event.key === 'Escape') {\r\n this.close();\r\n }\r\n }),\r\n );\r\n }\r\n\r\n // Attach menu panel to overlay\r\n const menuElement = this.menuPanel.nativeElement;\r\n this._overlayRef.attach(menuElement);\r\n\r\n // Focus first item after attachment\r\n setTimeout(() => {\r\n this._focusFirstItem();\r\n }, 0);\r\n }\r\n\r\n private _getPositionsForMenuPosition(position: FuiMenuPosition): FuiConnectedPosition[] {\r\n const offset = 4;\r\n\r\n switch (position) {\r\n case 'bottom-start':\r\n return [\r\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset },\r\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset },\r\n ];\r\n case 'bottom':\r\n return [\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: offset },\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -offset },\r\n ];\r\n case 'bottom-end':\r\n return [\r\n { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: offset },\r\n { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -offset },\r\n ];\r\n case 'top-start':\r\n return [\r\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -offset },\r\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset },\r\n ];\r\n case 'top':\r\n return [\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -offset },\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: offset },\r\n ];\r\n case 'top-end':\r\n return [\r\n { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -offset },\r\n { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: offset },\r\n ];\r\n case 'right-start':\r\n return [\r\n { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: offset },\r\n { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -offset },\r\n ];\r\n case 'right':\r\n return [\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: offset },\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -offset },\r\n ];\r\n case 'right-end':\r\n return [\r\n { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', offsetX: offset },\r\n { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -offset },\r\n ];\r\n case 'left-start':\r\n return [\r\n { originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top', offsetX: -offset },\r\n { originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top', offsetX: offset },\r\n ];\r\n case 'left':\r\n return [\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -offset },\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: offset },\r\n ];\r\n case 'left-end':\r\n return [\r\n { originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom', offsetX: -offset },\r\n { originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom', offsetX: offset },\r\n ];\r\n default:\r\n return [{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: offset }];\r\n }\r\n }\r\n\r\n private _restoreFocus(): void {\r\n // Prefer the trigger element for focus restoration\r\n const triggerElement = this._triggerElement();\r\n if (triggerElement) {\r\n triggerElement.focus();\r\n } else if (this._previousFocusedElement) {\r\n this._previousFocusedElement.focus();\r\n }\r\n this._previousFocusedElement = null;\r\n }\r\n\r\n private _getMenuItems(): HTMLElement[] {\r\n const menuElement = this.menuPanel?.nativeElement;\r\n if (!menuElement) return [];\r\n\r\n return Array.from(menuElement.querySelectorAll('fui-menu-item:not([aria-disabled=\"true\"])'));\r\n }\r\n\r\n /** @internal Called by FuiMenuTriggerDirective */\r\n _focusFirstItem(): void {\r\n const items = this._getMenuItems();\r\n if (items.length > 0) {\r\n this._focusItem(items[0]);\r\n }\r\n }\r\n\r\n /** @internal Called by FuiMenuTriggerDirective */\r\n _focusLastItem(): void {\r\n const items = this._getMenuItems();\r\n if (items.length > 0) {\r\n this._focusItem(items[items.length - 1]);\r\n }\r\n }\r\n\r\n private _focusNextItem(): void {\r\n const items = this._getMenuItems();\r\n if (items.length === 0) {\r\n return;\r\n }\r\n\r\n const currentIndex = items.findIndex((item) => item === document.activeElement);\r\n const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\r\n this._focusItem(items[nextIndex]);\r\n }\r\n\r\n private _focusPreviousItem(): void {\r\n const items = this._getMenuItems();\r\n if (items.length === 0) {\r\n return;\r\n }\r\n\r\n const currentIndex = items.findIndex((item) => item === document.activeElement);\r\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\r\n this._focusItem(items[prevIndex]);\r\n }\r\n\r\n /**\r\n * Focuses a menu item and updates roving tabindex across all items.\r\n */\r\n private _focusItem(element: HTMLElement): void {\r\n this._updateRovingTabindex(element);\r\n element.focus();\r\n }\r\n\r\n /**\r\n * Resets all items to tabindex=\"-1\" when the menu closes.\r\n */\r\n private _resetRovingTabindex(): void {\r\n const items = this._menuItems();\r\n for (const item of items) {\r\n item.tabIndex.set('-1');\r\n }\r\n }\r\n\r\n /**\r\n * Updates roving tabindex: sets tabindex=\"0\" on the target item\r\n * and tabindex=\"-1\" on all other items.\r\n */\r\n private _updateRovingTabindex(targetElement: HTMLElement): void {\r\n const items = this._menuItems();\r\n for (const item of items) {\r\n if (item._elementRef.nativeElement === targetElement) {\r\n item.tabIndex.set('0');\r\n } else {\r\n item.tabIndex.set('-1');\r\n }\r\n }\r\n }\r\n\r\n private _disposeOverlay(): void {\r\n this._overlaySubscriptions.unsubscribe();\r\n if (this._overlayRef) {\r\n this._overlayRef.dispose();\r\n this._overlayRef = null;\r\n }\r\n }\r\n\r\n private _startCloseAnimation(): void {\r\n // Clear any existing timeout\r\n this._clearCloseTimeout();\r\n\r\n // Trigger leave animation\r\n this._animationState.set('leave');\r\n\r\n // Wait for animation to complete before closing (matches CSS transition duration)\r\n this._closeAnimationTimeout = window.setTimeout(() => {\r\n this._closeMenu();\r\n this._animationState.set('void');\r\n }, 150); // Match the CSS transition duration\r\n }\r\n\r\n private _clearCloseTimeout(): void {\r\n if (this._closeAnimationTimeout !== null) {\r\n clearTimeout(this._closeAnimationTimeout);\r\n this._closeAnimationTimeout = null;\r\n }\r\n }\r\n\r\n /**\r\n * Checks if this menu's overlay is the topmost (most recently opened) overlay.\r\n * This ensures that only the topmost menu responds to keyboard events when\r\n * multiple menus are open (e.g., nested menus).\r\n */\r\n private _isTopmostOverlay(): boolean {\r\n if (!this._overlayRef) {\r\n return false;\r\n }\r\n\r\n const activeOverlays = this._overlayService.getActiveOverlays();\r\n\r\n // The last overlay in the array is the most recently created (topmost)\r\n const topmostOverlay = activeOverlays[activeOverlays.length - 1];\r\n\r\n return topmostOverlay === this._overlayRef;\r\n }\r\n}\r\n","@if (_isOpen() || _animationState() === 'leave') {\r\n <div class=\"fui-menu__panel\" #menuPanel role=\"menu\" [attr.data-animation-state]=\"_animationState()\">\r\n <ng-content></ng-content>\r\n </div>\r\n}\r\n","import { Directive, ElementRef, inject, HostListener, input, effect, AfterViewInit } from '@angular/core';\r\nimport { FuiMenuComponent } from './menu.component';\r\n\r\n/**\r\n * # fuiMenuTrigger Directive\r\n *\r\n * A directive that marks an element as a menu trigger, similar to Angular Material's matMenuTriggerFor.\r\n * This directive should be used in conjunction with FuiMenuComponent.\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Usage\r\n * ```html\r\n * <button fuiMenuTrigger [menuTriggerFor]=\"menu\">Open Menu</button>\r\n * <fui-menu #menu>\r\n * <fui-menu-item>Option 1</fui-menu-item>\r\n * <fui-menu-item>Option 2</fui-menu-item>\r\n * </fui-menu>\r\n * ```\r\n *\r\n * ### With Menu Reference\r\n * ```html\r\n * <button fuiMenuTrigger [menuTriggerFor]=\"userMenu\">\r\n * <fui-icon name=\"user\"></fui-icon>\r\n * User Menu\r\n * </button>\r\n *\r\n * <fui-menu #userMenu position=\"bottom-end\">\r\n * <fui-menu-item>Profile</fui-menu-item>\r\n * <fui-menu-item>Settings</fui-menu-item>\r\n * <fui-menu-item variant=\"danger\">Logout</fui-menu-item>\r\n * </fui-menu>\r\n * ```\r\n *\r\n * ### Passing Data to Menu\r\n * ```html\r\n * <button fuiMenuTrigger\r\n * [menuTriggerFor]=\"dynamicMenu\"\r\n * [menuTriggerData]=\"{ user: currentUser, role: 'admin' }\">\r\n * Open Menu\r\n * </button>\r\n *\r\n * <fui-menu #dynamicMenu>\r\n * <!-- Access menu data in your component via menu.menuData() -->\r\n * </fui-menu>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiMenuTriggerDirective, FuiMenuComponent, FuiMenuItemComponent } from '@raintonic/formaui/components/menu';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiMenuTriggerDirective, FuiMenuComponent, FuiMenuItemComponent],\r\n * template: `\r\n * <button fuiMenuTrigger [menuTriggerFor]=\"menu\">Open Menu</button>\r\n * <fui-menu #menu>\r\n * <fui-menu-item>Option 1</fui-menu-item>\r\n * <fui-menu-item>Option 2</fui-menu-item>\r\n * </fui-menu>\r\n * `\r\n * })\r\n * export class MyComponent { }\r\n * ```\r\n */\r\n@Directive({\r\n selector: '[fuiMenuTrigger]',\r\n standalone: true,\r\n host: {\r\n '[attr.aria-haspopup]': '\"true\"',\r\n '[attr.aria-expanded]': 'menu?.isOpen() ? \"true\" : \"false\"',\r\n },\r\n})\r\nexport class FuiMenuTriggerDirective implements AfterViewInit {\r\n private readonly _elementRef = inject(ElementRef<HTMLElement>);\r\n\r\n /** The menu instance that this trigger should open */\r\n readonly menuTriggerFor = input<FuiMenuComponent | null>();\r\n\r\n /**\r\n * Data to be passed to the menu.\r\n * Can be accessed in the menu component or menu items.\r\n * Similar to Angular Material's matMenuTriggerData.\r\n */\r\n readonly menuTriggerData = input<unknown>();\r\n\r\n /** The menu instance that this trigger is associated with */\r\n menu: FuiMenuComponent | null = null;\r\n\r\n constructor() {\r\n // Set up the menu reference when fuiMenuTriggerFor changes\r\n effect(() => {\r\n const menuRef = this.menuTriggerFor();\r\n if (menuRef) {\r\n this.menu = menuRef;\r\n // Set the trigger element on the menu for positioning\r\n menuRef.setTriggerElement(this._elementRef.nativeElement);\r\n }\r\n });\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n // Ensure the menu reference is set after view initialization\r\n const menuRef = this.menuTriggerFor();\r\n\r\n if (menuRef) {\r\n this.menu = menuRef;\r\n menuRef.setTriggerElement(this._elementRef.nativeElement);\r\n }\r\n }\r\n\r\n @HostListener('click', ['$event'])\r\n onClick(event: Event): void {\r\n if (this.menu) {\r\n event.preventDefault();\r\n\r\n // Update trigger element to ensure correct positioning when multiple triggers exist\r\n this.menu.setTriggerElement(this._elementRef.nativeElement);\r\n\r\n // Pass data to menu before opening/toggling\r\n const data = this.menuTriggerData();\r\n if (data !== undefined && this.menu.setMenuData) {\r\n this.menu.setMenuData(data);\r\n }\r\n\r\n this.menu.toggle();\r\n }\r\n }\r\n\r\n @HostListener('keydown', ['$event'])\r\n onKeydown(event: KeyboardEvent): void {\r\n const menu = this.menu;\r\n if (!menu) return;\r\n\r\n // Update trigger element and pass data to menu before opening\r\n const prepareMenu = (): void => {\r\n // Update trigger element to ensure correct positioning when multiple triggers exist\r\n menu.setTriggerElement(this._elementRef.nativeElement);\r\n\r\n // Pass data to menu\r\n const data = this.menuTriggerData();\r\n if (data !== undefined) {\r\n menu.setMenuData(data);\r\n }\r\n };\r\n\r\n switch (event.key) {\r\n case 'Enter':\r\n case ' ':\r\n event.preventDefault();\r\n prepareMenu();\r\n menu.toggle();\r\n break;\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n prepareMenu();\r\n menu.open();\r\n // Focus first item after menu opens\r\n setTimeout(() => {\r\n menu._focusFirstItem();\r\n }, 0);\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n prepareMenu();\r\n menu.open();\r\n // Focus last item after menu opens\r\n setTimeout(() => {\r\n menu._focusLastItem();\r\n }, 0);\r\n break;\r\n }\r\n }\r\n\r\n /** Gets the trigger element */\r\n getElement(): HTMLElement {\r\n return this._elementRef.nativeElement;\r\n }\r\n}\r\n","// Public API for menu components\r\nexport * from './menu.component';\r\nexport * from './menu-item.component';\r\nexport * from './menu-trigger.directive';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject, ChangeDetectorRef, input, output, signal, computed, HostListener, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
-
import { FuiIconComponent } from '@raintonic/formaui/components/icon';
|
|
5
|
-
import { FuiIntlBase } from '@raintonic/formaui/core';
|
|
6
|
-
|
|
7
|
-
class FuiSidebarIntl extends FuiIntlBase {
|
|
8
|
-
rootAriaLabel = 'Navigation sidebar';
|
|
9
|
-
navAriaLabel = 'Main navigation';
|
|
10
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiSidebarIntl, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
11
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiSidebarIntl, providedIn: 'root' });
|
|
12
|
-
}
|
|
13
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiSidebarIntl, decorators: [{
|
|
14
|
-
type: Injectable,
|
|
15
|
-
args: [{ providedIn: 'root' }]
|
|
16
|
-
}] });
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* # FuiSidebar Component
|
|
20
|
-
*
|
|
21
|
-
* A flexible sidebar component following Carbon Design System principles.
|
|
22
|
-
* Provides navigation with Angular Material-like APIs and responsive behavior.
|
|
23
|
-
*
|
|
24
|
-
* ## Features
|
|
25
|
-
* - Multiple modes: side, over, push
|
|
26
|
-
* - Collapsible with toggle functionality
|
|
27
|
-
* - Hierarchical navigation support
|
|
28
|
-
* - Responsive behavior
|
|
29
|
-
* - Theme integration
|
|
30
|
-
* - Accessibility support
|
|
31
|
-
* - Custom content projection
|
|
32
|
-
*
|
|
33
|
-
* ## Usage
|
|
34
|
-
*
|
|
35
|
-
* ### Basic Sidebar
|
|
36
|
-
* ```html
|
|
37
|
-
* <fui-sidebar
|
|
38
|
-
* [opened]="sidebarOpen"
|
|
39
|
-
* [mode]="'side'"
|
|
40
|
-
* [navItems]="navigationItems"
|
|
41
|
-
* (openedChange)="onSidebarToggle($event)"
|
|
42
|
-
* (navItemClick)="onNavItemClick($event)">
|
|
43
|
-
*
|
|
44
|
-
* <div header>
|
|
45
|
-
* <h3>Navigation</h3>
|
|
46
|
-
* </div>
|
|
47
|
-
*
|
|
48
|
-
* <div footer>
|
|
49
|
-
* <p>Version 1.0.0</p>
|
|
50
|
-
* </div>
|
|
51
|
-
* </fui-sidebar>
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* ### Responsive Sidebar
|
|
55
|
-
* ```html
|
|
56
|
-
* <fui-sidebar
|
|
57
|
-
* [opened]="sidebarOpen"
|
|
58
|
-
* [mode]="isDesktop ? 'side' : 'over'"
|
|
59
|
-
* [backdrop]="!isDesktop"
|
|
60
|
-
* [navItems]="navigationItems">
|
|
61
|
-
* </fui-sidebar>
|
|
62
|
-
* ```
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```typescript
|
|
66
|
-
* import { FuiSidebarComponent, FuiSidebarNavItem } from '@raintonic/formaui/components/sidebar';
|
|
67
|
-
*
|
|
68
|
-
* @Component({
|
|
69
|
-
* standalone: true,
|
|
70
|
-
* imports: [FuiSidebarComponent],
|
|
71
|
-
* template: `
|
|
72
|
-
* <fui-sidebar
|
|
73
|
-
* [opened]="sidebarOpen"
|
|
74
|
-
* [mode]="sidebarMode"
|
|
75
|
-
* [navItems]="navItems"
|
|
76
|
-
* (openedChange)="onSidebarToggle($event)"
|
|
77
|
-
* (navItemClick)="onNavItemClick($event)">
|
|
78
|
-
*
|
|
79
|
-
* <div header class="sidebar-header">
|
|
80
|
-
* <h3>Holiday ERP</h3>
|
|
81
|
-
* </div>
|
|
82
|
-
* </fui-sidebar>
|
|
83
|
-
* `
|
|
84
|
-
* })
|
|
85
|
-
* export class AppLayoutComponent {
|
|
86
|
-
* sidebarOpen = true;
|
|
87
|
-
* sidebarMode: FuiSidebarMode = 'side';
|
|
88
|
-
*
|
|
89
|
-
* navItems: FuiSidebarNavItem[] = [
|
|
90
|
-
* { id: 'dashboard', label: 'Dashboard', icon: 'house', route: '/dashboard' },
|
|
91
|
-
* {
|
|
92
|
-
* id: 'sales',
|
|
93
|
-
* label: 'Sales',
|
|
94
|
-
* icon: 'shopping-cart',
|
|
95
|
-
* children: [
|
|
96
|
-
* { id: 'orders', label: 'Orders', route: '/sales/orders' },
|
|
97
|
-
* { id: 'invoices', label: 'Invoices', route: '/sales/invoices' },
|
|
98
|
-
* ]
|
|
99
|
-
* },
|
|
100
|
-
* { id: 'products', label: 'Products', icon: 'package', route: '/products' },
|
|
101
|
-
* ];
|
|
102
|
-
*
|
|
103
|
-
* onSidebarToggle(opened: boolean): void {
|
|
104
|
-
* this.sidebarOpen = opened;
|
|
105
|
-
* }
|
|
106
|
-
*
|
|
107
|
-
* onNavItemClick(item: FuiSidebarNavItem): void {
|
|
108
|
-
* console.log('Navigation item clicked:', item.id);
|
|
109
|
-
* }
|
|
110
|
-
* }
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
|
-
class FuiSidebarComponent {
|
|
114
|
-
intl = inject(FuiSidebarIntl);
|
|
115
|
-
_cdr = inject(ChangeDetectorRef);
|
|
116
|
-
constructor() {
|
|
117
|
-
this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });
|
|
118
|
-
}
|
|
119
|
-
// Inputs using signal-based API
|
|
120
|
-
opened = input(true, ...(ngDevMode ? [{ debugName: "opened" }] : /* istanbul ignore next */ []));
|
|
121
|
-
mode = input('side', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
122
|
-
position = input('start', ...(ngDevMode ? [{ debugName: "position" }] : /* istanbul ignore next */ []));
|
|
123
|
-
backdrop = input(false, ...(ngDevMode ? [{ debugName: "backdrop" }] : /* istanbul ignore next */ []));
|
|
124
|
-
width = input('16rem', ...(ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []));
|
|
125
|
-
navItems = input([], ...(ngDevMode ? [{ debugName: "navItems" }] : /* istanbul ignore next */ []));
|
|
126
|
-
collapsible = input(true, ...(ngDevMode ? [{ debugName: "collapsible" }] : /* istanbul ignore next */ []));
|
|
127
|
-
// Outputs using signal-based API
|
|
128
|
-
openedChange = output();
|
|
129
|
-
navItemClick = output();
|
|
130
|
-
backdropClick = output();
|
|
131
|
-
// Internal state
|
|
132
|
-
expandedItems = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedItems" }] : /* istanbul ignore next */ []));
|
|
133
|
-
// Computed properties
|
|
134
|
-
sidebarClasses = computed(() => {
|
|
135
|
-
const classes = ['fui-sidebar'];
|
|
136
|
-
if (this.opened()) {
|
|
137
|
-
classes.push('fui-sidebar--opened');
|
|
138
|
-
}
|
|
139
|
-
classes.push(`fui-sidebar--${this.mode()}`);
|
|
140
|
-
classes.push(`fui-sidebar--${this.position()}`);
|
|
141
|
-
return classes.join(' ');
|
|
142
|
-
}, ...(ngDevMode ? [{ debugName: "sidebarClasses" }] : /* istanbul ignore next */ []));
|
|
143
|
-
backdropClasses = computed(() => {
|
|
144
|
-
const classes = ['fui-sidebar-backdrop'];
|
|
145
|
-
if (this.opened() && this.backdrop()) {
|
|
146
|
-
classes.push('fui-sidebar-backdrop--visible');
|
|
147
|
-
}
|
|
148
|
-
return classes.join(' ');
|
|
149
|
-
}, ...(ngDevMode ? [{ debugName: "backdropClasses" }] : /* istanbul ignore next */ []));
|
|
150
|
-
sidebarStyles = computed(() => {
|
|
151
|
-
return {
|
|
152
|
-
width: this.width(),
|
|
153
|
-
};
|
|
154
|
-
}, ...(ngDevMode ? [{ debugName: "sidebarStyles" }] : /* istanbul ignore next */ []));
|
|
155
|
-
/**
|
|
156
|
-
* Toggle sidebar open/closed state
|
|
157
|
-
*/
|
|
158
|
-
toggle() {
|
|
159
|
-
const _isNewState = !this.opened();
|
|
160
|
-
this.openedChange.emit(_isNewState);
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Open the sidebar
|
|
164
|
-
*/
|
|
165
|
-
open() {
|
|
166
|
-
if (!this.opened()) {
|
|
167
|
-
this.openedChange.emit(true);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Close the sidebar
|
|
172
|
-
*/
|
|
173
|
-
close() {
|
|
174
|
-
if (this.opened()) {
|
|
175
|
-
this.openedChange.emit(false);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Handle navigation item click
|
|
180
|
-
*/
|
|
181
|
-
onNavItemClick(item) {
|
|
182
|
-
if (item.disabled) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
// Handle expandable items
|
|
186
|
-
if (item.children && item.children.length > 0) {
|
|
187
|
-
this.toggleItemExpansion(item.id);
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
this.navItemClick.emit(item);
|
|
191
|
-
// Close sidebar on mobile when item is clicked
|
|
192
|
-
if (this.mode() === 'over') {
|
|
193
|
-
this.close();
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Toggle expansion state of a navigation item
|
|
199
|
-
*/
|
|
200
|
-
toggleItemExpansion(itemId) {
|
|
201
|
-
const _areExpanded = this.expandedItems();
|
|
202
|
-
const _areNewExpanded = new Set(_areExpanded);
|
|
203
|
-
if (_areNewExpanded.has(itemId)) {
|
|
204
|
-
_areNewExpanded.delete(itemId);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
_areNewExpanded.add(itemId);
|
|
208
|
-
}
|
|
209
|
-
this.expandedItems.set(_areNewExpanded);
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Check if item is expanded
|
|
213
|
-
*/
|
|
214
|
-
isItemExpanded(itemId) {
|
|
215
|
-
return this.expandedItems().has(itemId);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Handle backdrop click
|
|
219
|
-
*/
|
|
220
|
-
onBackdropClick() {
|
|
221
|
-
this.backdropClick.emit();
|
|
222
|
-
this.close();
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Get navigation item classes
|
|
226
|
-
*/
|
|
227
|
-
getNavItemClasses(item, level = 0) {
|
|
228
|
-
const classes = ['fui-sidebar__nav-item'];
|
|
229
|
-
if (item.active) {
|
|
230
|
-
classes.push('fui-sidebar__nav-item--active');
|
|
231
|
-
}
|
|
232
|
-
if (item.disabled) {
|
|
233
|
-
classes.push('fui-sidebar__nav-item--disabled');
|
|
234
|
-
}
|
|
235
|
-
if (level > 0) {
|
|
236
|
-
classes.push('fui-sidebar__nav-item--child');
|
|
237
|
-
}
|
|
238
|
-
if (item.children && item.children.length > 0) {
|
|
239
|
-
classes.push('fui-sidebar__nav-item--expandable');
|
|
240
|
-
if (this.isItemExpanded(item.id)) {
|
|
241
|
-
classes.push('fui-sidebar__nav-item--expanded');
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return classes.join(' ');
|
|
245
|
-
}
|
|
246
|
-
onEsc() {
|
|
247
|
-
if (this.opened() && (this.mode() === 'over' || this.backdrop())) {
|
|
248
|
-
this.close();
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
252
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiSidebarComponent, isStandalone: true, selector: "fui-sidebar", inputs: { opened: { classPropertyName: "opened", publicName: "opened", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, backdrop: { classPropertyName: "backdrop", publicName: "backdrop", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, navItems: { classPropertyName: "navItems", publicName: "navItems", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openedChange: "openedChange", navItemClick: "navItemClick", backdropClick: "backdropClick" }, host: { listeners: { "document:keydown.escape": "onEsc()" }, properties: { "class.fui-sidebar-container--opened": "opened()", "class.fui-sidebar-container--over": "mode() === \"over\"", "class.fui-sidebar-container--push": "mode() === \"push\"", "class.fui-sidebar-container--side": "mode() === \"side\"", "class.fui-sidebar-container--start": "position() === \"start\"", "class.fui-sidebar-container--end": "position() === \"end\"" }, classAttribute: "fui-sidebar-container" }, ngImport: i0, template: "<!-- Backdrop -->\r\n@if (backdrop()) {\r\n <div [class]=\"backdropClasses()\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\r\n}\r\n\r\n<!-- Sidebar -->\r\n<aside\r\n [class]=\"sidebarClasses()\"\r\n [style]=\"sidebarStyles()\"\r\n [attr.aria-modal]=\"mode() === 'over' && opened() ? 'true' : null\"\r\n [attr.role]=\"mode() === 'over' && opened() ? 'dialog' : null\"\r\n [attr.aria-label]=\"mode() === 'over' && opened() ? intl.rootAriaLabel : null\"\r\n>\r\n <!-- Header Content -->\r\n <div class=\"fui-sidebar__header\">\r\n <ng-content select=\"[header]\"></ng-content>\r\n </div>\r\n\r\n <!-- Navigation -->\r\n @if (navItems().length > 0) {\r\n <nav class=\"fui-sidebar__nav\" [attr.aria-label]=\"intl.navAriaLabel\">\r\n <ul class=\"fui-sidebar__nav-list\">\r\n @for (item of navItems(); track item.id) {\r\n <li>\r\n <!-- Navigation Item -->\r\n <button\r\n type=\"button\"\r\n [class]=\"getNavItemClasses(item)\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-expanded]=\"item.children?.length ? isItemExpanded(item.id) : null\"\r\n [attr.aria-current]=\"item.active ? 'page' : null\"\r\n (click)=\"onNavItemClick(item)\"\r\n >\r\n @if (item.icon) {\r\n <fui-icon [name]=\"item.icon\" size=\"md\" class=\"fui-sidebar__nav-icon\"> </fui-icon>\r\n }\r\n\r\n <span class=\"fui-sidebar__nav-label\">{{ item.label }}</span>\r\n\r\n @if (item.children && item.children.length > 0) {\r\n <fui-icon\r\n name=\"caret-down\"\r\n size=\"sm\"\r\n class=\"fui-sidebar__nav-caret\"\r\n [class.fui-sidebar__nav-caret--expanded]=\"isItemExpanded(item.id)\"\r\n >\r\n </fui-icon>\r\n }\r\n </button>\r\n\r\n <!-- Child Items -->\r\n @if (item.children && item.children.length > 0 && isItemExpanded(item.id)) {\r\n <ul class=\"fui-sidebar__nav-children\">\r\n @for (child of item.children; track child.id) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n [class]=\"getNavItemClasses(child, 1)\"\r\n [disabled]=\"child.disabled\"\r\n [attr.aria-current]=\"child.active ? 'page' : null\"\r\n (click)=\"onNavItemClick(child)\"\r\n >\r\n @if (child.icon) {\r\n <fui-icon [name]=\"child.icon\" size=\"sm\" class=\"fui-sidebar__nav-icon\"> </fui-icon>\r\n }\r\n\r\n <span class=\"fui-sidebar__nav-label\">{{ child.label }}</span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </nav>\r\n }\r\n\r\n <!-- Custom Content -->\r\n <div class=\"fui-sidebar__content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer Content -->\r\n <div class=\"fui-sidebar__footer\">\r\n <ng-content select=\"[footer]\"></ng-content>\r\n </div>\r\n</aside>\r\n", styles: [".fui-sidebar-container{position:relative;display:flex;height:100%}.fui-sidebar-container--side .fui-sidebar{position:relative;transform:none}.fui-sidebar-container--side:not(.fui-sidebar-container--opened) .fui-sidebar{width:0;overflow:hidden}.fui-sidebar-container--over .fui-sidebar{position:fixed;top:0;bottom:0;transform:translate(-100%)}.fui-sidebar-container--over.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--over.fui-sidebar-container--end .fui-sidebar{transform:translate(100%)}.fui-sidebar-container--over.fui-sidebar-container--end.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--push .fui-sidebar{position:relative;transform:translate(-100%)}.fui-sidebar-container--push.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--push.fui-sidebar-container--end .fui-sidebar{transform:translate(100%)}.fui-sidebar-container--push.fui-sidebar-container--end.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--end .fui-sidebar{right:0;left:auto}.fui-sidebar-backdrop{position:fixed;inset:0;background-color:var(--fui-dialog-backdrop-color, rgba(0, 0, 0, .32));opacity:0;visibility:hidden}.fui-sidebar-backdrop--visible{opacity:1;visibility:visible}.fui-sidebar{--fui-sidebar-width: 16rem;--fui-sidebar-bg: var(--fui-surface-02);--fui-sidebar-border-color: var(--fui-border-color);--fui-sidebar-nav-item-min-height: 2rem;--fui-sidebar-nav-item-border-radius: var(--fui-border-radius-lg);--fui-sidebar-nav-item-font-size: var(--fui-font-size-02);contain:layout style;display:flex;flex-direction:column;width:var(--fui-sidebar-width);height:100%;background-color:var(--fui-sidebar-bg);border-right:1px solid var(--fui-sidebar-border-color);overflow:hidden}.fui-sidebar__header{flex-shrink:0;padding:1rem .75rem;border-bottom:1px solid var(--fui-border-color)}.fui-sidebar__header:empty{display:none}.fui-sidebar__header [header] h1,.fui-sidebar__header [header] h2,.fui-sidebar__header [header] h3,.fui-sidebar__header [header] h4,.fui-sidebar__header [header] h5,.fui-sidebar__header [header] h6{margin:0;color:var(--fui-text-primary);font-size:var(--fui-font-size-03);font-weight:600}.fui-sidebar__nav{flex:1;overflow-y:auto;padding:.5rem 0}.fui-sidebar__nav-list{list-style:none;margin:0;padding:0}.fui-sidebar__nav-item{display:flex;align-items:center;width:calc(100% - 1.5rem);margin:.25rem .75rem;border-radius:var(--fui-sidebar-nav-item-border-radius);padding:.5rem .75rem;border:none;background-color:transparent;color:var(--fui-text-primary);font-size:var(--fui-sidebar-nav-item-font-size);text-align:left;cursor:pointer;gap:.5rem;min-height:var(--fui-sidebar-nav-item-min-height)}.fui-sidebar__nav-item:hover:not(.fui-sidebar__nav-item--disabled){background-color:var(--fui-surface-02)}.fui-sidebar__nav-item:active:not(.fui-sidebar__nav-item--disabled){background-color:var(--fui-surface-05)}.fui-sidebar__nav-item--active{background-color:var(--fui-primary-10);color:var(--fui-primary);font-weight:600}.fui-sidebar__nav-item--active .fui-sidebar__nav-icon{color:var(--fui-primary)}.fui-sidebar__nav-item--disabled{color:var(--fui-text-secondary);cursor:not-allowed}.fui-sidebar__nav-item--disabled .fui-sidebar__nav-icon{color:var(--fui-icon-on-color-disabled)}.fui-sidebar__nav-item--child{padding-left:2rem;font-size:.8125rem}.fui-sidebar__nav-item--expandable .fui-sidebar__nav-caret{margin-left:auto}.fui-sidebar__nav-item--expandable.fui-sidebar__nav-item--expanded .fui-sidebar__nav-caret{transform:rotate(180deg)}.fui-sidebar__nav-item:focus-visible{outline:2px solid var(--fui-primary);outline-offset:-2px}.fui-sidebar__nav-icon{flex-shrink:0;color:var(--fui-icon-secondary)}.fui-sidebar__nav-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fui-sidebar__nav-caret{flex-shrink:0;color:var(--fui-icon-tertiary)}.fui-sidebar__nav-children{list-style:none;margin:0;padding:0}.fui-sidebar__content{flex-shrink:0;padding:.75rem}.fui-sidebar__footer{flex-shrink:0;padding:.75rem;border-top:1px solid var(--fui-border-color);margin-top:auto}.fui-sidebar__footer [footer]{font-size:var(--fui-font-size-01);color:var(--fui-text-secondary);text-align:center}@media(max-width:768px){.fui-sidebar{width:14rem}.fui-sidebar__nav-item{padding:.5rem;font-size:.8125rem}.fui-sidebar__nav-item--child{padding-left:1.5rem}}@media(max-width:576px){.fui-sidebar{width:12rem}.fui-sidebar__header,.fui-sidebar__content,.fui-sidebar__footer{padding:.5rem}.fui-sidebar__nav-item{padding:.25rem .5rem;min-height:2.25rem}.fui-sidebar__nav-item--child{padding-left:1rem}}@media(prefers-reduced-motion:reduce){.fui-sidebar,.fui-sidebar-backdrop,.fui-sidebar-container.fui-sidebar-container--over .fui-sidebar,.fui-sidebar-container.fui-sidebar-container--push .fui-sidebar{transition:none!important}}.fui-theme-dark .fui-sidebar{border-right-color:var(--fui-border-color)}.fui-theme-dark .fui-sidebar__header{border-bottom-color:var(--fui-border-color)}.fui-theme-dark .fui-sidebar__footer{border-top-color:var(--fui-border-color)}.fui-theme-dark .fui-sidebar__nav-children{background-color:var(--fui-surface-05)}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
253
|
-
}
|
|
254
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiSidebarComponent, decorators: [{
|
|
255
|
-
type: Component,
|
|
256
|
-
args: [{ selector: 'fui-sidebar', standalone: true, imports: [FuiIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
257
|
-
class: 'fui-sidebar-container',
|
|
258
|
-
'[class.fui-sidebar-container--opened]': 'opened()',
|
|
259
|
-
'[class.fui-sidebar-container--over]': 'mode() === "over"',
|
|
260
|
-
'[class.fui-sidebar-container--push]': 'mode() === "push"',
|
|
261
|
-
'[class.fui-sidebar-container--side]': 'mode() === "side"',
|
|
262
|
-
'[class.fui-sidebar-container--start]': 'position() === "start"',
|
|
263
|
-
'[class.fui-sidebar-container--end]': 'position() === "end"',
|
|
264
|
-
}, template: "<!-- Backdrop -->\r\n@if (backdrop()) {\r\n <div [class]=\"backdropClasses()\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\r\n}\r\n\r\n<!-- Sidebar -->\r\n<aside\r\n [class]=\"sidebarClasses()\"\r\n [style]=\"sidebarStyles()\"\r\n [attr.aria-modal]=\"mode() === 'over' && opened() ? 'true' : null\"\r\n [attr.role]=\"mode() === 'over' && opened() ? 'dialog' : null\"\r\n [attr.aria-label]=\"mode() === 'over' && opened() ? intl.rootAriaLabel : null\"\r\n>\r\n <!-- Header Content -->\r\n <div class=\"fui-sidebar__header\">\r\n <ng-content select=\"[header]\"></ng-content>\r\n </div>\r\n\r\n <!-- Navigation -->\r\n @if (navItems().length > 0) {\r\n <nav class=\"fui-sidebar__nav\" [attr.aria-label]=\"intl.navAriaLabel\">\r\n <ul class=\"fui-sidebar__nav-list\">\r\n @for (item of navItems(); track item.id) {\r\n <li>\r\n <!-- Navigation Item -->\r\n <button\r\n type=\"button\"\r\n [class]=\"getNavItemClasses(item)\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-expanded]=\"item.children?.length ? isItemExpanded(item.id) : null\"\r\n [attr.aria-current]=\"item.active ? 'page' : null\"\r\n (click)=\"onNavItemClick(item)\"\r\n >\r\n @if (item.icon) {\r\n <fui-icon [name]=\"item.icon\" size=\"md\" class=\"fui-sidebar__nav-icon\"> </fui-icon>\r\n }\r\n\r\n <span class=\"fui-sidebar__nav-label\">{{ item.label }}</span>\r\n\r\n @if (item.children && item.children.length > 0) {\r\n <fui-icon\r\n name=\"caret-down\"\r\n size=\"sm\"\r\n class=\"fui-sidebar__nav-caret\"\r\n [class.fui-sidebar__nav-caret--expanded]=\"isItemExpanded(item.id)\"\r\n >\r\n </fui-icon>\r\n }\r\n </button>\r\n\r\n <!-- Child Items -->\r\n @if (item.children && item.children.length > 0 && isItemExpanded(item.id)) {\r\n <ul class=\"fui-sidebar__nav-children\">\r\n @for (child of item.children; track child.id) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n [class]=\"getNavItemClasses(child, 1)\"\r\n [disabled]=\"child.disabled\"\r\n [attr.aria-current]=\"child.active ? 'page' : null\"\r\n (click)=\"onNavItemClick(child)\"\r\n >\r\n @if (child.icon) {\r\n <fui-icon [name]=\"child.icon\" size=\"sm\" class=\"fui-sidebar__nav-icon\"> </fui-icon>\r\n }\r\n\r\n <span class=\"fui-sidebar__nav-label\">{{ child.label }}</span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </nav>\r\n }\r\n\r\n <!-- Custom Content -->\r\n <div class=\"fui-sidebar__content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer Content -->\r\n <div class=\"fui-sidebar__footer\">\r\n <ng-content select=\"[footer]\"></ng-content>\r\n </div>\r\n</aside>\r\n", styles: [".fui-sidebar-container{position:relative;display:flex;height:100%}.fui-sidebar-container--side .fui-sidebar{position:relative;transform:none}.fui-sidebar-container--side:not(.fui-sidebar-container--opened) .fui-sidebar{width:0;overflow:hidden}.fui-sidebar-container--over .fui-sidebar{position:fixed;top:0;bottom:0;transform:translate(-100%)}.fui-sidebar-container--over.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--over.fui-sidebar-container--end .fui-sidebar{transform:translate(100%)}.fui-sidebar-container--over.fui-sidebar-container--end.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--push .fui-sidebar{position:relative;transform:translate(-100%)}.fui-sidebar-container--push.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--push.fui-sidebar-container--end .fui-sidebar{transform:translate(100%)}.fui-sidebar-container--push.fui-sidebar-container--end.fui-sidebar-container--opened .fui-sidebar{transform:translate(0)}.fui-sidebar-container--end .fui-sidebar{right:0;left:auto}.fui-sidebar-backdrop{position:fixed;inset:0;background-color:var(--fui-dialog-backdrop-color, rgba(0, 0, 0, .32));opacity:0;visibility:hidden}.fui-sidebar-backdrop--visible{opacity:1;visibility:visible}.fui-sidebar{--fui-sidebar-width: 16rem;--fui-sidebar-bg: var(--fui-surface-02);--fui-sidebar-border-color: var(--fui-border-color);--fui-sidebar-nav-item-min-height: 2rem;--fui-sidebar-nav-item-border-radius: var(--fui-border-radius-lg);--fui-sidebar-nav-item-font-size: var(--fui-font-size-02);contain:layout style;display:flex;flex-direction:column;width:var(--fui-sidebar-width);height:100%;background-color:var(--fui-sidebar-bg);border-right:1px solid var(--fui-sidebar-border-color);overflow:hidden}.fui-sidebar__header{flex-shrink:0;padding:1rem .75rem;border-bottom:1px solid var(--fui-border-color)}.fui-sidebar__header:empty{display:none}.fui-sidebar__header [header] h1,.fui-sidebar__header [header] h2,.fui-sidebar__header [header] h3,.fui-sidebar__header [header] h4,.fui-sidebar__header [header] h5,.fui-sidebar__header [header] h6{margin:0;color:var(--fui-text-primary);font-size:var(--fui-font-size-03);font-weight:600}.fui-sidebar__nav{flex:1;overflow-y:auto;padding:.5rem 0}.fui-sidebar__nav-list{list-style:none;margin:0;padding:0}.fui-sidebar__nav-item{display:flex;align-items:center;width:calc(100% - 1.5rem);margin:.25rem .75rem;border-radius:var(--fui-sidebar-nav-item-border-radius);padding:.5rem .75rem;border:none;background-color:transparent;color:var(--fui-text-primary);font-size:var(--fui-sidebar-nav-item-font-size);text-align:left;cursor:pointer;gap:.5rem;min-height:var(--fui-sidebar-nav-item-min-height)}.fui-sidebar__nav-item:hover:not(.fui-sidebar__nav-item--disabled){background-color:var(--fui-surface-02)}.fui-sidebar__nav-item:active:not(.fui-sidebar__nav-item--disabled){background-color:var(--fui-surface-05)}.fui-sidebar__nav-item--active{background-color:var(--fui-primary-10);color:var(--fui-primary);font-weight:600}.fui-sidebar__nav-item--active .fui-sidebar__nav-icon{color:var(--fui-primary)}.fui-sidebar__nav-item--disabled{color:var(--fui-text-secondary);cursor:not-allowed}.fui-sidebar__nav-item--disabled .fui-sidebar__nav-icon{color:var(--fui-icon-on-color-disabled)}.fui-sidebar__nav-item--child{padding-left:2rem;font-size:.8125rem}.fui-sidebar__nav-item--expandable .fui-sidebar__nav-caret{margin-left:auto}.fui-sidebar__nav-item--expandable.fui-sidebar__nav-item--expanded .fui-sidebar__nav-caret{transform:rotate(180deg)}.fui-sidebar__nav-item:focus-visible{outline:2px solid var(--fui-primary);outline-offset:-2px}.fui-sidebar__nav-icon{flex-shrink:0;color:var(--fui-icon-secondary)}.fui-sidebar__nav-label{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fui-sidebar__nav-caret{flex-shrink:0;color:var(--fui-icon-tertiary)}.fui-sidebar__nav-children{list-style:none;margin:0;padding:0}.fui-sidebar__content{flex-shrink:0;padding:.75rem}.fui-sidebar__footer{flex-shrink:0;padding:.75rem;border-top:1px solid var(--fui-border-color);margin-top:auto}.fui-sidebar__footer [footer]{font-size:var(--fui-font-size-01);color:var(--fui-text-secondary);text-align:center}@media(max-width:768px){.fui-sidebar{width:14rem}.fui-sidebar__nav-item{padding:.5rem;font-size:.8125rem}.fui-sidebar__nav-item--child{padding-left:1.5rem}}@media(max-width:576px){.fui-sidebar{width:12rem}.fui-sidebar__header,.fui-sidebar__content,.fui-sidebar__footer{padding:.5rem}.fui-sidebar__nav-item{padding:.25rem .5rem;min-height:2.25rem}.fui-sidebar__nav-item--child{padding-left:1rem}}@media(prefers-reduced-motion:reduce){.fui-sidebar,.fui-sidebar-backdrop,.fui-sidebar-container.fui-sidebar-container--over .fui-sidebar,.fui-sidebar-container.fui-sidebar-container--push .fui-sidebar{transition:none!important}}.fui-theme-dark .fui-sidebar{border-right-color:var(--fui-border-color)}.fui-theme-dark .fui-sidebar__header{border-bottom-color:var(--fui-border-color)}.fui-theme-dark .fui-sidebar__footer{border-top-color:var(--fui-border-color)}.fui-theme-dark .fui-sidebar__nav-children{background-color:var(--fui-surface-05)}\n"] }]
|
|
265
|
-
}], ctorParameters: () => [], propDecorators: { opened: [{ type: i0.Input, args: [{ isSignal: true, alias: "opened", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], backdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdrop", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], navItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "navItems", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], openedChange: [{ type: i0.Output, args: ["openedChange"] }], navItemClick: [{ type: i0.Output, args: ["navItemClick"] }], backdropClick: [{ type: i0.Output, args: ["backdropClick"] }], onEsc: [{
|
|
266
|
-
type: HostListener,
|
|
267
|
-
args: ['document:keydown.escape']
|
|
268
|
-
}] } });
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Generated bundle index. Do not edit.
|
|
272
|
-
*/
|
|
273
|
-
|
|
274
|
-
export { FuiSidebarComponent, FuiSidebarIntl };
|
|
275
|
-
//# sourceMappingURL=raintonic-formaui-components-sidebar.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-sidebar.mjs","sources":["../../../lib/components/sidebar/sidebar.intl.ts","../../../lib/components/sidebar/sidebar.component.ts","../../../lib/components/sidebar/sidebar.component.html","../../../lib/components/sidebar/raintonic-formaui-components-sidebar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { FuiIntlBase } from '@raintonic/formaui/core';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FuiSidebarIntl extends FuiIntlBase {\r\n rootAriaLabel = 'Navigation sidebar';\r\n navAriaLabel = 'Main navigation';\r\n}\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n ViewEncapsulation,\r\n input,\r\n output,\r\n computed,\r\n signal,\r\n inject,\r\n InputSignal,\r\n OutputEmitterRef,\r\n Signal,\r\n WritableSignal,\r\n HostListener,\r\n} from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\n\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { FuiSidebarIntl } from './sidebar.intl';\r\n\r\n/**\r\n * Sidebar mode type\r\n */\r\nexport type FuiSidebarMode = 'side' | 'over' | 'push';\r\n\r\n/**\r\n * Sidebar position type\r\n */\r\nexport type FuiSidebarPosition = 'start' | 'end';\r\n\r\n/**\r\n * Sidebar navigation item interface\r\n */\r\nexport interface FuiSidebarNavItem {\r\n id: string;\r\n label: string;\r\n icon?: string;\r\n route?: string;\r\n active?: boolean;\r\n disabled?: boolean;\r\n children?: FuiSidebarNavItem[];\r\n expanded?: boolean;\r\n}\r\n\r\n/**\r\n * # FuiSidebar Component\r\n *\r\n * A flexible sidebar component following Carbon Design System principles.\r\n * Provides navigation with Angular Material-like APIs and responsive behavior.\r\n *\r\n * ## Features\r\n * - Multiple modes: side, over, push\r\n * - Collapsible with toggle functionality\r\n * - Hierarchical navigation support\r\n * - Responsive behavior\r\n * - Theme integration\r\n * - Accessibility support\r\n * - Custom content projection\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Sidebar\r\n * ```html\r\n * <fui-sidebar\r\n * [opened]=\"sidebarOpen\"\r\n * [mode]=\"'side'\"\r\n * [navItems]=\"navigationItems\"\r\n * (openedChange)=\"onSidebarToggle($event)\"\r\n * (navItemClick)=\"onNavItemClick($event)\">\r\n *\r\n * <div header>\r\n * <h3>Navigation</h3>\r\n * </div>\r\n *\r\n * <div footer>\r\n * <p>Version 1.0.0</p>\r\n * </div>\r\n * </fui-sidebar>\r\n * ```\r\n *\r\n * ### Responsive Sidebar\r\n * ```html\r\n * <fui-sidebar\r\n * [opened]=\"sidebarOpen\"\r\n * [mode]=\"isDesktop ? 'side' : 'over'\"\r\n * [backdrop]=\"!isDesktop\"\r\n * [navItems]=\"navigationItems\">\r\n * </fui-sidebar>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiSidebarComponent, FuiSidebarNavItem } from '@raintonic/formaui/components/sidebar';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiSidebarComponent],\r\n * template: `\r\n * <fui-sidebar\r\n * [opened]=\"sidebarOpen\"\r\n * [mode]=\"sidebarMode\"\r\n * [navItems]=\"navItems\"\r\n * (openedChange)=\"onSidebarToggle($event)\"\r\n * (navItemClick)=\"onNavItemClick($event)\">\r\n *\r\n * <div header class=\"sidebar-header\">\r\n * <h3>Holiday ERP</h3>\r\n * </div>\r\n * </fui-sidebar>\r\n * `\r\n * })\r\n * export class AppLayoutComponent {\r\n * sidebarOpen = true;\r\n * sidebarMode: FuiSidebarMode = 'side';\r\n *\r\n * navItems: FuiSidebarNavItem[] = [\r\n * { id: 'dashboard', label: 'Dashboard', icon: 'house', route: '/dashboard' },\r\n * {\r\n * id: 'sales',\r\n * label: 'Sales',\r\n * icon: 'shopping-cart',\r\n * children: [\r\n * { id: 'orders', label: 'Orders', route: '/sales/orders' },\r\n * { id: 'invoices', label: 'Invoices', route: '/sales/invoices' },\r\n * ]\r\n * },\r\n * { id: 'products', label: 'Products', icon: 'package', route: '/products' },\r\n * ];\r\n *\r\n * onSidebarToggle(opened: boolean): void {\r\n * this.sidebarOpen = opened;\r\n * }\r\n *\r\n * onNavItemClick(item: FuiSidebarNavItem): void {\r\n * console.log('Navigation item clicked:', item.id);\r\n * }\r\n * }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-sidebar',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './sidebar.component.html',\r\n styleUrls: ['./sidebar.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-sidebar-container',\r\n '[class.fui-sidebar-container--opened]': 'opened()',\r\n '[class.fui-sidebar-container--over]': 'mode() === \"over\"',\r\n '[class.fui-sidebar-container--push]': 'mode() === \"push\"',\r\n '[class.fui-sidebar-container--side]': 'mode() === \"side\"',\r\n '[class.fui-sidebar-container--start]': 'position() === \"start\"',\r\n '[class.fui-sidebar-container--end]': 'position() === \"end\"',\r\n },\r\n})\r\nexport class FuiSidebarComponent {\r\n readonly intl = inject(FuiSidebarIntl);\r\n private readonly _cdr = inject(ChangeDetectorRef);\r\n\r\n constructor() {\r\n this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });\r\n }\r\n\r\n // Inputs using signal-based API\r\n readonly opened: InputSignal<boolean> = input(true);\r\n readonly mode: InputSignal<FuiSidebarMode> = input<FuiSidebarMode>('side');\r\n readonly position: InputSignal<FuiSidebarPosition> = input<FuiSidebarPosition>('start');\r\n readonly backdrop: InputSignal<boolean> = input(false);\r\n readonly width: InputSignal<string> = input('16rem');\r\n readonly navItems: InputSignal<FuiSidebarNavItem[]> = input<FuiSidebarNavItem[]>([]);\r\n readonly collapsible: InputSignal<boolean> = input(true);\r\n\r\n // Outputs using signal-based API\r\n readonly openedChange: OutputEmitterRef<boolean> = output<boolean>();\r\n readonly navItemClick: OutputEmitterRef<FuiSidebarNavItem> = output<FuiSidebarNavItem>();\r\n readonly backdropClick: OutputEmitterRef<void> = output();\r\n\r\n // Internal state\r\n readonly expandedItems: WritableSignal<Set<string>> = signal(new Set());\r\n\r\n // Computed properties\r\n readonly sidebarClasses: Signal<string> = computed(() => {\r\n const classes: string[] = ['fui-sidebar'];\r\n\r\n if (this.opened()) {\r\n classes.push('fui-sidebar--opened');\r\n }\r\n\r\n classes.push(`fui-sidebar--${this.mode()}`);\r\n classes.push(`fui-sidebar--${this.position()}`);\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n readonly backdropClasses: Signal<string> = computed(() => {\r\n const classes: string[] = ['fui-sidebar-backdrop'];\r\n\r\n if (this.opened() && this.backdrop()) {\r\n classes.push('fui-sidebar-backdrop--visible');\r\n }\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n readonly sidebarStyles: Signal<Record<string, string>> = computed(() => {\r\n return {\r\n width: this.width(),\r\n };\r\n });\r\n\r\n /**\r\n * Toggle sidebar open/closed state\r\n */\r\n toggle(): void {\r\n const _isNewState = !this.opened();\r\n this.openedChange.emit(_isNewState);\r\n }\r\n\r\n /**\r\n * Open the sidebar\r\n */\r\n open(): void {\r\n if (!this.opened()) {\r\n this.openedChange.emit(true);\r\n }\r\n }\r\n\r\n /**\r\n * Close the sidebar\r\n */\r\n close(): void {\r\n if (this.opened()) {\r\n this.openedChange.emit(false);\r\n }\r\n }\r\n\r\n /**\r\n * Handle navigation item click\r\n */\r\n onNavItemClick(item: FuiSidebarNavItem): void {\r\n if (item.disabled) {\r\n return;\r\n }\r\n\r\n // Handle expandable items\r\n if (item.children && item.children.length > 0) {\r\n this.toggleItemExpansion(item.id);\r\n } else {\r\n this.navItemClick.emit(item);\r\n\r\n // Close sidebar on mobile when item is clicked\r\n if (this.mode() === 'over') {\r\n this.close();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Toggle expansion state of a navigation item\r\n */\r\n toggleItemExpansion(itemId: string): void {\r\n const _areExpanded = this.expandedItems();\r\n const _areNewExpanded = new Set(_areExpanded);\r\n\r\n if (_areNewExpanded.has(itemId)) {\r\n _areNewExpanded.delete(itemId);\r\n } else {\r\n _areNewExpanded.add(itemId);\r\n }\r\n\r\n this.expandedItems.set(_areNewExpanded);\r\n }\r\n\r\n /**\r\n * Check if item is expanded\r\n */\r\n isItemExpanded(itemId: string): boolean {\r\n return this.expandedItems().has(itemId);\r\n }\r\n\r\n /**\r\n * Handle backdrop click\r\n */\r\n onBackdropClick(): void {\r\n this.backdropClick.emit();\r\n this.close();\r\n }\r\n\r\n /**\r\n * Get navigation item classes\r\n */\r\n getNavItemClasses(item: FuiSidebarNavItem, level = 0): string {\r\n const classes: string[] = ['fui-sidebar__nav-item'];\r\n\r\n if (item.active) {\r\n classes.push('fui-sidebar__nav-item--active');\r\n }\r\n\r\n if (item.disabled) {\r\n classes.push('fui-sidebar__nav-item--disabled');\r\n }\r\n\r\n if (level > 0) {\r\n classes.push('fui-sidebar__nav-item--child');\r\n }\r\n\r\n if (item.children && item.children.length > 0) {\r\n classes.push('fui-sidebar__nav-item--expandable');\r\n\r\n if (this.isItemExpanded(item.id)) {\r\n classes.push('fui-sidebar__nav-item--expanded');\r\n }\r\n }\r\n\r\n return classes.join(' ');\r\n }\r\n\r\n @HostListener('document:keydown.escape')\r\n onEsc(): void {\r\n if (this.opened() && (this.mode() === 'over' || this.backdrop())) {\r\n this.close();\r\n }\r\n }\r\n}\r\n","<!-- Backdrop -->\r\n@if (backdrop()) {\r\n <div [class]=\"backdropClasses()\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\r\n}\r\n\r\n<!-- Sidebar -->\r\n<aside\r\n [class]=\"sidebarClasses()\"\r\n [style]=\"sidebarStyles()\"\r\n [attr.aria-modal]=\"mode() === 'over' && opened() ? 'true' : null\"\r\n [attr.role]=\"mode() === 'over' && opened() ? 'dialog' : null\"\r\n [attr.aria-label]=\"mode() === 'over' && opened() ? intl.rootAriaLabel : null\"\r\n>\r\n <!-- Header Content -->\r\n <div class=\"fui-sidebar__header\">\r\n <ng-content select=\"[header]\"></ng-content>\r\n </div>\r\n\r\n <!-- Navigation -->\r\n @if (navItems().length > 0) {\r\n <nav class=\"fui-sidebar__nav\" [attr.aria-label]=\"intl.navAriaLabel\">\r\n <ul class=\"fui-sidebar__nav-list\">\r\n @for (item of navItems(); track item.id) {\r\n <li>\r\n <!-- Navigation Item -->\r\n <button\r\n type=\"button\"\r\n [class]=\"getNavItemClasses(item)\"\r\n [disabled]=\"item.disabled\"\r\n [attr.aria-expanded]=\"item.children?.length ? isItemExpanded(item.id) : null\"\r\n [attr.aria-current]=\"item.active ? 'page' : null\"\r\n (click)=\"onNavItemClick(item)\"\r\n >\r\n @if (item.icon) {\r\n <fui-icon [name]=\"item.icon\" size=\"md\" class=\"fui-sidebar__nav-icon\"> </fui-icon>\r\n }\r\n\r\n <span class=\"fui-sidebar__nav-label\">{{ item.label }}</span>\r\n\r\n @if (item.children && item.children.length > 0) {\r\n <fui-icon\r\n name=\"caret-down\"\r\n size=\"sm\"\r\n class=\"fui-sidebar__nav-caret\"\r\n [class.fui-sidebar__nav-caret--expanded]=\"isItemExpanded(item.id)\"\r\n >\r\n </fui-icon>\r\n }\r\n </button>\r\n\r\n <!-- Child Items -->\r\n @if (item.children && item.children.length > 0 && isItemExpanded(item.id)) {\r\n <ul class=\"fui-sidebar__nav-children\">\r\n @for (child of item.children; track child.id) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n [class]=\"getNavItemClasses(child, 1)\"\r\n [disabled]=\"child.disabled\"\r\n [attr.aria-current]=\"child.active ? 'page' : null\"\r\n (click)=\"onNavItemClick(child)\"\r\n >\r\n @if (child.icon) {\r\n <fui-icon [name]=\"child.icon\" size=\"sm\" class=\"fui-sidebar__nav-icon\"> </fui-icon>\r\n }\r\n\r\n <span class=\"fui-sidebar__nav-label\">{{ child.label }}</span>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </nav>\r\n }\r\n\r\n <!-- Custom Content -->\r\n <div class=\"fui-sidebar__content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <!-- Footer Content -->\r\n <div class=\"fui-sidebar__footer\">\r\n <ng-content select=\"[footer]\"></ng-content>\r\n </div>\r\n</aside>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject, ChangeDetectorRef, input, booleanAttribute, output, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
-
import { FuiIconComponent } from '@raintonic/formaui/components/icon';
|
|
5
|
-
import { FuiIntlBase } from '@raintonic/formaui/core';
|
|
6
|
-
|
|
7
|
-
const FUI_TAG_VARIANTS = [
|
|
8
|
-
'primary',
|
|
9
|
-
'secondary',
|
|
10
|
-
'success',
|
|
11
|
-
'warning',
|
|
12
|
-
'danger',
|
|
13
|
-
'info',
|
|
14
|
-
];
|
|
15
|
-
const FUI_TAG_SIZES = ['sm', 'md'];
|
|
16
|
-
|
|
17
|
-
class FuiTagIntl extends FuiIntlBase {
|
|
18
|
-
removeAriaLabel(label) {
|
|
19
|
-
return `Remove ${label}`;
|
|
20
|
-
}
|
|
21
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiTagIntl, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
|
|
22
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiTagIntl, providedIn: 'root' });
|
|
23
|
-
}
|
|
24
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiTagIntl, decorators: [{
|
|
25
|
-
type: Injectable,
|
|
26
|
-
args: [{ providedIn: 'root' }]
|
|
27
|
-
}] });
|
|
28
|
-
|
|
29
|
-
class FuiTagComponent {
|
|
30
|
-
intl = inject(FuiTagIntl);
|
|
31
|
-
_cdr = inject(ChangeDetectorRef);
|
|
32
|
-
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
33
|
-
variant = input('primary', { ...(ngDevMode ? { debugName: "variant" } : /* istanbul ignore next */ {}), transform: (v) => (FUI_TAG_VARIANTS.includes(v) ? v : 'primary') });
|
|
34
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
35
|
-
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
36
|
-
removable = input(false, ...(ngDevMode ? [{ debugName: "removable" }] : /* istanbul ignore next */ []));
|
|
37
|
-
selectable = input(false, ...(ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []));
|
|
38
|
-
selected = input(false, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
|
|
39
|
-
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
40
|
-
removed = output();
|
|
41
|
-
selectedChange = output();
|
|
42
|
-
_selected = signal(false, ...(ngDevMode ? [{ debugName: "_selected" }] : /* istanbul ignore next */ []));
|
|
43
|
-
computedClasses = computed(() => {
|
|
44
|
-
return `fui-tag fui-tag--${this.variant()} fui-tag--${this.size()}`;
|
|
45
|
-
}, ...(ngDevMode ? [{ debugName: "computedClasses" }] : /* istanbul ignore next */ []));
|
|
46
|
-
constructor() {
|
|
47
|
-
effect(() => {
|
|
48
|
-
this._selected.set(this.selected());
|
|
49
|
-
});
|
|
50
|
-
this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });
|
|
51
|
-
}
|
|
52
|
-
onClick() {
|
|
53
|
-
if (this.disabled())
|
|
54
|
-
return;
|
|
55
|
-
if (this.selectable()) {
|
|
56
|
-
this._selected.update((v) => !v);
|
|
57
|
-
this.selectedChange.emit(this._selected());
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
onSpace(event) {
|
|
61
|
-
event.preventDefault();
|
|
62
|
-
this.onClick();
|
|
63
|
-
}
|
|
64
|
-
onRemove(event) {
|
|
65
|
-
event.stopPropagation();
|
|
66
|
-
if (!this.disabled()) {
|
|
67
|
-
this.removed.emit({ tag: this });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiTagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
71
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiTagComponent, isStandalone: true, selector: "fui-tag", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed", selectedChange: "selectedChange" }, host: { listeners: { "click": "onClick()", "keydown.enter": "onClick()", "keydown.space": "onSpace($event)" }, properties: { "class": "computedClasses()", "class.fui-tag--selected": "_selected()", "class.fui-tag--disabled": "disabled()", "attr.role": "selectable() ? \"option\" : null", "attr.aria-selected": "selectable() ? _selected() : null", "attr.aria-pressed": "selectable() ? _selected() : null", "attr.tabindex": "selectable() || removable() ? 0 : null" }, classAttribute: "fui-tag" }, ngImport: i0, template: "<span class=\"fui-tag__content\">\r\n @if (icon()) {\r\n <fui-icon class=\"fui-tag__icon\" [name]=\"icon()!\" size=\"sm\" aria-hidden=\"true\" />\r\n }\r\n <span class=\"fui-tag__label\">{{ label() }}</span>\r\n</span>\r\n\r\n@if (removable() && !disabled()) {\r\n <button\r\n class=\"fui-tag__remove\"\r\n type=\"button\"\r\n [attr.aria-label]=\"intl.removeAriaLabel(label())\"\r\n (click)=\"onRemove($event)\"\r\n (keydown.enter)=\"onRemove($event)\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\" aria-hidden=\"true\" />\r\n </button>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-tag{display:inline-flex;align-items:center;gap:var(--fui-gap-4, .25rem);border-radius:var(--fui-border-radius-pill, 999px);font-family:var(--fui-font-family-sans);font-weight:var(--fui-font-weight-medium, 500);cursor:default;-webkit-user-select:none;user-select:none;transition:background-color border-color color var(--fui-duration-fast-02, .15s) var(--fui-ease-standard) 0ms}.fui-tag--sm{padding:.125rem var(--fui-gap-8, .5rem);font-size:var(--fui-font-size-01);height:1.25rem}.fui-tag--md{padding:.25rem var(--fui-gap-12, .75rem);font-size:var(--fui-font-size-02);height:1.625rem}.fui-tag--primary{background-color:var(--fui-primary-20);color:var(--fui-primary-80)}.fui-tag--secondary{background-color:var(--fui-secondary-20);color:var(--fui-secondary-80)}.fui-tag--success{background-color:var(--fui-success-20);color:var(--fui-success-80)}.fui-tag--warning{background-color:var(--fui-warning-20);color:var(--fui-warning-80)}.fui-tag--danger{background-color:var(--fui-danger-20);color:var(--fui-danger-80)}.fui-tag--info{background-color:var(--fui-info-20);color:var(--fui-info-80)}.fui-tag--selected.fui-tag--primary{background-color:var(--fui-primary);color:var(--fui-white)}.fui-tag--selected.fui-tag--secondary{background-color:var(--fui-secondary-80);color:var(--fui-white)}.fui-tag--selected.fui-tag--success{background-color:var(--fui-success);color:var(--fui-white)}.fui-tag--selected.fui-tag--warning{background-color:var(--fui-warning);color:var(--fui-white)}.fui-tag--selected.fui-tag--danger{background-color:var(--fui-danger);color:var(--fui-white)}.fui-tag--selected.fui-tag--info{background-color:var(--fui-info);color:var(--fui-white)}.fui-tag__content{display:inline-flex;align-items:center;gap:var(--fui-gap-4, .25rem)}.fui-tag__remove{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-tag__remove:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-tag__remove{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;width:1rem;height:1rem;margin-left:var(--fui-gap-4, .25rem)}.fui-tag__remove:hover{background-color:var(--fui-black-10)}.fui-tag[tabindex=\"0\"]{cursor:pointer}.fui-tag:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-tag--disabled{opacity:var(--fui-opacity-disabled, .38);cursor:not-allowed;pointer-events:none}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
72
|
-
}
|
|
73
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiTagComponent, decorators: [{
|
|
74
|
-
type: Component,
|
|
75
|
-
args: [{ selector: 'fui-tag', standalone: true, imports: [FuiIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
76
|
-
class: 'fui-tag',
|
|
77
|
-
'[class]': 'computedClasses()',
|
|
78
|
-
'[class.fui-tag--selected]': '_selected()',
|
|
79
|
-
'[class.fui-tag--disabled]': 'disabled()',
|
|
80
|
-
'[attr.role]': 'selectable() ? "option" : null',
|
|
81
|
-
'[attr.aria-selected]': 'selectable() ? _selected() : null',
|
|
82
|
-
'[attr.aria-pressed]': 'selectable() ? _selected() : null',
|
|
83
|
-
'[attr.tabindex]': 'selectable() || removable() ? 0 : null',
|
|
84
|
-
'(click)': 'onClick()',
|
|
85
|
-
'(keydown.enter)': 'onClick()',
|
|
86
|
-
'(keydown.space)': 'onSpace($event)',
|
|
87
|
-
}, template: "<span class=\"fui-tag__content\">\r\n @if (icon()) {\r\n <fui-icon class=\"fui-tag__icon\" [name]=\"icon()!\" size=\"sm\" aria-hidden=\"true\" />\r\n }\r\n <span class=\"fui-tag__label\">{{ label() }}</span>\r\n</span>\r\n\r\n@if (removable() && !disabled()) {\r\n <button\r\n class=\"fui-tag__remove\"\r\n type=\"button\"\r\n [attr.aria-label]=\"intl.removeAriaLabel(label())\"\r\n (click)=\"onRemove($event)\"\r\n (keydown.enter)=\"onRemove($event)\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\" aria-hidden=\"true\" />\r\n </button>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-tag{display:inline-flex;align-items:center;gap:var(--fui-gap-4, .25rem);border-radius:var(--fui-border-radius-pill, 999px);font-family:var(--fui-font-family-sans);font-weight:var(--fui-font-weight-medium, 500);cursor:default;-webkit-user-select:none;user-select:none;transition:background-color border-color color var(--fui-duration-fast-02, .15s) var(--fui-ease-standard) 0ms}.fui-tag--sm{padding:.125rem var(--fui-gap-8, .5rem);font-size:var(--fui-font-size-01);height:1.25rem}.fui-tag--md{padding:.25rem var(--fui-gap-12, .75rem);font-size:var(--fui-font-size-02);height:1.625rem}.fui-tag--primary{background-color:var(--fui-primary-20);color:var(--fui-primary-80)}.fui-tag--secondary{background-color:var(--fui-secondary-20);color:var(--fui-secondary-80)}.fui-tag--success{background-color:var(--fui-success-20);color:var(--fui-success-80)}.fui-tag--warning{background-color:var(--fui-warning-20);color:var(--fui-warning-80)}.fui-tag--danger{background-color:var(--fui-danger-20);color:var(--fui-danger-80)}.fui-tag--info{background-color:var(--fui-info-20);color:var(--fui-info-80)}.fui-tag--selected.fui-tag--primary{background-color:var(--fui-primary);color:var(--fui-white)}.fui-tag--selected.fui-tag--secondary{background-color:var(--fui-secondary-80);color:var(--fui-white)}.fui-tag--selected.fui-tag--success{background-color:var(--fui-success);color:var(--fui-white)}.fui-tag--selected.fui-tag--warning{background-color:var(--fui-warning);color:var(--fui-white)}.fui-tag--selected.fui-tag--danger{background-color:var(--fui-danger);color:var(--fui-white)}.fui-tag--selected.fui-tag--info{background-color:var(--fui-info);color:var(--fui-white)}.fui-tag__content{display:inline-flex;align-items:center;gap:var(--fui-gap-4, .25rem)}.fui-tag__remove{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-tag__remove:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-tag__remove{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;width:1rem;height:1rem;margin-left:var(--fui-gap-4, .25rem)}.fui-tag__remove:hover{background-color:var(--fui-black-10)}.fui-tag[tabindex=\"0\"]{cursor:pointer}.fui-tag:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-tag--disabled{opacity:var(--fui-opacity-disabled, .38);cursor:not-allowed;pointer-events:none}\n"] }]
|
|
88
|
-
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], selectedChange: [{ type: i0.Output, args: ["selectedChange"] }] } });
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Generated bundle index. Do not edit.
|
|
92
|
-
*/
|
|
93
|
-
|
|
94
|
-
export { FUI_TAG_SIZES, FUI_TAG_VARIANTS, FuiTagComponent, FuiTagIntl };
|
|
95
|
-
//# sourceMappingURL=raintonic-formaui-components-tag.mjs.map
|