UNPKG

carbon-components-angular

Version:
1 lines 81.3 kB
{"version":3,"file":"carbon-components-angular-dialog.mjs","sources":["../../src/dialog/dialog-config.interface.ts","../../src/dialog/dialog.service.ts","../../src/dialog/dialog.component.ts","../../src/dialog/dialog.directive.ts","../../src/dialog/overflow-menu/overflow-menu-pane.component.ts","../../src/dialog/overflow-menu/overflow-menu-custom-pane.component.ts","../../src/dialog/overflow-menu/overflow-menu.directive.ts","../../src/dialog/overflow-menu/overflow-menu.component.ts","../../src/dialog/overflow-menu/overflow-menu-option.component.ts","../../src/dialog/dialog.module.ts","../../src/dialog/carbon-components-angular-dialog.ts"],"sourcesContent":["import { ElementRef, TemplateRef } from \"@angular/core\";\n\n/**\n * An enum of the various reasons a dialog may close. For use with `CloseMeta` and `shouldClose`\n *\n * It's expected that `interaction` will be a common closure reason.\n */\nexport enum CloseReasons {\n\t/**\n\t * For when the component is closed by being destroyed\n\t */\n\tdestroyed,\n\t/**\n\t * For use in cases where the dialog closes for programmatic reasons other than destruction\n\t */\n\tprogrammatic,\n\t/**\n\t * interaction reasons will also provide a target for the interaction\n\t */\n\tinteraction,\n\t/**\n\t * For use in cases where the dialog closes due to being hidden\n\t */\n\thidden\n}\n\n/**\n * Interface representing various metadata that can be passed to `shouldClose` and the `close` event\n */\nexport interface CloseMeta {\n\treason: CloseReasons;\n\ttarget?: EventTarget;\n}\n\n/**\n * Data structure for definig properties of a `Dialog` component.\n **/\nexport interface DialogConfig {\n\t/**\n\t * Title for the `Dialog` header.\n\t */\n\ttitle?: string;\n\t/**\n\t * Body content for the `Dialog`.\n\t */\n\tcontent: string | TemplateRef<any>;\n\t/**\n\t * Parameter for triggering `Dialog` display.\n\t */\n\ttrigger?: \"click\" | \"hover\" | \"mouseenter\";\n\t/**\n\t * Parameter for triggering the `Dialog` close event.\n\t */\n\tcloseTrigger?: \"mouseout\" | \"mouseleave\";\n\t/**\n\t * Callback to control the closing behaviour. return `true` to close, and `false` to prevent closing\n\t */\n\tshouldClose?: (meta?: CloseMeta) => boolean;\n\t/**\n\t * If true the dialog will close when hidden (by scrolling or otherwise going out of the viewport)\n\t * If false the dialog will stay open until explicitly closed\n\t * When true this closure method can be picked up via `CloseReasons.hidden`\n\t */\n\tcloseWhenHidden?: boolean;\n\t/**\n\t * Parameter defining the placement in which the `Dialog` appears.\n\t */\n\tplacement?: string;\n\t/**\n\t * Used to set the offset of the `Dialog` relative to the content it\n\t * is associated to.\n\t */\n\tgap?: number;\n\t/**\n\t * Reference to the Parent element that links the `Dialog`.\n\t */\n\tparentRef?: ElementRef;\n\t/**\n\t * Set to `true` to open the dialog next to the triggering component\n\t */\n\tappendInline?: boolean;\n\t/**\n\t * Config object passed to the rendered component. (Optional)\n\t */\n\tdata?: Object;\n\t/**\n\t * Additional arbitrary properties (mostly for internal/extended component use)\n\t */\n\t[propName: string]: any;\n\t/**\n\t * Classes to add to the dialog container\n\t */\n\twrapperClass?: string;\n\t/**\n\t * This specifies any vertical and horizontal offset for the position of the dialog\n\t */\n\toffset?: { x: number, y: number };\n\t/**\n\t * This prevents the dialog from being toggled\n\t */\n\tdisabled?: boolean;\n}\n","import {\n\tInjector,\n\tComponentRef,\n\tInjectable,\n\tViewContainerRef\n} from \"@angular/core\";\nimport { CloseReasons, DialogConfig } from \"./dialog-config.interface\";\nimport { PlaceholderService } from \"carbon-components-angular/placeholder\";\nimport { Dialog } from \"./dialog.component\";\nimport { tabbableSelector } from \"carbon-components-angular/common\";\n\n/**\n * `Dialog` object to be injected into other components.\n */\n@Injectable()\nexport class DialogService {\n\t/**\n\t * Used in `singletonClickListen`, don't count on its existence and values.\n\t */\n\tprotected static listeningForBodyClicks = false;\n\n\t/**\n\t * A set of all known dialog components\n\t */\n\tprotected static dialogRefs = new Set<ComponentRef<Dialog>>();\n\n\t/**\n\t * Closes all known `Dialog`s. Does not focus any previous elements, since we can't know which would be correct\n\t */\n\tpublic static closeAll() {\n\t\tDialogService.dialogRefs.forEach(ref => ref.instance.doClose({\n\t\t\treason: CloseReasons.programmatic\n\t\t}));\n\t\tDialogService.dialogRefs.clear();\n\t}\n\n\t/**\n\t * Creates an instance of `DialogService`.\n\t */\n\tconstructor(protected injector: Injector, protected placeholderService: PlaceholderService) {}\n\n\t/**\n\t * If `dialogRef` is defined, the Dialog is already open. If\n\t * `dialogRef` is undefined, we create the `Dialog` component and reference to it.\n\t * A subscription is created to track if the `Dialog` should close.\n\t *\n\t * @param viewContainer a `ViewContainerRef` to instantiate the component against.\n\t * May be `null` if an `cds-placeholder` exists and `dialogConfig.appendInline` is false\n\t * @param dialogConfig the `DialogConfig` for the component\n\t */\n\topen(viewContainer: ViewContainerRef, dialogConfig: DialogConfig, component: any) {\n\t\tif (!component) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet dialogRef;\n\t\tif (dialogConfig.appendInline) {\n\t\t\t// add our component to the view\n\t\t\tdialogRef = viewContainer.createComponent(component, { index: 0, injector: this.injector });\n\t\t} else if (!this.placeholderService.hasPlaceholderRef()) {\n\t\t\tdialogRef = viewContainer.createComponent(component, { index: 0, injector: this.injector });\n\t\t\tif (dialogRef) {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\twindow.document.querySelector(\"body\").appendChild(dialogRef.location.nativeElement);\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tdialogRef = this.placeholderService.createComponent(component, this.injector);\n\t\t}\n\n\t\t// keep track of all initialized dialogs\n\t\tDialogService.dialogRefs.add(dialogRef);\n\n\t\t// initialize some extra options\n\t\tdialogConfig[\"previouslyFocusedElement\"] = document.activeElement;\n\t\tdialogRef.instance.dialogConfig = dialogConfig;\n\n\t\tdialogRef.instance.elementRef.nativeElement.focus();\n\n\t\treturn dialogRef as ComponentRef<Dialog>;\n\t}\n\n\t/**\n\t * On close of `Dialog` item, sets focus back to previous item, unsets\n\t * the current `dialogRef` item. Unsubscribes to the event of `Dialog` close.\n\t *\n\t * @param dialogRef the dialogRef to close\n\t */\n\tclose(dialogRef: ComponentRef<Dialog>) {\n\t\t// to handle the case where we have a null `this.dialogRef`\n\t\tif (!dialogRef) { return; }\n\n\t\tconst elementToFocus = dialogRef.instance.dialogConfig[\"previouslyFocusedElement\"];\n\n\t\tdialogRef.destroy();\n\n\t\t// update the globally tracked dialogRefs\n\t\tif (DialogService.dialogRefs.has(dialogRef)) {\n\t\t\tDialogService.dialogRefs.delete(dialogRef);\n\t\t}\n\n\t\t// Keeps the focus on the dialog trigger if there are no focusable elements. Change focus to previously focused element\n\t\t// if there are focusable elements in the dialog.\n\t\tif (!dialogRef.location.nativeElement.querySelectorAll(tabbableSelector)) {\n\t\t\telementToFocus.focus();\n\t\t}\n\t}\n\n\t/**\n\t * Fix for safari hijacking clicks.\n\t *\n\t * Runs on `ngOnInit` of every dialog. Ensures we don't have multiple listeners\n\t * because having many of them could degrade performance in certain cases (and is\n\t * not necessary for our use case)\n\t *\n\t * This is an internally used function, can change at any point (even get removed)\n\t * and changes to it won't be considered a breaking change. Use at your own risk.\n\t */\n\tsingletonClickListen() {\n\t\tif (!DialogService.listeningForBodyClicks) {\n\t\t\tdocument.body.firstElementChild.addEventListener(\"click\", () => null, true);\n\t\t\tDialogService.listeningForBodyClicks = true;\n\t\t}\n\t}\n}\n","import {\n\tComponent,\n\tInput,\n\tOutput,\n\tEventEmitter,\n\tElementRef,\n\tViewChild,\n\tOnInit,\n\tAfterViewInit,\n\tOnDestroy,\n\tHostListener,\n\tOptional\n} from \"@angular/core\";\nimport {\n\tObservable,\n\tSubscription\n} from \"rxjs\";\n// the AbsolutePosition is required to import the declaration correctly\nimport Position, { position, AbsolutePosition, Positions } from \"@carbon/utils-position\";\nimport { cycleTabs, getFocusElementList } from \"carbon-components-angular/common\";\nimport { CloseMeta, CloseReasons, DialogConfig } from \"./dialog-config.interface\";\nimport { AnimationFrameService, ElementService } from \"carbon-components-angular/utils\";\n\n/**\n * Implements a `Dialog` that can be positioned anywhere on the page.\n * Used to implement a popover or tooltip.\n */\n@Component({\n\tselector: \"cds-dialog, ibm-dialog\",\n\ttemplate: \"\"\n})\nexport class Dialog implements OnInit, AfterViewInit, OnDestroy {\n\t/**\n\t * Emits event that handles the closing of a `Dialog` object.\n\t */\n\t@Output() close: EventEmitter<CloseMeta> = new EventEmitter();\n\t/**\n\t * Receives `DialogConfig` interface object with properties of `Dialog`\n\t * explicitly defined.\n\t */\n\t@Input() dialogConfig: DialogConfig;\n\t/**\n\t * Maintains a reference to the view DOM element of the `Dialog`.\n\t */\n\t@ViewChild(\"dialog\") dialog: ElementRef;\n\n\t/**\n\t * Stores the data received from `dialogConfig`.\n\t */\n\tpublic data = {};\n\n\t/**\n\t * The placement of the `Dialog` is received from the `Position` service.\n\t */\n\tpublic placement: string;\n\n\tprotected visibilitySubscription = new Subscription();\n\n\tprotected animationFrameSubscription = new Subscription();\n\n\t/**\n\t * Handles offsetting the `Dialog` item based on the defined position\n\t * to not obscure the content beneath.\n\t */\n\tprotected addGap = {\n\t\t\"left\": pos => position.addOffset(pos, 0, -this.dialogConfig.gap),\n\t\t\"right\": pos => position.addOffset(pos, 0, this.dialogConfig.gap),\n\t\t\"top\": pos => position.addOffset(pos, -this.dialogConfig.gap),\n\t\t\"bottom\": pos => position.addOffset(pos, this.dialogConfig.gap),\n\t\t\"left-bottom\": pos => position.addOffset(pos, 0, -this.dialogConfig.gap),\n\t\t\"right-bottom\": pos => position.addOffset(pos, 0, this.dialogConfig.gap)\n\t};\n\n\t/**\n\t * Extra placements. Child classes can add to this for use in `placeDialog`.\n\t */\n\tprotected placements: Positions = {};\n\n\t/**\n\t * Creates an instance of `Dialog`.\n\t * @param elementRef\n\t * @param elementService\n\t */\n\tconstructor(\n\t\tprotected elementRef: ElementRef,\n\t\tprotected elementService: ElementService,\n\t\t@Optional() protected animationFrameService: AnimationFrameService = null\n\t) {}\n\n\t/**\n\t * Initialize the `Dialog`, set the placement and gap, and add a `Subscription` to resize events.\n\t */\n\tngOnInit() {\n\t\tthis.placement = this.dialogConfig.placement.split(\",\")[0];\n\t\tthis.data = this.dialogConfig.data;\n\n\t\t// run any additional initialization code that consuming classes may have\n\t\tthis.onDialogInit();\n\t}\n\n\t/**\n\t * After the DOM is ready, focus is set and dialog is placed\n\t * in respect to the parent element.\n\t */\n\tngAfterViewInit() {\n\t\tconst dialogElement = this.dialog.nativeElement;\n\t\t// split the wrapper class list and apply separately to avoid IE\n\t\t// 1. throwing an error due to assigning a readonly property (classList)\n\t\t// 2. throwing a SyntaxError due to passing an empty string to `add`\n\t\tif (this.dialogConfig.wrapperClass) {\n\t\t\tfor (const extraClass of this.dialogConfig.wrapperClass.split(\" \")) {\n\t\t\t\tdialogElement.classList.add(extraClass);\n\t\t\t}\n\t\t}\n\n\t\t// only focus the dialog if there are focusable elements within the dialog\n\t\tif (getFocusElementList(this.dialog.nativeElement).length > 0) {\n\t\t\tdialogElement.focus();\n\t\t}\n\n\t\tconst parentElement = this.dialogConfig.parentRef.nativeElement;\n\n\t\tif (this.animationFrameService) {\n\t\t\tthis.animationFrameSubscription = this.animationFrameService.tick.subscribe(() => {\n\t\t\t\tthis.placeDialog();\n\t\t\t});\n\t\t}\n\n\t\tif (this.dialogConfig.closeWhenHidden) {\n\t\t\tthis.visibilitySubscription = this.elementService\n\t\t\t\t.visibility(parentElement, parentElement)\n\t\t\t\t.subscribe(value => {\n\t\t\t\t\tthis.placeDialog();\n\t\t\t\t\tif (!value.visible) {\n\t\t\t\t\t\tthis.doClose({\n\t\t\t\t\t\t\treason: CloseReasons.hidden\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tthis.placeDialog();\n\t\t// run afterDialogViewInit on the next tick\n\t\tsetTimeout(() => this.afterDialogViewInit());\n\t}\n\n\t/**\n\t * Empty method to be overridden by consuming classes to run any additional initialization code.\n\t */\n\tonDialogInit() {}\n\n\t/**\n\t * Empty method to be overridden by consuming classes to run any additional initialization code after the view is available.\n\t * NOTE: this does _not_ guarantee the dialog will be positioned, simply that it will exist in the DOM\n\t */\n\tafterDialogViewInit() {}\n\n\t/**\n\t * Uses the position service to position the `Dialog` in screen space\n\t */\n\tplaceDialog(): void {\n\t\tconst positionService = new Position(this.placements);\n\t\t// helper to find the position based on the current/given environment\n\t\tconst findPosition = (reference, target, placement) => {\n\t\t\tlet pos;\n\t\t\tif (this.dialogConfig.appendInline) {\n\t\t\t\tpos = this.addGap[placement](positionService.findRelative(reference, target, placement));\n\t\t\t} else {\n\t\t\t\tpos = this.addGap[placement](positionService.findAbsolute(reference, target, placement));\n\t\t\t}\n\n\t\t\tif (this.dialogConfig.offset) {\n\t\t\t\t// Apply vertical and horizontal offsets given through the dialogConfig\n\t\t\t\tpos.top = pos.top + this.dialogConfig.offset.y;\n\t\t\t\tpos.left = pos.left + this.dialogConfig.offset.x;\n\t\t\t}\n\n\t\t\treturn pos;\n\t\t};\n\n\t\tlet parentEl = this.dialogConfig.parentRef.nativeElement;\n\t\tlet el = this.dialog.nativeElement;\n\t\tlet dialogPlacement = this.placement;\n\n\t\t// split always returns an array, so we can just use the auto position logic\n\t\t// for single positions too\n\t\tconst placements = this.dialogConfig.placement.split(\",\");\n\n\t\t// find the best placement\n\t\tdialogPlacement = positionService.findBestPlacement(parentEl, el, placements);\n\n\t\t// calculate the final position\n\t\tconst pos = findPosition(parentEl, el, dialogPlacement);\n\n\t\t// update the element\n\t\tpositionService.setElement(el, pos);\n\t\tsetTimeout(() => { this.placement = dialogPlacement; });\n\t}\n\n\t/**\n\t * Sets up a KeyboardEvent to close `Dialog` with Escape key.\n\t * @param event\n\t */\n\t@HostListener(\"keydown\", [\"$event\"])\n\tescapeClose(event: KeyboardEvent) {\n\t\tswitch (event.key) {\n\t\t\tcase \"Escape\": {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\tthis.doClose({\n\t\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\t\ttarget: event.target\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"Tab\": {\n\t\t\t\tcycleTabs(event, this.elementRef.nativeElement);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets up a event Listener to close `Dialog` if click event occurs outside\n\t * `Dialog` object.\n\t * @param event\n\t */\n\t@HostListener(\"document:click\", [\"$event\"])\n\tclickClose(event) {\n\t\tif (!this.elementRef.nativeElement.contains(event.target)\n\t\t\t&& !this.dialogConfig.parentRef.nativeElement.contains(event.target) ) {\n\t\t\tthis.doClose({\n\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\ttarget: event.target\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Closes `Dialog` object by emitting the close event upwards to parents.\n\t */\n\tpublic doClose(meta: CloseMeta = { reason: CloseReasons.interaction }) {\n\t\tthis.close.emit(meta);\n\t}\n\n\t/**\n\t * At destruction of component, `Dialog` unsubscribes from all the subscriptions.\n\t */\n\tngOnDestroy() {\n\t\tthis.visibilitySubscription.unsubscribe();\n\t\tif (this.animationFrameSubscription) {\n\t\t\tthis.animationFrameSubscription.unsubscribe();\n\t\t}\n\t}\n}\n","import {\n\tDirective,\n\tInput,\n\tOutput,\n\tEventEmitter,\n\tOnInit,\n\tOnDestroy,\n\tElementRef,\n\tTemplateRef,\n\tViewContainerRef,\n\tOnChanges,\n\tHostBinding,\n\tSimpleChanges,\n\tComponentRef\n} from \"@angular/core\";\nimport { DialogService } from \"./dialog.service\";\nimport { CloseMeta, CloseReasons, DialogConfig } from \"./dialog-config.interface\";\nimport { EventService } from \"carbon-components-angular/utils\";\nimport { Dialog } from \"./dialog.component\";\nimport { fromEvent, Subscription } from \"rxjs\";\n\n/**\n * A generic directive that can be inherited from to create dialogs (for example, a tooltip or popover)\n *\n * This class contains the relevant initialization code, specific templates, options, and additional inputs\n * should be specified in the derived class.\n *\n * NOTE: All child classes should add `DialogService` as a provider, otherwise they will lose context that\n * the service relies on.\n */\n@Directive({\n\tselector: \"[cdsDialog], [ibmDialog]\",\n\texportAs: \"dialog\",\n\tproviders: [\n\t\tDialogService\n\t]\n})\nexport class DialogDirective implements OnInit, OnDestroy, OnChanges {\n\tstatic dialogCounter = 0;\n\t/**\n\t * Title for the dialog\n\t */\n\t@Input() title = \"\";\n\t/**\n\t * @deprecated as of v5, use `cdsDialog` instead\n\t * Dialog body content.\n\t */\n\t@Input() set ibmDialog(body: string | TemplateRef<any>) {\n\t\tthis.cdsDialog = body;\n\t}\n\n\t@Input() cdsDialog: string | TemplateRef<any>;\n\t/**\n\t * Defines how the Dialog is triggered.(Hover and click behave the same on mobile - both respond to a single tap).\n\t * Do not add focusable elements if trigger is `hover` or `mouseenter`.\n\t */\n\t@Input() trigger: \"click\" | \"hover\" | \"mouseenter\" = \"click\";\n\t/**\n\t * Defines how the Dialog close event is triggered.\n\t *\n\t * [See here](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseleave_event)\n\t * for more on the difference between `mouseleave` and `mouseout`.\n\t *\n\t * Defaults to `click` when `trigger` is set to `click`.\n\t */\n\t@Input() closeTrigger: \"mouseout\" | \"mouseleave\" = \"mouseleave\";\n\t/**\n\t * Placement of the dialog, usually relative to the element the directive is on.\n\t */\n\t@Input() placement = \"left\";\n\t/**\n\t * This specifies any vertical and horizontal offset for the position of the dialog\n\t */\n\t@Input() offset: { x: number, y: number };\n\t/**\n\t * Classes to add to the dialog container\n\t */\n\t@Input() wrapperClass: string;\n\t/**\n\t * Spacing between the dialog and it's triggering element\n\t */\n\t@Input() gap = 0;\n\t/**\n\t * Set to `true` to open the dialog next to the triggering component\n\t */\n\t@Input() appendInline = false;\n\t/**\n\t * Optional data for templates\n\t */\n\t@Input() data = {};\n\n\t@Input() @HostBinding(\"attr.aria-expanded\") isOpen = false;\n\t/**\n\t * This prevents the dialog from being toggled\n\t */\n\t@Input() disabled = false;\n\t/**\n\t * This input allows explicit control over how the dialog should close\n\t */\n\t@Input() shouldClose: (meta: CloseMeta) => boolean;\n\t/**\n\t * Config object passed to the rendered component\n\t */\n\tdialogConfig: DialogConfig;\n\t/**\n\t * Emits an event when the dialog is closed\n\t */\n\t@Output() onClose: EventEmitter<any> = new EventEmitter();\n\t/**\n\t * Emits an event when the dialog is opened\n\t */\n\t@Output() onOpen: EventEmitter<any> = new EventEmitter();\n\t/**\n\t * Emits an event when the state of `isOpen` changes. Allows `isOpen` to be double bound\n\t */\n\t@Output() isOpenChange = new EventEmitter<boolean>();\n\n\t@HostBinding(\"attr.role\") role = \"button\";\n\t@HostBinding(\"attr.aria-haspopup\") hasPopup = true;\n\t@HostBinding(\"attr.aria-owns\") get ariaOwns(): string {\n\t\treturn this.isOpen ? this.dialogConfig.compID : null;\n\t}\n\n\t/**\n\t * Keeps a reference to the currently opened dialog\n\t */\n\tprotected dialogRef: ComponentRef<Dialog>;\n\n\tprivate subscriptions: Subscription[] = [];\n\n\t/**\n\t * Creates an instance of DialogDirective.\n\t * @param elementRef\n\t * @param viewContainerRef\n\t * @param dialogService\n\t * @param eventService\n\t */\n\tconstructor(\n\t\tprotected elementRef: ElementRef,\n\t\tprotected viewContainerRef: ViewContainerRef,\n\t\tprotected dialogService: DialogService,\n\t\t/**\n\t\t * Deprecated as of v5\n\t\t */\n\t\tprotected eventService: EventService\n\t) {}\n\n\tngOnChanges(changes: SimpleChanges) {\n\t\t// set the config object (this can [and should!] be added to in child classes depending on what they need)\n\t\tthis.dialogConfig = {\n\t\t\ttitle: this.title,\n\t\t\tcontent: this.cdsDialog,\n\t\t\tplacement: this.placement,\n\t\t\tparentRef: this.elementRef,\n\t\t\tgap: this.gap,\n\t\t\ttrigger: this.trigger,\n\t\t\tcloseTrigger: this.closeTrigger,\n\t\t\tshouldClose: this.shouldClose || (() => true),\n\t\t\tappendInline: this.appendInline,\n\t\t\twrapperClass: this.wrapperClass,\n\t\t\tdata: this.data,\n\t\t\toffset: this.offset,\n\t\t\tdisabled: this.disabled\n\t\t};\n\n\t\tif (changes.isOpen) {\n\t\t\tif (changes.isOpen.currentValue) {\n\t\t\t\tthis.open();\n\t\t\t} else if (!changes.isOpen.firstChange) {\n\t\t\t\tthis.close({\n\t\t\t\t\treason: CloseReasons.programmatic\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Run any code a child class may need.\n\t\tthis.onDialogChanges(changes);\n\t\tthis.updateConfig();\n\t}\n\n\t/**\n\t * Sets the config object and binds events for hovering or clicking before\n\t * running code from child class.\n\t */\n\tngOnInit() {\n\t\t// fix for safari hijacking clicks\n\t\tthis.dialogService.singletonClickListen();\n\n\t\tconst element: HTMLElement = this.elementRef.nativeElement;\n\n\t\tthis.subscriptions.push(\n\t\t\tfromEvent(element, \"keydown\").subscribe((event: KeyboardEvent) => {\n\t\t\t\tif (event.target === this.dialogConfig.parentRef.nativeElement &&\n\t\t\t\t\t(event.key === \"Tab\" || event.key === \"Tab\" && event.shiftKey) ||\n\t\t\t\t\tevent.key === \"Escape\") {\n\t\t\t\t\tthis.close({\n\t\t\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\t\t\ttarget: event.target\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})\n\t\t);\n\n\t\t// bind events for hovering or clicking the host\n\t\tif (this.trigger === \"hover\" || this.trigger === \"mouseenter\") {\n\t\t\tthis.subscriptions.push(\n\t\t\t\tfromEvent(element, \"mouseenter\").subscribe(() => this.open()),\n\t\t\t\tfromEvent(element, this.closeTrigger).subscribe((event) => {\n\t\t\t\t\tthis.close({\n\t\t\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\t\t\ttarget: event.target\n\t\t\t\t\t});\n\t\t\t\t}),\n\t\t\t\tfromEvent(element, \"focus\").subscribe(() => this.open()),\n\t\t\t\tfromEvent(element, \"blur\").subscribe((event) => {\n\t\t\t\t\tthis.close({\n\t\t\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\t\t\ttarget: event.target\n\t\t\t\t\t});\n\t\t\t\t})\n\t\t\t);\n\t\t} else {\n\t\t\tthis.subscriptions.push(\n\t\t\t\tfromEvent(element, \"click\").subscribe((event) => {\n\t\t\t\t\tthis.toggle({\n\t\t\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\t\t\ttarget: event.target\n\t\t\t\t\t});\n\t\t\t\t}),\n\t\t\t\tfromEvent(element, \"keydown\").subscribe((event: KeyboardEvent) => {\n\t\t\t\t\tif (event.key === \"Enter\" || event.key === \" \") {\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\tthis.open();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tDialogDirective.dialogCounter++;\n\t\tthis.dialogConfig.compID = \"dialog-\" + DialogDirective.dialogCounter;\n\n\t\t// run any code a child class may need\n\t\tthis.onDialogInit();\n\t\tthis.updateConfig();\n\t}\n\n\t/**\n\t * When the host dies, kill the popover.\n\t * - Useful for use in a modal or similar.\n\t */\n\tngOnDestroy() {\n\t\tthis.close({\n\t\t\treason: CloseReasons.destroyed\n\t\t});\n\t\tthis.subscriptions.forEach((subscription) => subscription.unsubscribe());\n\t}\n\n\t/**\n\t * Helper method to call dialogService 'open'.\n\t * - Enforce accessibility by updating an aria attr for nativeElement.\n\t */\n\topen(component?) {\n\t\t// don't allow dialogs to be opened if they're already open\n\t\tif (this.dialogRef || this.disabled) { return; }\n\n\t\t// actually open the dialog, emit events, and set the open state\n\t\tthis.dialogRef = this.dialogService.open(this.viewContainerRef, this.dialogConfig, component);\n\t\tthis.isOpen = true;\n\t\tthis.onOpen.emit();\n\t\tthis.isOpenChange.emit(true);\n\n\t\t// Handles emitting all the close events to clean everything up\n\t\t// Also enforce accessibility on close by updating an aria attr on the nativeElement.\n\t\tconst subscription = this.dialogRef.instance.close.subscribe((meta: CloseMeta) => {\n\t\t\tif (!this.dialogRef) { return; }\n\t\t\tif (this.dialogConfig.shouldClose && this.dialogConfig.shouldClose(meta)) {\n\t\t\t\t// close the dialog, emit events, and clear out the open states\n\t\t\t\tthis.dialogService.close(this.dialogRef);\n\t\t\t\tthis.dialogRef = null;\n\t\t\t\tthis.isOpen = false;\n\t\t\t\tthis.onClose.emit();\n\t\t\t\tthis.isOpenChange.emit(false);\n\t\t\t\tsubscription.unsubscribe();\n\t\t\t}\n\t\t});\n\n\t\treturn this.dialogRef;\n\t}\n\n\t/**\n\t * Helper method to toggle the open state of the dialog\n\t */\n\ttoggle(meta: CloseMeta = { reason: CloseReasons.interaction }) {\n\t\tif (!this.isOpen) {\n\t\t\tthis.open();\n\t\t} else {\n\t\t\tthis.close(meta);\n\t\t}\n\t}\n\n\t/**\n\t * Helper method to close the dialogRef.\n\t */\n\tclose(meta: CloseMeta = { reason: CloseReasons.interaction }) {\n\t\tif (this.dialogRef) {\n\t\t\tthis.dialogRef.instance.doClose(meta);\n\t\t}\n\t}\n\n\t/**\n\t * Empty method for child classes to override and specify additional init steps.\n\t * Run after DialogDirective completes it's ngOnInit.\n\t */\n\tprotected onDialogInit() {}\n\n\t/**\n\t * Empty method for child to override and specify additional on changes steps.\n\t * run after DialogDirective completes it's ngOnChanges.\n\t */\n\tprotected onDialogChanges(_changes: SimpleChanges) {}\n\n\tprotected updateConfig() {}\n}\n","import {\n\tComponent,\n\tHostListener,\n\tElementRef,\n\tAfterViewInit,\n\tOptional\n} from \"@angular/core\";\nimport { Dialog } from \"../dialog.component\";\nimport { position } from \"@carbon/utils-position\";\nimport { isFocusInLastItem, isFocusInFirstItem } from \"carbon-components-angular/common\";\nimport { I18n } from \"carbon-components-angular/i18n\";\nimport { ExperimentalService } from \"carbon-components-angular/experimental\";\nimport { AnimationFrameService, ElementService } from \"carbon-components-angular/utils\";\nimport { CloseReasons } from \"../dialog-config.interface\";\nimport { closestAttr } from \"carbon-components-angular/utils\";\n\n/**\n * Extend the `Dialog` component to create an overflow menu.\n *\n * Not used directly. See overflow-menu.component and overflow-menu.directive for more\n */\n@Component({\n\tselector: \"cds-overflow-menu-pane, ibm-overflow-menu-pane\",\n\ttemplate: `\n\t\t<ul\n\t\t\t[attr.id]=\"dialogConfig.compID\"\n\t\t\t[attr.aria-label]=\"dialogConfig.menuLabel\"\n\t\t\t[attr.data-floating-menu-direction]=\"placement ? placement : null\"\n\t\t\t[ngClass]=\"{'cds--overflow-menu--flip': dialogConfig.flip}\"\n\t\t\trole=\"menu\"\n\t\t\t#dialog\n\t\t\tclass=\"cds--overflow-menu-options cds--overflow-menu-options--open\"\n\t\t\t(click)=\"onClose($event)\"\n\t\t\t[attr.aria-label]=\"dialogConfig.menuLabel\">\n\t\t\t<ng-template\n\t\t\t\t[ngTemplateOutlet]=\"dialogConfig.content\"\n\t\t\t\t[ngTemplateOutletContext]=\"{overflowMenu: this}\">\n\t\t\t</ng-template>\n\t\t</ul>\n\t`\n})\nexport class OverflowMenuPane extends Dialog implements AfterViewInit {\n\tconstructor(\n\t\tprotected elementRef: ElementRef,\n\t\tprotected i18n: I18n,\n\t\tprotected experimental: ExperimentalService,\n\t\t@Optional() protected animationFrameService: AnimationFrameService = null,\n\t\t// mark `elementService` as optional since making it mandatory would be a breaking change\n\t\t@Optional() protected elementService: ElementService = null) {\n\t\tsuper(elementRef, elementService, animationFrameService);\n\t}\n\n\tonDialogInit() {\n\t\tconst positionOverflowMenu = pos => {\n\t\t\tlet offset;\n\t\t\t/*\n\t\t\t* 20 is half the width of the overflow menu trigger element.\n\t\t\t* we also move the element by half of it's own width, since\n\t\t\t* position service will try and center everything\n\t\t\t*/\n\t\t\tconst closestRel = closestAttr(\"position\", [\"relative\", \"fixed\", \"absolute\"], this.elementRef.nativeElement);\n\t\t\tconst topFix = closestRel ? closestRel.getBoundingClientRect().top * -1 : 0;\n\t\t\tconst leftFix = closestRel ? closestRel.getBoundingClientRect().left * -1 : 0;\n\n\t\t\toffset = Math.round(this.dialog.nativeElement.offsetWidth / 2) - 20;\n\t\t\tif (this.dialogConfig.flip) {\n\t\t\t\treturn position.addOffset(pos, topFix, (-offset + leftFix));\n\t\t\t}\n\t\t\treturn position.addOffset(pos, topFix, (offset + leftFix));\n\t\t};\n\n\t\tthis.addGap[\"bottom\"] = positionOverflowMenu;\n\n\t\tthis.addGap[\"top\"] = positionOverflowMenu;\n\n\t\tif (!this.dialogConfig.menuLabel) {\n\t\t\tthis.dialogConfig.menuLabel = this.i18n.get().OVERFLOW_MENU.OVERFLOW;\n\t\t}\n\t}\n\n\t@HostListener(\"keydown\", [\"$event\"])\n\thostkeys(event: KeyboardEvent) {\n\t\tconst listItems = this.listItems();\n\n\t\tswitch (event.key) {\n\t\t\tcase \"ArrowDown\":\n\t\t\t\tevent.preventDefault();\n\t\t\t\tif (!isFocusInLastItem(event, listItems)) {\n\t\t\t\t\tconst index = listItems.findIndex(item => item === event.target);\n\t\t\t\t\tlistItems[index + 1].focus();\n\t\t\t\t} else {\n\t\t\t\t\tlistItems[0].focus();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"ArrowUp\":\n\t\t\t\tevent.preventDefault();\n\t\t\t\tif (!isFocusInFirstItem(event, listItems)) {\n\t\t\t\t\tconst index = listItems.findIndex(item => item === event.target);\n\t\t\t\t\tlistItems[index - 1].focus();\n\t\t\t\t} else {\n\t\t\t\t\tlistItems[listItems.length - 1].focus();\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"Home\":\n\t\t\t\tevent.preventDefault();\n\t\t\t\tlistItems[0].focus();\n\t\t\t\tbreak;\n\n\t\t\tcase \"End\":\n\t\t\t\tevent.preventDefault();\n\t\t\t\tlistItems[listItems.length - 1].focus();\n\t\t\t\tbreak;\n\n\t\t\tcase \"Escape\":\n\t\t\tcase \"Tab\":\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\tthis.doClose({\n\t\t\t\t\treason: CloseReasons.interaction,\n\t\t\t\t\ttarget: event.target\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tdefault: break;\n\t\t}\n\t}\n\n\tonClose(event) {\n\t\tthis.doClose({\n\t\t\treason: CloseReasons.interaction,\n\t\t\ttarget: event.target\n\t\t});\n\t}\n\n\tafterDialogViewInit() {\n\t\tconst focusElementList = this.listItems();\n\t\tfocusElementList.forEach(button => {\n\t\t\t// Allows user to set tabindex to 0.\n\t\t\tif (button.getAttribute(\"tabindex\") === null) {\n\t\t\t\tbutton.tabIndex = -1;\n\t\t\t}\n\t\t});\n\t\tif (focusElementList[0]) {\n\t\t\tfocusElementList[0].tabIndex = 0;\n\t\t\tfocusElementList[0].focus();\n\t\t}\n\t}\n\n\tprotected listItems() {\n\t\tconst selector = \".cds--overflow-menu-options__option:not([disabled]) .cds--overflow-menu-options__btn\";\n\t\treturn Array.from<HTMLElement>(this.elementRef.nativeElement.querySelectorAll(selector));\n\t}\n}\n","import { AfterViewInit, Component, ElementRef, Optional } from \"@angular/core\";\nimport { position } from \"@carbon/utils-position\";\nimport { I18n } from \"carbon-components-angular/i18n\";\nimport { AnimationFrameService, ElementService } from \"carbon-components-angular/utils\";\nimport { closestAttr } from \"carbon-components-angular/utils\";\nimport { CloseReasons } from \"../dialog-config.interface\";\nimport { Dialog } from \"../dialog.component\";\n\n/**\n * @deprecated as of v5\n * Use Toggletip or Popover components instead\n */\n@Component({\n\tselector: \"cds-overflow-custom-menu-pane, ibm-overflow-custom-menu-pane\",\n\ttemplate: `\n\t\t<div\n\t\t\t[attr.id]=\"dialogConfig.compID\"\n\t\t\t[attr.aria-label]=\"dialogConfig.menuLabel\"\n\t\t\t[attr.data-floating-menu-direction]=\"placement ? placement : null\"\n\t\t\t[ngClass]=\"{'cds--overflow-menu--flip': dialogConfig.flip}\"\n\t\t\tclass=\"cds--overflow-menu-options cds--overflow-menu-options--open\"\n\t\t\trole=\"menu\"\n\t\t\t(click)=\"onClick($event)\"\n\t\t\t#dialog\n\t\t\t[attr.aria-label]=\"dialogConfig.menuLabel\">\n\t\t\t<ng-template\n\t\t\t\t[ngTemplateOutlet]=\"dialogConfig.content\"\n\t\t\t\t[ngTemplateOutletContext]=\"{overflowMenu: this}\">\n\t\t\t</ng-template>\n\t\t</div>\n\t`\n})\nexport class OverflowMenuCustomPane extends Dialog implements AfterViewInit {\n\tconstructor(\n\t\tprotected elementRef: ElementRef,\n\t\tprotected i18n: I18n,\n\t\t@Optional() protected animationFrameService: AnimationFrameService = null,\n\t\t// mark `elementService` as optional since making it mandatory would be a breaking change\n\t\t@Optional() protected elementService: ElementService = null\n\t) {\n\t\tsuper(elementRef, elementService, animationFrameService);\n\t}\n\n\tonClick(event) {\n\t\tthis.doClose({\n\t\t\treason: CloseReasons.interaction,\n\t\t\ttarget: event.target\n\t\t});\n\t}\n\n\tonDialogInit() {\n\t\tconst positionOverflowMenu = pos => {\n\t\t\tlet offset;\n\t\t\t/*\n\t\t\t* 20 is half the width of the overflow menu trigger element.\n\t\t\t* we also move the element by half of it's own width, since\n\t\t\t* position service will try and center everything\n\t\t\t*/\n\t\t\tconst closestRel = closestAttr(\"position\", [\"relative\", \"fixed\", \"absolute\"], this.elementRef.nativeElement);\n\t\t\tconst topFix = closestRel ? closestRel.getBoundingClientRect().top * -1 : 0;\n\t\t\tconst leftFix = closestRel ? closestRel.getBoundingClientRect().left * -1 : 0;\n\n\t\t\toffset = Math.round(this.dialog.nativeElement.offsetWidth / 2) - 20;\n\t\t\tif (this.dialogConfig.flip) {\n\t\t\t\treturn position.addOffset(pos, topFix, (-offset + leftFix));\n\t\t\t}\n\t\t\treturn position.addOffset(pos, topFix, (offset + leftFix));\n\t\t};\n\n\t\tthis.addGap[\"bottom\"] = positionOverflowMenu;\n\n\t\tthis.addGap[\"top\"] = positionOverflowMenu;\n\n\t\tif (!this.dialogConfig.menuLabel) {\n\t\t\tthis.dialogConfig.menuLabel = this.i18n.get().OVERFLOW_MENU.OVERFLOW;\n\t\t}\n\t}\n}\n","import {\n\tDirective,\n\tElementRef,\n\tViewContainerRef,\n\tInput,\n\tTemplateRef,\n\tHostListener\n} from \"@angular/core\";\nimport { DialogDirective } from \"../dialog.directive\";\nimport { DialogService } from \"../dialog.service\";\nimport { OverflowMenuPane } from \"./overflow-menu-pane.component\";\nimport { OverflowMenuCustomPane } from \"./overflow-menu-custom-pane.component\";\nimport { EventService } from \"carbon-components-angular/utils\";\n\n\n/**\n * Directive for extending `Dialog` to create overflow menus.\n *\n * class: OverflowMenuDirective (extends DialogDirective)\n *\n *\n * selector: `cdsOverflowMenu`\n *\n *\n * ```html\n * <div [cdsOverflowMenu]=\"templateRef\"></div>\n * <ng-template #templateRef>\n * \t<!-- overflow menu options here -->\n * </ng-template>\n * ```\n *\n * ```html\n * <div [cdsOverflowMenu]=\"templateRef\" [customPane]=\"true\"></div>\n * <ng-template #templateRef>\n * <!-- custom content goes here -->\n * </ng-template>\n * ```\n */\n@Directive({\n\tselector: \"[cdsOverflowMenu], [ibmOverflowMenu]\",\n\texportAs: \"overflowMenu\",\n\tproviders: [\n\t\tDialogService\n\t]\n})\nexport class OverflowMenuDirective extends DialogDirective {\n\t/**\n\t * @deprecated as of v5\n\t * Takes a template ref of `OverflowMenuOptions`s\n\t */\n\t@Input() set ibmOverflowMenu(template: TemplateRef<any>) {\n\t\tthis.cdsOverflowMenu = template;\n\t}\n\n\t@Input() cdsOverflowMenu: TemplateRef<any>;\n\t/**\n\t * Controls wether the overflow menu is flipped\n\t */\n\t@Input() flip = false;\n\t/**\n\t * This specifies any vertical and horizontal offset for the position of the dialog\n\t */\n\t@Input() offset: { x: number, y: number };\n\t/**\n\t * Classes to add to the dialog container\n\t */\n\t@Input() wrapperClass = \"\";\n\t/**\n\t * Set to true to for custom content\n\t */\n\t@Input() customPane = false;\n\n\t/**\n\t * Creates an instance of `OverflowMenuDirective`.\n\t */\n\tconstructor(\n\t\tprotected elementRef: ElementRef,\n\t\tprotected viewContainerRef: ViewContainerRef,\n\t\tprotected dialogService: DialogService,\n\t\tprotected eventService: EventService\n\t) {\n\t\tsuper(elementRef, viewContainerRef, dialogService, eventService);\n\t}\n\n\tupdateConfig() {\n\t\tthis.dialogConfig.content = this.cdsOverflowMenu;\n\t\tthis.dialogConfig.flip = this.flip;\n\t\tthis.dialogConfig.offset = this.offset;\n\t\tthis.dialogConfig.wrapperClass = this.wrapperClass;\n\t}\n\n\t@HostListener(\"keydown\", [\"$event\"])\n\thostkeys(event: KeyboardEvent) {\n\t\tswitch (event.key) {\n\t\t\tcase \"Enter\":\n\t\t\tcase \" \":\n\t\t\t\tevent.preventDefault();\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\topen() {\n\t\treturn super.open(this.customPane ? OverflowMenuCustomPane : OverflowMenuPane);\n\t}\n}\n","import {\n\tComponent,\n\tContentChild,\n\tElementRef,\n\tEventEmitter,\n\tInput,\n\tOutput,\n\tTemplateRef,\n\tViewEncapsulation\n} from \"@angular/core\";\nimport { I18n } from \"carbon-components-angular/i18n\";\nimport { OverflowMenuDirective } from \"./overflow-menu.directive\";\nimport { BaseIconButton } from \"carbon-components-angular/button\";\n\n/**\n * The OverFlow menu component encapsulates the OverFlowMenu directive, and the menu iconography into one convienent component.\n *\n * Get started with importing the module:\n *\n * ```typescript\n * import { DialogModule } from 'carbon-components-angular';\n * ```\n *\n * ```html\n * <cds-overflow-menu>\n *\t<cds-overflow-menu-option>Option 1</cds-overflow-menu-option>\n *\t<cds-overflow-menu-option>Option 2</cds-overflow-menu-option>\n * </cds-overflow-menu>\n * ```\n *\n * [See demo](../../?path=/story/components-overflow-menu--basic)\n */\n@Component({\n\tselector: \"cds-overflow-menu, ibm-overflow-menu\",\n\ttemplate: `\n\t\t<cds-tooltip\n\t\t\tclass=\"cds--icon-tooltip\"\n\t\t\t[description]=\"description\"\n\t\t\t[caret]=\"caret\"\n\t\t\t[dropShadow]=\"dropShadow\"\n\t\t\t[highContrast]=\"highContrast\"\n\t\t\t[isOpen]=\"isOpen\"\n\t\t\t[align]=\"align\"\n\t\t\t[autoAlign]=\"autoAlign\"\n\t\t\t[enterDelayMs]=\"enterDelayMs\"\n\t\t\t[leaveDelayMs]=\"leaveDelayMs\">\n\t\t\t<button\n\t\t\t\tcdsButton=\"ghost\"\n\t\t\t\t[cdsOverflowMenu]=\"options\"\n\t\t\t\t[ngClass]=\"{'cds--overflow-menu--open': open}\"\n\t\t\t\tclass=\"cds--overflow-menu {{triggerClass}}\"\n\t\t\t\t[iconOnly]=\"true\"\n\t\t\t\t[attr.aria-label]=\"buttonLabel\"\n\t\t\t\t[flip]=\"flip\"\n\t\t\t\t[isOpen]=\"open\"\n\t\t\t\t(isOpenChange)=\"handleOpenChange($event)\"\n\t\t\t\t[offset]=\"offset\"\n\t\t\t\t[wrapperClass]=\"wrapperClass\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\ttype=\"button\"\n\t\t\t\t[placement]=\"placement\">\n\t\t\t\t<ng-template *ngIf=\"customTrigger; else defaultIcon\" [ngTemplateOutlet]=\"customTrigger\"></ng-template>\n\t\t\t</button>\n\t\t</cds-tooltip>\n\n\t\t<ng-template #options>\n\t\t\t<ng-content></ng-content>\n\t\t</ng-template>\n\t\t<ng-template #defaultIcon>\n\t\t\t<svg cdsIcon=\"overflow-menu--vertical\" size=\"16\" class=\"cds--overflow-menu__icon\"></svg>\n\t\t</ng-template>\n\t`,\n\tstyles: [`\n\t\t.cds--overflow-menu--open {\n\t\t\topacity: 1\n\t\t}\n\n\t\t/*\n\t\tRotate the overflow menu container as well as the icon, since\n\t\twe calculate our menu position based on the container, not the icon.\n\t\t*/\n\t\t.cds--data-table-v2 .cds--overflow-menu {\n\t\t\ttransform: rotate(90deg);\n\t\t}\n\n\t\t.cds--data-table-v2 .cds--overflow-menu__icon {\n\t\t\ttransform: rotate(180deg);\n\t\t}\n\t`],\n\tencapsulation: ViewEncapsulation.None\n})\nexport class OverflowMenu extends BaseIconButton {\n\t@Input() buttonLabel = this.i18n.get().OVERFLOW_MENU.OVERFLOW;\n\n\t@Input() description = this.i18n.get().OVERFLOW_MENU.ICON_DESCRIPTION;\n\n\t@Input() flip = false;\n\n\t@Input() placement: \"bottom\" | \"top\" | \"bottom,top\" | \"top,bottom\" = \"bottom\";\n\n\t@Input() open = false;\n\n\t@Output() openChange = new EventEmitter<boolean>();\n\t/**\n\t * Sets the custom overflow menu trigger\n\t */\n\t@Input() customTrigger: TemplateRef<any>;\n\n\t/**\n\t * This specifies any vertical and horizontal offset for the position of the dialog\n\t */\n\t@Input() offset: { x: number, y: number };\n\n\t@Input() wrapperClass = \"\";\n\n\t/**\n\t * This appends additional classes to the overflow trigger/button.\n\t */\n\t@Input() triggerClass = \"\";\n\n\t@ContentChild(OverflowMenuDirective) overflowMenuDirective: OverflowMenuDirective;\n\n\tconstructor(protected elementRef: ElementRef, protected i18n: I18n) {\n\t\tsuper();\n\t}\n\n\thandleOpenChange(event: boolean) {\n\t\tthis.open = event;\n\t\tthis.openChange.emit(event);\n\t}\n}\n","import {\n\tHostBinding,\n\tComponent,\n\tInput,\n\tElementRef,\n\tOutput,\n\tEventEmitter,\n\tAfterViewInit\n} from \"@angular/core\";\n\n/**\n * Available HTML anchor targets\n */\nexport enum Target {\n\tself = \"_self\",\n\tblank = \"_blank\",\n\tparent = \"_parent\",\n\ttop = \"_top\"\n}\n\n/**\n * Security HTML anchor rel when target is set\n */\nconst REL = \"noreferrer noopener\";\n\n/**\n * `OverflowMenuOption` represents a single option in an overflow menu\n *\n * Presently it has three possible states - normal, disabled, and danger:\n * ```\n * <cds-overflow-menu-option>Simple option</cds-overflow-menu-option>\n * <cds-overflow-menu-option disabled=\"true\">Disabled</cds-overflow-menu-option>\n * <cds-overflow-menu-option type=\"danger\">Danger option</cds-overflow-menu-option>\n * ```\n *\n * For content that expands beyond the overflow menu `OverflowMenuOption` automatically adds a title attribute.\n */\n@Component({\n\tselector: \"cds-overflow-menu-option, ibm-overflow-menu-option\",\n\ttemplate: `\n\t\t<button\n\t\t\t*ngIf=\"!href\"\n\t\t\tclass=\"cds--overflow-menu-options__btn {{innerClass}}\"\n\t\t\trole=\"menuitem\"\n\t\t\t[tabindex]=\"tabIndex\"\n\t\t\t(focus)=\"onFocus()\"\n\t\t\t(blur)=\"onBlur()\"\n\t\t\t(click)=\"onClick()\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[attr.title]=\"title\">\n\t\t\t<ng-container *ngTemplateOutlet=\"tempOutlet\"></ng-container>\n\t\t</button>\n\n\t\t<a\n\t\t\t*ngIf=\"href\"\n\t\t\tclass=\"cds--overflow-menu-options__btn {{innerClass}}\"\n\t\t\trole=\"menuitem\"\n\t\t\t[tabindex]=\"tabIndex\"\n\t\t\t(focus)=\"onFocus()\"\n\t\t\t(blur)=\"onBlur()\"\n\t\t\t(click)=\"onClick()\"\n\t\t\t[attr.disabled]=\"disabled\"\n\t\t\t[href]=\"href\"\n\t\t\t[attr.target]=\"target\"\n\t\t\t[attr.rel]=\"rel\"\n\t\t\t[attr.title]=\"title\">\n\t\t\t<ng-container *ngTemplateOutlet=\"tempOutlet\"></ng-container>\n\t\t</a>\n\n\t\t<ng-template #tempOutlet>\n\t\t\t<div class=\"cds--overflow-menu-options__option-content\">\n\t\t\t\t<ng-content></ng-content>\n\t\t\t</div>\n\t\t</ng-template>\n\t`\n})\nexport class OverflowMenuOption implements AfterViewInit {\n\t@HostBinding(\"class.cds--overflow-menu-options__option\") optionClass = true;\n\t@HostBinding(\"attr.role\") role = \"presentation\";\n\n\t@HostBinding(\"class.cds--overflow-menu-options__option--danger\")\n\tpublic get isDanger(): Boolean {\n\t\treturn this.type === \"danger\";\n\t}\n\n\t@HostBinding(\"class.cds--overflow-menu-options__option--disabled\")\n\tpublic get isDisabled(): Boolean {\n\t\treturn this.disabled;\n\t}\n\t/**\n\t * Set to `true` to display a dividing line above this option\n\t */\n\t@HostBinding(\"class.cds--overflow-menu--divider\") @Input() divider = false;\n\t/**\n\t * toggles between `normal` and `danger` states\n\t */\n\t@Input() type: \"normal\" | \"danger\" = \"normal\";\n\t/**\n\t * disable/enable interactions\n\t */\n\t@Input() disabled = false;\n\t/**\n\t * If it's an anchor, this is its location\n\t */\n\t@Input() href: string;\n\t/**\n\t * Allows to add a target to the anchor\n\t */\n\t@Input() set target(value: Target) {\n\t\tif (!Object.values(Target).includes(value)) {\n\t\t\tconsole.warn(\n`\\`target\\` must have one of the following values: ${Object.values(Target).join(\", \")}.\nPlease use the \\`Target\\` enum exported by carbon-components-angular`);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._target = value;\n\t}\n\t/**\n\t * Apply a custom class to the inner button/anchor\n\t */\n\t@Input() innerClass = \"\";\n\n\tget target() {\n\t\treturn this._target;\n\t}\n\t/**\n\t * rel only returns its value if target is defined\n\t */\n\tget rel() {\n\t\treturn this._target ? REL : null;\n\t}\n\n\t@Output() selected: EventEmitter<any> = new EventEmitter();\n\n\tpublic tabIndex = -1;\n\t// note: title must be a real attribute (i.e. not a getter) as of Angular@6 due to\n\t// change after checked errors\n\tpublic title = null;\n\n\tprotected _target: Target;\n\n\tconstructor(protected elementRef: ElementRef) {}\n\n\tonClick() {\n\t\tthis.selected.emit();\n\t}\n\n\tonFocus() {\n\t\tsetTimeout(() => this.tabIndex = 0);\n\t}\n\n\tonBlur() {\n\t\tsetTimeout(() => this.tabIndex = -1);\n\t}\n\n\tngAfterViewInit() {\n\t\tconst button = this.elementRef.nativeElement.querySelector(\"button, a\");\n\t\tconst textContainer = button.querySelector(\".cds--overflow-menu-options__option-content\");\n\t\tif (textContainer.scrollWidth > textContainer.offsetWidth) {\n\t\t\tthis.title = button.textContent;\n\t\t}\n\t}\n}\n","// modules\nimport { NgModule } from \"@angular/core\";\nimport { CommonModule } from \"@angular/common\";\n\n// imports\nimport { DialogService } from \"./dialog.service\";\nimport { Dialog } from \"./dialog.component\";\nimport { DialogDirective } from \"./dialog.directive\";\n\nimport { OverflowMenu } from \"./overflow-menu/overflow-menu.component\";\nimport { OverflowMenuPane } from \"./overflow-menu/overflow-menu-pane.component\";\nimport { OverflowMenuCustomPane } from \"./overflow-menu/overflow-menu-custom-pane.component\";\nimport { OverflowMenuDirective } from \"./overflow-menu/overflow-menu.directive\";\nimport { OverflowMenuOption } from \"./overflow-menu/overflow-menu-option.component\";\nimport { I18nModule } from \"carbon-components-angular/i18n\";\nimport { PlaceholderModule } from \"carbon-components-angular/placeholder\";\nimport { ExperimentalModule } from \"carbon-components-angular/experimental\";\nimport { UtilsModule } from \"carbon-components-angular/utils\";\nimport { IconModule } from \"carbon-components-angular/icon\";\nimport { ButtonModule } from \"carbon-components-angular/button\";\nimport { TooltipModule } from \"carbon-components-angular/tooltip\";\n\n@NgModule({\n\tdeclarations: [\n\t\tDialog,\n\t\tOverflowMenu,\n\t\tOverflowMenuPane,\n\t\tOverflowMenuCustomPane,\n\t\tDialogDirective,\n\t\tOverflowMenuDirective,\n\t\tOverflowMenuOption\n\t],\n\texports: [\n\t\tDialog,\n\t\tOverflowMenu,\n\t\tOverflowMenuPane,\n\t\tOverflowMenuCustomPane,\n\t\tDialogDirective,\n\t\tOverflowMenuDirective,\n\t\tOverflowMenuOption\n\t],\n\tproviders: [ DialogService ],\n\timports: [\n\t\tCommonModule,\n\t\tI18nModule,\n\t\tPlaceholderModule,\n\t\tExperimentalModule,\n\t\tUtilsModule,\n\t\tIconModule,\n\t\tButtonModule,\n\t\tTooltipModule\n\t]\n})\nexport class DialogModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i1.DialogService","i2","i3","i4","i6.OverflowMenuDirective"],"mappings":"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