ember-safe-button 4.0.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,10 +2,17 @@
2
2
 
3
3
  # ember-safe-button
4
4
 
5
- Provides a button for potentially dangerous actions that need confirmation. The
6
- first click unlocks the safety, the second confirms. If no confirmation is
7
- provided, the safety rolls back after a timeout.
5
+ Provides a button for potentially dangerous actions that need confirmation
6
+ without popping a modal. The first click unlocks the safety, the second confirms
7
+ the action. If no confirmation is provided, the safety rolls back after a
8
+ timeout so you never stay in a risky state.
8
9
 
10
+ This is ideal for destructive actions (delete, remove, revoke) where you want
11
+ users to stay in context, keep focus, and still get a deliberate second click.
12
+ It slows accidental taps just enough to prevent mistakes, but stays lighter
13
+ weight than a full dialog.
14
+
15
+ - GitLab: [![GitLab](./public/gitlab-mark.svg)](https://gitlab.com/michal-bryxi/open-source/ember-safe-button)
9
16
  - Demo page: https://ember-safe-button.netlify.app
10
17
 
11
18
  ## Compatibility
@@ -22,12 +29,58 @@ ember install ember-safe-button
22
29
 
23
30
  ## Usage
24
31
 
25
- Minimal example:
32
+ Minimal example (GJS):
33
+
34
+ ```gjs
35
+ import Component from '@glimmer/component';
36
+ import { action } from '@ember/object';
37
+ import { SafeButton } from 'ember-safe-button';
38
+
39
+ export default class DeleteButton extends Component {
40
+ @action
41
+ confirmDelete() {
42
+ // delete the record
43
+ }
44
+
45
+ <template>
46
+ <SafeButton @message="delete" @onConfirm={{this.confirmDelete}} />
47
+ </template>
48
+ }
49
+ ```
50
+
51
+ Minimal example (HBS):
26
52
 
27
53
  ```hbs
28
54
  <SafeButton @message="delete" @onConfirm={{this.safeButtonClicked}} />
29
55
  ```
30
56
 
57
+ ### Animations
58
+
59
+ `@animation` expects an animation object. Built-in animations are exported as
60
+ `animations`:
61
+
62
+ ```gjs
63
+ import Component from '@glimmer/component';
64
+ import { action } from '@ember/object';
65
+ import { SafeButton, animations } from 'ember-safe-button';
66
+ // animations = { poing, slide, flip, zoom, roll, "lift-bars" }
67
+
68
+ export default class AnimatedDelete extends Component {
69
+ @action
70
+ confirmDelete() {
71
+ // delete the record
72
+ }
73
+
74
+ <template>
75
+ <SafeButton
76
+ @animation={{animations.flip}}
77
+ @message="delete"
78
+ @onConfirm={{this.confirmDelete}}
79
+ />
80
+ </template>
81
+ }
82
+ ```
83
+
31
84
  Which will produce:
32
85
 
33
86
  ![Example](./public/demo.gif)
@@ -14,7 +14,7 @@ import { setComponentTemplate } from '@ember/component';
14
14
  import { g, i, n } from 'decorator-transforms/runtime-esm';
15
15
 
16
16
  const DEFAULT_TIMEOUT = 3000;
17
- const DEFAULT_ANIMATION = 'slide';
17
+ const DEFAULT_ANIMATION = embeddedAnimations.slide;
18
18
  /**
19
19
  Main component.
20
20
 
@@ -30,7 +30,7 @@ const DEFAULT_ANIMATION = 'slide';
30
30
  ```
31
31
  @class SafeButtonComponent
32
32
  @param {string} [class="ember-safe-button"] CSS class to be applied on the wrapping element.
33
- @param {object} [animation="slid"] Definition of animation; It can either be string and point to one of the pre-defined animations; Or it can be an object describing Web Animation API
33
+ @param {object} [animation=slide] Definition of animation. It must be an object describing Web Animation API
34
34
  @param {number} [timeout=3000] Number of millisenconds after which the safety rolls back over the trigger.
35
35
  @param {string} [message="delete"] Text to be printed on the buttons in case block is not provided.
36
36
  @param {function} onConfirm - Action to trigger whenever user clicks the trigger.
@@ -107,7 +107,8 @@ class SafeButtonComponent extends Component {
107
107
  #safetyStatus = (i(this, "safetyStatus"), void 0);
108
108
  get activeAnimation() {
109
109
  const animation = this.args.animation || DEFAULT_ANIMATION;
110
- return typeof animation === 'string' ? embeddedAnimations[animation] : animation;
110
+ assert('@animation must be an animation object, not a string', animation && typeof animation === 'object');
111
+ return animation;
111
112
  }
112
113
  get webAnimations() {
113
114
  const {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/components/safe-button/index.gjs"],"sourcesContent":["import Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { assert } from '@ember/debug';\nimport { action } from '@ember/object';\nimport { hash } from '@ember/helper';\n\nimport { timeout } from 'ember-concurrency';\nimport { task } from 'ember-concurrency';\n\nimport embeddedAnimations from './animations/index.js';\nimport Safety from '../safety/index.gjs';\nimport Trigger from '../trigger/index.gjs';\nimport { SAFETY_STATUS } from '../../states.js';\n\nconst DEFAULT_TIMEOUT = 3000;\nconst DEFAULT_ANIMATION = 'slide';\n\n/**\n Main component.\n\n ```hbs\n <SafeButton\n class=\"border-black\"\n @animation={{this.animation}}\n @message=\"Delete me\"\n @timeout={{2000}}\n @onConfirm={{action safeButtonClicked}} />\n ```\n\n ```\n @class SafeButtonComponent\n @param {string} [class=\"ember-safe-button\"] CSS class to be applied on the wrapping element.\n @param {object} [animation=\"slid\"] Definition of animation; It can either be string and point to one of the pre-defined animations; Or it can be an object describing Web Animation API\n @param {number} [timeout=3000] Number of millisenconds after which the safety rolls back over the trigger.\n @param {string} [message=\"delete\"] Text to be printed on the buttons in case block is not provided.\n @param {function} onConfirm - Action to trigger whenever user clicks the trigger.\n ```\n\n When trying to construct your own `@animation` object you can take inspiration from the simple `slide` animation. The thing to keep in mind is that these go directly as parameters to [element.animate()](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) and that there are in fact four animations of which always two fire at the same time:\n\n - `safety.unlocking` and `trigger.unlocking`\n - `safety.locking` and `trigger.locking`\n\n ```js\n {\n safety: {\n unlocking: {\n keyframes: [\n { transform: 'translateX(0)' },\n { transform: 'translateX(-100%)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n locking: {\n keyframes: [\n { transform: 'translateX(-100%)' },\n { transform: 'translateX(0)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n },\n trigger: {\n unlocking: {\n keyframes: [\n { transform: 'translateX(100%)' },\n { transform: 'translateX(0)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n locking: {\n keyframes: [\n { transform: 'translateX(0)' },\n { transform: 'translateX(100%)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n },\n }\n ```\n */\nexport default class SafeButtonComponent extends Component {\n constructor() {\n super(...arguments);\n\n assert(\n '@onConfirm attribute must be set',\n typeof this.args.onConfirm === 'function',\n );\n }\n\n @tracked safetyStatus = SAFETY_STATUS.LOCKED;\n\n get activeAnimation() {\n const animation = this.args.animation || DEFAULT_ANIMATION;\n\n return typeof animation === 'string'\n ? embeddedAnimations[animation]\n : animation;\n }\n\n get webAnimations() {\n const { activeAnimation, onUnlocked, onLocked } = this;\n\n return {\n safety: {\n unlocking: ({ element }) => {\n let animation = element.animate(\n activeAnimation.safety.unlocking.keyframes,\n activeAnimation.safety.unlocking.options,\n );\n animation.onfinish = onUnlocked;\n },\n locking: ({ element }) => {\n let animation = element.animate(\n activeAnimation.safety.locking.keyframes,\n activeAnimation.safety.locking.options,\n );\n animation.onfinish = onLocked;\n },\n },\n trigger: {\n unlocking({ element }) {\n element.animate(\n activeAnimation.trigger.unlocking.keyframes,\n activeAnimation.trigger.unlocking.options,\n );\n },\n locking({ element }) {\n element.animate(\n activeAnimation.trigger.locking.keyframes,\n activeAnimation.trigger.locking.options,\n );\n },\n },\n };\n }\n\n get timeout() {\n return this.args.timeout || DEFAULT_TIMEOUT;\n }\n\n get displayedMessage() {\n return this.args.message || 'delete';\n }\n\n @action\n onUnlocking() {\n this.safetyStatus = SAFETY_STATUS.UNLOCKING;\n }\n\n @action\n onUnlocked() {\n this.safetyStatus = SAFETY_STATUS.UNLOCKED;\n this.triggerSafety.perform();\n }\n\n @action\n onLocked() {\n this.safetyStatus = SAFETY_STATUS.LOCKED;\n }\n\n triggerSafety = task(async () => {\n await timeout(this.timeout);\n this.safetyStatus = SAFETY_STATUS.LOCKING;\n });\n\n <template>\n <div class=\"ember-safe-button\" ...attributes>\n {{#if (has-block)}}\n {{yield\n (hash\n trigger=(component\n Trigger\n onClick=@onConfirm\n safetyStatus=this.safetyStatus\n displayedMessage=this.displayedMessage\n webAnimations=this.webAnimations.trigger\n )\n safety=(component\n Safety\n onClick=this.onUnlocking\n safetyStatus=this.safetyStatus\n displayedMessage=this.displayedMessage\n webAnimations=this.webAnimations.safety\n )\n )\n }}\n {{else}}\n <Trigger\n @onClick={{@onConfirm}}\n @safetyStatus={{this.safetyStatus}}\n @displayedMessage={{this.displayedMessage}}\n @webAnimations={{this.webAnimations.trigger}}\n />\n <Safety\n @onClick={{this.onUnlocking}}\n @safetyStatus={{this.safetyStatus}}\n @displayedMessage={{this.displayedMessage}}\n @webAnimations={{this.webAnimations.safety}}\n />\n {{/if}}\n </div>\n </template>\n}\n"],"names":["DEFAULT_TIMEOUT","DEFAULT_ANIMATION","SafeButtonComponent","Component","constructor","arguments","assert","args","onConfirm","g","prototype","tracked","SAFETY_STATUS","LOCKED","i","activeAnimation","animation","embeddedAnimations","webAnimations","onUnlocked","onLocked","safety","unlocking","element","animate","keyframes","options","onfinish","locking","trigger","timeout","displayedMessage","message","onUnlocking","safetyStatus","UNLOCKING","n","action","UNLOCKED","triggerSafety","perform","_buildTask","context","generator","LOCKING","setComponentTemplate","precompileTemplate","strictMode","scope","hash","Trigger","Safety"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/components/safe-button/index.gjs"],"sourcesContent":["import Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { assert } from '@ember/debug';\nimport { action } from '@ember/object';\nimport { hash } from '@ember/helper';\n\nimport { timeout } from 'ember-concurrency';\nimport { task } from 'ember-concurrency';\n\nimport embeddedAnimations from './animations/index.js';\nimport Safety from '../safety/index.gjs';\nimport Trigger from '../trigger/index.gjs';\nimport { SAFETY_STATUS } from '../../states.js';\n\nconst DEFAULT_TIMEOUT = 3000;\nconst DEFAULT_ANIMATION = embeddedAnimations.slide;\n\n/**\n Main component.\n\n ```hbs\n <SafeButton\n class=\"border-black\"\n @animation={{this.animation}}\n @message=\"Delete me\"\n @timeout={{2000}}\n @onConfirm={{action safeButtonClicked}} />\n ```\n\n ```\n @class SafeButtonComponent\n @param {string} [class=\"ember-safe-button\"] CSS class to be applied on the wrapping element.\n @param {object} [animation=slide] Definition of animation. It must be an object describing Web Animation API\n @param {number} [timeout=3000] Number of millisenconds after which the safety rolls back over the trigger.\n @param {string} [message=\"delete\"] Text to be printed on the buttons in case block is not provided.\n @param {function} onConfirm - Action to trigger whenever user clicks the trigger.\n ```\n\n When trying to construct your own `@animation` object you can take inspiration from the simple `slide` animation. The thing to keep in mind is that these go directly as parameters to [element.animate()](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) and that there are in fact four animations of which always two fire at the same time:\n\n - `safety.unlocking` and `trigger.unlocking`\n - `safety.locking` and `trigger.locking`\n\n ```js\n {\n safety: {\n unlocking: {\n keyframes: [\n { transform: 'translateX(0)' },\n { transform: 'translateX(-100%)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n locking: {\n keyframes: [\n { transform: 'translateX(-100%)' },\n { transform: 'translateX(0)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n },\n trigger: {\n unlocking: {\n keyframes: [\n { transform: 'translateX(100%)' },\n { transform: 'translateX(0)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n locking: {\n keyframes: [\n { transform: 'translateX(0)' },\n { transform: 'translateX(100%)' },\n ],\n options: {\n duration: 1000,\n fill: 'both',\n easing: 'ease',\n },\n },\n },\n }\n ```\n */\nexport default class SafeButtonComponent extends Component {\n constructor() {\n super(...arguments);\n\n assert(\n '@onConfirm attribute must be set',\n typeof this.args.onConfirm === 'function',\n );\n }\n\n @tracked safetyStatus = SAFETY_STATUS.LOCKED;\n\n get activeAnimation() {\n const animation = this.args.animation || DEFAULT_ANIMATION;\n\n assert(\n '@animation must be an animation object, not a string',\n animation && typeof animation === 'object',\n );\n\n return animation;\n }\n\n get webAnimations() {\n const { activeAnimation, onUnlocked, onLocked } = this;\n\n return {\n safety: {\n unlocking: ({ element }) => {\n let animation = element.animate(\n activeAnimation.safety.unlocking.keyframes,\n activeAnimation.safety.unlocking.options,\n );\n animation.onfinish = onUnlocked;\n },\n locking: ({ element }) => {\n let animation = element.animate(\n activeAnimation.safety.locking.keyframes,\n activeAnimation.safety.locking.options,\n );\n animation.onfinish = onLocked;\n },\n },\n trigger: {\n unlocking({ element }) {\n element.animate(\n activeAnimation.trigger.unlocking.keyframes,\n activeAnimation.trigger.unlocking.options,\n );\n },\n locking({ element }) {\n element.animate(\n activeAnimation.trigger.locking.keyframes,\n activeAnimation.trigger.locking.options,\n );\n },\n },\n };\n }\n\n get timeout() {\n return this.args.timeout || DEFAULT_TIMEOUT;\n }\n\n get displayedMessage() {\n return this.args.message || 'delete';\n }\n\n @action\n onUnlocking() {\n this.safetyStatus = SAFETY_STATUS.UNLOCKING;\n }\n\n @action\n onUnlocked() {\n this.safetyStatus = SAFETY_STATUS.UNLOCKED;\n this.triggerSafety.perform();\n }\n\n @action\n onLocked() {\n this.safetyStatus = SAFETY_STATUS.LOCKED;\n }\n\n triggerSafety = task(async () => {\n await timeout(this.timeout);\n this.safetyStatus = SAFETY_STATUS.LOCKING;\n });\n\n <template>\n <div class=\"ember-safe-button\" ...attributes>\n {{#if (has-block)}}\n {{yield\n (hash\n trigger=(component\n Trigger\n onClick=@onConfirm\n safetyStatus=this.safetyStatus\n displayedMessage=this.displayedMessage\n webAnimations=this.webAnimations.trigger\n )\n safety=(component\n Safety\n onClick=this.onUnlocking\n safetyStatus=this.safetyStatus\n displayedMessage=this.displayedMessage\n webAnimations=this.webAnimations.safety\n )\n )\n }}\n {{else}}\n <Trigger\n @onClick={{@onConfirm}}\n @safetyStatus={{this.safetyStatus}}\n @displayedMessage={{this.displayedMessage}}\n @webAnimations={{this.webAnimations.trigger}}\n />\n <Safety\n @onClick={{this.onUnlocking}}\n @safetyStatus={{this.safetyStatus}}\n @displayedMessage={{this.displayedMessage}}\n @webAnimations={{this.webAnimations.safety}}\n />\n {{/if}}\n </div>\n </template>\n}\n"],"names":["DEFAULT_TIMEOUT","DEFAULT_ANIMATION","embeddedAnimations","slide","SafeButtonComponent","Component","constructor","arguments","assert","args","onConfirm","g","prototype","tracked","SAFETY_STATUS","LOCKED","i","activeAnimation","animation","webAnimations","onUnlocked","onLocked","safety","unlocking","element","animate","keyframes","options","onfinish","locking","trigger","timeout","displayedMessage","message","onUnlocking","safetyStatus","UNLOCKING","n","action","UNLOCKED","triggerSafety","perform","_buildTask","context","generator","LOCKING","setComponentTemplate","precompileTemplate","strictMode","scope","hash","Trigger","Safety"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default as Trigger } from './components/trigger/index.js';
2
2
  export { default as Safety } from './components/safety/index.js';
3
3
  export { default as SafeButton } from './components/safe-button/index.js';
4
+ export { default as animations } from './components/safe-button/animations/index.js';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
package/package.json CHANGED
@@ -1,11 +1,18 @@
1
1
  {
2
2
  "name": "ember-safe-button",
3
- "version": "4.0.2",
3
+ "version": "5.0.0",
4
4
  "description": "For potentially dangerous actions that better needs a confirmation.",
5
5
  "keywords": [
6
6
  "ember-addon"
7
7
  ],
8
- "repository": "https://gitlab.com/michal-bryxi-oss/ember-safe-button",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://gitlab.com/michal-bryxi/open-source/ember-safe-button.git"
11
+ },
12
+ "homepage": "https://ember-safe-button.netlify.app",
13
+ "bugs": {
14
+ "url": "https://gitlab.com/michal-bryxi/open-source/ember-safe-button/-/issues"
15
+ },
9
16
  "license": "MIT",
10
17
  "author": "",
11
18
  "imports": {
@@ -25,19 +32,21 @@
25
32
  "addon-main.cjs",
26
33
  "declarations",
27
34
  "dist",
28
- "src"
35
+ "src",
36
+ "README.md",
37
+ "LICENSE.md"
29
38
  ],
30
39
  "dependencies": {
31
40
  "@ember/render-modifiers": "3.0.0",
32
41
  "@embroider/addon-shim": "^1.10.2",
33
- "decorator-transforms": "^2.2.2",
42
+ "decorator-transforms": "^2.3.1",
34
43
  "ember-concurrency": "5.1.0",
35
44
  "ember-modifier": "4.2.2"
36
45
  },
37
46
  "devDependencies": {
38
- "@babel/core": "^7.25.2",
39
- "@babel/eslint-parser": "^7.25.1",
40
- "@babel/runtime": "^7.25.6",
47
+ "@babel/core": "^7.28.6",
48
+ "@babel/eslint-parser": "^7.28.6",
49
+ "@babel/runtime": "^7.28.6",
41
50
  "@ember/app-tsconfig": "^1.0.3",
42
51
  "@ember/library-tsconfig": "^1.0.0",
43
52
  "@ember/test-helpers": "^5.2.1",
@@ -49,9 +58,9 @@
49
58
  "@embroider/vite": "^1.1.5",
50
59
  "@eslint/js": "^9.17.0",
51
60
  "@glimmer/component": "^2.0.0",
52
- "@rollup/plugin-babel": "^6.0.4",
61
+ "@rollup/plugin-babel": "^6.1.0",
53
62
  "@tailwindcss/vite": "^4.0.0",
54
- "babel-plugin-ember-template-compilation": "^2.2.5",
63
+ "babel-plugin-ember-template-compilation": "^2.4.1",
55
64
  "concurrently": "^9.0.1",
56
65
  "ember-concurrency": "5.1.0",
57
66
  "ember-modifier": "4.2.2",
@@ -13,7 +13,7 @@ import Trigger from '../trigger/index.gjs';
13
13
  import { SAFETY_STATUS } from '../../states.js';
14
14
 
15
15
  const DEFAULT_TIMEOUT = 3000;
16
- const DEFAULT_ANIMATION = 'slide';
16
+ const DEFAULT_ANIMATION = embeddedAnimations.slide;
17
17
 
18
18
  /**
19
19
  Main component.
@@ -30,7 +30,7 @@ const DEFAULT_ANIMATION = 'slide';
30
30
  ```
31
31
  @class SafeButtonComponent
32
32
  @param {string} [class="ember-safe-button"] CSS class to be applied on the wrapping element.
33
- @param {object} [animation="slid"] Definition of animation; It can either be string and point to one of the pre-defined animations; Or it can be an object describing Web Animation API
33
+ @param {object} [animation=slide] Definition of animation. It must be an object describing Web Animation API
34
34
  @param {number} [timeout=3000] Number of millisenconds after which the safety rolls back over the trigger.
35
35
  @param {string} [message="delete"] Text to be printed on the buttons in case block is not provided.
36
36
  @param {function} onConfirm - Action to trigger whenever user clicks the trigger.
@@ -109,9 +109,12 @@ export default class SafeButtonComponent extends Component {
109
109
  get activeAnimation() {
110
110
  const animation = this.args.animation || DEFAULT_ANIMATION;
111
111
 
112
- return typeof animation === 'string'
113
- ? embeddedAnimations[animation]
114
- : animation;
112
+ assert(
113
+ '@animation must be an animation object, not a string',
114
+ animation && typeof animation === 'object',
115
+ );
116
+
117
+ return animation;
115
118
  }
116
119
 
117
120
  get webAnimations() {
package/src/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { default as Trigger } from './components/trigger/index.gjs';
2
2
  export { default as Safety } from './components/safety/index.gjs';
3
3
  export { default as SafeButton } from './components/safe-button/index.gjs';
4
+ export { default as animations } from './components/safe-button/animations/index.js';