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 +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
|
|