@sixbell-telco/sdk
Version:
A collection of reusable components designed for use in Sixbell Telco Angular projects
327 lines (322 loc) • 13.9 kB
JavaScript
import * as i0 from '@angular/core';
import { input, model, output, computed, Component, Host } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IconComponent } from '@sixbell-telco/sdk/components/icon';
import { ClickOutsideDirective } from '@sixbell-telco/sdk/directives/click-outside';
import { cn } from '@sixbell-telco/sdk/utils/cn';
import { cva, cx } from 'class-variance-authority';
/**
* @internal
* Generates base dropdown button classes with style variants
*/
const dropdownButton = cva(['btn', 'text-pretty', 'font-medium', 'leading-normal', 'items-center', 'align-top'], {
variants: {
variant: {
primary: ['btn-primary'],
secondary: ['btn-secondary'],
tertiary: ['btn-tertiary'],
accent: ['btn-accent'],
info: ['btn-info'],
success: ['btn-success'],
warning: ['btn-warning'],
error: ['btn-error'],
icon: [
'btn-ghost',
'text-neutral',
'hover:text-primary',
'hover:bg-transparent',
'active:focus:bg-transparent',
'active:focus:border-transparent',
'focus-visible:outline-current',
],
},
size: {
xs: ['btn-xs'],
sm: ['btn-sm'],
md: ['btn-md'],
lg: ['btn-lg'],
xl: ['btn-xl'],
},
iconPosition: {
left: [''],
right: ['flex-row-reverse'],
},
},
compoundVariants: [],
defaultVariants: {
variant: 'secondary',
size: 'md',
iconPosition: 'left',
},
});
/**
* @internal
* Generates base dropdown menu classes with positioning variants
*/
const dropdownMenu = cva(['dropdown'], {
variants: {
menuPosition: {
top: ['dropdown-top'],
bottom: ['dropdown-bottom'],
right: ['dropdown-right'],
left: ['dropdown-left'],
},
menuAlignment: {
start: [''],
end: ['dropdown-end'],
},
},
compoundVariants: [],
defaultVariants: {
menuPosition: 'bottom',
menuAlignment: 'start',
},
});
/**
* @internal
* Combines dropdown button and menu classes
*/
const dropdownComponent = ({ variant, menuAlignment, menuPosition, iconPosition } = {}) => cx(dropdownButton({ variant, iconPosition }), dropdownMenu({ menuAlignment, menuPosition }));
/**
* A customizable dropdown component with menu positioning and various styling options
*
* @remarks
* Built with Tailwind CSS and class-variance-authority for style management.
* Supports multiple button variants, menu positioning, and responsive behavior.
*
* @example
* ```html
* <st-dropdown
* variant="primary"
* menuPosition="bottom"
* menuAlignment="end"
* icon="chevron-down"
* >
* <button>Actions</button>
* <div slot="menu">
* <button class="menu-item">Edit</button>
* <button class="menu-item">Delete</button>
* </div>
* </st-dropdown>
* ```
*
* @example
* ```html
* <st-dropdown
* variant="icon"
* menuPosition="right"
* icon="more-vertical"
* >
* <div slot="menu">...</div>
* </st-dropdown>
* ```
*/
class DropdownComponent {
/**
* Button style variant
* @defaultValue 'secondary'
*/
variant = input();
/**
* Ghost button style (transparent background)
* @defaultValue false
*/
ghost = input(false);
/**
* Outline button style (border with transparent fill)
* @defaultValue false
*/
outline = input(false);
/**
* Link button style (appears as a hyperlink)
* @defaultValue false
*/
link = input(false);
/**
* Soft button style (muted/subdued color variant)
* @defaultValue false
*/
soft = input(false);
/**
* Dash button style (dashed border)
* @defaultValue false
*/
dash = input(false);
/**
* Circular button shape
* @defaultValue false
*/
circle = input(false);
/**
* Square button shape
* @defaultValue false
*/
square = input(false);
/**
* Glass effect styling
* @defaultValue false
*/
glass = input(false);
/**
* Button size variant
* @defaultValue 'md'
*/
size = input();
/**
* Add drop shadow
* @defaultValue false
*/
shadow = input(false);
/**
* Icon name (from icon library)
*/
icon = input();
/**
* Position of icon relative to text
*/
iconPosition = input();
/**
* Position of dropdown menu relative to button
* @defaultValue 'bottom'
*/
menuPosition = input('bottom');
/**
* Alignment of dropdown menu content
*/
menuAlignment = input();
/**
* Button label text
*/
label = input('');
/**
* Controls dropdown open/close state
* @defaultValue false
*/
isOpened = model(false);
/**
* Event emitted when dropdown toggle state changes
*/
toggled = output();
/**
* @internal
* Computed class string for the dropdown button
*/
buttonClass = computed(() => {
return cn(dropdownButton({
variant: this.variant(),
size: this.size(),
iconPosition: this.iconPosition(),
}), {
'btn-ghost': this.ghost(),
'btn-outline': this.outline(),
'btn-link': this.link(),
'btn-soft': this.soft(),
'btn-dash': this.dash(),
'btn-circle': this.circle(),
'btn-square': this.square(),
glass: this.glass(),
'shadow-main': this.shadow(),
});
});
/**
* @internal
* Computed class string for the dropdown menu container
*/
menuClass = computed(() => {
return cn(dropdownMenu({
menuPosition: this.menuPosition(),
menuAlignment: this.menuAlignment(),
}));
});
/**
* @internal
* Computed class string for the dropdown content
*/
dropdownContentClass = computed(() => {
return cn('menu dropdown-content rounded-box bg-base-300 p-2 shadow-main', {
'mb-1': this.menuPosition() === 'top',
'mt-1': this.menuPosition() === 'bottom',
'ml-1': this.menuPosition() === 'right',
'mr-1': this.menuPosition() === 'left',
});
});
/**
* @internal
* Toggles dropdown visibility state
*/
handleToggle() {
this.isOpened.set(!this.isOpened());
this.toggled.emit(this.isOpened());
}
/**
* @internal
* Handles click outside to close dropdown
*/
handleClickOuside() {
this.isOpened.set(false);
this.toggled.emit(this.isOpened());
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.0", type: DropdownComponent, isStandalone: true, selector: "st-dropdown", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, ghost: { classPropertyName: "ghost", publicName: "ghost", isSignal: true, isRequired: false, transformFunction: null }, outline: { classPropertyName: "outline", publicName: "outline", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null }, soft: { classPropertyName: "soft", publicName: "soft", isSignal: true, isRequired: false, transformFunction: null }, dash: { classPropertyName: "dash", publicName: "dash", isSignal: true, isRequired: false, transformFunction: null }, circle: { classPropertyName: "circle", publicName: "circle", isSignal: true, isRequired: false, transformFunction: null }, square: { classPropertyName: "square", publicName: "square", isSignal: true, isRequired: false, transformFunction: null }, glass: { classPropertyName: "glass", publicName: "glass", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, shadow: { classPropertyName: "shadow", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, iconPosition: { classPropertyName: "iconPosition", publicName: "iconPosition", isSignal: true, isRequired: false, transformFunction: null }, menuPosition: { classPropertyName: "menuPosition", publicName: "menuPosition", isSignal: true, isRequired: false, transformFunction: null }, menuAlignment: { classPropertyName: "menuAlignment", publicName: "menuAlignment", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, isOpened: { classPropertyName: "isOpened", publicName: "isOpened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpened: "isOpenedChange", toggled: "toggled" }, ngImport: i0, template: "@let iconVar = icon();\n@let labelVar = label();\n@let isOpenedVar = isOpened();\n@let menuClassVar = menuClass();\n@let buttonClassVar = buttonClass();\n@let dropdownContentClassVar = dropdownContentClass();\n\n<details dropdown [class]=\"menuClassVar\" [attr.open]=\"isOpenedVar ? undefined : null\" stClickOutside (outsideClick)=\"handleClickOuside()\">\n\t<summary [class]=\"buttonClassVar\" (click)=\"handleToggle()\">\n\t\t@if (iconVar) {\n\t\t\t<st-icon [icon]=\"iconVar\" color=\"inherit\" size=\"auto\"></st-icon>\n\t\t}\n\t\t<div>\n\t\t\t{{ labelVar }}\n\t\t</div>\n\t</summary>\n\t<ul [class]=\"dropdownContentClassVar\">\n\t\t<ng-content></ng-content>\n\t</ul>\n</details>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: ClickOutsideDirective, selector: "[stClickOutside]", outputs: ["outsideClick"] }, { kind: "component", type: IconComponent, selector: "st-icon", inputs: ["color", "size", "icon"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DropdownComponent, decorators: [{
type: Component,
args: [{ selector: 'st-dropdown', imports: [CommonModule, ClickOutsideDirective, IconComponent], template: "@let iconVar = icon();\n@let labelVar = label();\n@let isOpenedVar = isOpened();\n@let menuClassVar = menuClass();\n@let buttonClassVar = buttonClass();\n@let dropdownContentClassVar = dropdownContentClass();\n\n<details dropdown [class]=\"menuClassVar\" [attr.open]=\"isOpenedVar ? undefined : null\" stClickOutside (outsideClick)=\"handleClickOuside()\">\n\t<summary [class]=\"buttonClassVar\" (click)=\"handleToggle()\">\n\t\t@if (iconVar) {\n\t\t\t<st-icon [icon]=\"iconVar\" color=\"inherit\" size=\"auto\"></st-icon>\n\t\t}\n\t\t<div>\n\t\t\t{{ labelVar }}\n\t\t</div>\n\t</summary>\n\t<ul [class]=\"dropdownContentClassVar\">\n\t\t<ng-content></ng-content>\n\t</ul>\n</details>\n" }]
}] });
/**
* A selectable item component for use within dropdown menus
*
* @remarks
* Designed to be used inside `<st-dropdown>` components. Handles selection events
* and automatically closes the parent dropdown when clicked.
*
* @example
* ```html
* <st-dropdown-item (selected)="handleItemSelect()">
* <st-icon icon="check"></st-icon>
* <span typography>Select Item</span>
* </st-dropdown-item>
* ```
*
* @example
* ```html
* <st-dropdown-item class="custom-item-style" (selected)="logSelection()">
* Custom styled item
* </st-dropdown-item>
* ```
*/
class DropdownItemComponent {
dropdown;
/**
* Event emitted when the item is selected
*/
selected = output();
/**
* @internal
* Reference to parent dropdown component
*/
constructor(dropdown) {
this.dropdown = dropdown;
}
/**
* @internal
* Handles item selection and dropdown state
*/
handleSelect() {
this.selected.emit();
this.dropdown.handleToggle();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DropdownItemComponent, deps: [{ token: DropdownComponent, host: true }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.0", type: DropdownItemComponent, isStandalone: true, selector: "st-dropdown-item", outputs: { selected: "selected" }, ngImport: i0, template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->\n<li (click)=\"handleSelect()\">\n\t<ng-content></ng-content>\n</li>\n" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DropdownItemComponent, decorators: [{
type: Component,
args: [{ selector: 'st-dropdown-item', standalone: true, template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->\n<li (click)=\"handleSelect()\">\n\t<ng-content></ng-content>\n</li>\n" }]
}], ctorParameters: () => [{ type: DropdownComponent, decorators: [{
type: Host
}] }] });
/**
* Generated bundle index. Do not edit.
*/
export { DropdownComponent, DropdownItemComponent, dropdownButton, dropdownComponent, dropdownMenu };
//# sourceMappingURL=sixbell-telco-sdk-components-dropdown.mjs.map