@raintonic/formaui 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/raintonic-formaui-components-accordion.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-alert.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-avatar.mjs +2 -2
- 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-button-group.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-button-group.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 +2 -2
- package/fesm2022/raintonic-formaui-components-chip.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-data-table.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-date-picker.mjs +4 -4
- 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 +2 -2
- package/fesm2022/raintonic-formaui-components-dropdown-menu.mjs.map +1 -1
- 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 +2 -2
- package/fesm2022/raintonic-formaui-components-form-field.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 +2 -2
- 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 +2 -2
- package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-popover.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-progressbar.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-radio.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-select.mjs +4 -4
- 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 +4 -4
- package/fesm2022/raintonic-formaui-components-sidebar-nav-menu.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 +2 -2
- package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -1
- 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 +2 -2
- package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-toggle-group.mjs +4 -4
- package/fesm2022/raintonic-formaui-components-toggle-group.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-topbar.mjs +2 -2
- package/fesm2022/raintonic-formaui-components-topbar.mjs.map +1 -1
- package/fesm2022/raintonic-formaui-components-tree-select.mjs +2 -2
- 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 +4 -4
- package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -1
- package/fesm2022/raintonic-formaui.mjs +1 -1
- package/fesm2022/raintonic-formaui.mjs.map +1 -1
- package/llms-full.txt +8 -8
- package/package.json +1 -1
- package/styles/generated/_tokens.scss +8 -8
- package/styles/styles.css +8 -8
- package/types/raintonic-formaui.d.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-dropdown-menu.mjs","sources":["../../../lib/components/dropdown-menu/dropdown-menu-item.component.ts","../../../lib/components/dropdown-menu/dropdown-menu-item.component.html","../../../lib/components/dropdown-menu/dropdown-menu.component.ts","../../../lib/components/dropdown-menu/dropdown-menu.component.html","../../../lib/components/dropdown-menu/dropdown-menu-trigger.directive.ts","../../../lib/components/dropdown-menu/index.ts","../../../lib/components/dropdown-menu/raintonic-formaui-components-dropdown-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 dropdown-menu item variants\r\n */\r\nexport type DropdownMenuItemVariant = 'default' | 'danger';\r\n\r\nexport const DROPDOWN_MENU_ITEM_VARIANTS = ['default', 'danger'] as const;\r\n\r\n/**\r\n * # FuiDropdownMenuItem Component\r\n *\r\n * A menu item component designed to be used within fui-dropdown-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-dropdown-menu-item>Profile</fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * ### Menu Item with Icon\r\n * ```html\r\n * <fui-dropdown-menu-item>\r\n * <fui-icon name=\"user\" fuiPrefix></fui-icon>\r\n * Profile\r\n * </fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * ### Danger Menu Item\r\n * ```html\r\n * <fui-dropdown-menu-item variant=\"danger\">\r\n * <fui-icon name=\"trash\" fuiPrefix></fui-icon>\r\n * Delete Account\r\n * </fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * ### Disabled Menu Item\r\n * ```html\r\n * <fui-dropdown-menu-item [disabled]=\"true\">\r\n * Unavailable Option\r\n * </fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiDropdownMenuItemComponent } from '@raintonic/formaui/components/dropdown-menu';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiDropdownMenuItemComponent],\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-dropdown-menu-item',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './dropdown-menu-item.component.html',\r\n styleUrl: './dropdown-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 FuiDropdownMenuItemComponent {\r\n /**\r\n * Menu item variant that determines the visual style\r\n * @default 'default'\r\n */\r\n readonly variant = input<DropdownMenuItemVariant, DropdownMenuItemVariant | string>('default', {\r\n transform: (v) =>\r\n (DROPDOWN_MENU_ITEM_VARIANTS as readonly string[]).includes(v) ? (v as DropdownMenuItemVariant) : '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 FuiDropdownMenuComponent.\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-dropdown-menu-item', `fui-dropdown-menu-item--${this.variant()}`];\r\n\r\n if (this.disabled()) {\r\n classes.push('fui-dropdown-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 DestroyRef,\r\n effect,\r\n ElementRef,\r\n HostListener,\r\n inject,\r\n input,\r\n OnDestroy,\r\n output,\r\n signal,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport { FuiDropdownMenuItemComponent } from './dropdown-menu-item.component';\r\n\r\nimport { FuiOverlayService } from '@raintonic/formaui/cdk/overlay';\r\nimport { FuiConnectedPosition } from '@raintonic/formaui/cdk/overlay';\r\nimport { FuiPopupOverlayDirective } from '@raintonic/formaui/cdk/form-field';\r\n\r\n/**\r\n * Available dropdown-menu positions relative to the trigger element\r\n */\r\nexport type FuiDropdownMenuPosition =\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 FUI_DROPDOWN_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 dropdown-menu sizes\r\n */\r\nexport type FuiDropdownMenuSize = 'sm' | 'md' | 'lg';\r\n\r\nexport const FUI_DROPDOWN_MENU_SIZES = ['sm', 'md', 'lg'] as const;\r\n\r\n/**\r\n * # FuiDropdownMenu 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 fuiDropdownMenuTrigger 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 DropdownMenu with External Trigger\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### DropdownMenu with Custom Position\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #menu position=\"top-start\" size=\"lg\">\r\n * <fui-dropdown-menu-item>Profile</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item variant=\"danger\">Logout</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### DropdownMenu without Portal (for special cases)\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #menu [attachToBody]=\"false\">\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### DropdownMenu with Data Passed from Trigger\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger\r\n * [fuiDropdownMenuTriggerFor]=\"dynamicMenu\"\r\n * [menuTriggerData]=\"{ user: currentUser, items: menuItems }\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #dynamicMenu>\r\n * <!-- Access data in component using menu.menuData() -->\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ```typescript\r\n * @Component({\r\n * template: `\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item *ngFor=\"let item of menu.menuData()?.items\">\r\n * {{ item.label }}\r\n * </fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * `\r\n * })\r\n * export class MyComponent { }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-dropdown-menu',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './dropdown-menu.component.html',\r\n styleUrl: './dropdown-menu.component.scss',\r\n host: {\r\n '[class]': 'computedClasses()',\r\n '[attr.data-open]': 'isOpen() ? \"true\" : null',\r\n },\r\n hostDirectives: [\r\n {\r\n directive: FuiPopupOverlayDirective,\r\n inputs: [\r\n 'positions',\r\n 'panelClass',\r\n 'backdropClass',\r\n 'scrollStrategy',\r\n 'minWidthFromTrigger',\r\n 'closeOnEscape',\r\n 'closeOnBackdrop',\r\n 'viewportMargin',\r\n ],\r\n outputs: ['openedChange', 'escapeKey', 'backdropClick'],\r\n },\r\n ],\r\n})\r\nexport class FuiDropdownMenuComponent 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<FuiDropdownMenuPosition>('bottom-start');\r\n\r\n /**\r\n * Menu size variant\r\n * @default 'md'\r\n */\r\n readonly size = input<FuiDropdownMenuSize>('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 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 _closeAnimationTimeout: number | null = null;\r\n\r\n // Computed properties\r\n readonly computedClasses = computed(() => {\r\n const classes: string[] = [\r\n 'fui-dropdown-menu',\r\n `fui-dropdown-menu--${this.position()}`,\r\n `fui-dropdown-menu--${this.size()}`,\r\n ];\r\n\r\n if (this.disabled()) {\r\n classes.push('fui-dropdown-menu--disabled');\r\n }\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n // Injected dependencies\r\n private readonly _destroyRef = inject(DestroyRef);\r\n private readonly _elementRef: ElementRef<HTMLElement> = inject(ElementRef);\r\n // Kept for _isTopmostOverlay() — getActiveOverlays() is not exposed on the directive\r\n private readonly _overlayService: FuiOverlayService = inject(FuiOverlayService);\r\n readonly _popup = inject(FuiPopupOverlayDirective);\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(FuiDropdownMenuItemComponent, { descendants: true });\r\n\r\n constructor() {\r\n // Disable the directive's own ESC handler — we handle ESC via document:keydown\r\n // with _isTopmostOverlay() to support nested menus correctly.\r\n this._popup.closeOnEscape.set(false);\r\n\r\n // Drive the open/close animation lifecycle via an effect, so the close-animation\r\n // setTimeout is scheduled in reaction to the open-state signal changing.\r\n effect(() => {\r\n if (this._isOpen()) {\r\n // Panel just became open: initiate overlay creation.\r\n // _animationState is set to 'enter' INSIDE _openMenu(), deferred until AFTER\r\n // the overlay portal and position have been applied. This prevents the panel\r\n // from flashing at the in-place (wrong) position: the panel renders initially\r\n // with the default 'void' CSS state (opacity:0; translateY(-14px)), then the\r\n // enter transition fires from the correctly-positioned overlay location.\r\n this._openMenu();\r\n } else {\r\n // Panel just became closed: start the leave animation + cleanup timer.\r\n this._startCloseAnimation();\r\n }\r\n });\r\n\r\n // Emit open change events — cleaned up on destroy\r\n const openChangeEffect = effect(() => {\r\n this.openChange.emit(this._isOpen());\r\n });\r\n this._destroyRef.onDestroy(() => {\r\n openChangeEffect.destroy();\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 @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 // The directive's closeOnEscape is set false; we own the ESC handling here\r\n // via the document-level listener with _isTopmostOverlay() for nested menu support.\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.close();\r\n break;\r\n }\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-dropdown-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._restoreFocus();\r\n // Dispose overlay if still open (directive's ngOnDestroy would handle this,\r\n // but we call it explicitly to ensure cleanup order is predictable)\r\n if (this._popup.panelOpen()) {\r\n this._popup.close();\r\n }\r\n }\r\n\r\n private _openMenu(): void {\r\n // Panel is @if-rendered: it becomes part of the DOM only after _isOpen() = true\r\n // and a change-detection cycle. We use a double requestAnimationFrame to ensure\r\n // the panel element is rendered before wiring to the directive.\r\n requestAnimationFrame(() => {\r\n if (this._destroyRef.destroyed) return;\r\n requestAnimationFrame(() => {\r\n if (this._destroyRef.destroyed) return;\r\n const triggerEl = this._triggerElement();\r\n if (!triggerEl || !this.menuPanel) return;\r\n\r\n // Wire trigger and panel into the popup directive\r\n this._popup.setTrigger({ nativeElement: triggerEl } as ElementRef<HTMLElement>);\r\n this._popup.setPanel(this.menuPanel);\r\n\r\n // Configure directive options for this open session\r\n this._popup.panelClass.set(['fui-dropdown-menu-panel', `fui-dropdown-menu-panel--${this.size()}`]);\r\n this._popup.backdropClass.set('fui-dropdown-menu-backdrop');\r\n // Disable directive's internal backdrop-close: we handle it via backdropClick output\r\n // so our leave-animation close() runs instead of the directive's synchronous close().\r\n this._popup.closeOnBackdrop.set(false);\r\n // ESC is handled by the document-level handler with _isTopmostOverlay()\r\n this._popup.closeOnEscape.set(false);\r\n this._popup.positions.set(this._getPositionsForMenuPosition(this.position()));\r\n\r\n // Open the overlay\r\n this._popup.open();\r\n\r\n // Defer the enter animation until AFTER the overlay's internal position RAF\r\n // has run. The overlay-ref schedules a RAF inside attach() to apply position;\r\n // this RAF is queued AFTER that one (FIFO), so by the time it fires the panel\r\n // is at the correct trigger position. The panel rendered with 'void' state\r\n // (opacity:0) and the transition now fires from the correctly-placed location.\r\n requestAnimationFrame(() => {\r\n if (this._destroyRef.destroyed) return;\r\n this._animationState.set('enter');\r\n });\r\n\r\n // Subscribe to backdrop clicks so our animated close() runs (leave animation)\r\n const backdropSub = this._popup.backdropClick.subscribe(() => {\r\n backdropSub.unsubscribe();\r\n if (this.closeOnClickOutside()) {\r\n this.close();\r\n }\r\n });\r\n\r\n // aria and focus\r\n triggerEl.setAttribute('aria-expanded', 'true');\r\n this._previousFocusedElement = document.activeElement as HTMLElement;\r\n\r\n setTimeout(() => {\r\n if (this._destroyRef.destroyed) return;\r\n this._focusFirstItem();\r\n }, 0);\r\n });\r\n });\r\n }\r\n\r\n private _closeMenu(): void {\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._popup.close();\r\n this._restoreFocus();\r\n }\r\n\r\n private _getPositionsForMenuPosition(position: FuiDropdownMenuPosition): 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-dropdown-menu-item:not([aria-disabled=\"true\"])'));\r\n }\r\n\r\n /** @internal Called by FuiDropdownMenuTriggerDirective */\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 FuiDropdownMenuTriggerDirective */\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 _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 = setTimeout(() => {\r\n this._closeMenu();\r\n this._animationState.set('void');\r\n }, 150) as unknown as number;\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 const ref = this._popup.overlayRef();\r\n if (!ref) {\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 === ref;\r\n }\r\n}\r\n","@if (_isOpen() || _animationState() === 'leave') {\r\n <div class=\"fui-dropdown-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 { FuiDropdownMenuComponent } from './dropdown-menu.component';\r\n\r\n/**\r\n * # fuiDropdownMenuTrigger Directive\r\n *\r\n * A directive that marks an element as a dropdown menu trigger, similar to Angular Material's matMenuTriggerFor.\r\n * This directive should be used in conjunction with FuiDropdownMenuComponent.\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Usage\r\n * ```html\r\n * <button fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">Open Menu</button>\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### With Menu Reference\r\n * ```html\r\n * <button fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"userMenu\">\r\n * <fui-icon name=\"user\"></fui-icon>\r\n * User Menu\r\n * </button>\r\n *\r\n * <fui-dropdown-menu #userMenu position=\"bottom-end\">\r\n * <fui-dropdown-menu-item>Profile</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Settings</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item variant=\"danger\">Logout</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### Passing Data to Menu\r\n * ```html\r\n * <button fuiDropdownMenuTrigger\r\n * [fuiDropdownMenuTriggerFor]=\"dynamicMenu\"\r\n * [menuTriggerData]=\"{ user: currentUser, role: 'admin' }\">\r\n * Open Menu\r\n * </button>\r\n *\r\n * <fui-dropdown-menu #dynamicMenu>\r\n * <!-- Access menu data in your component via menu.menuData() -->\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiDropdownMenuTriggerDirective, FuiDropdownMenuComponent, FuiDropdownMenuItemComponent } from '@raintonic/formaui/components/dropdown-menu';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiDropdownMenuTriggerDirective, FuiDropdownMenuComponent, FuiDropdownMenuItemComponent],\r\n * template: `\r\n * <button fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">Open Menu</button>\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * `\r\n * })\r\n * export class MyComponent { }\r\n * ```\r\n */\r\n@Directive({\r\n selector: '[fuiDropdownMenuTrigger]',\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 FuiDropdownMenuTriggerDirective 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 fuiDropdownMenuTriggerFor = input<FuiDropdownMenuComponent | 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: FuiDropdownMenuComponent | null = null;\r\n\r\n constructor() {\r\n // Set up the menu reference when fuiDropdownMenuTriggerFor changes\r\n effect(() => {\r\n const menuRef = this.fuiDropdownMenuTriggerFor();\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.fuiDropdownMenuTriggerFor();\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 dropdown-menu components\r\nexport * from './dropdown-menu.component';\r\nexport * from './dropdown-menu-item.component';\r\nexport * from './dropdown-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
|
+
{"version":3,"file":"raintonic-formaui-components-dropdown-menu.mjs","sources":["../../../lib/components/dropdown-menu/dropdown-menu-item.component.ts","../../../lib/components/dropdown-menu/dropdown-menu-item.component.html","../../../lib/components/dropdown-menu/dropdown-menu.component.ts","../../../lib/components/dropdown-menu/dropdown-menu.component.html","../../../lib/components/dropdown-menu/dropdown-menu-trigger.directive.ts","../../../lib/components/dropdown-menu/index.ts","../../../lib/components/dropdown-menu/raintonic-formaui-components-dropdown-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 dropdown-menu item variants\r\n */\r\nexport type DropdownMenuItemVariant = 'default' | 'danger';\r\n\r\nexport const DROPDOWN_MENU_ITEM_VARIANTS = ['default', 'danger'] as const;\r\n\r\n/**\r\n * # FuiDropdownMenuItem Component\r\n *\r\n * A menu item component designed to be used within fui-dropdown-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-dropdown-menu-item>Profile</fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * ### Menu Item with Icon\r\n * ```html\r\n * <fui-dropdown-menu-item>\r\n * <fui-icon name=\"user\" fuiPrefix></fui-icon>\r\n * Profile\r\n * </fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * ### Danger Menu Item\r\n * ```html\r\n * <fui-dropdown-menu-item variant=\"danger\">\r\n * <fui-icon name=\"trash\" fuiPrefix></fui-icon>\r\n * Delete Account\r\n * </fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * ### Disabled Menu Item\r\n * ```html\r\n * <fui-dropdown-menu-item [disabled]=\"true\">\r\n * Unavailable Option\r\n * </fui-dropdown-menu-item>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiDropdownMenuItemComponent } from '@raintonic/formaui/components/dropdown-menu';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiDropdownMenuItemComponent],\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-dropdown-menu-item',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './dropdown-menu-item.component.html',\r\n styleUrl: './dropdown-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 FuiDropdownMenuItemComponent {\r\n /**\r\n * Menu item variant that determines the visual style\r\n * @default 'default'\r\n */\r\n readonly variant = input<DropdownMenuItemVariant, DropdownMenuItemVariant | string>('default', {\r\n transform: (v) =>\r\n (DROPDOWN_MENU_ITEM_VARIANTS as readonly string[]).includes(v) ? (v as DropdownMenuItemVariant) : '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 FuiDropdownMenuComponent.\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-dropdown-menu-item', `fui-dropdown-menu-item--${this.variant()}`];\r\n\r\n if (this.disabled()) {\r\n classes.push('fui-dropdown-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 DestroyRef,\r\n effect,\r\n ElementRef,\r\n HostListener,\r\n inject,\r\n input,\r\n OnDestroy,\r\n output,\r\n signal,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport { FuiDropdownMenuItemComponent } from './dropdown-menu-item.component';\r\n\r\nimport { FuiOverlayService } from '@raintonic/formaui/cdk/overlay';\r\nimport { FuiConnectedPosition } from '@raintonic/formaui/cdk/overlay';\r\nimport { FuiPopupOverlayDirective } from '@raintonic/formaui/cdk/form-field';\r\n\r\n/**\r\n * Available dropdown-menu positions relative to the trigger element\r\n */\r\nexport type FuiDropdownMenuPosition =\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 FUI_DROPDOWN_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 dropdown-menu sizes\r\n */\r\nexport type FuiDropdownMenuSize = 'sm' | 'md' | 'lg';\r\n\r\nexport const FUI_DROPDOWN_MENU_SIZES = ['sm', 'md', 'lg'] as const;\r\n\r\n/**\r\n * # FuiDropdownMenu 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 fuiDropdownMenuTrigger 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 DropdownMenu with External Trigger\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### DropdownMenu with Custom Position\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #menu position=\"top-start\" size=\"lg\">\r\n * <fui-dropdown-menu-item>Profile</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item variant=\"danger\">Logout</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### DropdownMenu without Portal (for special cases)\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #menu [attachToBody]=\"false\">\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### DropdownMenu with Data Passed from Trigger\r\n * ```html\r\n * <button fuiButton fuiDropdownMenuTrigger\r\n * [fuiDropdownMenuTriggerFor]=\"dynamicMenu\"\r\n * [menuTriggerData]=\"{ user: currentUser, items: menuItems }\">\r\n * Open Menu\r\n * </button>\r\n * <fui-dropdown-menu #dynamicMenu>\r\n * <!-- Access data in component using menu.menuData() -->\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ```typescript\r\n * @Component({\r\n * template: `\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item *ngFor=\"let item of menu.menuData()?.items\">\r\n * {{ item.label }}\r\n * </fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * `\r\n * })\r\n * export class MyComponent { }\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-dropdown-menu',\r\n standalone: true,\r\n imports: [],\r\n templateUrl: './dropdown-menu.component.html',\r\n styleUrl: './dropdown-menu.component.scss',\r\n host: {\r\n '[class]': 'computedClasses()',\r\n '[attr.data-open]': 'isOpen() ? \"true\" : null',\r\n },\r\n hostDirectives: [\r\n {\r\n directive: FuiPopupOverlayDirective,\r\n inputs: [\r\n 'positions',\r\n 'panelClass',\r\n 'backdropClass',\r\n 'scrollStrategy',\r\n 'minWidthFromTrigger',\r\n 'closeOnEscape',\r\n 'closeOnBackdrop',\r\n 'viewportMargin',\r\n ],\r\n outputs: ['openedChange', 'escapeKey', 'backdropClick'],\r\n },\r\n ],\r\n})\r\nexport class FuiDropdownMenuComponent 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<FuiDropdownMenuPosition>('bottom-start');\r\n\r\n /**\r\n * Menu size variant\r\n * @default 'md'\r\n */\r\n readonly size = input<FuiDropdownMenuSize>('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 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 _closeAnimationTimeout: number | null = null;\r\n\r\n // Computed properties\r\n readonly computedClasses = computed(() => {\r\n const classes: string[] = [\r\n 'fui-dropdown-menu',\r\n `fui-dropdown-menu--${this.position()}`,\r\n `fui-dropdown-menu--${this.size()}`,\r\n ];\r\n\r\n if (this.disabled()) {\r\n classes.push('fui-dropdown-menu--disabled');\r\n }\r\n\r\n return classes.join(' ');\r\n });\r\n\r\n // Injected dependencies\r\n private readonly _destroyRef = inject(DestroyRef);\r\n private readonly _elementRef: ElementRef<HTMLElement> = inject(ElementRef);\r\n // Kept for _isTopmostOverlay() — getActiveOverlays() is not exposed on the directive\r\n private readonly _overlayService: FuiOverlayService = inject(FuiOverlayService);\r\n readonly _popup = inject(FuiPopupOverlayDirective);\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(FuiDropdownMenuItemComponent, { descendants: true });\r\n\r\n constructor() {\r\n // Disable the directive's own ESC handler — we handle ESC via document:keydown\r\n // with _isTopmostOverlay() to support nested menus correctly.\r\n this._popup.closeOnEscape.set(false);\r\n\r\n // Drive the open/close animation lifecycle via an effect, so the close-animation\r\n // setTimeout is scheduled in reaction to the open-state signal changing.\r\n effect(() => {\r\n if (this._isOpen()) {\r\n // Panel just became open: initiate overlay creation.\r\n // _animationState is set to 'enter' INSIDE _openMenu(), deferred until AFTER\r\n // the overlay portal and position have been applied. This prevents the panel\r\n // from flashing at the in-place (wrong) position: the panel renders initially\r\n // with the default 'void' CSS state (opacity:0; translateY(-14px)), then the\r\n // enter transition fires from the correctly-positioned overlay location.\r\n this._openMenu();\r\n } else {\r\n // Panel just became closed: start the leave animation + cleanup timer.\r\n this._startCloseAnimation();\r\n }\r\n });\r\n\r\n // Emit open change events — cleaned up on destroy\r\n const openChangeEffect = effect(() => {\r\n this.openChange.emit(this._isOpen());\r\n });\r\n this._destroyRef.onDestroy(() => {\r\n openChangeEffect.destroy();\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 @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 // The directive's closeOnEscape is set false; we own the ESC handling here\r\n // via the document-level listener with _isTopmostOverlay() for nested menu support.\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this.close();\r\n break;\r\n }\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-dropdown-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._restoreFocus();\r\n // Dispose overlay if still open (directive's ngOnDestroy would handle this,\r\n // but we call it explicitly to ensure cleanup order is predictable)\r\n if (this._popup.panelOpen()) {\r\n this._popup.close();\r\n }\r\n }\r\n\r\n private _openMenu(): void {\r\n // Panel is @if-rendered: it becomes part of the DOM only after _isOpen() = true\r\n // and a change-detection cycle. We use a double requestAnimationFrame to ensure\r\n // the panel element is rendered before wiring to the directive.\r\n requestAnimationFrame(() => {\r\n if (this._destroyRef.destroyed) return;\r\n requestAnimationFrame(() => {\r\n if (this._destroyRef.destroyed) return;\r\n const triggerEl = this._triggerElement();\r\n if (!triggerEl || !this.menuPanel) return;\r\n\r\n // Wire trigger and panel into the popup directive\r\n this._popup.setTrigger({ nativeElement: triggerEl } as ElementRef<HTMLElement>);\r\n this._popup.setPanel(this.menuPanel);\r\n\r\n // Configure directive options for this open session\r\n this._popup.panelClass.set(['fui-dropdown-menu-panel', `fui-dropdown-menu-panel--${this.size()}`]);\r\n this._popup.backdropClass.set('fui-dropdown-menu-backdrop');\r\n // Disable directive's internal backdrop-close: we handle it via backdropClick output\r\n // so our leave-animation close() runs instead of the directive's synchronous close().\r\n this._popup.closeOnBackdrop.set(false);\r\n // ESC is handled by the document-level handler with _isTopmostOverlay()\r\n this._popup.closeOnEscape.set(false);\r\n this._popup.positions.set(this._getPositionsForMenuPosition(this.position()));\r\n\r\n // Open the overlay\r\n this._popup.open();\r\n\r\n // Defer the enter animation until AFTER the overlay's internal position RAF\r\n // has run. The overlay-ref schedules a RAF inside attach() to apply position;\r\n // this RAF is queued AFTER that one (FIFO), so by the time it fires the panel\r\n // is at the correct trigger position. The panel rendered with 'void' state\r\n // (opacity:0) and the transition now fires from the correctly-placed location.\r\n requestAnimationFrame(() => {\r\n if (this._destroyRef.destroyed) return;\r\n this._animationState.set('enter');\r\n });\r\n\r\n // Subscribe to backdrop clicks so our animated close() runs (leave animation)\r\n const backdropSub = this._popup.backdropClick.subscribe(() => {\r\n backdropSub.unsubscribe();\r\n if (this.closeOnClickOutside()) {\r\n this.close();\r\n }\r\n });\r\n\r\n // aria and focus\r\n triggerEl.setAttribute('aria-expanded', 'true');\r\n this._previousFocusedElement = document.activeElement as HTMLElement;\r\n\r\n setTimeout(() => {\r\n if (this._destroyRef.destroyed) return;\r\n this._focusFirstItem();\r\n }, 0);\r\n });\r\n });\r\n }\r\n\r\n private _closeMenu(): void {\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._popup.close();\r\n this._restoreFocus();\r\n }\r\n\r\n private _getPositionsForMenuPosition(position: FuiDropdownMenuPosition): 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-dropdown-menu-item:not([aria-disabled=\"true\"])'));\r\n }\r\n\r\n /** @internal Called by FuiDropdownMenuTriggerDirective */\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 FuiDropdownMenuTriggerDirective */\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 _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 = setTimeout(() => {\r\n this._closeMenu();\r\n this._animationState.set('void');\r\n }, 150) as unknown as number;\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 const ref = this._popup.overlayRef();\r\n if (!ref) {\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 === ref;\r\n }\r\n}\r\n","@if (_isOpen() || _animationState() === 'leave') {\r\n <div class=\"fui-dropdown-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 { FuiDropdownMenuComponent } from './dropdown-menu.component';\r\n\r\n/**\r\n * # fuiDropdownMenuTrigger Directive\r\n *\r\n * A directive that marks an element as a dropdown menu trigger, similar to Angular Material's matMenuTriggerFor.\r\n * This directive should be used in conjunction with FuiDropdownMenuComponent.\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic Usage\r\n * ```html\r\n * <button fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">Open Menu</button>\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### With Menu Reference\r\n * ```html\r\n * <button fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"userMenu\">\r\n * <fui-icon name=\"user\"></fui-icon>\r\n * User Menu\r\n * </button>\r\n *\r\n * <fui-dropdown-menu #userMenu position=\"bottom-end\">\r\n * <fui-dropdown-menu-item>Profile</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Settings</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item variant=\"danger\">Logout</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * ### Passing Data to Menu\r\n * ```html\r\n * <button fuiDropdownMenuTrigger\r\n * [fuiDropdownMenuTriggerFor]=\"dynamicMenu\"\r\n * [menuTriggerData]=\"{ user: currentUser, role: 'admin' }\">\r\n * Open Menu\r\n * </button>\r\n *\r\n * <fui-dropdown-menu #dynamicMenu>\r\n * <!-- Access menu data in your component via menu.menuData() -->\r\n * </fui-dropdown-menu>\r\n * ```\r\n *\r\n * @example\r\n * ```typescript\r\n * import { FuiDropdownMenuTriggerDirective, FuiDropdownMenuComponent, FuiDropdownMenuItemComponent } from '@raintonic/formaui/components/dropdown-menu';\r\n *\r\n * @Component({\r\n * standalone: true,\r\n * imports: [FuiDropdownMenuTriggerDirective, FuiDropdownMenuComponent, FuiDropdownMenuItemComponent],\r\n * template: `\r\n * <button fuiDropdownMenuTrigger [fuiDropdownMenuTriggerFor]=\"menu\">Open Menu</button>\r\n * <fui-dropdown-menu #menu>\r\n * <fui-dropdown-menu-item>Option 1</fui-dropdown-menu-item>\r\n * <fui-dropdown-menu-item>Option 2</fui-dropdown-menu-item>\r\n * </fui-dropdown-menu>\r\n * `\r\n * })\r\n * export class MyComponent { }\r\n * ```\r\n */\r\n@Directive({\r\n selector: '[fuiDropdownMenuTrigger]',\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 FuiDropdownMenuTriggerDirective 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 fuiDropdownMenuTriggerFor = input<FuiDropdownMenuComponent | 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: FuiDropdownMenuComponent | null = null;\r\n\r\n constructor() {\r\n // Set up the menu reference when fuiDropdownMenuTriggerFor changes\r\n effect(() => {\r\n const menuRef = this.fuiDropdownMenuTriggerFor();\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.fuiDropdownMenuTriggerFor();\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 dropdown-menu components\r\nexport * from './dropdown-menu.component';\r\nexport * from './dropdown-menu-item.component';\r\nexport * from './dropdown-menu-trigger.directive';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ class FuiEmptyStateComponent {
|
|
|
12
12
|
return s === 'sm' ? 'md' : 'lg';
|
|
13
13
|
}, ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
14
14
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiEmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiEmptyStateComponent, isStandalone: true, selector: "fui-empty-state", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "class.fui-empty-state--sm": "size() === \"sm\"", "class.fui-empty-state--md": "size() === \"md\"", "class.fui-empty-state--lg": "size() === \"lg\"" }, classAttribute: "fui-empty-state" }, ngImport: i0, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-spacing-13, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-spacing-6, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-spacing-4, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-sans);font-size:var(--fui-text-lg);font-weight:var(--fui-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-text-base);color:var(--fui-text-secondary);margin:0;line-height:
|
|
15
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiEmptyStateComponent, isStandalone: true, selector: "fui-empty-state", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "class.fui-empty-state--sm": "size() === \"sm\"", "class.fui-empty-state--md": "size() === \"md\"", "class.fui-empty-state--lg": "size() === \"lg\"" }, classAttribute: "fui-empty-state" }, ngImport: i0, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-spacing-13, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-spacing-6, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-spacing-4, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-sans);font-size:var(--fui-text-lg);font-weight:var(--fui-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-text-base);color:var(--fui-text-secondary);margin:0;line-height:var(--fui-leading-normal)}.fui-empty-state__actions{margin-top:var(--fui-spacing-7, 1rem);display:flex;gap:var(--fui-spacing-4, .5rem)}.fui-empty-state--sm{padding:var(--fui-spacing-9, 1.5rem)}.fui-empty-state--sm .fui-empty-state__title{font-size:var(--fui-text-md)}.fui-empty-state--lg{padding:4.5rem}.fui-empty-state--lg .fui-empty-state__title{font-size:var(--fui-text-xl)}\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 });
|
|
16
16
|
}
|
|
17
17
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiEmptyStateComponent, decorators: [{
|
|
18
18
|
type: Component,
|
|
@@ -22,7 +22,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
22
22
|
'[class.fui-empty-state--md]': 'size() === "md"',
|
|
23
23
|
'[class.fui-empty-state--lg]': 'size() === "lg"',
|
|
24
24
|
role: 'status',
|
|
25
|
-
}, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-spacing-13, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-spacing-6, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-spacing-4, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-sans);font-size:var(--fui-text-lg);font-weight:var(--fui-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-text-base);color:var(--fui-text-secondary);margin:0;line-height:
|
|
25
|
+
}, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-spacing-13, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-spacing-6, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-spacing-4, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-sans);font-size:var(--fui-text-lg);font-weight:var(--fui-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-text-base);color:var(--fui-text-secondary);margin:0;line-height:var(--fui-leading-normal)}.fui-empty-state__actions{margin-top:var(--fui-spacing-7, 1rem);display:flex;gap:var(--fui-spacing-4, .5rem)}.fui-empty-state--sm{padding:var(--fui-spacing-9, 1.5rem)}.fui-empty-state--sm .fui-empty-state__title{font-size:var(--fui-text-md)}.fui-empty-state--lg{padding:4.5rem}.fui-empty-state--lg .fui-empty-state__title{font-size:var(--fui-text-xl)}\n"] }]
|
|
26
26
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
27
27
|
|
|
28
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-empty-state.mjs","sources":["../../../lib/components/empty-state/empty-state.component.ts","../../../lib/components/empty-state/empty-state.component.html","../../../lib/components/empty-state/raintonic-formaui-components-empty-state.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input } from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\n\r\n@Component({\r\n selector: 'fui-empty-state',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './empty-state.component.html',\r\n styleUrls: ['./empty-state.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-empty-state',\r\n '[class.fui-empty-state--sm]': 'size() === \"sm\"',\r\n '[class.fui-empty-state--md]': 'size() === \"md\"',\r\n '[class.fui-empty-state--lg]': 'size() === \"lg\"',\r\n role: 'status',\r\n },\r\n})\r\nexport class FuiEmptyStateComponent {\r\n readonly icon = input<string | null>(null);\r\n readonly title = input<string | null>(null);\r\n readonly description = input<string | null>(null);\r\n readonly size = input<'sm' | 'md' | 'lg'>('md');\r\n\r\n readonly iconSize = computed(() => {\r\n const s = this.size();\r\n return s === 'sm' ? 'md' : 'lg';\r\n });\r\n}\r\n","<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAmBa,sBAAsB,CAAA;AACxB,IAAA,IAAI,GAAG,KAAK,CAAgB,IAAI,2EAAC;AACjC,IAAA,KAAK,GAAG,KAAK,CAAgB,IAAI,4EAAC;AAClC,IAAA,WAAW,GAAG,KAAK,CAAgB,IAAI,kFAAC;AACxC,IAAA,IAAI,GAAG,KAAK,CAAqB,IAAI,2EAAC;AAEtC,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAK;AAChC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;AACjC,IAAA,CAAC,+EAAC;uGATS,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAtB,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,UAAA,EAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,EAAA,cAAA,EAAA,iBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnBnC,ohBAgBA,EAAA,MAAA,EAAA,CAAA,
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-empty-state.mjs","sources":["../../../lib/components/empty-state/empty-state.component.ts","../../../lib/components/empty-state/empty-state.component.html","../../../lib/components/empty-state/raintonic-formaui-components-empty-state.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input } from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\n\r\n@Component({\r\n selector: 'fui-empty-state',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './empty-state.component.html',\r\n styleUrls: ['./empty-state.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-empty-state',\r\n '[class.fui-empty-state--sm]': 'size() === \"sm\"',\r\n '[class.fui-empty-state--md]': 'size() === \"md\"',\r\n '[class.fui-empty-state--lg]': 'size() === \"lg\"',\r\n role: 'status',\r\n },\r\n})\r\nexport class FuiEmptyStateComponent {\r\n readonly icon = input<string | null>(null);\r\n readonly title = input<string | null>(null);\r\n readonly description = input<string | null>(null);\r\n readonly size = input<'sm' | 'md' | 'lg'>('md');\r\n\r\n readonly iconSize = computed(() => {\r\n const s = this.size();\r\n return s === 'sm' ? 'md' : 'lg';\r\n });\r\n}\r\n","<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAmBa,sBAAsB,CAAA;AACxB,IAAA,IAAI,GAAG,KAAK,CAAgB,IAAI,2EAAC;AACjC,IAAA,KAAK,GAAG,KAAK,CAAgB,IAAI,4EAAC;AAClC,IAAA,WAAW,GAAG,KAAK,CAAgB,IAAI,kFAAC;AACxC,IAAA,IAAI,GAAG,KAAK,CAAqB,IAAI,2EAAC;AAEtC,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAK;AAChC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;AACjC,IAAA,CAAC,+EAAC;uGATS,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAtB,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,UAAA,EAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,EAAA,cAAA,EAAA,iBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnBnC,ohBAgBA,EAAA,MAAA,EAAA,CAAA,u/BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDVY,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAaf,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAhBlC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,EAAA,UAAA,EACf,IAAI,EAAA,OAAA,EACP,CAAC,gBAAgB,CAAC,EAAA,eAAA,EAGV,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,KAAK,EAAE,iBAAiB;AACxB,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,IAAI,EAAE,QAAQ;AACf,qBAAA,EAAA,QAAA,EAAA,ohBAAA,EAAA,MAAA,EAAA,CAAA,u/BAAA,CAAA,EAAA;;;AEjBH;;AAEG;;;;"}
|
|
@@ -246,7 +246,7 @@ class FuiFileUploadComponent {
|
|
|
246
246
|
return URL.createObjectURL(file);
|
|
247
247
|
}
|
|
248
248
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiFileUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
249
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiFileUploadComponent, isStandalone: true, selector: "fui-file-upload", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesSelected: "filesSelected", fileRemoved: "fileRemoved", filesDropped: "filesDropped", validationErrors: "validationErrors" }, host: { properties: { "class.fui-file-upload--disabled": "disabled()", "class.fui-file-upload--drag-over": "_isDragOver()", "class.fui-file-upload--has-files": "_files().length > 0" }, classAttribute: "fui-file-upload" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag & drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\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-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-out);transition-delay:0ms}.fui-motion-fade-out{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in);transition-delay:0ms}.fui-motion-slide-in-bottom{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition-property:transform,opacity;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay: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-base) var(--fui-ease-out)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-spacing-4);padding:var(--fui-spacing-11, 2rem);border:2px dashed var(--fui-border-default);border-radius:var(--fui-radius-md);background-color:var(--fui-bg-subtle);cursor:pointer;text-align:center;transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-border-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-brand-fg);font-weight:var(--fui-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-spacing-6, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-spacing-2)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-spacing-6, .75rem);padding:var(--fui-spacing-4, .5rem) var(--fui-spacing-6, .75rem);border:1px solid var(--fui-border-default);border-radius:var(--fui-radius-sm);background-color:var(--fui-bg-default, var(--fui-bg-default));transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__file-item--error{border-color:var(--fui-border-error);background-color:var(--fui-error-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);font-weight:var(--fui-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition-property:opacity,color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-text-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-border-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-state-disabled-opacity, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition: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 });
|
|
249
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiFileUploadComponent, isStandalone: true, selector: "fui-file-upload", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesSelected: "filesSelected", fileRemoved: "fileRemoved", filesDropped: "filesDropped", validationErrors: "validationErrors" }, host: { properties: { "class.fui-file-upload--disabled": "disabled()", "class.fui-file-upload--drag-over": "_isDragOver()", "class.fui-file-upload--has-files": "_files().length > 0" }, classAttribute: "fui-file-upload" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag & drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\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-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-out);transition-delay:0ms}.fui-motion-fade-out{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in);transition-delay:0ms}.fui-motion-slide-in-bottom{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition-property:transform,opacity;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay: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-base) var(--fui-ease-out)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-spacing-4);padding:var(--fui-spacing-11, 2rem);border:var(--fui-border-width-md) dashed var(--fui-border-default);border-radius:var(--fui-radius-md);background-color:var(--fui-bg-subtle);cursor:pointer;text-align:center;transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-border-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-primary-fg);font-weight:var(--fui-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-spacing-6, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-spacing-2)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-spacing-6, .75rem);padding:var(--fui-spacing-4, .5rem) var(--fui-spacing-6, .75rem);border:var(--fui-border-width-sm) solid var(--fui-border-default);border-radius:var(--fui-radius-sm);background-color:var(--fui-bg-default, var(--fui-bg-default));transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__file-item--error{border-color:var(--fui-border-error);background-color:var(--fui-error-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);font-weight:var(--fui-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition-property:opacity,color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-text-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-border-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-state-disabled-opacity, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition: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 });
|
|
250
250
|
}
|
|
251
251
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiFileUploadComponent, decorators: [{
|
|
252
252
|
type: Component,
|
|
@@ -255,7 +255,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
255
255
|
'[class.fui-file-upload--disabled]': 'disabled()',
|
|
256
256
|
'[class.fui-file-upload--drag-over]': '_isDragOver()',
|
|
257
257
|
'[class.fui-file-upload--has-files]': '_files().length > 0',
|
|
258
|
-
}, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag & drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\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-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-out);transition-delay:0ms}.fui-motion-fade-out{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in);transition-delay:0ms}.fui-motion-slide-in-bottom{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition-property:transform,opacity;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay: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-base) var(--fui-ease-out)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-spacing-4);padding:var(--fui-spacing-11, 2rem);border:
|
|
258
|
+
}, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag & drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\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-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-out);transition-delay:0ms}.fui-motion-fade-out{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in);transition-delay:0ms}.fui-motion-slide-in-bottom{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition-property:transform,opacity;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay: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-base) var(--fui-ease-out)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-spacing-4);padding:var(--fui-spacing-11, 2rem);border:var(--fui-border-width-md) dashed var(--fui-border-default);border-radius:var(--fui-radius-md);background-color:var(--fui-bg-subtle);cursor:pointer;text-align:center;transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-border-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-primary-fg);font-weight:var(--fui-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-spacing-6, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-spacing-2)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-spacing-6, .75rem);padding:var(--fui-spacing-4, .5rem) var(--fui-spacing-6, .75rem);border:var(--fui-border-width-sm) solid var(--fui-border-default);border-radius:var(--fui-radius-sm);background-color:var(--fui-bg-default, var(--fui-bg-default));transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__file-item--error{border-color:var(--fui-border-error);background-color:var(--fui-error-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);font-weight:var(--fui-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition-property:opacity,color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-text-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-border-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-state-disabled-opacity, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition:none}}\n"] }]
|
|
259
259
|
}], ctorParameters: () => [], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], fileRemoved: [{ type: i0.Output, args: ["fileRemoved"] }], filesDropped: [{ type: i0.Output, args: ["filesDropped"] }], validationErrors: [{ type: i0.Output, args: ["validationErrors"] }], fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
|
|
260
260
|
|
|
261
261
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"raintonic-formaui-components-file-upload.mjs","sources":["../../../lib/components/file-upload/file-upload.intl.ts","../../../lib/components/file-upload/file-upload.component.ts","../../../lib/components/file-upload/file-upload.component.html","../../../lib/components/file-upload/raintonic-formaui-components-file-upload.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { FuiIntlBase } from '@raintonic/formaui/core';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FuiFileUploadIntl extends FuiIntlBase {\r\n dropzoneAriaLabel = 'Drop files here or click to browse';\r\n removeFileAriaLabel(name: string): string {\r\n return `Remove ${name}`;\r\n }\r\n}\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n ViewEncapsulation,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n ElementRef,\r\n WritableSignal,\r\n booleanAttribute,\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 { FileUploadFile, FileUploadValidationError } from './file-upload.types';\r\nimport { FuiFileUploadIntl } from './file-upload.intl';\r\n\r\n/**\r\n * # FuiFileUploadComponent\r\n *\r\n * A file upload component with drag-and-drop support, file previews, and validation.\r\n *\r\n * ## Features\r\n * - Drag & drop file upload\r\n * - Click to browse\r\n * - File type, size, and count validation\r\n * - Image preview thumbnails\r\n * - Accessible (keyboard, ARIA)\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic\r\n * ```html\r\n * <fui-file-upload\r\n * accept=\"image/*,.pdf\"\r\n * [multiple]=\"true\"\r\n * [maxFileSize]=\"5242880\"\r\n * (filesSelected)=\"onFiles($event)\"\r\n * ></fui-file-upload>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-file-upload',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './file-upload.component.html',\r\n styleUrls: ['./file-upload.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-file-upload',\r\n '[class.fui-file-upload--disabled]': 'disabled()',\r\n '[class.fui-file-upload--drag-over]': '_isDragOver()',\r\n '[class.fui-file-upload--has-files]': '_files().length > 0',\r\n },\r\n})\r\nexport class FuiFileUploadComponent {\r\n readonly intl = inject(FuiFileUploadIntl);\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\r\n readonly accept = input('');\r\n readonly multiple = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly maxFileSize = input(0);\r\n readonly maxFiles = input(0);\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly showPreview = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n // Outputs\r\n readonly filesSelected = output<FileUploadFile[]>();\r\n readonly fileRemoved = output<FileUploadFile>();\r\n readonly filesDropped = output<FileUploadFile[]>();\r\n readonly validationErrors = output<FileUploadValidationError[]>();\r\n\r\n // Internal state\r\n readonly _files: WritableSignal<FileUploadFile[]> = signal([]);\r\n readonly _isDragOver: WritableSignal<boolean> = signal(false);\r\n\r\n // ViewChild\r\n readonly fileInput = viewChild<ElementRef<HTMLInputElement>>('fileInput');\r\n\r\n // Public methods\r\n browse(): void {\r\n if (this.disabled()) return;\r\n this.fileInput()?.nativeElement.click();\r\n }\r\n\r\n removeFile(index: number): void {\r\n if (this.disabled()) return;\r\n const files = [...this._files()];\r\n const removed = files.splice(index, 1)[0];\r\n if (removed) {\r\n if (removed.previewUrl) {\r\n URL.revokeObjectURL(removed.previewUrl);\r\n }\r\n this._files.set(files);\r\n this.fileRemoved.emit(removed);\r\n }\r\n }\r\n\r\n clearAll(): void {\r\n const files = this._files();\r\n for (const f of files) {\r\n if (f.previewUrl) {\r\n URL.revokeObjectURL(f.previewUrl);\r\n }\r\n }\r\n this._files.set([]);\r\n }\r\n\r\n getFiles(): FileUploadFile[] {\r\n return this._files();\r\n }\r\n\r\n // Template event handlers\r\n _onFileInputChange(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n this._processFiles(input.files);\r\n }\r\n // Reset input so the same file can be selected again\r\n input.value = '';\r\n }\r\n\r\n _onDragEnter(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragOver(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragLeave(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n }\r\n\r\n _onDrop(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n\r\n if (this.disabled()) return;\r\n\r\n const files = event.dataTransfer?.files;\r\n if (files && files.length > 0) {\r\n this._processFiles(files);\r\n this.filesDropped.emit(this._files());\r\n }\r\n }\r\n\r\n _formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 B';\r\n const units = ['B', 'KB', 'MB', 'GB'];\r\n const k = 1024;\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n const size = parseFloat((bytes / Math.pow(k, i)).toFixed(1));\r\n return `${size} ${units[i]}`;\r\n }\r\n\r\n // Private methods\r\n private _processFiles(fileList: FileList): void {\r\n const newFiles: FileUploadFile[] = [];\r\n const errors: FileUploadValidationError[] = [];\r\n const currentFiles = this._files();\r\n\r\n const filesToProcess = Array.from(fileList);\r\n\r\n for (const file of filesToProcess) {\r\n // Max files check\r\n const maxFiles = this.maxFiles();\r\n if (maxFiles > 0 && currentFiles.length + newFiles.length >= maxFiles) {\r\n errors.push({\r\n file,\r\n error: 'maxFiles',\r\n message: `Maximum ${maxFiles} file(s) allowed`,\r\n });\r\n continue;\r\n }\r\n\r\n const validationError = this._validateFile(file);\r\n if (validationError) {\r\n errors.push(validationError);\r\n continue;\r\n }\r\n\r\n const uploadFile: FileUploadFile = {\r\n file,\r\n name: file.name,\r\n size: file.size,\r\n type: file.type,\r\n };\r\n\r\n if (this.showPreview() && this._isImage(file)) {\r\n uploadFile.previewUrl = this._generatePreview(file);\r\n }\r\n\r\n newFiles.push(uploadFile);\r\n }\r\n\r\n if (errors.length > 0) {\r\n this.validationErrors.emit(errors);\r\n }\r\n\r\n if (newFiles.length > 0) {\r\n if (this.multiple()) {\r\n this._files.set([...currentFiles, ...newFiles]);\r\n } else {\r\n // Single mode: replace existing\r\n for (const f of currentFiles) {\r\n if (f.previewUrl) URL.revokeObjectURL(f.previewUrl);\r\n }\r\n this._files.set([newFiles[0]]);\r\n }\r\n this.filesSelected.emit(this._files());\r\n }\r\n }\r\n\r\n private _validateFile(file: File): FileUploadValidationError | null {\r\n // Type check\r\n const accept = this.accept();\r\n if (accept && !this._matchesAccept(file, accept)) {\r\n return {\r\n file,\r\n error: 'type',\r\n message: `File type \"${file.type || file.name.split('.').pop()}\" is not allowed`,\r\n };\r\n }\r\n\r\n // Size check\r\n const maxSize = this.maxFileSize();\r\n if (maxSize > 0 && file.size > maxSize) {\r\n return {\r\n file,\r\n error: 'size',\r\n message: `File size ${this._formatFileSize(file.size)} exceeds maximum ${this._formatFileSize(maxSize)}`,\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private _matchesAccept(file: File, accept: string): boolean {\r\n const acceptTypes = accept.split(',').map((t) => t.trim().toLowerCase());\r\n\r\n for (const acceptType of acceptTypes) {\r\n // Wildcard MIME type (e.g. \"image/*\")\r\n if (acceptType.endsWith('/*')) {\r\n const category = acceptType.slice(0, acceptType.indexOf('/'));\r\n if (file.type.toLowerCase().startsWith(category + '/')) {\r\n return true;\r\n }\r\n }\r\n // Extension match (e.g. \".pdf\")\r\n else if (acceptType.startsWith('.')) {\r\n if (file.name.toLowerCase().endsWith(acceptType)) {\r\n return true;\r\n }\r\n }\r\n // Exact MIME match\r\n else if (file.type.toLowerCase() === acceptType) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private _isImage(file: File): boolean {\r\n return file.type.startsWith('image/');\r\n }\r\n\r\n private _generatePreview(file: File): string {\r\n return URL.createObjectURL(file);\r\n }\r\n}\r\n","<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag & drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"raintonic-formaui-components-file-upload.mjs","sources":["../../../lib/components/file-upload/file-upload.intl.ts","../../../lib/components/file-upload/file-upload.component.ts","../../../lib/components/file-upload/file-upload.component.html","../../../lib/components/file-upload/raintonic-formaui-components-file-upload.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { FuiIntlBase } from '@raintonic/formaui/core';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FuiFileUploadIntl extends FuiIntlBase {\r\n dropzoneAriaLabel = 'Drop files here or click to browse';\r\n removeFileAriaLabel(name: string): string {\r\n return `Remove ${name}`;\r\n }\r\n}\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n ViewEncapsulation,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n ElementRef,\r\n WritableSignal,\r\n booleanAttribute,\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 { FileUploadFile, FileUploadValidationError } from './file-upload.types';\r\nimport { FuiFileUploadIntl } from './file-upload.intl';\r\n\r\n/**\r\n * # FuiFileUploadComponent\r\n *\r\n * A file upload component with drag-and-drop support, file previews, and validation.\r\n *\r\n * ## Features\r\n * - Drag & drop file upload\r\n * - Click to browse\r\n * - File type, size, and count validation\r\n * - Image preview thumbnails\r\n * - Accessible (keyboard, ARIA)\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic\r\n * ```html\r\n * <fui-file-upload\r\n * accept=\"image/*,.pdf\"\r\n * [multiple]=\"true\"\r\n * [maxFileSize]=\"5242880\"\r\n * (filesSelected)=\"onFiles($event)\"\r\n * ></fui-file-upload>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-file-upload',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './file-upload.component.html',\r\n styleUrls: ['./file-upload.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-file-upload',\r\n '[class.fui-file-upload--disabled]': 'disabled()',\r\n '[class.fui-file-upload--drag-over]': '_isDragOver()',\r\n '[class.fui-file-upload--has-files]': '_files().length > 0',\r\n },\r\n})\r\nexport class FuiFileUploadComponent {\r\n readonly intl = inject(FuiFileUploadIntl);\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\r\n readonly accept = input('');\r\n readonly multiple = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly maxFileSize = input(0);\r\n readonly maxFiles = input(0);\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly showPreview = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n // Outputs\r\n readonly filesSelected = output<FileUploadFile[]>();\r\n readonly fileRemoved = output<FileUploadFile>();\r\n readonly filesDropped = output<FileUploadFile[]>();\r\n readonly validationErrors = output<FileUploadValidationError[]>();\r\n\r\n // Internal state\r\n readonly _files: WritableSignal<FileUploadFile[]> = signal([]);\r\n readonly _isDragOver: WritableSignal<boolean> = signal(false);\r\n\r\n // ViewChild\r\n readonly fileInput = viewChild<ElementRef<HTMLInputElement>>('fileInput');\r\n\r\n // Public methods\r\n browse(): void {\r\n if (this.disabled()) return;\r\n this.fileInput()?.nativeElement.click();\r\n }\r\n\r\n removeFile(index: number): void {\r\n if (this.disabled()) return;\r\n const files = [...this._files()];\r\n const removed = files.splice(index, 1)[0];\r\n if (removed) {\r\n if (removed.previewUrl) {\r\n URL.revokeObjectURL(removed.previewUrl);\r\n }\r\n this._files.set(files);\r\n this.fileRemoved.emit(removed);\r\n }\r\n }\r\n\r\n clearAll(): void {\r\n const files = this._files();\r\n for (const f of files) {\r\n if (f.previewUrl) {\r\n URL.revokeObjectURL(f.previewUrl);\r\n }\r\n }\r\n this._files.set([]);\r\n }\r\n\r\n getFiles(): FileUploadFile[] {\r\n return this._files();\r\n }\r\n\r\n // Template event handlers\r\n _onFileInputChange(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n this._processFiles(input.files);\r\n }\r\n // Reset input so the same file can be selected again\r\n input.value = '';\r\n }\r\n\r\n _onDragEnter(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragOver(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragLeave(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n }\r\n\r\n _onDrop(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n\r\n if (this.disabled()) return;\r\n\r\n const files = event.dataTransfer?.files;\r\n if (files && files.length > 0) {\r\n this._processFiles(files);\r\n this.filesDropped.emit(this._files());\r\n }\r\n }\r\n\r\n _formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 B';\r\n const units = ['B', 'KB', 'MB', 'GB'];\r\n const k = 1024;\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n const size = parseFloat((bytes / Math.pow(k, i)).toFixed(1));\r\n return `${size} ${units[i]}`;\r\n }\r\n\r\n // Private methods\r\n private _processFiles(fileList: FileList): void {\r\n const newFiles: FileUploadFile[] = [];\r\n const errors: FileUploadValidationError[] = [];\r\n const currentFiles = this._files();\r\n\r\n const filesToProcess = Array.from(fileList);\r\n\r\n for (const file of filesToProcess) {\r\n // Max files check\r\n const maxFiles = this.maxFiles();\r\n if (maxFiles > 0 && currentFiles.length + newFiles.length >= maxFiles) {\r\n errors.push({\r\n file,\r\n error: 'maxFiles',\r\n message: `Maximum ${maxFiles} file(s) allowed`,\r\n });\r\n continue;\r\n }\r\n\r\n const validationError = this._validateFile(file);\r\n if (validationError) {\r\n errors.push(validationError);\r\n continue;\r\n }\r\n\r\n const uploadFile: FileUploadFile = {\r\n file,\r\n name: file.name,\r\n size: file.size,\r\n type: file.type,\r\n };\r\n\r\n if (this.showPreview() && this._isImage(file)) {\r\n uploadFile.previewUrl = this._generatePreview(file);\r\n }\r\n\r\n newFiles.push(uploadFile);\r\n }\r\n\r\n if (errors.length > 0) {\r\n this.validationErrors.emit(errors);\r\n }\r\n\r\n if (newFiles.length > 0) {\r\n if (this.multiple()) {\r\n this._files.set([...currentFiles, ...newFiles]);\r\n } else {\r\n // Single mode: replace existing\r\n for (const f of currentFiles) {\r\n if (f.previewUrl) URL.revokeObjectURL(f.previewUrl);\r\n }\r\n this._files.set([newFiles[0]]);\r\n }\r\n this.filesSelected.emit(this._files());\r\n }\r\n }\r\n\r\n private _validateFile(file: File): FileUploadValidationError | null {\r\n // Type check\r\n const accept = this.accept();\r\n if (accept && !this._matchesAccept(file, accept)) {\r\n return {\r\n file,\r\n error: 'type',\r\n message: `File type \"${file.type || file.name.split('.').pop()}\" is not allowed`,\r\n };\r\n }\r\n\r\n // Size check\r\n const maxSize = this.maxFileSize();\r\n if (maxSize > 0 && file.size > maxSize) {\r\n return {\r\n file,\r\n error: 'size',\r\n message: `File size ${this._formatFileSize(file.size)} exceeds maximum ${this._formatFileSize(maxSize)}`,\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private _matchesAccept(file: File, accept: string): boolean {\r\n const acceptTypes = accept.split(',').map((t) => t.trim().toLowerCase());\r\n\r\n for (const acceptType of acceptTypes) {\r\n // Wildcard MIME type (e.g. \"image/*\")\r\n if (acceptType.endsWith('/*')) {\r\n const category = acceptType.slice(0, acceptType.indexOf('/'));\r\n if (file.type.toLowerCase().startsWith(category + '/')) {\r\n return true;\r\n }\r\n }\r\n // Extension match (e.g. \".pdf\")\r\n else if (acceptType.startsWith('.')) {\r\n if (file.name.toLowerCase().endsWith(acceptType)) {\r\n return true;\r\n }\r\n }\r\n // Exact MIME match\r\n else if (file.type.toLowerCase() === acceptType) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private _isImage(file: File): boolean {\r\n return file.type.startsWith('image/');\r\n }\r\n\r\n private _generatePreview(file: File): string {\r\n return URL.createObjectURL(file);\r\n }\r\n}\r\n","<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag & drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|