stimulus-library 0.8.0 → 0.9.1

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.
@@ -0,0 +1,21 @@
1
+ import { BaseController } from "../../utilities/base_controller";
2
+ export class DisableInputsController extends BaseController {
3
+ connect() {
4
+ }
5
+ disable() {
6
+ let shouldClear = this.hasClearValue && this.clearValue;
7
+ this.inputTargets.forEach((el, _) => {
8
+ if (shouldClear) {
9
+ el.value = "";
10
+ }
11
+ el.disabled = true;
12
+ });
13
+ }
14
+ enable() {
15
+ this.inputTargets.forEach((el, _) => el.disabled = false);
16
+ }
17
+ }
18
+ DisableInputsController.targets = ["input"];
19
+ DisableInputsController.values = {
20
+ clear: Boolean,
21
+ };
@@ -19,8 +19,10 @@ export * from './dismissable_controller';
19
19
  export * from './element_save_controller';
20
20
  export * from './equalize_controller';
21
21
  export * from './empty_dom_controller';
22
+ export * from './persisted_dismissable_controller';
22
23
  export * from './prefetch_controller';
23
24
  export * from './print_button_controller';
25
+ export * from './refresh_page_controller';
24
26
  export * from './responsive_iframe_controller';
25
27
  export * from './self_destruct_controller';
26
28
  export * from './sticky_controller';
@@ -0,0 +1,44 @@
1
+ import { BaseController } from "../../utilities/base_controller";
2
+ export class FallbackImageController extends BaseController {
3
+ initialize() {
4
+ this._hasLoadedSuccessfully = this._hasLoadedSuccessfully.bind(this);
5
+ this._success = this._success.bind(this);
6
+ this._fail = this._fail.bind(this);
7
+ }
8
+ connect() {
9
+ let element = this.el;
10
+ element.onerror = this._fail;
11
+ if (element.complete && !this._hasLoadedSuccessfully()) {
12
+ this._fail();
13
+ }
14
+ else {
15
+ this._success();
16
+ }
17
+ }
18
+ disconnect() {
19
+ this.removeSuccessClasses();
20
+ this.removeFailClasses();
21
+ }
22
+ _success() {
23
+ this.addSuccessClasses();
24
+ }
25
+ _fail() {
26
+ let element = this.el;
27
+ this.addFailClasses();
28
+ if (this.hasPlaceholderValue && element.src !== this.placeholderValue) {
29
+ this.dispatchEvent(element, this.eventName("placeholder"));
30
+ element.src = this.placeholderValue;
31
+ element.onerror = this._fail;
32
+ }
33
+ else {
34
+ this.dispatchEvent(element, this.eventName("fail"));
35
+ element.style.display = "none";
36
+ }
37
+ }
38
+ _hasLoadedSuccessfully() {
39
+ let element = this.el;
40
+ return element.naturalHeight > 0 && element.naturalWidth > 0;
41
+ }
42
+ }
43
+ FallbackImageController.values = { placeholder: String };
44
+ FallbackImageController.classes = ["success", "fail"];
@@ -0,0 +1,19 @@
1
+ import { DismissableController } from "./dismissable_controller";
2
+ import { useLocalStorage } from "../mixins";
3
+ export class PersistedDismissableController extends DismissableController {
4
+ connect() {
5
+ this.localStorage = useLocalStorage(this, this.keyValue, false, { writeDefaults: false });
6
+ if (this.localStorage.value == true) {
7
+ this.dismiss();
8
+ }
9
+ }
10
+ dismiss() {
11
+ this.localStorage.value = true;
12
+ super.dismiss();
13
+ }
14
+ }
15
+ PersistedDismissableController.values = {
16
+ key: String,
17
+ };
18
+ export class PersistedRemoveController extends PersistedDismissableController {
19
+ }
@@ -0,0 +1,17 @@
1
+ import { BaseController } from "../utilities";
2
+ export class RefreshPageController extends BaseController {
3
+ get onLoad() {
4
+ return this.hasOnLoadValue ? this.onLoadValue : false;
5
+ }
6
+ connect() {
7
+ if (this.onLoad) {
8
+ this.refresh();
9
+ }
10
+ }
11
+ refresh() {
12
+ location.reload();
13
+ }
14
+ }
15
+ RefreshPageController.values = {
16
+ onLoad: Boolean,
17
+ };
@@ -0,0 +1,23 @@
1
+ import { BaseController } from "../../utilities/base_controller";
2
+ import { extractPredicates } from "./expressions";
3
+ import { EventBus } from "../../utilities/event_bus";
4
+ import { signalConnectEvent, signalValueEvent } from "./events";
5
+ import { useEventBus } from "../../mixins/use_event_bus";
6
+ export class SignalBaseController extends BaseController {
7
+ connect() {
8
+ EventBus.emit(signalConnectEvent(this.nameValue));
9
+ useEventBus(this, signalValueEvent(this.nameValue), this._onSignal);
10
+ }
11
+ get predicateString() {
12
+ return "";
13
+ }
14
+ get _predicates() {
15
+ return extractPredicates(this.predicateString);
16
+ }
17
+ allPredicatesMatch(value) {
18
+ return this._predicates.every(predicate => predicate(value));
19
+ }
20
+ }
21
+ SignalBaseController.values = {
22
+ name: String,
23
+ };
@@ -1,4 +1,6 @@
1
1
  export * from './signal_action_controller';
2
+ export * from './signal_disable_controller';
2
3
  export * from './signal_dom_children_controller';
4
+ export * from './signal_enable_controller';
3
5
  export * from './signal_input_controller';
4
6
  export * from './signal_visibility_controller';
@@ -1,23 +1,13 @@
1
- import { BaseController } from "../../utilities/base_controller";
2
- import { extractPredicates } from "./expressions";
3
- import { useEventBus } from "../../mixins/use_event_bus";
4
- import { EventBus } from "../../utilities";
5
- import { signalConnectEvent, signalEventName, signalValueEvent } from "./events";
6
- export class SignalActionController extends BaseController {
7
- get _predicates() {
8
- return extractPredicates(this.whenValue);
9
- }
10
- connect() {
11
- EventBus.emit(signalConnectEvent(this.nameValue));
12
- useEventBus(this, signalValueEvent(this.nameValue), this._onSignal);
13
- }
1
+ import { signalEventName } from "./events";
2
+ import { SignalBaseController } from "./base_controller";
3
+ export class SignalActionController extends SignalBaseController {
14
4
  _onSignal(payload) {
15
5
  let value = payload.value;
16
6
  if (!this.hasWhenValue) {
17
7
  this.dispatchEvent(this.el, signalEventName(this.nameValue, 'match'));
18
8
  return;
19
9
  }
20
- if (this._predicates.every(predicate => predicate(value))) {
10
+ if (this.allPredicatesMatch(value)) {
21
11
  this.dispatchEvent(this.el, signalEventName(this.nameValue, 'match'), { detail: { element: this.el, value } });
22
12
  }
23
13
  else {
@@ -0,0 +1,34 @@
1
+ import { signalEventName } from "./events";
2
+ import { SignalBaseController } from "./base_controller";
3
+ export class SignalDisableController extends SignalBaseController {
4
+ disable() {
5
+ this.el.setAttribute("disabled", "true");
6
+ }
7
+ enable() {
8
+ this.el.removeAttribute("disabled");
9
+ }
10
+ _onSignal(payload) {
11
+ let value = payload.value;
12
+ if (this.whenValue == "default") {
13
+ if (value == "") {
14
+ this.disable();
15
+ }
16
+ else {
17
+ this.enable();
18
+ }
19
+ return;
20
+ }
21
+ if (this.allPredicatesMatch(value)) {
22
+ this.dispatchEvent(this.el, signalEventName(this.nameValue, "disable"), { detail: { predicate: this.whenValue, value } });
23
+ this.disable();
24
+ }
25
+ else {
26
+ this.dispatchEvent(this.el, signalEventName(this.nameValue, "enable"), { detail: { predicate: this.whenValue, value } });
27
+ this.enable();
28
+ }
29
+ }
30
+ }
31
+ SignalDisableController.values = {
32
+ name: String,
33
+ when: String,
34
+ };
@@ -31,7 +31,9 @@ export class SignalDomChildrenController extends BaseController {
31
31
  }
32
32
  emitChildCount() {
33
33
  let childCount = this._children.length;
34
- EventBus.emit(signalValueEvent(this._name), { element: this.el, value: childCount.toString() });
34
+ let value = childCount.toString();
35
+ this.dispatchEvent(this.el, signalValueEvent(this._name), { detail: { value } });
36
+ EventBus.emit(signalValueEvent(this._name), { element: this.el, value });
35
37
  }
36
38
  }
37
39
  SignalDomChildrenController.values = {
@@ -0,0 +1,34 @@
1
+ import { signalEventName } from "./events";
2
+ import { SignalBaseController } from "./base_controller";
3
+ export class SignalEnableController extends SignalBaseController {
4
+ disable() {
5
+ this.el.setAttribute("disabled", "true");
6
+ }
7
+ enable() {
8
+ this.el.removeAttribute("disabled");
9
+ }
10
+ _onSignal(payload) {
11
+ let value = payload.value;
12
+ if (this.whenValue == "default") {
13
+ if (value == "") {
14
+ this.enable();
15
+ }
16
+ else {
17
+ this.disable();
18
+ }
19
+ return;
20
+ }
21
+ if (this.allPredicatesMatch(value)) {
22
+ this.dispatchEvent(this.el, signalEventName(this.nameValue, "enable"), { detail: { predicate: this.whenValue, value } });
23
+ this.enable();
24
+ }
25
+ else {
26
+ this.dispatchEvent(this.el, signalEventName(this.nameValue, "disable"), { detail: { predicate: this.whenValue, value } });
27
+ this.disable();
28
+ }
29
+ }
30
+ }
31
+ SignalEnableController.values = {
32
+ name: String,
33
+ when: String,
34
+ };
@@ -1,21 +1,9 @@
1
- import { BaseController } from "../../utilities/base_controller";
2
- import { useEventBus } from "../../mixins/use_event_bus";
3
- import { extractPredicates } from "./expressions";
4
- import { signalConnectEvent, signalValueEvent, signalVisibilityEvent } from "./events";
5
- import { EventBus } from "../../utilities";
6
- import { installClassMethods } from "../../mixins/install_class_methods";
7
- export class SignalVisibilityController extends BaseController {
8
- get _predicates() {
9
- return extractPredicates(this.showValue);
10
- }
1
+ import { signalVisibilityEvent } from "./events";
2
+ import { SignalBaseController } from "./base_controller";
3
+ export class SignalVisibilityController extends SignalBaseController {
11
4
  get defaultHideClasses() {
12
5
  return ["hide"];
13
6
  }
14
- connect() {
15
- installClassMethods(this);
16
- EventBus.emit(signalConnectEvent(this.nameValue));
17
- useEventBus(this, signalValueEvent(this.nameValue), this._onSignal);
18
- }
19
7
  _onSignal(payload) {
20
8
  let value = payload.value;
21
9
  if (this.showValue == "default") {
@@ -27,7 +15,7 @@ export class SignalVisibilityController extends BaseController {
27
15
  }
28
16
  return;
29
17
  }
30
- if (this._predicates.every(predicate => predicate(value))) {
18
+ if (this.allPredicatesMatch(value)) {
31
19
  this.dispatchEvent(this.el, signalVisibilityEvent(this.nameValue, "show"), { detail: { predicate: this.showValue, value } });
32
20
  this.removeHideClasses(this.el);
33
21
  }
@@ -4,3 +4,4 @@ export * from './duration_controller';
4
4
  export * from './tabs_controller';
5
5
  export * from './time_distance_controller';
6
6
  export * from './tree_view_controller';
7
+ export * from './tween_number_controller';
@@ -0,0 +1,66 @@
1
+ import { BaseController } from "../../utilities/base_controller";
2
+ import { useIntersection } from "../../mixins/use_intersection";
3
+ import { EasingFunctions } from "../../utilities/easingFunctions";
4
+ export class TweenNumberController extends BaseController {
5
+ get start() {
6
+ if (this.hasStartValue) {
7
+ return this.startValue;
8
+ }
9
+ else {
10
+ throw new Error("Required value `start` is missing");
11
+ }
12
+ }
13
+ get end() {
14
+ if (this.hasEndValue) {
15
+ return this.endValue;
16
+ }
17
+ else {
18
+ throw new Error("Required value `end` is missing");
19
+ }
20
+ }
21
+ get durationMs() {
22
+ if (this.hasDurationValue) {
23
+ return this.durationValue;
24
+ }
25
+ else {
26
+ throw new Error("Required value `duration` is missing");
27
+ }
28
+ }
29
+ get easingFunction() {
30
+ let str = this.hasEasingValue ? this.easingValue : null;
31
+ let fallback = EasingFunctions.linear;
32
+ if (str == null) {
33
+ return fallback;
34
+ }
35
+ // @ts-ignore
36
+ return EasingFunctions[str] || fallback;
37
+ }
38
+ connect() {
39
+ useIntersection(this, this.el, this.appear);
40
+ }
41
+ appear(_entry) {
42
+ this.tween();
43
+ }
44
+ ;
45
+ tween() {
46
+ let startTimestamp = null;
47
+ const step = (timestamp) => {
48
+ if (!startTimestamp) {
49
+ startTimestamp = timestamp;
50
+ }
51
+ const elapsed = timestamp - startTimestamp;
52
+ const progress = Math.min(elapsed / this.durationMs, 1);
53
+ this.element.innerHTML = Math.floor(this.easingFunction(progress) * (this.end - this.start) + this.start).toString();
54
+ if (progress < 1) {
55
+ requestAnimationFrame(step);
56
+ }
57
+ };
58
+ requestAnimationFrame(step);
59
+ }
60
+ }
61
+ TweenNumberController.values = {
62
+ start: Number,
63
+ end: Number,
64
+ duration: Number,
65
+ easing: String,
66
+ };
@@ -50,6 +50,9 @@ export class BaseController extends Controller {
50
50
  const element = document.head.querySelector(`meta[name="${name}"]`);
51
51
  return (element === null || element === void 0 ? void 0 : element.getAttribute('content')) || null;
52
52
  }
53
+ eventName(eventName) {
54
+ return `${this.identifier}:${eventName}`;
55
+ }
53
56
  dispatchEvent(element, eventName, options = {}) {
54
57
  dispatchEvent(this, element, eventName, options);
55
58
  }
@@ -0,0 +1,143 @@
1
+ const pow = Math.pow;
2
+ const sqrt = Math.sqrt;
3
+ const sin = Math.sin;
4
+ const cos = Math.cos;
5
+ const PI = Math.PI;
6
+ const c1 = 1.70158;
7
+ const c2 = c1 * 1.525;
8
+ const c3 = c1 + 1;
9
+ const c4 = (2 * PI) / 3;
10
+ const c5 = (2 * PI) / 4.5;
11
+ const bounceOut = function (x) {
12
+ const n1 = 7.5625;
13
+ const d1 = 2.75;
14
+ if (x < 1 / d1) {
15
+ return n1 * x * x;
16
+ }
17
+ else if (x < 2 / d1) {
18
+ return n1 * (x -= 1.5 / d1) * x + 0.75;
19
+ }
20
+ else if (x < 2.5 / d1) {
21
+ return n1 * (x -= 2.25 / d1) * x + 0.9375;
22
+ }
23
+ else {
24
+ return n1 * (x -= 2.625 / d1) * x + 0.984375;
25
+ }
26
+ };
27
+ export const EasingFunctions = {
28
+ linear: (x) => x,
29
+ easeInQuad: function (x) {
30
+ return x * x;
31
+ },
32
+ easeOutQuad: function (x) {
33
+ return 1 - (1 - x) * (1 - x);
34
+ },
35
+ easeInOutQuad: function (x) {
36
+ return x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2;
37
+ },
38
+ easeInCubic: function (x) {
39
+ return x * x * x;
40
+ },
41
+ easeOutCubic: function (x) {
42
+ return 1 - pow(1 - x, 3);
43
+ },
44
+ easeInOutCubic: function (x) {
45
+ return x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2;
46
+ },
47
+ easeInQuart: function (x) {
48
+ return x * x * x * x;
49
+ },
50
+ easeOutQuart: function (x) {
51
+ return 1 - pow(1 - x, 4);
52
+ },
53
+ easeInOutQuart: function (x) {
54
+ return x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2;
55
+ },
56
+ easeInQuint: function (x) {
57
+ return x * x * x * x * x;
58
+ },
59
+ easeOutQuint: function (x) {
60
+ return 1 - pow(1 - x, 5);
61
+ },
62
+ easeInOutQuint: function (x) {
63
+ return x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2;
64
+ },
65
+ easeInSine: function (x) {
66
+ return 1 - cos((x * PI) / 2);
67
+ },
68
+ easeOutSine: function (x) {
69
+ return sin((x * PI) / 2);
70
+ },
71
+ easeInOutSine: function (x) {
72
+ return -(cos(PI * x) - 1) / 2;
73
+ },
74
+ easeInExpo: function (x) {
75
+ return x === 0 ? 0 : pow(2, 10 * x - 10);
76
+ },
77
+ easeOutExpo: function (x) {
78
+ return x === 1 ? 1 : 1 - pow(2, -10 * x);
79
+ },
80
+ easeInOutExpo: function (x) {
81
+ return x === 0
82
+ ? 0
83
+ : x === 1
84
+ ? 1
85
+ : x < 0.5
86
+ ? pow(2, 20 * x - 10) / 2
87
+ : (2 - pow(2, -20 * x + 10)) / 2;
88
+ },
89
+ easeInCirc: function (x) {
90
+ return 1 - sqrt(1 - pow(x, 2));
91
+ },
92
+ easeOutCirc: function (x) {
93
+ return sqrt(1 - pow(x - 1, 2));
94
+ },
95
+ easeInOutCirc: function (x) {
96
+ return x < 0.5
97
+ ? (1 - sqrt(1 - pow(2 * x, 2))) / 2
98
+ : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2;
99
+ },
100
+ easeInBack: function (x) {
101
+ return c3 * x * x * x - c1 * x * x;
102
+ },
103
+ easeOutBack: function (x) {
104
+ return 1 + c3 * pow(x - 1, 3) + c1 * pow(x - 1, 2);
105
+ },
106
+ easeInOutBack: function (x) {
107
+ return x < 0.5
108
+ ? (pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2
109
+ : (pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2;
110
+ },
111
+ easeInElastic: function (x) {
112
+ return x === 0
113
+ ? 0
114
+ : x === 1
115
+ ? 1
116
+ : -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * c4);
117
+ },
118
+ easeOutElastic: function (x) {
119
+ return x === 0
120
+ ? 0
121
+ : x === 1
122
+ ? 1
123
+ : pow(2, -10 * x) * sin((x * 10 - 0.75) * c4) + 1;
124
+ },
125
+ easeInOutElastic: function (x) {
126
+ return x === 0
127
+ ? 0
128
+ : x === 1
129
+ ? 1
130
+ : x < 0.5
131
+ ? -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c5)) / 2
132
+ : (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c5)) / 2 + 1;
133
+ },
134
+ easeInBounce: function (x) {
135
+ return 1 - bounceOut(1 - x);
136
+ },
137
+ easeOutBounce: bounceOut,
138
+ easeInOutBounce: function (x) {
139
+ return x < 0.5
140
+ ? (1 - bounceOut(1 - 2 * x)) / 2
141
+ : (1 + bounceOut(2 * x - 1)) / 2;
142
+ },
143
+ };
package/package.json CHANGED
@@ -1,56 +1,56 @@
1
- {
2
- "name": "stimulus-library",
3
- "description": "A library of useful controllers for Stimulus",
4
- "keywords": [
5
- "stimulusjs",
6
- "stimulus-js",
7
- "stimulus library",
8
- "stimulus controller",
9
- "ruby on rails",
10
- "ruby-on-rails"
11
- ],
12
- "version": "0.8.0",
13
- "license": "MIT",
14
- "author": {
15
- "name": "Sub-Xaero",
16
- "url": "https://github.com/Sub-Xaero/"
17
- },
18
- "homepage": "https://sub-xaero.github.io/stimulus-library/",
19
- "repository": {
20
- "type": "git",
21
- "url": "https://github.com/Sub-Xaero/stimulus-library"
22
- },
23
- "files": [
24
- "dist"
25
- ],
26
- "module": "dist/index.js",
27
- "types": "dist/index.d.ts",
28
- "scripts": {
29
- "build": "tsc",
30
- "dev": "tsc --watch",
31
- "prepack": "yarn build",
32
- "release": "standard-version",
33
- "test": "cypress run",
34
- "test:treeshake": "agadoo dist"
35
- },
36
- "dependencies": {
37
- "@babel/runtime": "^7.17.9",
38
- "@hotwired/stimulus": "^3.0.1",
39
- "date-fns": "^2.28.0",
40
- "dialog-polyfill": "^0.5.6",
41
- "lodash-es": "^4.17.21",
42
- "mitt": "^3.0.0",
43
- "smoothscroll-polyfill": "^0.4.4"
44
- },
45
- "devDependencies": {
46
- "@types/lodash-es": "^4.17.6",
47
- "@types/smoothscroll-polyfill": "^0.3.1",
48
- "agadoo": "^2.0.0",
49
- "cypress": "^10.0.3",
50
- "fast-glob": "^3.2.11",
51
- "rimraf": "^3.0.2",
52
- "standard-version": "^9.5.0",
53
- "typescript": "^4.7.3",
54
- "vite": "^2.9.10"
55
- }
56
- }
1
+ {
2
+ "name": "stimulus-library",
3
+ "description": "A library of useful controllers for Stimulus",
4
+ "keywords": [
5
+ "stimulusjs",
6
+ "stimulus-js",
7
+ "stimulus library",
8
+ "stimulus controller",
9
+ "ruby on rails",
10
+ "ruby-on-rails"
11
+ ],
12
+ "version": "0.9.1",
13
+ "license": "MIT",
14
+ "author": {
15
+ "name": "Sub-Xaero",
16
+ "url": "https://github.com/Sub-Xaero/"
17
+ },
18
+ "homepage": "https://sub-xaero.github.io/stimulus-library/",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/Sub-Xaero/stimulus-library"
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "module": "dist/index.js",
27
+ "types": "dist/index.d.ts",
28
+ "scripts": {
29
+ "build": "tsc",
30
+ "dev": "tsc --watch",
31
+ "prepack": "yarn build",
32
+ "release": "standard-version",
33
+ "test": "cypress run",
34
+ "test:treeshake": "agadoo dist"
35
+ },
36
+ "dependencies": {
37
+ "@babel/runtime": "^7.17.9",
38
+ "@hotwired/stimulus": "^3.0.1",
39
+ "date-fns": "^2.28.0",
40
+ "dialog-polyfill": "^0.5.6",
41
+ "lodash-es": "^4.17.21",
42
+ "mitt": "^3.0.0",
43
+ "smoothscroll-polyfill": "^0.4.4"
44
+ },
45
+ "devDependencies": {
46
+ "@types/lodash-es": "^4.17.6",
47
+ "@types/smoothscroll-polyfill": "^0.3.1",
48
+ "agadoo": "^2.0.0",
49
+ "cypress": "^10.0.3",
50
+ "fast-glob": "^3.2.11",
51
+ "rimraf": "^3.0.2",
52
+ "standard-version": "^9.5.0",
53
+ "typescript": "^4.7.3",
54
+ "vite": "^2.9.10"
55
+ }
56
+ }