From a25f6caa101d199fc2c81c1b6978bbbd40861065 Mon Sep 17 00:00:00 2001 From: Stanislav Romanov Date: Sun, 27 Mar 2022 16:04:08 +0300 Subject: [PATCH] Add component button --- app/components/button.hbs | 14 ++++ app/components/button.js | 83 +++++++++++++++++++++ tests/integration/components/button-test.js | 26 +++++++ 3 files changed, 123 insertions(+) create mode 100644 app/components/button.hbs create mode 100644 app/components/button.js create mode 100644 tests/integration/components/button-test.js diff --git a/app/components/button.hbs b/app/components/button.hbs new file mode 100644 index 0000000..c9631ca --- /dev/null +++ b/app/components/button.hbs @@ -0,0 +1,14 @@ + diff --git a/app/components/button.js b/app/components/button.js new file mode 100644 index 0000000..6529436 --- /dev/null +++ b/app/components/button.js @@ -0,0 +1,83 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; + +export default class ButtonComponent extends Component { + @tracked _state = 'default'; + + get disabled() { + if (this.args.disabled !== undefined) { + return this.args.disabled; + } + + return this.isPending; + } + + get type() { + return this.args.type ?? 'button'; + } + + get icon() { + if (this.isPending && this.args.pendingIcon) { + return this.args.pendingIcon; + } else if (this.isFulfilled && this.args.fulfilledIcon) { + return this.args.fulfilledIcon; + } else if (this.isRejected && this.args.rejectedIcon) { + return this.args.rejectedIcon; + } else if (this.isSettled && this.args.settledIcon) { + return this.args.settledIcon; + } + + return this.args.icon ?? null; + } + + get state() { + return this.args.state ?? this._state; + } + set state(state) { + this._state = state; + } + + get isPending() { + return this.state === 'pending'; + } + + get isFulfilled() { + return this.state === 'fulfilled'; + } + + get isRejected() { + return this.state === 'rejected'; + } + + get isSettled() { + return this.isFulfilled || this.isRejected; + } + + get text() { + return this.args[`${this.state}Text`] || this.args.text; + } + + @action + async handleClick() { + if (typeof this.args.onClick !== 'function') { + return; + } + + this.state = 'pending'; + + try { + await this.args.onClick(); + + if (!this.isDestroyed) { + this.state = 'fulfilled'; + } + } catch (error) { + if (!this.isDestroyed) { + this.state = 'rejected'; + } + + throw error; + } + } +} diff --git a/tests/integration/components/button-test.js b/tests/integration/components/button-test.js new file mode 100644 index 0000000..a17185a --- /dev/null +++ b/tests/integration/components/button-test.js @@ -0,0 +1,26 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | button', function (hooks) { + setupRenderingTest(hooks); + + test('it renders', async function (assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs` + `); + + assert.dom(this.element).hasText('template block text'); + }); +});