stimulus_reflex 3.5.0.pre10 → 3.5.0.rc1
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -7
- data/README.md +3 -3
- data/app/assets/javascripts/stimulus_reflex.js +310 -21
- data/app/assets/javascripts/stimulus_reflex.umd.js +307 -23
- data/app/channels/stimulus_reflex/channel.rb +1 -18
- data/lib/generators/stimulus_reflex/stimulus_reflex_generator.rb +4 -10
- data/lib/generators/stimulus_reflex/templates/app/reflexes/%file_name%_reflex.rb.tt +1 -1
- data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +1 -1
- data/lib/generators/stimulus_reflex/templates/config/initializers/cable_ready.rb +5 -0
- data/lib/install/development.rb +2 -2
- data/lib/install/importmap.rb +3 -3
- data/lib/stimulus_reflex/cable_ready_channels.rb +1 -0
- data/lib/stimulus_reflex/engine.rb +0 -4
- data/lib/stimulus_reflex/importmap.rb +3 -3
- data/lib/stimulus_reflex/reflex.rb +17 -8
- data/lib/stimulus_reflex/reflex_data.rb +5 -1
- data/lib/stimulus_reflex/reflex_factory.rb +2 -1
- data/lib/stimulus_reflex/version.rb +1 -1
- data/lib/stimulus_reflex/version_checker.rb +54 -0
- data/lib/tasks/stimulus_reflex/stimulus_reflex.rake +0 -2
- data/package.json +10 -8
- data/rollup.config.mjs +0 -19
- data/stimulus_reflex.gemspec +2 -2
- data/yarn.lock +173 -168
- metadata +15 -12
- data/app/assets/javascripts/stimulus_reflex.min.js +0 -2
- data/app/assets/javascripts/stimulus_reflex.min.js.map +0 -1
- data/app/assets/javascripts/stimulus_reflex.umd.min.js +0 -1065
- data/app/assets/javascripts/stimulus_reflex.umd.min.js.map +0 -1
|
@@ -1,8 +1,284 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@hotwired/stimulus"), require("
|
|
3
|
-
factory(global.StimulusReflex = {}, global.Stimulus, global.
|
|
4
|
-
})(this, (function(exports, stimulus,
|
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@hotwired/stimulus"), require("cable_ready"), require("@rails/actioncable")) : typeof define === "function" && define.amd ? define([ "exports", "@hotwired/stimulus", "cable_ready", "@rails/actioncable" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
|
|
3
|
+
factory(global.StimulusReflex = {}, global.Stimulus, global.CableReady, global.ActionCable));
|
|
4
|
+
})(this, (function(exports, stimulus, CableReady, actioncable) {
|
|
5
5
|
"use strict";
|
|
6
|
+
/*!
|
|
7
|
+
* Toastify js 1.12.0
|
|
8
|
+
* https://github.com/apvarun/toastify-js
|
|
9
|
+
* @license MIT licensed
|
|
10
|
+
*
|
|
11
|
+
* Copyright (C) 2018 Varun A P
|
|
12
|
+
*/ class Toastify {
|
|
13
|
+
defaults={
|
|
14
|
+
oldestFirst: true,
|
|
15
|
+
text: "Toastify is awesome!",
|
|
16
|
+
node: undefined,
|
|
17
|
+
duration: 3e3,
|
|
18
|
+
selector: undefined,
|
|
19
|
+
callback: function() {},
|
|
20
|
+
destination: undefined,
|
|
21
|
+
newWindow: false,
|
|
22
|
+
close: false,
|
|
23
|
+
gravity: "toastify-top",
|
|
24
|
+
positionLeft: false,
|
|
25
|
+
position: "",
|
|
26
|
+
backgroundColor: "",
|
|
27
|
+
avatar: "",
|
|
28
|
+
className: "",
|
|
29
|
+
stopOnFocus: true,
|
|
30
|
+
onClick: function() {},
|
|
31
|
+
offset: {
|
|
32
|
+
x: 0,
|
|
33
|
+
y: 0
|
|
34
|
+
},
|
|
35
|
+
escapeMarkup: true,
|
|
36
|
+
ariaLive: "polite",
|
|
37
|
+
style: {
|
|
38
|
+
background: ""
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
constructor(options) {
|
|
42
|
+
this.version = "1.12.0";
|
|
43
|
+
this.options = {};
|
|
44
|
+
this.toastElement = null;
|
|
45
|
+
this._rootElement = document.body;
|
|
46
|
+
this._init(options);
|
|
47
|
+
}
|
|
48
|
+
showToast() {
|
|
49
|
+
this.toastElement = this._buildToast();
|
|
50
|
+
if (typeof this.options.selector === "string") {
|
|
51
|
+
this._rootElement = document.getElementById(this.options.selector);
|
|
52
|
+
} else if (this.options.selector instanceof HTMLElement || this.options.selector instanceof ShadowRoot) {
|
|
53
|
+
this._rootElement = this.options.selector;
|
|
54
|
+
} else {
|
|
55
|
+
this._rootElement = document.body;
|
|
56
|
+
}
|
|
57
|
+
if (!this._rootElement) {
|
|
58
|
+
throw "Root element is not defined";
|
|
59
|
+
}
|
|
60
|
+
this._rootElement.insertBefore(this.toastElement, this._rootElement.firstChild);
|
|
61
|
+
this._reposition();
|
|
62
|
+
if (this.options.duration > 0) {
|
|
63
|
+
this.toastElement.timeOutValue = window.setTimeout((() => {
|
|
64
|
+
this._removeElement(this.toastElement);
|
|
65
|
+
}), this.options.duration);
|
|
66
|
+
}
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
hideToast() {
|
|
70
|
+
if (this.toastElement.timeOutValue) {
|
|
71
|
+
clearTimeout(this.toastElement.timeOutValue);
|
|
72
|
+
}
|
|
73
|
+
this._removeElement(this.toastElement);
|
|
74
|
+
}
|
|
75
|
+
_init(options) {
|
|
76
|
+
this.options = Object.assign(this.defaults, options);
|
|
77
|
+
if (this.options.backgroundColor) {
|
|
78
|
+
console.warn('DEPRECATION NOTICE: "backgroundColor" is being deprecated. Please use the "style.background" property.');
|
|
79
|
+
}
|
|
80
|
+
this.toastElement = null;
|
|
81
|
+
this.options.gravity = options.gravity === "bottom" ? "toastify-bottom" : "toastify-top";
|
|
82
|
+
this.options.stopOnFocus = options.stopOnFocus === undefined ? true : options.stopOnFocus;
|
|
83
|
+
if (options.backgroundColor) {
|
|
84
|
+
this.options.style.background = options.backgroundColor;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
_buildToast() {
|
|
88
|
+
if (!this.options) {
|
|
89
|
+
throw "Toastify is not initialized";
|
|
90
|
+
}
|
|
91
|
+
let divElement = document.createElement("div");
|
|
92
|
+
divElement.className = `toastify on ${this.options.className}`;
|
|
93
|
+
divElement.className += ` toastify-${this.options.position}`;
|
|
94
|
+
divElement.className += ` ${this.options.gravity}`;
|
|
95
|
+
for (const property in this.options.style) {
|
|
96
|
+
divElement.style[property] = this.options.style[property];
|
|
97
|
+
}
|
|
98
|
+
if (this.options.ariaLive) {
|
|
99
|
+
divElement.setAttribute("aria-live", this.options.ariaLive);
|
|
100
|
+
}
|
|
101
|
+
if (this.options.node && this.options.node.nodeType === Node.ELEMENT_NODE) {
|
|
102
|
+
divElement.appendChild(this.options.node);
|
|
103
|
+
} else {
|
|
104
|
+
if (this.options.escapeMarkup) {
|
|
105
|
+
divElement.innerText = this.options.text;
|
|
106
|
+
} else {
|
|
107
|
+
divElement.innerHTML = this.options.text;
|
|
108
|
+
}
|
|
109
|
+
if (this.options.avatar !== "") {
|
|
110
|
+
let avatarElement = document.createElement("img");
|
|
111
|
+
avatarElement.src = this.options.avatar;
|
|
112
|
+
avatarElement.className = "toastify-avatar";
|
|
113
|
+
if (this.options.position == "left") {
|
|
114
|
+
divElement.appendChild(avatarElement);
|
|
115
|
+
} else {
|
|
116
|
+
divElement.insertAdjacentElement("afterbegin", avatarElement);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (this.options.close === true) {
|
|
121
|
+
let closeElement = document.createElement("button");
|
|
122
|
+
closeElement.type = "button";
|
|
123
|
+
closeElement.setAttribute("aria-label", "Close");
|
|
124
|
+
closeElement.className = "toast-close";
|
|
125
|
+
closeElement.innerHTML = "✖";
|
|
126
|
+
closeElement.addEventListener("click", (event => {
|
|
127
|
+
event.stopPropagation();
|
|
128
|
+
this._removeElement(this.toastElement);
|
|
129
|
+
window.clearTimeout(this.toastElement.timeOutValue);
|
|
130
|
+
}));
|
|
131
|
+
const width = window.innerWidth > 0 ? window.innerWidth : screen.width;
|
|
132
|
+
if (this.options.position == "left" && width > 360) {
|
|
133
|
+
divElement.insertAdjacentElement("afterbegin", closeElement);
|
|
134
|
+
} else {
|
|
135
|
+
divElement.appendChild(closeElement);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (this.options.stopOnFocus && this.options.duration > 0) {
|
|
139
|
+
divElement.addEventListener("mouseover", (event => {
|
|
140
|
+
window.clearTimeout(divElement.timeOutValue);
|
|
141
|
+
}));
|
|
142
|
+
divElement.addEventListener("mouseleave", (() => {
|
|
143
|
+
divElement.timeOutValue = window.setTimeout((() => {
|
|
144
|
+
this._removeElement(divElement);
|
|
145
|
+
}), this.options.duration);
|
|
146
|
+
}));
|
|
147
|
+
}
|
|
148
|
+
if (typeof this.options.destination !== "undefined") {
|
|
149
|
+
divElement.addEventListener("click", (event => {
|
|
150
|
+
event.stopPropagation();
|
|
151
|
+
if (this.options.newWindow === true) {
|
|
152
|
+
window.open(this.options.destination, "_blank");
|
|
153
|
+
} else {
|
|
154
|
+
window.location = this.options.destination;
|
|
155
|
+
}
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
if (typeof this.options.onClick === "function" && typeof this.options.destination === "undefined") {
|
|
159
|
+
divElement.addEventListener("click", (event => {
|
|
160
|
+
event.stopPropagation();
|
|
161
|
+
this.options.onClick();
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
if (typeof this.options.offset === "object") {
|
|
165
|
+
const x = this._getAxisOffsetAValue("x", this.options);
|
|
166
|
+
const y = this._getAxisOffsetAValue("y", this.options);
|
|
167
|
+
const xOffset = this.options.position == "left" ? x : `-${x}`;
|
|
168
|
+
const yOffset = this.options.gravity == "toastify-top" ? y : `-${y}`;
|
|
169
|
+
divElement.style.transform = `translate(${xOffset},${yOffset})`;
|
|
170
|
+
}
|
|
171
|
+
return divElement;
|
|
172
|
+
}
|
|
173
|
+
_removeElement(toastElement) {
|
|
174
|
+
toastElement.className = toastElement.className.replace(" on", "");
|
|
175
|
+
window.setTimeout((() => {
|
|
176
|
+
if (this.options.node && this.options.node.parentNode) {
|
|
177
|
+
this.options.node.parentNode.removeChild(this.options.node);
|
|
178
|
+
}
|
|
179
|
+
if (toastElement.parentNode) {
|
|
180
|
+
toastElement.parentNode.removeChild(toastElement);
|
|
181
|
+
}
|
|
182
|
+
this.options.callback.call(toastElement);
|
|
183
|
+
this._reposition();
|
|
184
|
+
}), 400);
|
|
185
|
+
}
|
|
186
|
+
_reposition() {
|
|
187
|
+
let topLeftOffsetSize = {
|
|
188
|
+
top: 15,
|
|
189
|
+
bottom: 15
|
|
190
|
+
};
|
|
191
|
+
let topRightOffsetSize = {
|
|
192
|
+
top: 15,
|
|
193
|
+
bottom: 15
|
|
194
|
+
};
|
|
195
|
+
let offsetSize = {
|
|
196
|
+
top: 15,
|
|
197
|
+
bottom: 15
|
|
198
|
+
};
|
|
199
|
+
let allToasts = this._rootElement.querySelectorAll(".toastify");
|
|
200
|
+
let classUsed;
|
|
201
|
+
for (let i = 0; i < allToasts.length; i++) {
|
|
202
|
+
if (allToasts[i].classList.contains("toastify-top") === true) {
|
|
203
|
+
classUsed = "toastify-top";
|
|
204
|
+
} else {
|
|
205
|
+
classUsed = "toastify-bottom";
|
|
206
|
+
}
|
|
207
|
+
let height = allToasts[i].offsetHeight;
|
|
208
|
+
classUsed = classUsed.substr(9, classUsed.length - 1);
|
|
209
|
+
let offset = 15;
|
|
210
|
+
let width = window.innerWidth > 0 ? window.innerWidth : screen.width;
|
|
211
|
+
if (width <= 360) {
|
|
212
|
+
allToasts[i].style[classUsed] = `${offsetSize[classUsed]}px`;
|
|
213
|
+
offsetSize[classUsed] += height + offset;
|
|
214
|
+
} else {
|
|
215
|
+
if (allToasts[i].classList.contains("toastify-left") === true) {
|
|
216
|
+
allToasts[i].style[classUsed] = `${topLeftOffsetSize[classUsed]}px`;
|
|
217
|
+
topLeftOffsetSize[classUsed] += height + offset;
|
|
218
|
+
} else {
|
|
219
|
+
allToasts[i].style[classUsed] = `${topRightOffsetSize[classUsed]}px`;
|
|
220
|
+
topRightOffsetSize[classUsed] += height + offset;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
_getAxisOffsetAValue(axis, options) {
|
|
226
|
+
if (options.offset[axis]) {
|
|
227
|
+
if (isNaN(options.offset[axis])) {
|
|
228
|
+
return options.offset[axis];
|
|
229
|
+
} else {
|
|
230
|
+
return `${options.offset[axis]}px`;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return "0px";
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function StartToastifyInstance(options) {
|
|
237
|
+
return new Toastify(options);
|
|
238
|
+
}
|
|
239
|
+
CableReady.operations.stimulusReflexVersionMismatch = operation => {
|
|
240
|
+
const levels = {
|
|
241
|
+
info: {},
|
|
242
|
+
success: {
|
|
243
|
+
background: "#198754",
|
|
244
|
+
color: "white"
|
|
245
|
+
},
|
|
246
|
+
warn: {
|
|
247
|
+
background: "#ffc107",
|
|
248
|
+
color: "black"
|
|
249
|
+
},
|
|
250
|
+
error: {
|
|
251
|
+
background: "#dc3545",
|
|
252
|
+
color: "white"
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const defaults = {
|
|
256
|
+
selector: setupToastify(),
|
|
257
|
+
close: true,
|
|
258
|
+
duration: 30 * 1e3,
|
|
259
|
+
gravity: "bottom",
|
|
260
|
+
position: "right",
|
|
261
|
+
newWindow: true,
|
|
262
|
+
style: levels[operation.level || "info"]
|
|
263
|
+
};
|
|
264
|
+
StartToastifyInstance({
|
|
265
|
+
...defaults,
|
|
266
|
+
...operation
|
|
267
|
+
}).showToast();
|
|
268
|
+
};
|
|
269
|
+
function setupToastify() {
|
|
270
|
+
const id = "stimulus-reflex-toast-element";
|
|
271
|
+
let element = document.querySelector(`#${id}`);
|
|
272
|
+
if (!element) {
|
|
273
|
+
element = document.createElement("div");
|
|
274
|
+
element.id = id;
|
|
275
|
+
document.documentElement.appendChild(element);
|
|
276
|
+
const styles = document.createElement("style");
|
|
277
|
+
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 `;
|
|
278
|
+
document.head.appendChild(styles);
|
|
279
|
+
}
|
|
280
|
+
return element;
|
|
281
|
+
}
|
|
6
282
|
let deprecationWarnings = true;
|
|
7
283
|
var Deprecate = {
|
|
8
284
|
get enabled() {
|
|
@@ -149,6 +425,7 @@
|
|
|
149
425
|
}
|
|
150
426
|
return list;
|
|
151
427
|
};
|
|
428
|
+
const reflexNameToControllerIdentifier = reflexName => reflexName.replace(/([a-z0–9])([A-Z])/g, "$1-$2").replace(/(::)/g, "--").replace(/-reflex$/gi, "").toLowerCase();
|
|
152
429
|
const stages = [ "created", "before", "delivered", "queued", "after", "finalized", "success", "error", "halted", "forbidden" ];
|
|
153
430
|
let lastReflex;
|
|
154
431
|
const reflexes = new Proxy({}, {
|
|
@@ -585,7 +862,7 @@
|
|
|
585
862
|
return attrs;
|
|
586
863
|
};
|
|
587
864
|
var name = "stimulus_reflex";
|
|
588
|
-
var version = "3.5.0-
|
|
865
|
+
var version = "3.5.0-rc1";
|
|
589
866
|
var description = "Build reactive applications with the Rails tooling you already know and love.";
|
|
590
867
|
var keywords = [ "ruby", "rails", "websockets", "actioncable", "turbolinks", "reactive", "cable", "ujs", "ssr", "stimulus", "reflex", "stimulus_reflex", "dom", "morphdom" ];
|
|
591
868
|
var homepage = "https://docs.stimulusreflex.com";
|
|
@@ -607,17 +884,18 @@
|
|
|
607
884
|
"build:watch": "yarn rollup -wc",
|
|
608
885
|
watch: "yarn build:watch",
|
|
609
886
|
test: "web-test-runner javascript/test/**/*.test.js",
|
|
887
|
+
"test:watch": "yarn test --watch",
|
|
610
888
|
"docs:dev": "vitepress dev docs",
|
|
611
|
-
"docs:build": "vitepress build docs",
|
|
889
|
+
"docs:build": "vitepress build docs && cp docs/_redirects docs/.vitepress/dist",
|
|
612
890
|
"docs:preview": "vitepress preview docs"
|
|
613
891
|
};
|
|
614
892
|
var peerDependencies = {
|
|
615
893
|
"@hotwired/stimulus": ">= 3.0"
|
|
616
894
|
};
|
|
617
895
|
var dependencies = {
|
|
618
|
-
"@hotwired/stimulus": "
|
|
619
|
-
"@rails/actioncable": "
|
|
620
|
-
cable_ready: "5.0.0-
|
|
896
|
+
"@hotwired/stimulus": "^3",
|
|
897
|
+
"@rails/actioncable": "^6 || ^7",
|
|
898
|
+
cable_ready: "5.0.0-rc1"
|
|
621
899
|
};
|
|
622
900
|
var devDependencies = {
|
|
623
901
|
"@open-wc/testing": "^3.1.7",
|
|
@@ -626,10 +904,11 @@
|
|
|
626
904
|
"@rollup/plugin-terser": "^0.4.0",
|
|
627
905
|
"@web/dev-server-esbuild": "^0.3.3",
|
|
628
906
|
"@web/dev-server-rollup": "^0.3.21",
|
|
629
|
-
"@web/test-runner": "^0.15.
|
|
907
|
+
"@web/test-runner": "^0.15.1",
|
|
630
908
|
"prettier-standard": "^16.4.1",
|
|
631
|
-
rollup: "^3.
|
|
632
|
-
|
|
909
|
+
rollup: "^3.19.1",
|
|
910
|
+
"toastify-js": "^1.12.0",
|
|
911
|
+
vitepress: "^1.0.0-alpha.56"
|
|
633
912
|
};
|
|
634
913
|
var packageInfo = {
|
|
635
914
|
name: name,
|
|
@@ -847,11 +1126,11 @@
|
|
|
847
1126
|
toString: () => reflex.error
|
|
848
1127
|
})));
|
|
849
1128
|
};
|
|
850
|
-
const localReflexControllers = element =>
|
|
851
|
-
const
|
|
852
|
-
|
|
853
|
-
return
|
|
854
|
-
}
|
|
1129
|
+
const localReflexControllers = element => {
|
|
1130
|
+
const potentialIdentifiers = attributeValues(element.getAttribute(Schema.controller));
|
|
1131
|
+
const potentialControllers = potentialIdentifiers.map((identifier => App.app.getControllerForElementAndIdentifier(element, identifier)));
|
|
1132
|
+
return potentialControllers.filter((controller => controller && controller.StimulusReflex));
|
|
1133
|
+
};
|
|
855
1134
|
const allReflexControllers = element => {
|
|
856
1135
|
let controllers = [];
|
|
857
1136
|
while (element) {
|
|
@@ -862,8 +1141,9 @@
|
|
|
862
1141
|
};
|
|
863
1142
|
const findControllerByReflexName = (reflexName, controllers) => {
|
|
864
1143
|
const controller = controllers.find((controller => {
|
|
865
|
-
if (!controller.identifier) return;
|
|
866
|
-
|
|
1144
|
+
if (!controller || !controller.identifier) return;
|
|
1145
|
+
const identifier = reflexNameToControllerIdentifier(extractReflexName(reflexName));
|
|
1146
|
+
return identifier === controller.identifier;
|
|
867
1147
|
}));
|
|
868
1148
|
return controller || controllers[0];
|
|
869
1149
|
};
|
|
@@ -871,18 +1151,22 @@
|
|
|
871
1151
|
const reflexElements = document.querySelectorAll(`[${Schema.reflex}]`);
|
|
872
1152
|
reflexElements.forEach((element => scanForReflexesOnElement(element)));
|
|
873
1153
|
}), 20);
|
|
874
|
-
const scanForReflexesOnElement = element => {
|
|
1154
|
+
const scanForReflexesOnElement = (element, controller = null) => {
|
|
875
1155
|
const controllerAttribute = element.getAttribute(Schema.controller);
|
|
876
|
-
const controllers = attributeValues(controllerAttribute);
|
|
1156
|
+
const controllers = attributeValues(controllerAttribute).filter((controller => controller !== "stimulus-reflex"));
|
|
877
1157
|
const reflexAttribute = element.getAttribute(Schema.reflex);
|
|
878
1158
|
const reflexAttributeNames = attributeValues(reflexAttribute);
|
|
879
1159
|
const actionAttribute = element.getAttribute(Schema.action);
|
|
880
1160
|
const actions = attributeValues(actionAttribute).filter((action => !action.includes("#__perform")));
|
|
881
1161
|
reflexAttributeNames.forEach((reflexName => {
|
|
882
|
-
const
|
|
1162
|
+
const potentialControllers = [ controller ].concat(allReflexControllers(element));
|
|
1163
|
+
controller = findControllerByReflexName(reflexName, potentialControllers);
|
|
883
1164
|
const controllerName = controller ? controller.identifier : "stimulus-reflex";
|
|
884
1165
|
actions.push(`${reflexName.split("->")[0]}->${controllerName}#__perform`);
|
|
885
|
-
|
|
1166
|
+
const parentControllerElement = element.closest(`[data-controller~=${controllerName}]`);
|
|
1167
|
+
if (!parentControllerElement) {
|
|
1168
|
+
controllers.push(controllerName);
|
|
1169
|
+
}
|
|
886
1170
|
}));
|
|
887
1171
|
const controllerValue = attributeValue(controllers);
|
|
888
1172
|
const actionValue = attributeValue(actions);
|
|
@@ -1005,7 +1289,7 @@
|
|
|
1005
1289
|
});
|
|
1006
1290
|
}
|
|
1007
1291
|
});
|
|
1008
|
-
scanForReflexesOnElement(controller.element);
|
|
1292
|
+
scanForReflexesOnElement(controller.element, controller);
|
|
1009
1293
|
emitEvent("stimulus-reflex:controller-registered", {
|
|
1010
1294
|
detail: {
|
|
1011
1295
|
controller: controller
|
|
@@ -27,24 +27,7 @@ class StimulusReflex::Channel < StimulusReflex.configuration.parent_channel.cons
|
|
|
27
27
|
reflex.logger&.error error_message
|
|
28
28
|
reflex.broadcast_error data: data, error: "#{exception} #{exception.backtrace.first.split(":in ")[0] if Rails.env.development?}"
|
|
29
29
|
else
|
|
30
|
-
|
|
31
|
-
mismatch = "Reflex failed due to stimulus_reflex gem/NPM package version mismatch. Package versions must match exactly.\nNote that if you are using pre-release builds, gems use the \"x.y.z.preN\" version format, while NPM packages use \"x.y.z-preN\".\n\nstimulus_reflex gem: #{StimulusReflex::VERSION}\nstimulus_reflex NPM: #{data["version"]}"
|
|
32
|
-
|
|
33
|
-
StimulusReflex.config.logger.error("\n\e[31m#{mismatch}\e[0m") unless StimulusReflex.config.on_failed_sanity_checks == :ignore
|
|
34
|
-
|
|
35
|
-
if Rails.env.development?
|
|
36
|
-
CableReady::Channels.instance[stream_name].console_log(
|
|
37
|
-
message: mismatch,
|
|
38
|
-
level: "error",
|
|
39
|
-
id: data["id"]
|
|
40
|
-
).broadcast
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
if StimulusReflex.config.on_failed_sanity_checks == :exit
|
|
44
|
-
sleep 0.1
|
|
45
|
-
exit!
|
|
46
|
-
end
|
|
47
|
-
else
|
|
30
|
+
unless exception.is_a?(StimulusReflex::Reflex::VersionMismatchError)
|
|
48
31
|
StimulusReflex.config.logger.error error_message
|
|
49
32
|
end
|
|
50
33
|
|
|
@@ -34,20 +34,20 @@ class StimulusReflexGenerator < Rails::Generators::NamedBase
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
reflex_entrypoint = Rails.env.test? ? "tmp/app/reflexes" : "app/reflexes"
|
|
37
|
-
reflex_src =
|
|
37
|
+
reflex_src = "app/reflexes/%file_name%_reflex.rb.tt"
|
|
38
38
|
reflex_path = Rails.root.join(reflex_entrypoint, "#{file_name}_reflex.rb")
|
|
39
|
-
stimulus_controller_src =
|
|
39
|
+
stimulus_controller_src = "app/javascript/controllers/%file_name%_controller.js.tt"
|
|
40
40
|
stimulus_controller_path = Rails.root.join(entrypoint, "controllers/#{file_name}_controller.js")
|
|
41
41
|
|
|
42
42
|
template(reflex_src, reflex_path) unless options[:skip_reflex]
|
|
43
43
|
template(stimulus_controller_src, stimulus_controller_path) unless options[:skip_stimulus]
|
|
44
44
|
|
|
45
45
|
if file_name == "example"
|
|
46
|
-
controller_src =
|
|
46
|
+
controller_src = "app/controllers/examples_controller.rb.tt"
|
|
47
47
|
controller_path = Rails.root.join("app/controllers/examples_controller.rb")
|
|
48
48
|
template(controller_src, controller_path)
|
|
49
49
|
|
|
50
|
-
view_src =
|
|
50
|
+
view_src = "app/views/examples/show.html.erb.tt"
|
|
51
51
|
view_path = Rails.root.join("app/views/examples/show.html.erb")
|
|
52
52
|
template(view_src, view_path)
|
|
53
53
|
|
|
@@ -83,10 +83,4 @@ class StimulusReflexGenerator < Rails::Generators::NamedBase
|
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
|
-
|
|
87
|
-
private
|
|
88
|
-
|
|
89
|
-
def fetch(file)
|
|
90
|
-
source_paths.first + file
|
|
91
|
-
end
|
|
92
86
|
end
|
|
@@ -8,7 +8,7 @@ class ApplicationReflex < StimulusReflex::Reflex
|
|
|
8
8
|
# If your ActionCable connection is: `identified_by :current_user`
|
|
9
9
|
# delegate :current_user, to: :connection
|
|
10
10
|
#
|
|
11
|
-
# current_user delegation
|
|
11
|
+
# current_user delegation allows you to use the Current pattern, too:
|
|
12
12
|
# before_reflex do
|
|
13
13
|
# Current.user = current_user
|
|
14
14
|
# end
|
|
@@ -19,4 +19,9 @@ CableReady.configure do |config|
|
|
|
19
19
|
# Change the default Active Job queue used for broadcast_later and broadcast_later_to
|
|
20
20
|
#
|
|
21
21
|
# config.broadcast_job_queue = :default
|
|
22
|
+
|
|
23
|
+
# Specify a default debounce time for CableReady::Updatable callbacks
|
|
24
|
+
# Doing so is a best practice to avoid heavy ActionCable traffic
|
|
25
|
+
#
|
|
26
|
+
# config.updatable_debounce_time = 0.1.seconds
|
|
22
27
|
end
|
data/lib/install/development.rb
CHANGED
|
@@ -36,13 +36,13 @@ lines = development_working_path.readlines
|
|
|
36
36
|
|
|
37
37
|
if (index = lines.index { |line| line =~ /^[^#]*config.session_store/ })
|
|
38
38
|
if /^[^#]*cookie_store/.match?(lines[index])
|
|
39
|
-
write_redis_recommendation(development_working_path, lines, index,
|
|
39
|
+
write_redis_recommendation(development_working_path, lines, index, gemfile)
|
|
40
40
|
halt "StimulusReflex does not support session cookies. See https://docs.stimulusreflex.com/hello-world/setup#session-storage"
|
|
41
41
|
return
|
|
42
42
|
elsif /^[^#]*redis_session_store/.match?(lines[index])
|
|
43
43
|
say "⏩ Already using redis-session-store for session storage. Skipping."
|
|
44
44
|
else
|
|
45
|
-
write_redis_recommendation(development_working_path, lines, index,
|
|
45
|
+
write_redis_recommendation(development_working_path, lines, index, gemfile)
|
|
46
46
|
say "🤷 We recommend using redis-session-store for session storage. See https://docs.stimulusreflex.com/hello-world/setup#session-storage"
|
|
47
47
|
end
|
|
48
48
|
# no session store defined, so let's opt-in to redis-session-store
|
data/lib/install/importmap.rb
CHANGED
|
@@ -50,7 +50,7 @@ backup(importmap_path) do
|
|
|
50
50
|
|
|
51
51
|
if !importmap.include?("pin \"@hotwired/stimulus\"")
|
|
52
52
|
append_file(importmap_path, <<~RUBY, verbose: false)
|
|
53
|
-
pin "@hotwired/stimulus", to: "stimulus.
|
|
53
|
+
pin "@hotwired/stimulus", to: "stimulus.js", preload: true
|
|
54
54
|
RUBY
|
|
55
55
|
say "✅ pin @hotwired/stimulus"
|
|
56
56
|
else
|
|
@@ -68,7 +68,7 @@ backup(importmap_path) do
|
|
|
68
68
|
|
|
69
69
|
if !importmap.include?("pin \"cable_ready\"")
|
|
70
70
|
append_file(importmap_path, <<~RUBY, verbose: false)
|
|
71
|
-
pin "cable_ready", to: "cable_ready.
|
|
71
|
+
pin "cable_ready", to: "cable_ready.js", preload: true
|
|
72
72
|
RUBY
|
|
73
73
|
say "✅ pin cable_ready"
|
|
74
74
|
else
|
|
@@ -77,7 +77,7 @@ backup(importmap_path) do
|
|
|
77
77
|
|
|
78
78
|
if !importmap.include?("pin \"stimulus_reflex\"")
|
|
79
79
|
append_file(importmap_path, <<~RUBY, verbose: false)
|
|
80
|
-
pin "stimulus_reflex", to: "stimulus_reflex.
|
|
80
|
+
pin "stimulus_reflex", to: "stimulus_reflex.js", preload: true
|
|
81
81
|
RUBY
|
|
82
82
|
say "✅ pin stimulus_reflex"
|
|
83
83
|
else
|
|
@@ -17,11 +17,7 @@ module StimulusReflex
|
|
|
17
17
|
#
|
|
18
18
|
PRECOMPILE_ASSETS = %w[
|
|
19
19
|
stimulus_reflex.js
|
|
20
|
-
stimulus_reflex.min.js
|
|
21
|
-
stimulus_reflex.min.js.map
|
|
22
20
|
stimulus_reflex.umd.js
|
|
23
|
-
stimulus_reflex.umd.min.js
|
|
24
|
-
stimulus_reflex.umd.min.js.map
|
|
25
21
|
]
|
|
26
22
|
|
|
27
23
|
initializer "stimulus_reflex.assets" do |app|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
pin "@rails/actioncable", to: "actioncable.esm.js", preload: true
|
|
4
|
-
pin "@hotwired/stimulus", to: "stimulus.
|
|
4
|
+
pin "@hotwired/stimulus", to: "stimulus.js", preload: true
|
|
5
5
|
pin "morphdom", to: "https://ga.jspm.io/npm:morphdom@2.6.1/dist/morphdom.js", preload: true
|
|
6
|
-
pin "cable_ready", to: "cable_ready.
|
|
7
|
-
pin "stimulus_reflex", to: "stimulus_reflex.
|
|
6
|
+
pin "cable_ready", to: "cable_ready.js", preload: true
|
|
7
|
+
pin "stimulus_reflex", to: "stimulus_reflex.js", preload: true
|
|
@@ -1,16 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "stimulus_reflex/cable_readiness"
|
|
4
|
+
require "stimulus_reflex/version_checker"
|
|
4
5
|
|
|
5
6
|
# TODO remove xpath_controller and xpath_element for v4
|
|
6
|
-
ClientAttributes = Struct.new(
|
|
7
|
+
ClientAttributes = Struct.new(
|
|
8
|
+
:id,
|
|
9
|
+
:tab_id,
|
|
10
|
+
:reflex_controller,
|
|
11
|
+
:xpath_controller,
|
|
12
|
+
:xpath_element,
|
|
13
|
+
:permanent_attribute_name,
|
|
14
|
+
:version,
|
|
15
|
+
:npm_version,
|
|
16
|
+
:suppress_logging,
|
|
17
|
+
keyword_init: true
|
|
18
|
+
)
|
|
7
19
|
|
|
8
20
|
class StimulusReflex::Reflex
|
|
9
|
-
class VersionMismatchError < StandardError; end
|
|
10
|
-
|
|
11
21
|
prepend StimulusReflex::CableReadiness
|
|
12
|
-
include
|
|
22
|
+
include StimulusReflex::VersionChecker
|
|
13
23
|
include StimulusReflex::Callbacks
|
|
24
|
+
include ActiveSupport::Rescuable
|
|
14
25
|
include ActionView::Helpers::TagHelper
|
|
15
26
|
include CableReady::Identifiable
|
|
16
27
|
|
|
@@ -23,7 +34,7 @@ class StimulusReflex::Reflex
|
|
|
23
34
|
delegate :controller_class, :flash, :session, to: :request
|
|
24
35
|
delegate :broadcast, :broadcast_halt, :broadcast_forbid, :broadcast_error, to: :broadcaster
|
|
25
36
|
# TODO remove xpath_controller and xpath_element for v4
|
|
26
|
-
delegate :id, :tab_id, :reflex_controller, :xpath_controller, :xpath_element, :permanent_attribute_name, :version, :suppress_logging, to: :client_attributes
|
|
37
|
+
delegate :id, :tab_id, :reflex_controller, :xpath_controller, :xpath_element, :permanent_attribute_name, :version, :npm_version, :suppress_logging, to: :client_attributes
|
|
27
38
|
|
|
28
39
|
def initialize(channel, url: nil, element: nil, selectors: [], method_name: nil, params: {}, client_attributes: {})
|
|
29
40
|
@channel = channel
|
|
@@ -38,9 +49,7 @@ class StimulusReflex::Reflex
|
|
|
38
49
|
@payload = {}
|
|
39
50
|
@headers = {}
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
raise VersionMismatchError.new("stimulus_reflex gem / NPM package version mismatch")
|
|
43
|
-
end
|
|
52
|
+
check_version!
|
|
44
53
|
|
|
45
54
|
self.params
|
|
46
55
|
end
|
|
@@ -52,7 +52,7 @@ class StimulusReflex::ReflexData
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def params
|
|
55
|
-
form_params.
|
|
55
|
+
form_params.deep_merge(url_params)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def form_params
|
|
@@ -85,6 +85,10 @@ class StimulusReflex::ReflexData
|
|
|
85
85
|
data["reflexController"]
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
def npm_version
|
|
89
|
+
data["version"].to_s
|
|
90
|
+
end
|
|
91
|
+
|
|
88
92
|
def version
|
|
89
93
|
data["version"].to_s.gsub("-pre", ".pre")
|
|
90
94
|
end
|
|
@@ -20,7 +20,8 @@ class StimulusReflex::ReflexFactory
|
|
|
20
20
|
reflex_controller: reflex_data.reflex_controller,
|
|
21
21
|
permanent_attribute_name: reflex_data.permanent_attribute_name,
|
|
22
22
|
suppress_logging: reflex_data.suppress_logging,
|
|
23
|
-
version: reflex_data.version
|
|
23
|
+
version: reflex_data.version,
|
|
24
|
+
npm_version: reflex_data.npm_version
|
|
24
25
|
})
|
|
25
26
|
end
|
|
26
27
|
|