stimulus_reflex 3.5.0.pre10 → 3.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of stimulus_reflex might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7cb01c3a44e8b59bd999bc745276af2f32d073e7a96503f229b72681ab482a3
4
- data.tar.gz: 2978f4e101687acc6740da064c8d002cd5b137f566e8d9bed5e80a93f7c69942
3
+ metadata.gz: f9e4f16a6c108abed76ee50881ec95b7595a8182092422eaec27a9ba32cfb3b6
4
+ data.tar.gz: 5f463ec6bedc1462e477714599f68a9c22479114af4284de427caac9144cf71c
5
5
  SHA512:
6
- metadata.gz: d39ef8e76cc723f99813eb3bbb45c69954f87a915b35a90fb73e094b59a43eff92a236bafe9f19af3d749c0ad553b2687812f9a7bb487a36349fc12f705e536e
7
- data.tar.gz: e632dc8af1e1e7d370b49014f4b8eb1d8ad002f55c8c7e2016a21902c8dc041385aa2360e71dfbd14cc9f2d3e430f094f943fea313b2f87ecb66a8a45f6e0d9a
6
+ metadata.gz: f05665f72b18c7cd0afee54fa099ec29df4e736fa83d8ec87756a3be80be3402d74d715cafa70b41092091794d2fc4a002e6998d676574365e5b756f53eaa6a0
7
+ data.tar.gz: f9d044f8d60a6154aab10ed680b51da5b6afc499d35a19a4eaefb233164519f74aef05e2583fe9f6194bf4989f6894a3065f3de164658ea9691da9df0dec030d
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stimulus_reflex (3.5.0.pre10)
4
+ stimulus_reflex (3.5.0.rc1)
5
5
  actioncable (>= 5.2, < 8)
6
6
  actionpack (>= 5.2, < 8)
7
7
  actionview (>= 5.2, < 8)
8
8
  activesupport (>= 5.2, < 8)
9
- cable_ready (>= 5.0.0.pre10)
9
+ cable_ready (>= 5.0.0.rc1)
10
10
  nokogiri (~> 1.0)
11
- rack (~> 2.0)
11
+ rack (>= 2, < 4)
12
12
  railties (>= 5.2, < 8)
13
13
  redis (>= 4.0, < 6.0)
14
14
 
@@ -82,14 +82,14 @@ GEM
82
82
  tzinfo (~> 2.0)
83
83
  ast (2.4.2)
84
84
  builder (3.2.4)
85
- cable_ready (5.0.0.pre10)
85
+ cable_ready (5.0.0.rc1)
86
86
  actionpack (>= 5.2)
87
87
  actionview (>= 5.2)
88
88
  activesupport (>= 5.2)
89
89
  railties (>= 5.2)
90
90
  thread-local (>= 1.1.0)
91
91
  concurrent-ruby (1.2.0)
92
- connection_pool (2.3.0)
92
+ connection_pool (2.4.0)
93
93
  crass (1.0.6)
94
94
  date (3.3.3)
95
95
  erubi (1.12.0)
@@ -131,7 +131,7 @@ GEM
131
131
  parser (3.2.1.0)
132
132
  ast (~> 2.4.1)
133
133
  racc (1.6.2)
134
- rack (2.2.6.2)
134
+ rack (2.2.6.4)
135
135
  rack-test (2.0.2)
136
136
  rack (>= 1.3)
137
137
  rails (7.0.4.2)
@@ -164,7 +164,7 @@ GEM
164
164
  rake (13.0.6)
165
165
  redis (5.0.6)
166
166
  redis-client (>= 0.9.0)
167
- redis-client (0.12.2)
167
+ redis-client (0.14.0)
168
168
  connection_pool
169
169
  regexp_parser (2.7.0)
170
170
  rexml (3.2.5)
data/README.md CHANGED
@@ -84,7 +84,7 @@ Please note that we are not actively providing support on Stack Overflow. If you
84
84
 
85
85
  ## 🚀 Installation and upgrading
86
86
 
87
- CLI and manual setup procedures are fully detailed in the [official docs](https://docs.stimulusreflex.com/setup).
87
+ CLI and manual setup procedures are fully detailed in the [official docs](https://docs.stimulusreflex.com/hello-world/setup.html).
88
88
 
89
89
  ### Rubygem
90
90
 
@@ -109,7 +109,7 @@ yarn add stimulus_reflex
109
109
 
110
110
  # ...
111
111
 
112
- pin 'stimulus_reflex', to: 'stimulus_reflex.min.js', preload: true
112
+ pin 'stimulus_reflex', to: 'stimulus_reflex.js', preload: true
113
113
  ```
114
114
 
115
115
  #### Rails Asset pipeline (Sprockets):
@@ -117,7 +117,7 @@ pin 'stimulus_reflex', to: 'stimulus_reflex.min.js', preload: true
117
117
  ```html+erb
118
118
  <!-- app/views/layouts/application.html.erb -->
119
119
 
120
- <%= javascript_include_tag "stimulus_reflex.umd.min.js", "data-turbo-track": "reload" %>
120
+ <%= javascript_include_tag "stimulus_reflex.umd.js", "data-turbo-track": "reload" %>
121
121
  ```
122
122
 
123
123
  ## 🙏 Contributing
@@ -1,8 +1,288 @@
1
1
  import { Controller } from "@hotwired/stimulus";
2
2
 
3
+ import CableReady, { Utils } from "cable_ready";
4
+
3
5
  import { createConsumer } from "@rails/actioncable";
4
6
 
5
- import CableReady, { Utils } from "cable_ready";
7
+ /*!
8
+ * Toastify js 1.12.0
9
+ * https://github.com/apvarun/toastify-js
10
+ * @license MIT licensed
11
+ *
12
+ * Copyright (C) 2018 Varun A P
13
+ */ class Toastify {
14
+ defaults={
15
+ oldestFirst: true,
16
+ text: "Toastify is awesome!",
17
+ node: undefined,
18
+ duration: 3e3,
19
+ selector: undefined,
20
+ callback: function() {},
21
+ destination: undefined,
22
+ newWindow: false,
23
+ close: false,
24
+ gravity: "toastify-top",
25
+ positionLeft: false,
26
+ position: "",
27
+ backgroundColor: "",
28
+ avatar: "",
29
+ className: "",
30
+ stopOnFocus: true,
31
+ onClick: function() {},
32
+ offset: {
33
+ x: 0,
34
+ y: 0
35
+ },
36
+ escapeMarkup: true,
37
+ ariaLive: "polite",
38
+ style: {
39
+ background: ""
40
+ }
41
+ };
42
+ constructor(options) {
43
+ this.version = "1.12.0";
44
+ this.options = {};
45
+ this.toastElement = null;
46
+ this._rootElement = document.body;
47
+ this._init(options);
48
+ }
49
+ showToast() {
50
+ this.toastElement = this._buildToast();
51
+ if (typeof this.options.selector === "string") {
52
+ this._rootElement = document.getElementById(this.options.selector);
53
+ } else if (this.options.selector instanceof HTMLElement || this.options.selector instanceof ShadowRoot) {
54
+ this._rootElement = this.options.selector;
55
+ } else {
56
+ this._rootElement = document.body;
57
+ }
58
+ if (!this._rootElement) {
59
+ throw "Root element is not defined";
60
+ }
61
+ this._rootElement.insertBefore(this.toastElement, this._rootElement.firstChild);
62
+ this._reposition();
63
+ if (this.options.duration > 0) {
64
+ this.toastElement.timeOutValue = window.setTimeout((() => {
65
+ this._removeElement(this.toastElement);
66
+ }), this.options.duration);
67
+ }
68
+ return this;
69
+ }
70
+ hideToast() {
71
+ if (this.toastElement.timeOutValue) {
72
+ clearTimeout(this.toastElement.timeOutValue);
73
+ }
74
+ this._removeElement(this.toastElement);
75
+ }
76
+ _init(options) {
77
+ this.options = Object.assign(this.defaults, options);
78
+ if (this.options.backgroundColor) {
79
+ console.warn('DEPRECATION NOTICE: "backgroundColor" is being deprecated. Please use the "style.background" property.');
80
+ }
81
+ this.toastElement = null;
82
+ this.options.gravity = options.gravity === "bottom" ? "toastify-bottom" : "toastify-top";
83
+ this.options.stopOnFocus = options.stopOnFocus === undefined ? true : options.stopOnFocus;
84
+ if (options.backgroundColor) {
85
+ this.options.style.background = options.backgroundColor;
86
+ }
87
+ }
88
+ _buildToast() {
89
+ if (!this.options) {
90
+ throw "Toastify is not initialized";
91
+ }
92
+ let divElement = document.createElement("div");
93
+ divElement.className = `toastify on ${this.options.className}`;
94
+ divElement.className += ` toastify-${this.options.position}`;
95
+ divElement.className += ` ${this.options.gravity}`;
96
+ for (const property in this.options.style) {
97
+ divElement.style[property] = this.options.style[property];
98
+ }
99
+ if (this.options.ariaLive) {
100
+ divElement.setAttribute("aria-live", this.options.ariaLive);
101
+ }
102
+ if (this.options.node && this.options.node.nodeType === Node.ELEMENT_NODE) {
103
+ divElement.appendChild(this.options.node);
104
+ } else {
105
+ if (this.options.escapeMarkup) {
106
+ divElement.innerText = this.options.text;
107
+ } else {
108
+ divElement.innerHTML = this.options.text;
109
+ }
110
+ if (this.options.avatar !== "") {
111
+ let avatarElement = document.createElement("img");
112
+ avatarElement.src = this.options.avatar;
113
+ avatarElement.className = "toastify-avatar";
114
+ if (this.options.position == "left") {
115
+ divElement.appendChild(avatarElement);
116
+ } else {
117
+ divElement.insertAdjacentElement("afterbegin", avatarElement);
118
+ }
119
+ }
120
+ }
121
+ if (this.options.close === true) {
122
+ let closeElement = document.createElement("button");
123
+ closeElement.type = "button";
124
+ closeElement.setAttribute("aria-label", "Close");
125
+ closeElement.className = "toast-close";
126
+ closeElement.innerHTML = "&#10006;";
127
+ closeElement.addEventListener("click", (event => {
128
+ event.stopPropagation();
129
+ this._removeElement(this.toastElement);
130
+ window.clearTimeout(this.toastElement.timeOutValue);
131
+ }));
132
+ const width = window.innerWidth > 0 ? window.innerWidth : screen.width;
133
+ if (this.options.position == "left" && width > 360) {
134
+ divElement.insertAdjacentElement("afterbegin", closeElement);
135
+ } else {
136
+ divElement.appendChild(closeElement);
137
+ }
138
+ }
139
+ if (this.options.stopOnFocus && this.options.duration > 0) {
140
+ divElement.addEventListener("mouseover", (event => {
141
+ window.clearTimeout(divElement.timeOutValue);
142
+ }));
143
+ divElement.addEventListener("mouseleave", (() => {
144
+ divElement.timeOutValue = window.setTimeout((() => {
145
+ this._removeElement(divElement);
146
+ }), this.options.duration);
147
+ }));
148
+ }
149
+ if (typeof this.options.destination !== "undefined") {
150
+ divElement.addEventListener("click", (event => {
151
+ event.stopPropagation();
152
+ if (this.options.newWindow === true) {
153
+ window.open(this.options.destination, "_blank");
154
+ } else {
155
+ window.location = this.options.destination;
156
+ }
157
+ }));
158
+ }
159
+ if (typeof this.options.onClick === "function" && typeof this.options.destination === "undefined") {
160
+ divElement.addEventListener("click", (event => {
161
+ event.stopPropagation();
162
+ this.options.onClick();
163
+ }));
164
+ }
165
+ if (typeof this.options.offset === "object") {
166
+ const x = this._getAxisOffsetAValue("x", this.options);
167
+ const y = this._getAxisOffsetAValue("y", this.options);
168
+ const xOffset = this.options.position == "left" ? x : `-${x}`;
169
+ const yOffset = this.options.gravity == "toastify-top" ? y : `-${y}`;
170
+ divElement.style.transform = `translate(${xOffset},${yOffset})`;
171
+ }
172
+ return divElement;
173
+ }
174
+ _removeElement(toastElement) {
175
+ toastElement.className = toastElement.className.replace(" on", "");
176
+ window.setTimeout((() => {
177
+ if (this.options.node && this.options.node.parentNode) {
178
+ this.options.node.parentNode.removeChild(this.options.node);
179
+ }
180
+ if (toastElement.parentNode) {
181
+ toastElement.parentNode.removeChild(toastElement);
182
+ }
183
+ this.options.callback.call(toastElement);
184
+ this._reposition();
185
+ }), 400);
186
+ }
187
+ _reposition() {
188
+ let topLeftOffsetSize = {
189
+ top: 15,
190
+ bottom: 15
191
+ };
192
+ let topRightOffsetSize = {
193
+ top: 15,
194
+ bottom: 15
195
+ };
196
+ let offsetSize = {
197
+ top: 15,
198
+ bottom: 15
199
+ };
200
+ let allToasts = this._rootElement.querySelectorAll(".toastify");
201
+ let classUsed;
202
+ for (let i = 0; i < allToasts.length; i++) {
203
+ if (allToasts[i].classList.contains("toastify-top") === true) {
204
+ classUsed = "toastify-top";
205
+ } else {
206
+ classUsed = "toastify-bottom";
207
+ }
208
+ let height = allToasts[i].offsetHeight;
209
+ classUsed = classUsed.substr(9, classUsed.length - 1);
210
+ let offset = 15;
211
+ let width = window.innerWidth > 0 ? window.innerWidth : screen.width;
212
+ if (width <= 360) {
213
+ allToasts[i].style[classUsed] = `${offsetSize[classUsed]}px`;
214
+ offsetSize[classUsed] += height + offset;
215
+ } else {
216
+ if (allToasts[i].classList.contains("toastify-left") === true) {
217
+ allToasts[i].style[classUsed] = `${topLeftOffsetSize[classUsed]}px`;
218
+ topLeftOffsetSize[classUsed] += height + offset;
219
+ } else {
220
+ allToasts[i].style[classUsed] = `${topRightOffsetSize[classUsed]}px`;
221
+ topRightOffsetSize[classUsed] += height + offset;
222
+ }
223
+ }
224
+ }
225
+ }
226
+ _getAxisOffsetAValue(axis, options) {
227
+ if (options.offset[axis]) {
228
+ if (isNaN(options.offset[axis])) {
229
+ return options.offset[axis];
230
+ } else {
231
+ return `${options.offset[axis]}px`;
232
+ }
233
+ }
234
+ return "0px";
235
+ }
236
+ }
237
+
238
+ function StartToastifyInstance(options) {
239
+ return new Toastify(options);
240
+ }
241
+
242
+ CableReady.operations.stimulusReflexVersionMismatch = operation => {
243
+ const levels = {
244
+ info: {},
245
+ success: {
246
+ background: "#198754",
247
+ color: "white"
248
+ },
249
+ warn: {
250
+ background: "#ffc107",
251
+ color: "black"
252
+ },
253
+ error: {
254
+ background: "#dc3545",
255
+ color: "white"
256
+ }
257
+ };
258
+ const defaults = {
259
+ selector: setupToastify(),
260
+ close: true,
261
+ duration: 30 * 1e3,
262
+ gravity: "bottom",
263
+ position: "right",
264
+ newWindow: true,
265
+ style: levels[operation.level || "info"]
266
+ };
267
+ StartToastifyInstance({
268
+ ...defaults,
269
+ ...operation
270
+ }).showToast();
271
+ };
272
+
273
+ function setupToastify() {
274
+ const id = "stimulus-reflex-toast-element";
275
+ let element = document.querySelector(`#${id}`);
276
+ if (!element) {
277
+ element = document.createElement("div");
278
+ element.id = id;
279
+ document.documentElement.appendChild(element);
280
+ const styles = document.createElement("style");
281
+ styles.innerHTML = `\n #${id} .toastify {\n padding: 12px 20px;\n color: #ffffff;\n display: inline-block;\n background: -webkit-linear-gradient(315deg, #73a5ff, #5477f5);\n background: linear-gradient(135deg, #73a5ff, #5477f5);\n position: fixed;\n opacity: 0;\n transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);\n border-radius: 2px;\n cursor: pointer;\n text-decoration: none;\n max-width: calc(50% - 20px);\n z-index: 2147483647;\n bottom: -150px;\n right: 15px;\n }\n\n #${id} .toastify.on {\n opacity: 1;\n }\n\n #${id} .toast-close {\n background: transparent;\n border: 0;\n color: white;\n cursor: pointer;\n font-family: inherit;\n font-size: 1em;\n opacity: 0.4;\n padding: 0 5px;\n }\n `;
282
+ document.head.appendChild(styles);
283
+ }
284
+ return element;
285
+ }
6
286
 
7
287
  let deprecationWarnings = true;
8
288
 
@@ -170,6 +450,8 @@ const getReflexRoots = element => {
170
450
  return list;
171
451
  };
172
452
 
453
+ const reflexNameToControllerIdentifier = reflexName => reflexName.replace(/([a-z0–9])([A-Z])/g, "$1-$2").replace(/(::)/g, "--").replace(/-reflex$/gi, "").toLowerCase();
454
+
173
455
  const stages = [ "created", "before", "delivered", "queued", "after", "finalized", "success", "error", "halted", "forbidden" ];
174
456
 
175
457
  let lastReflex;
@@ -656,7 +938,7 @@ const extractDataAttributes = element => {
656
938
 
657
939
  var name = "stimulus_reflex";
658
940
 
659
- var version = "3.5.0-pre10";
941
+ var version = "3.5.0-rc1";
660
942
 
661
943
  var description = "Build reactive applications with the Rails tooling you already know and love.";
662
944
 
@@ -693,8 +975,9 @@ var scripts = {
693
975
  "build:watch": "yarn rollup -wc",
694
976
  watch: "yarn build:watch",
695
977
  test: "web-test-runner javascript/test/**/*.test.js",
978
+ "test:watch": "yarn test --watch",
696
979
  "docs:dev": "vitepress dev docs",
697
- "docs:build": "vitepress build docs",
980
+ "docs:build": "vitepress build docs && cp docs/_redirects docs/.vitepress/dist",
698
981
  "docs:preview": "vitepress preview docs"
699
982
  };
700
983
 
@@ -703,9 +986,9 @@ var peerDependencies = {
703
986
  };
704
987
 
705
988
  var dependencies = {
706
- "@hotwired/stimulus": ">= 3.0, < 4",
707
- "@rails/actioncable": ">= 6.0, < 8",
708
- cable_ready: "5.0.0-pre10"
989
+ "@hotwired/stimulus": "^3",
990
+ "@rails/actioncable": "^6 || ^7",
991
+ cable_ready: "5.0.0-rc1"
709
992
  };
710
993
 
711
994
  var devDependencies = {
@@ -715,10 +998,11 @@ var devDependencies = {
715
998
  "@rollup/plugin-terser": "^0.4.0",
716
999
  "@web/dev-server-esbuild": "^0.3.3",
717
1000
  "@web/dev-server-rollup": "^0.3.21",
718
- "@web/test-runner": "^0.15.0",
1001
+ "@web/test-runner": "^0.15.1",
719
1002
  "prettier-standard": "^16.4.1",
720
- rollup: "^3.17.1",
721
- vitepress: "^1.0.0-alpha.47"
1003
+ rollup: "^3.19.1",
1004
+ "toastify-js": "^1.12.0",
1005
+ vitepress: "^1.0.0-alpha.56"
722
1006
  };
723
1007
 
724
1008
  var packageInfo = {
@@ -948,11 +1232,11 @@ const error = (reflex, event) => {
948
1232
  })));
949
1233
  };
950
1234
 
951
- const localReflexControllers = element => attributeValues(element.getAttribute(Schema.controller)).reduce(((memo, name) => {
952
- const controller = App.app.getControllerForElementAndIdentifier(element, name);
953
- if (controller && controller.StimulusReflex) memo.push(controller);
954
- return memo;
955
- }), []);
1235
+ const localReflexControllers = element => {
1236
+ const potentialIdentifiers = attributeValues(element.getAttribute(Schema.controller));
1237
+ const potentialControllers = potentialIdentifiers.map((identifier => App.app.getControllerForElementAndIdentifier(element, identifier)));
1238
+ return potentialControllers.filter((controller => controller && controller.StimulusReflex));
1239
+ };
956
1240
 
957
1241
  const allReflexControllers = element => {
958
1242
  let controllers = [];
@@ -965,8 +1249,9 @@ const allReflexControllers = element => {
965
1249
 
966
1250
  const findControllerByReflexName = (reflexName, controllers) => {
967
1251
  const controller = controllers.find((controller => {
968
- if (!controller.identifier) return;
969
- return extractReflexName(reflexName).replace(/([a-z0–9])([A-Z])/g, "$1-$2").replace(/(::)/g, "--").toLowerCase() === controller.identifier;
1252
+ if (!controller || !controller.identifier) return;
1253
+ const identifier = reflexNameToControllerIdentifier(extractReflexName(reflexName));
1254
+ return identifier === controller.identifier;
970
1255
  }));
971
1256
  return controller || controllers[0];
972
1257
  };
@@ -976,18 +1261,22 @@ const scanForReflexes = debounce((() => {
976
1261
  reflexElements.forEach((element => scanForReflexesOnElement(element)));
977
1262
  }), 20);
978
1263
 
979
- const scanForReflexesOnElement = element => {
1264
+ const scanForReflexesOnElement = (element, controller = null) => {
980
1265
  const controllerAttribute = element.getAttribute(Schema.controller);
981
- const controllers = attributeValues(controllerAttribute);
1266
+ const controllers = attributeValues(controllerAttribute).filter((controller => controller !== "stimulus-reflex"));
982
1267
  const reflexAttribute = element.getAttribute(Schema.reflex);
983
1268
  const reflexAttributeNames = attributeValues(reflexAttribute);
984
1269
  const actionAttribute = element.getAttribute(Schema.action);
985
1270
  const actions = attributeValues(actionAttribute).filter((action => !action.includes("#__perform")));
986
1271
  reflexAttributeNames.forEach((reflexName => {
987
- const controller = findControllerByReflexName(reflexName, allReflexControllers(element));
1272
+ const potentialControllers = [ controller ].concat(allReflexControllers(element));
1273
+ controller = findControllerByReflexName(reflexName, potentialControllers);
988
1274
  const controllerName = controller ? controller.identifier : "stimulus-reflex";
989
1275
  actions.push(`${reflexName.split("->")[0]}->${controllerName}#__perform`);
990
- controllers.push(controllerName);
1276
+ const parentControllerElement = element.closest(`[data-controller~=${controllerName}]`);
1277
+ if (!parentControllerElement) {
1278
+ controllers.push(controllerName);
1279
+ }
991
1280
  }));
992
1281
  const controllerValue = attributeValue(controllers);
993
1282
  const actionValue = attributeValue(actions);
@@ -1114,7 +1403,7 @@ const register = (controller, options = {}) => {
1114
1403
  });
1115
1404
  }
1116
1405
  });
1117
- scanForReflexesOnElement(controller.element);
1406
+ scanForReflexesOnElement(controller.element, controller);
1118
1407
  emitEvent("stimulus-reflex:controller-registered", {
1119
1408
  detail: {
1120
1409
  controller: controller