diff --git a/src/components/action-sheet/action-sheet-component.ts b/src/components/action-sheet/action-sheet-component.ts index f129ac6abc..5f379bf0c4 100644 --- a/src/components/action-sheet/action-sheet-component.ts +++ b/src/components/action-sheet/action-sheet-component.ts @@ -3,7 +3,7 @@ import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from import { assert } from '../../util/util'; import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller'; import { Config } from '../../config/config'; -import { Key } from '../../platform/key'; +import { KEY_ESCAPE } from '../../platform/key'; import { Platform } from '../../platform/platform'; import { NavParams } from '../../navigation/nav-params'; import { NavOptions } from '../../navigation/nav-util'; @@ -135,11 +135,9 @@ export class ActionSheetCmp { @HostListener('body:keyup', ['$event']) keyUp(ev: KeyboardEvent) { - if (this.enabled && this._viewCtrl.isLast()) { - if (ev.keyCode === Key.ESCAPE) { - console.debug('actionsheet, escape button'); - this.bdClick(); - } + if (this.enabled && ev.keyCode === KEY_ESCAPE && this._viewCtrl.isLast()) { + console.debug('actionsheet, escape button'); + this.bdClick(); } } diff --git a/src/components/action-sheet/action-sheet-controller.ts b/src/components/action-sheet/action-sheet-controller.ts new file mode 100644 index 0000000000..b5096df99e --- /dev/null +++ b/src/components/action-sheet/action-sheet-controller.ts @@ -0,0 +1,170 @@ +import { Injectable } from '@angular/core'; + +import { ActionSheet } from './action-sheet'; +import { ActionSheetOptions } from './action-sheet-options'; +import { App } from '../app/app'; +import { Config } from '../../config/config'; + +/** + * @name ActionSheetController + * @description + * An Action Sheet is a dialog that lets the user choose from a set of + * options. It appears on top of the app's content, and must be manually + * dismissed by the user before they can resume interaction with the app. + * Dangerous (destructive) options are made obvious in `ios` mode. There are easy + * ways to cancel out of the action sheet, such as tapping the backdrop or + * hitting the escape key on desktop. + * + * An action sheet is created from an array of `buttons`, with each button + * including properties for its `text`, and optionally a `handler` and `role`. + * If a handler returns `false` then the action sheet will not be dismissed. An + * action sheet can also optionally have a `title`, `subTitle` and an `icon`. + * + * A button's `role` property can either be `destructive` or `cancel`. Buttons + * without a role property will have the default look for the platform. Buttons + * with the `cancel` role will always load as the bottom button, no matter where + * they are in the array. All other buttons will be displayed in the order they + * have been added to the `buttons` array. Note: We recommend that `destructive` + * buttons are always the first button in the array, making them the top button. + * Additionally, if the action sheet is dismissed by tapping the backdrop, then + * it will fire the handler from the button with the cancel role. + * + * You can pass all of the action sheet's options in the first argument of + * the create method: `ActionSheet.create(opts)`. Otherwise the action sheet's + * instance has methods to add options, like `setTitle()` or `addButton()`. + * + * @usage + * ```ts + * import { ActionSheetController } from 'ionic-angular' + * + * export class MyClass{ + * + * constructor(public actionSheetCtrl: ActionSheetController) {} + * + * presentActionSheet() { + * let actionSheet = this.actionSheetCtrl.create({ + * title: 'Modify your album', + * buttons: [ + * { + * text: 'Destructive', + * role: 'destructive', + * handler: () => { + * console.log('Destructive clicked'); + * } + * }, + * { + * text: 'Archive', + * handler: () => { + * console.log('Archive clicked'); + * } + * }, + * { + * text: 'Cancel', + * role: 'cancel', + * handler: () => { + * console.log('Cancel clicked'); + * } + * } + * ] + * }); + * + * actionSheet.present(); + * } + * } + * ``` + * + * @advanced + * + * ActionSheet create options + * + * | Option | Type | Description | + * |-----------------------|------------|--------------------------------------------------------------------| + * | title |`string` | The title for the Action Sheet. | + * | subTitle |`string` | The sub-title for the Action Sheet. | + * | cssClass |`string` | Additional classes for custom styles, separated by spaces. | + * | enableBackdropDismiss |`boolean` | If the Action Sheet should close when the user taps the backdrop. | + * | buttons |`array`| An array of buttons to display. | + * + * ActionSheet button options + * + * | Option | Type | Description | + * |----------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------| + * | text | `string` | The buttons text. | + * | icon | `icon` | The buttons icons. | + * | handler | `any` | An express the button should evaluate. | + * | cssClass | `string` | Additional classes for custom styles, separated by spaces. | + * | role | `string` | How the button should be displayed, `destructive` or `cancel`. If not role is provided, it will display the button without any additional styles.| + * + * + * ### Dismissing And Async Navigation + * + * After an action sheet has been dismissed, the app may need to also transition + * to another page depending on the handler's logic. However, because multiple + * transitions were fired at roughly the same time, it's difficult for the + * nav controller to cleanly animate multiple transitions that may + * have been kicked off asynchronously. This is further described in the + * [`Nav Transition Promises`](../../nav/NavController/#nav-transition-promises) section. For action sheets, + * this means it's best to wait for the action sheet to finish its transition + * out before starting a new transition on the same nav controller. + * + * In the example below, after the button has been clicked, its handler + * waits on async operation to complete, *then* it uses `pop` to navigate + * back a page in the same stack. The potential problem is that the async operation + * may have been completed before the action sheet has even finished its transition + * out. In this case, it's best to ensure the action sheet has finished its transition + * out first, *then* start the next transition. + * + * ```ts + * let actionSheet = this.actionSheetCtrl.create({ + * title: 'Hello', + * buttons: [{ + * text: 'Ok', + * handler: () => { + * // user has clicked the action sheet button + * // begin the action sheet's dimiss transition + * let navTransition = actionSheet.dismiss(); + * + * // start some async method + * someAsyncOperation().then(() => { + * // once the async operation has completed + * // then run the next nav transition after the + * // first transition has finished animating out + * + * navTransition.then(() => { + * this.nav.pop(); + * }); + * }); + * return false; + * } + * }] + * }); + * + * actionSheet.present(); + * ``` + * + * It's important to note that the handler returns `false`. A feature of + * button handlers is that they automatically dismiss the action sheet when their button + * was clicked, however, we'll need more control regarding the transition. Because + * the handler returns `false`, then the action sheet does not automatically dismiss + * itself. Instead, you now have complete control of when the action sheet has finished + * transitioning, and the ability to wait for the action sheet to finish transitioning + * out before starting a new transition. + * + * + * @demo /docs/v2/demos/src/action-sheet/ + * @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs} + */ +@Injectable() +export class ActionSheetController { + + constructor(private _app: App, public config: Config) { } + + /** + * Open an action sheet with a title, subTitle, and an array of buttons + * @param {ActionSheetOptions} opts Action sheet options + */ + create(opts: ActionSheetOptions = {}): ActionSheet { + return new ActionSheet(this._app, opts, this.config); + } + +} diff --git a/src/components/action-sheet/action-sheet.ts b/src/components/action-sheet/action-sheet.ts index c1539077eb..a9e3b9f5fe 100644 --- a/src/components/action-sheet/action-sheet.ts +++ b/src/components/action-sheet/action-sheet.ts @@ -1,25 +1,33 @@ -import { Injectable } from '@angular/core'; - import { ActionSheetCmp } from './action-sheet-component'; import { ActionSheetOptions } from './action-sheet-options'; +import { ActionSheetSlideIn, ActionSheetMdSlideIn, ActionSheetSlideOut, ActionSheetMdSlideOut, ActionSheetWpSlideIn, ActionSheetWpSlideOut } from './action-sheet-transitions'; import { App } from '../app/app'; +import { Config } from '../../config/config'; import { isPresent } from '../../util/util'; import { NavOptions } from '../../navigation/nav-util'; import { ViewController } from '../../navigation/view-controller'; + /** * @private */ export class ActionSheet extends ViewController { private _app: App; - constructor(app: App, opts: ActionSheetOptions) { + constructor(app: App, opts: ActionSheetOptions, config: Config) { opts.buttons = opts.buttons || []; opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true; super(ActionSheetCmp, opts, null); this._app = app; this.isOverlay = true; + + config.setTransition('action-sheet-slide-in', ActionSheetSlideIn); + config.setTransition('action-sheet-slide-out', ActionSheetSlideOut); + config.setTransition('action-sheet-md-slide-in', ActionSheetMdSlideIn); + config.setTransition('action-sheet-md-slide-out', ActionSheetMdSlideOut); + config.setTransition('action-sheet-wp-slide-in', ActionSheetWpSlideIn); + config.setTransition('action-sheet-wp-slide-out', ActionSheetWpSlideOut); } /** @@ -63,168 +71,3 @@ export class ActionSheet extends ViewController { } } - - -/** - * @name ActionSheetController - * @description - * An Action Sheet is a dialog that lets the user choose from a set of - * options. It appears on top of the app's content, and must be manually - * dismissed by the user before they can resume interaction with the app. - * Dangerous (destructive) options are made obvious in `ios` mode. There are easy - * ways to cancel out of the action sheet, such as tapping the backdrop or - * hitting the escape key on desktop. - * - * An action sheet is created from an array of `buttons`, with each button - * including properties for its `text`, and optionally a `handler` and `role`. - * If a handler returns `false` then the action sheet will not be dismissed. An - * action sheet can also optionally have a `title`, `subTitle` and an `icon`. - * - * A button's `role` property can either be `destructive` or `cancel`. Buttons - * without a role property will have the default look for the platform. Buttons - * with the `cancel` role will always load as the bottom button, no matter where - * they are in the array. All other buttons will be displayed in the order they - * have been added to the `buttons` array. Note: We recommend that `destructive` - * buttons are always the first button in the array, making them the top button. - * Additionally, if the action sheet is dismissed by tapping the backdrop, then - * it will fire the handler from the button with the cancel role. - * - * You can pass all of the action sheet's options in the first argument of - * the create method: `ActionSheet.create(opts)`. Otherwise the action sheet's - * instance has methods to add options, like `setTitle()` or `addButton()`. - * - * @usage - * ```ts - * import { ActionSheetController } from 'ionic-angular' - * - * export class MyClass{ - * - * constructor(public actionSheetCtrl: ActionSheetController) {} - * - * presentActionSheet() { - * let actionSheet = this.actionSheetCtrl.create({ - * title: 'Modify your album', - * buttons: [ - * { - * text: 'Destructive', - * role: 'destructive', - * handler: () => { - * console.log('Destructive clicked'); - * } - * }, - * { - * text: 'Archive', - * handler: () => { - * console.log('Archive clicked'); - * } - * }, - * { - * text: 'Cancel', - * role: 'cancel', - * handler: () => { - * console.log('Cancel clicked'); - * } - * } - * ] - * }); - * - * actionSheet.present(); - * } - * } - * ``` - * - * @advanced - * - * ActionSheet create options - * - * | Option | Type | Description | - * |-----------------------|------------|--------------------------------------------------------------------| - * | title |`string` | The title for the Action Sheet. | - * | subTitle |`string` | The sub-title for the Action Sheet. | - * | cssClass |`string` | Additional classes for custom styles, separated by spaces. | - * | enableBackdropDismiss |`boolean` | If the Action Sheet should close when the user taps the backdrop. | - * | buttons |`array`| An array of buttons to display. | - * - * ActionSheet button options - * - * | Option | Type | Description | - * |----------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------| - * | text | `string` | The buttons text. | - * | icon | `icon` | The buttons icons. | - * | handler | `any` | An express the button should evaluate. | - * | cssClass | `string` | Additional classes for custom styles, separated by spaces. | - * | role | `string` | How the button should be displayed, `destructive` or `cancel`. If not role is provided, it will display the button without any additional styles.| - * - * - * ### Dismissing And Async Navigation - * - * After an action sheet has been dismissed, the app may need to also transition - * to another page depending on the handler's logic. However, because multiple - * transitions were fired at roughly the same time, it's difficult for the - * nav controller to cleanly animate multiple transitions that may - * have been kicked off asynchronously. This is further described in the - * [`Nav Transition Promises`](../../nav/NavController/#nav-transition-promises) section. For action sheets, - * this means it's best to wait for the action sheet to finish its transition - * out before starting a new transition on the same nav controller. - * - * In the example below, after the button has been clicked, its handler - * waits on async operation to complete, *then* it uses `pop` to navigate - * back a page in the same stack. The potential problem is that the async operation - * may have been completed before the action sheet has even finished its transition - * out. In this case, it's best to ensure the action sheet has finished its transition - * out first, *then* start the next transition. - * - * ```ts - * let actionSheet = this.actionSheetCtrl.create({ - * title: 'Hello', - * buttons: [{ - * text: 'Ok', - * handler: () => { - * // user has clicked the action sheet button - * // begin the action sheet's dimiss transition - * let navTransition = actionSheet.dismiss(); - * - * // start some async method - * someAsyncOperation().then(() => { - * // once the async operation has completed - * // then run the next nav transition after the - * // first transition has finished animating out - * - * navTransition.then(() => { - * this.nav.pop(); - * }); - * }); - * return false; - * } - * }] - * }); - * - * actionSheet.present(); - * ``` - * - * It's important to note that the handler returns `false`. A feature of - * button handlers is that they automatically dismiss the action sheet when their button - * was clicked, however, we'll need more control regarding the transition. Because - * the handler returns `false`, then the action sheet does not automatically dismiss - * itself. Instead, you now have complete control of when the action sheet has finished - * transitioning, and the ability to wait for the action sheet to finish transitioning - * out before starting a new transition. - * - * - * @demo /docs/v2/demos/src/action-sheet/ - * @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs} - */ -@Injectable() -export class ActionSheetController { - - constructor(private _app: App) {} - - /** - * Open an action sheet with a title, subTitle, and an array of buttons - * @param {ActionSheetOptions} opts Action sheet options - */ - create(opts: ActionSheetOptions = {}): ActionSheet { - return new ActionSheet(this._app, opts); - } - -}