github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/components/two-step-button.js (about) 1 import Component from '@ember/component'; 2 import { action } from '@ember/object'; 3 import { next } from '@ember/runloop'; 4 import { equal } from '@ember/object/computed'; 5 import { task, waitForEvent } from 'ember-concurrency'; 6 import RSVP from 'rsvp'; 7 import { classNames, classNameBindings } from '@ember-decorators/component'; 8 import classic from 'ember-classic-decorator'; 9 10 @classic 11 @classNames('two-step-button') 12 @classNameBindings( 13 'inlineText:has-inline-text', 14 'fadingBackground:has-fading-background' 15 ) 16 export default class TwoStepButton extends Component { 17 idleText = ''; 18 cancelText = ''; 19 confirmText = ''; 20 confirmationMessage = ''; 21 awaitingConfirmation = false; 22 disabled = false; 23 alignRight = false; 24 inlineText = false; 25 onConfirm() {} 26 onCancel() {} 27 onPrompt() {} 28 29 state = 'idle'; 30 @equal('state', 'idle') isIdle; 31 @equal('state', 'prompt') isPendingConfirmation; 32 33 @task(function* () { 34 while (true) { 35 let ev = yield waitForEvent(document.body, 'click'); 36 if (!this.element.contains(ev.target) && !this.awaitingConfirmation) { 37 if (this.onCancel) { 38 this.onCancel(); 39 } 40 this.send('setToIdle'); 41 } 42 } 43 }) 44 cancelOnClickOutside; 45 46 @action 47 setToIdle() { 48 this.set('state', 'idle'); 49 this.cancelOnClickOutside.cancelAll(); 50 } 51 52 @action 53 promptForConfirmation() { 54 if (this.onPrompt) { 55 this.onPrompt(); 56 } 57 this.set('state', 'prompt'); 58 next(() => { 59 this.cancelOnClickOutside.perform(); 60 }); 61 } 62 63 @action 64 confirm() { 65 RSVP.resolve(this.onConfirm()).then(() => { 66 this.send('setToIdle'); 67 }); 68 } 69 }