stimulus_reflex 3.5.0.pre9 → 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 +0 -1
- data/Gemfile.lock +122 -127
- data/README.md +13 -19
- data/app/assets/javascripts/stimulus_reflex.js +1017 -523
- data/app/assets/javascripts/stimulus_reflex.umd.js +940 -496
- data/app/channels/stimulus_reflex/channel.rb +9 -24
- data/bin/console +0 -2
- data/bin/standardize +2 -1
- data/lib/generators/stimulus_reflex/stimulus_reflex_generator.rb +68 -9
- data/lib/generators/stimulus_reflex/templates/app/controllers/examples_controller.rb.tt +9 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/channels/consumer.js.tt +6 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/channels/index.js.esbuild.tt +4 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/channels/index.js.importmap.tt +2 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/channels/index.js.shakapacker.tt +5 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/channels/index.js.vite.tt +1 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/channels/index.js.webpacker.tt +5 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/config/cable_ready.js.tt +4 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/config/index.js.tt +2 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/config/mrujs.js.tt +9 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/config/stimulus_reflex.js.tt +5 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/%file_name%_controller.js.tt +141 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/application.js.tt +11 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/application_controller.js.tt +74 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/index.js.esbuild.tt +7 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/index.js.importmap.tt +5 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/index.js.shakapacker.tt +5 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/index.js.vite.tt +5 -0
- data/lib/generators/stimulus_reflex/templates/app/javascript/controllers/index.js.webpacker.tt +5 -0
- data/{test/tmp/app/reflexes/user_reflex.rb → lib/generators/stimulus_reflex/templates/app/reflexes/%file_name%_reflex.rb.tt} +38 -9
- data/lib/generators/stimulus_reflex/templates/app/reflexes/application_reflex.rb.tt +27 -0
- data/lib/generators/stimulus_reflex/templates/app/views/examples/show.html.erb.tt +207 -0
- data/lib/generators/stimulus_reflex/templates/config/initializers/cable_ready.rb +27 -0
- data/lib/generators/stimulus_reflex/templates/config/initializers/stimulus_reflex.rb +18 -13
- data/lib/generators/stimulus_reflex/templates/esbuild.config.mjs.tt +94 -0
- data/lib/install/action_cable.rb +155 -0
- data/lib/install/broadcaster.rb +90 -0
- data/lib/install/bundle.rb +56 -0
- data/lib/install/compression.rb +41 -0
- data/lib/install/config.rb +87 -0
- data/lib/install/development.rb +110 -0
- data/lib/install/esbuild.rb +114 -0
- data/lib/install/example.rb +22 -0
- data/lib/install/importmap.rb +133 -0
- data/lib/install/initializers.rb +25 -0
- data/lib/install/mrujs.rb +133 -0
- data/lib/install/npm_packages.rb +25 -0
- data/lib/install/reflexes.rb +25 -0
- data/lib/install/shakapacker.rb +64 -0
- data/lib/install/spring.rb +54 -0
- data/lib/install/updatable.rb +34 -0
- data/lib/install/vite.rb +64 -0
- data/lib/install/webpacker.rb +90 -0
- data/lib/install/yarn.rb +55 -0
- data/lib/stimulus_reflex/broadcasters/broadcaster.rb +15 -8
- data/lib/stimulus_reflex/broadcasters/page_broadcaster.rb +7 -8
- data/lib/stimulus_reflex/broadcasters/selector_broadcaster.rb +10 -10
- data/lib/stimulus_reflex/broadcasters/update.rb +3 -0
- data/lib/stimulus_reflex/cable_readiness.rb +29 -0
- data/lib/stimulus_reflex/cable_ready_channels.rb +6 -5
- data/lib/stimulus_reflex/callbacks.rb +17 -1
- data/lib/stimulus_reflex/concern_enhancer.rb +6 -4
- data/lib/stimulus_reflex/configuration.rb +12 -2
- data/lib/stimulus_reflex/dataset.rb +11 -1
- data/lib/stimulus_reflex/engine.rb +16 -9
- data/lib/stimulus_reflex/html/document.rb +59 -0
- data/lib/stimulus_reflex/html/document_fragment.rb +13 -0
- data/lib/stimulus_reflex/importmap.rb +6 -3
- data/lib/stimulus_reflex/installer.rb +274 -0
- data/lib/stimulus_reflex/open_struct_fix.rb +2 -0
- data/lib/stimulus_reflex/reflex.rb +40 -31
- data/lib/stimulus_reflex/reflex_data.rb +19 -3
- data/lib/stimulus_reflex/reflex_factory.rb +6 -3
- data/lib/stimulus_reflex/request_parameters.rb +2 -0
- data/lib/stimulus_reflex/utils/logger.rb +10 -0
- data/lib/stimulus_reflex/utils/sanity_checker.rb +8 -48
- data/lib/stimulus_reflex/version.rb +1 -1
- data/lib/stimulus_reflex/version_checker.rb +54 -0
- data/lib/stimulus_reflex.rb +2 -0
- data/lib/tasks/stimulus_reflex/stimulus_reflex.rake +250 -0
- data/package.json +36 -28
- data/{rollup.config.js → rollup.config.mjs} +6 -24
- data/stimulus_reflex.gemspec +16 -19
- data/yarn.lock +1331 -748
- metadata +129 -79
- data/LATEST +0 -1
- 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 -905
- data/app/assets/javascripts/stimulus_reflex.umd.min.js.map +0 -1
- data/lib/generators/stimulus_reflex/initializer_generator.rb +0 -14
- data/test/broadcasters/broadcaster_test.rb +0 -11
- data/test/broadcasters/broadcaster_test_case.rb +0 -39
- data/test/broadcasters/nothing_broadcaster_test.rb +0 -31
- data/test/broadcasters/page_broadcaster_test.rb +0 -79
- data/test/broadcasters/selector_broadcaster_test.rb +0 -173
- data/test/callbacks_test.rb +0 -652
- data/test/concern_enhancer_test.rb +0 -54
- data/test/element_test.rb +0 -254
- data/test/generators/stimulus_reflex_generator_test.rb +0 -58
- data/test/reflex_test.rb +0 -43
- data/test/test_helper.rb +0 -71
- data/test/tmp/app/reflexes/application_reflex.rb +0 -12
- data/yarn-error.log +0 -4964
@@ -1,39 +1,301 @@
|
|
1
1
|
(function(global, factory) {
|
2
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.
|
3
|
+
factory(global.StimulusReflex = {}, global.Stimulus, global.CableReady, global.ActionCable));
|
4
4
|
})(this, (function(exports, stimulus, CableReady, actioncable) {
|
5
5
|
"use strict";
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
+
}
|
9
40
|
};
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
30
190
|
};
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
+
}
|
35
223
|
}
|
36
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
|
+
}
|
282
|
+
let deprecationWarnings = true;
|
283
|
+
var Deprecate = {
|
284
|
+
get enabled() {
|
285
|
+
return deprecationWarnings;
|
286
|
+
},
|
287
|
+
get disabled() {
|
288
|
+
return !deprecationWarnings;
|
289
|
+
},
|
290
|
+
get value() {
|
291
|
+
return deprecationWarnings;
|
292
|
+
},
|
293
|
+
set(value) {
|
294
|
+
deprecationWarnings = !!value;
|
295
|
+
},
|
296
|
+
set deprecate(value) {
|
297
|
+
deprecationWarnings = !!value;
|
298
|
+
}
|
37
299
|
};
|
38
300
|
let debugging = false;
|
39
301
|
var Debug$1 = {
|
@@ -53,70 +315,35 @@
|
|
53
315
|
debugging = !!value;
|
54
316
|
}
|
55
317
|
};
|
56
|
-
const
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
reflex
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
});
|
68
|
-
};
|
69
|
-
const success = (event, halted) => {
|
70
|
-
const {detail: detail} = event || {};
|
71
|
-
const {selector: selector, payload: payload} = detail || {};
|
72
|
-
const {reflexId: reflexId, target: target, morph: morph} = detail.stimulusReflex || {};
|
73
|
-
const reflex = reflexes[reflexId];
|
74
|
-
if (Debug$1.disabled || reflex.promise.data.suppressLogging) return;
|
75
|
-
const progress = reflex.totalOperations > 1 ? ` ${reflex.completedOperations}/${reflex.totalOperations}` : "";
|
76
|
-
const duration = reflex.timestamp ? `in ${new Date - reflex.timestamp}ms` : "CLONED";
|
77
|
-
const operation = event.type.split(":")[1].split("-").slice(1).join("_");
|
78
|
-
console.log(`↓ reflex ↓ ${target} → ${selector || "∞"}${progress} ${duration}`, {
|
79
|
-
reflexId: reflexId,
|
80
|
-
morph: morph,
|
81
|
-
operation: operation,
|
82
|
-
halted: halted,
|
83
|
-
payload: payload
|
84
|
-
});
|
85
|
-
};
|
86
|
-
const error$1 = event => {
|
87
|
-
const {detail: detail} = event || {};
|
88
|
-
const {reflexId: reflexId, target: target, payload: payload} = detail.stimulusReflex || {};
|
89
|
-
const reflex = reflexes[reflexId];
|
90
|
-
if (Debug$1.disabled || reflex.promise.data.suppressLogging) return;
|
91
|
-
const duration = reflex.timestamp ? `in ${new Date - reflex.timestamp}ms` : "CLONED";
|
92
|
-
console.log(`↓ reflex ↓ ${target} ${duration} %cERROR: ${event.detail.body}`, "color: #f00;", {
|
93
|
-
reflexId: reflexId,
|
94
|
-
payload: payload
|
95
|
-
});
|
96
|
-
};
|
97
|
-
var Log = {
|
98
|
-
request: request,
|
99
|
-
success: success,
|
100
|
-
error: error$1
|
318
|
+
const defaultSchema = {
|
319
|
+
reflexAttribute: "data-reflex",
|
320
|
+
reflexPermanentAttribute: "data-reflex-permanent",
|
321
|
+
reflexRootAttribute: "data-reflex-root",
|
322
|
+
reflexSuppressLoggingAttribute: "data-reflex-suppress-logging",
|
323
|
+
reflexDatasetAttribute: "data-reflex-dataset",
|
324
|
+
reflexDatasetAllAttribute: "data-reflex-dataset-all",
|
325
|
+
reflexSerializeFormAttribute: "data-reflex-serialize-form",
|
326
|
+
reflexFormSelectorAttribute: "data-reflex-form-selector",
|
327
|
+
reflexIncludeInnerHtmlAttribute: "data-reflex-include-inner-html",
|
328
|
+
reflexIncludeTextContentAttribute: "data-reflex-include-text-content"
|
101
329
|
};
|
102
|
-
let
|
103
|
-
var
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
set deprecate(value) {
|
117
|
-
deprecationWarnings = !!value;
|
330
|
+
let schema = {};
|
331
|
+
var Schema = {
|
332
|
+
set(application) {
|
333
|
+
schema = {
|
334
|
+
...defaultSchema,
|
335
|
+
...application.schema
|
336
|
+
};
|
337
|
+
for (const attribute in schema) {
|
338
|
+
const attributeName = attribute.slice(0, -9);
|
339
|
+
Object.defineProperty(this, attributeName, {
|
340
|
+
get: () => schema[attribute],
|
341
|
+
configurable: true
|
342
|
+
});
|
343
|
+
}
|
118
344
|
}
|
119
345
|
};
|
346
|
+
const {debounce: debounce, dispatch: dispatch, xpathToElement: xpathToElement, xpathToElementArray: xpathToElementArray} = CableReady.Utils;
|
120
347
|
const uuidv4 = () => {
|
121
348
|
const crypto = window.crypto || window.msCrypto;
|
122
349
|
return ([ 1e7 ] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)));
|
@@ -141,33 +368,19 @@
|
|
141
368
|
if (uppercaseFirstLetter) value = value.substr(0, 1).toUpperCase() + value.substr(1);
|
142
369
|
return value;
|
143
370
|
};
|
144
|
-
const
|
145
|
-
|
146
|
-
|
147
|
-
clearTimeout(timeoutId);
|
148
|
-
timeoutId = setTimeout((() => {
|
149
|
-
timeoutId = null;
|
150
|
-
callback(...args);
|
151
|
-
}), delay);
|
152
|
-
};
|
153
|
-
};
|
371
|
+
const XPathToElement = xpathToElement;
|
372
|
+
const XPathToArray = xpathToElementArray;
|
373
|
+
const emitEvent = (name, detail = {}) => dispatch(document, name, detail);
|
154
374
|
const extractReflexName = reflexString => {
|
155
375
|
const match = reflexString.match(/(?:.*->)?(.*?)(?:Reflex)?#/);
|
156
376
|
return match ? match[1] : "";
|
157
377
|
};
|
158
|
-
const emitEvent = (event, detail) => {
|
159
|
-
document.dispatchEvent(new CustomEvent(event, {
|
160
|
-
bubbles: true,
|
161
|
-
cancelable: false,
|
162
|
-
detail: detail
|
163
|
-
}));
|
164
|
-
if (window.jQuery) window.jQuery(document).trigger(event, detail);
|
165
|
-
};
|
166
378
|
const elementToXPath = element => {
|
167
379
|
if (element.id !== "") return "//*[@id='" + element.id + "']";
|
168
380
|
if (element === document.body) return "/html/body";
|
381
|
+
if (element.nodeName === "HTML") return "/html";
|
169
382
|
let ix = 0;
|
170
|
-
const siblings = element
|
383
|
+
const siblings = element && element.parentNode ? element.parentNode.childNodes : [];
|
171
384
|
for (var i = 0; i < siblings.length; i++) {
|
172
385
|
const sibling = siblings[i];
|
173
386
|
if (sibling === element) {
|
@@ -181,14 +394,355 @@
|
|
181
394
|
}
|
182
395
|
}
|
183
396
|
};
|
184
|
-
const
|
185
|
-
const
|
186
|
-
|
187
|
-
const
|
188
|
-
|
189
|
-
|
397
|
+
const elementInvalid = element => element.type === "number" && element.validity && element.validity.badInput;
|
398
|
+
const getReflexElement = (args, element) => args[0] && args[0].nodeType === Node.ELEMENT_NODE ? args.shift() : element;
|
399
|
+
const getReflexOptions = args => {
|
400
|
+
const options = {};
|
401
|
+
if (args[0] && typeof args[0] === "object" && Object.keys(args[0]).filter((key => [ "id", "attrs", "selectors", "reflexId", "resolveLate", "serializeForm", "suppressLogging", "includeInnerHTML", "includeTextContent" ].includes(key))).length) {
|
402
|
+
const opts = args.shift();
|
403
|
+
Object.keys(opts).forEach((o => {
|
404
|
+
if (o === "reflexId") {
|
405
|
+
if (Deprecate.enabled) console.warn("reflexId option will be removed in v4. Use id instead.");
|
406
|
+
options["id"] = opts["reflexId"];
|
407
|
+
} else options[o] = opts[o];
|
408
|
+
}));
|
409
|
+
}
|
410
|
+
return options;
|
411
|
+
};
|
412
|
+
const getReflexRoots = element => {
|
413
|
+
let list = [];
|
414
|
+
while (list.length === 0 && element) {
|
415
|
+
let reflexRoot = element.getAttribute(Schema.reflexRoot);
|
416
|
+
if (reflexRoot) {
|
417
|
+
if (reflexRoot.length === 0 && element.id) reflexRoot = `#${element.id}`;
|
418
|
+
const selectors = reflexRoot.split(",").filter((s => s.trim().length));
|
419
|
+
if (Debug$1.enabled && selectors.length === 0) {
|
420
|
+
console.error(`No value found for ${Schema.reflexRoot}. Add an #id to the element or provide a value for ${Schema.reflexRoot}.`, element);
|
421
|
+
}
|
422
|
+
list = list.concat(selectors.filter((s => document.querySelector(s))));
|
423
|
+
}
|
424
|
+
element = element.parentElement ? element.parentElement.closest(`[${Schema.reflexRoot}]`) : null;
|
425
|
+
}
|
426
|
+
return list;
|
427
|
+
};
|
428
|
+
const reflexNameToControllerIdentifier = reflexName => reflexName.replace(/([a-z0–9])([A-Z])/g, "$1-$2").replace(/(::)/g, "--").replace(/-reflex$/gi, "").toLowerCase();
|
429
|
+
const stages = [ "created", "before", "delivered", "queued", "after", "finalized", "success", "error", "halted", "forbidden" ];
|
430
|
+
let lastReflex;
|
431
|
+
const reflexes = new Proxy({}, {
|
432
|
+
get: function(target, prop) {
|
433
|
+
if (stages.includes(prop)) return Object.fromEntries(Object.entries(target).filter((([_, reflex]) => reflex.stage === prop))); else if (prop === "last") return lastReflex; else if (prop === "all") return target;
|
434
|
+
return Reflect.get(...arguments);
|
435
|
+
},
|
436
|
+
set: function(target, prop, value) {
|
437
|
+
target[prop] = value;
|
438
|
+
lastReflex = value;
|
439
|
+
return true;
|
440
|
+
}
|
441
|
+
});
|
442
|
+
const invokeLifecycleMethod = (reflex, stage) => {
|
443
|
+
const specificLifecycleMethod = reflex.controller[[ "before", "after", "finalize" ].includes(stage) ? `${stage}${camelize(reflex.action)}` : `${camelize(reflex.action, false)}${camelize(stage)}`];
|
444
|
+
const genericLifecycleMethod = reflex.controller[[ "before", "after", "finalize" ].includes(stage) ? `${stage}Reflex` : `reflex${camelize(stage)}`];
|
445
|
+
if (typeof specificLifecycleMethod === "function") {
|
446
|
+
specificLifecycleMethod.call(reflex.controller, reflex.element, reflex.target, reflex.error, reflex.id, reflex.payload);
|
447
|
+
}
|
448
|
+
if (typeof genericLifecycleMethod === "function") {
|
449
|
+
genericLifecycleMethod.call(reflex.controller, reflex.element, reflex.target, reflex.error, reflex.id, reflex.payload);
|
450
|
+
}
|
451
|
+
};
|
452
|
+
const dispatchLifecycleEvent = (reflex, stage) => {
|
453
|
+
if (!reflex.controller.element.parentElement) {
|
454
|
+
if (Debug$1.enabled && !reflex.warned) {
|
455
|
+
console.warn(`StimulusReflex was not able execute callbacks or emit events for "${stage}" or later life-cycle stages for this Reflex. The StimulusReflex Controller Element is no longer present in the DOM. Could you move the StimulusReflex Controller to an element higher in your DOM?`);
|
456
|
+
reflex.warned = true;
|
457
|
+
}
|
458
|
+
return;
|
459
|
+
}
|
460
|
+
reflex.stage = stage;
|
461
|
+
reflex.lifecycle.push(stage);
|
462
|
+
const event = `stimulus-reflex:${stage}`;
|
463
|
+
const action = `${event}:${reflex.action}`;
|
464
|
+
const detail = {
|
465
|
+
reflex: reflex.target,
|
466
|
+
controller: reflex.controller,
|
467
|
+
id: reflex.id,
|
468
|
+
element: reflex.element,
|
469
|
+
payload: reflex.payload
|
470
|
+
};
|
471
|
+
const options = {
|
472
|
+
bubbles: true,
|
473
|
+
cancelable: false,
|
474
|
+
detail: detail
|
475
|
+
};
|
476
|
+
reflex.controller.element.dispatchEvent(new CustomEvent(event, options));
|
477
|
+
reflex.controller.element.dispatchEvent(new CustomEvent(action, options));
|
478
|
+
if (window.jQuery) {
|
479
|
+
window.jQuery(reflex.controller.element).trigger(event, detail);
|
480
|
+
window.jQuery(reflex.controller.element).trigger(action, detail);
|
481
|
+
}
|
482
|
+
};
|
483
|
+
document.addEventListener("stimulus-reflex:before", (event => invokeLifecycleMethod(reflexes[event.detail.id], "before")), true);
|
484
|
+
document.addEventListener("stimulus-reflex:queued", (event => invokeLifecycleMethod(reflexes[event.detail.id], "queued")), true);
|
485
|
+
document.addEventListener("stimulus-reflex:delivered", (event => invokeLifecycleMethod(reflexes[event.detail.id], "delivered")), true);
|
486
|
+
document.addEventListener("stimulus-reflex:success", (event => {
|
487
|
+
const reflex = reflexes[event.detail.id];
|
488
|
+
invokeLifecycleMethod(reflex, "success");
|
489
|
+
dispatchLifecycleEvent(reflex, "after");
|
490
|
+
}), true);
|
491
|
+
document.addEventListener("stimulus-reflex:nothing", (event => dispatchLifecycleEvent(reflexes[event.detail.id], "success")), true);
|
492
|
+
document.addEventListener("stimulus-reflex:error", (event => {
|
493
|
+
const reflex = reflexes[event.detail.id];
|
494
|
+
invokeLifecycleMethod(reflex, "error");
|
495
|
+
dispatchLifecycleEvent(reflex, "after");
|
496
|
+
}), true);
|
497
|
+
document.addEventListener("stimulus-reflex:halted", (event => invokeLifecycleMethod(reflexes[event.detail.id], "halted")), true);
|
498
|
+
document.addEventListener("stimulus-reflex:forbidden", (event => invokeLifecycleMethod(reflexes[event.detail.id], "forbidden")), true);
|
499
|
+
document.addEventListener("stimulus-reflex:after", (event => invokeLifecycleMethod(reflexes[event.detail.id], "after")), true);
|
500
|
+
document.addEventListener("stimulus-reflex:finalize", (event => invokeLifecycleMethod(reflexes[event.detail.id], "finalize")), true);
|
501
|
+
let app = {};
|
502
|
+
var App = {
|
503
|
+
get app() {
|
504
|
+
return app;
|
505
|
+
},
|
506
|
+
set(application) {
|
507
|
+
app = application;
|
508
|
+
}
|
509
|
+
};
|
510
|
+
let isolationMode = false;
|
511
|
+
var IsolationMode = {
|
512
|
+
get disabled() {
|
513
|
+
return !isolationMode;
|
514
|
+
},
|
515
|
+
set(value) {
|
516
|
+
isolationMode = value;
|
517
|
+
if (Deprecate.enabled && !isolationMode) {
|
518
|
+
document.addEventListener("DOMContentLoaded", (() => console.warn("Deprecation warning: the next version of StimulusReflex will standardize isolation mode, and the isolate option will be removed.\nPlease update your applications to assume that every tab will be isolated. Use CableReady operations to broadcast updates to other tabs and users.")), {
|
519
|
+
once: true
|
520
|
+
});
|
521
|
+
}
|
522
|
+
}
|
523
|
+
};
|
524
|
+
class Reflex {
|
525
|
+
constructor(data, controller) {
|
526
|
+
this.data = data.valueOf();
|
527
|
+
this.controller = controller;
|
528
|
+
this.element = data.reflexElement;
|
529
|
+
this.id = data.id;
|
530
|
+
this.error = null;
|
531
|
+
this.payload = null;
|
532
|
+
this.stage = "created";
|
533
|
+
this.lifecycle = [ "created" ];
|
534
|
+
this.warned = false;
|
535
|
+
this.target = data.target;
|
536
|
+
this.action = data.target.split("#")[1];
|
537
|
+
this.selector = null;
|
538
|
+
this.morph = null;
|
539
|
+
this.operation = null;
|
540
|
+
this.timestamp = new Date;
|
541
|
+
this.cloned = false;
|
542
|
+
}
|
543
|
+
get getPromise() {
|
544
|
+
const promise = new Promise(((resolve, reject) => {
|
545
|
+
this.promise = {
|
546
|
+
resolve: resolve,
|
547
|
+
reject: reject,
|
548
|
+
data: this.data
|
549
|
+
};
|
550
|
+
}));
|
551
|
+
promise.id = this.id;
|
552
|
+
Object.defineProperty(promise, "reflexId", {
|
553
|
+
get() {
|
554
|
+
if (Deprecate.enabled) console.warn("reflexId is deprecated and will be removed from v4. Use id instead.");
|
555
|
+
return this.id;
|
556
|
+
}
|
557
|
+
});
|
558
|
+
promise.reflex = this;
|
559
|
+
if (Debug$1.enabled) promise.catch((() => {}));
|
560
|
+
return promise;
|
561
|
+
}
|
562
|
+
}
|
563
|
+
const received = data => {
|
564
|
+
if (!data.cableReady) return;
|
565
|
+
if (data.version.replace(".pre", "-pre") !== CableReady.version) {
|
566
|
+
if (Debug$1.enabled) console.error(`Reflex failed due to cable_ready 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\ncable_ready gem: ${data.version}\ncable_ready NPM: ${CableReady.version}`);
|
567
|
+
return;
|
568
|
+
}
|
569
|
+
let reflexOperations = [];
|
570
|
+
for (let i = data.operations.length - 1; i >= 0; i--) {
|
571
|
+
if (data.operations[i].stimulusReflex) {
|
572
|
+
reflexOperations.push(data.operations[i]);
|
573
|
+
data.operations.splice(i, 1);
|
574
|
+
}
|
575
|
+
}
|
576
|
+
if (reflexOperations.some((operation => operation.stimulusReflex.url !== location.href))) {
|
577
|
+
if (Debug$1.enabled) {
|
578
|
+
console.error("Reflex failed due to mismatched URL.");
|
579
|
+
return;
|
580
|
+
}
|
581
|
+
}
|
582
|
+
let reflexData;
|
583
|
+
if (reflexOperations.length) {
|
584
|
+
reflexData = reflexOperations[0].stimulusReflex;
|
585
|
+
reflexData.payload = reflexOperations[0].payload;
|
586
|
+
}
|
587
|
+
if (reflexData) {
|
588
|
+
const {id: id, payload: payload} = reflexData;
|
589
|
+
let reflex;
|
590
|
+
if (!reflexes[id] && IsolationMode.disabled) {
|
591
|
+
const controllerElement = XPathToElement(reflexData.xpathController);
|
592
|
+
const reflexElement = XPathToElement(reflexData.xpathElement);
|
593
|
+
controllerElement.reflexController = controllerElement.reflexController || {};
|
594
|
+
controllerElement.reflexData = controllerElement.reflexData || {};
|
595
|
+
controllerElement.reflexError = controllerElement.reflexError || {};
|
596
|
+
const controller = App.app.getControllerForElementAndIdentifier(controllerElement, reflexData.reflexController);
|
597
|
+
controllerElement.reflexController[id] = controller;
|
598
|
+
controllerElement.reflexData[id] = reflexData;
|
599
|
+
reflex = new Reflex(reflexData, controller);
|
600
|
+
reflexes[id] = reflex;
|
601
|
+
reflex.cloned = true;
|
602
|
+
reflex.element = reflexElement;
|
603
|
+
controller.lastReflex = reflex;
|
604
|
+
dispatchLifecycleEvent(reflex, "before");
|
605
|
+
reflex.getPromise;
|
606
|
+
} else {
|
607
|
+
reflex = reflexes[id];
|
608
|
+
}
|
609
|
+
if (reflex) {
|
610
|
+
reflex.payload = payload;
|
611
|
+
reflex.totalOperations = reflexOperations.length;
|
612
|
+
reflex.pendingOperations = reflexOperations.length;
|
613
|
+
reflex.completedOperations = 0;
|
614
|
+
reflex.piggybackOperations = data.operations;
|
615
|
+
CableReady.perform(reflexOperations);
|
616
|
+
}
|
617
|
+
} else {
|
618
|
+
if (data.operations.length && reflexes[data.operations[0].reflexId]) {
|
619
|
+
CableReady.perform(data.operations);
|
620
|
+
}
|
621
|
+
}
|
622
|
+
};
|
623
|
+
let consumer;
|
624
|
+
let params;
|
625
|
+
let subscription;
|
626
|
+
let active;
|
627
|
+
const initialize$1 = (consumerValue, paramsValue) => {
|
628
|
+
consumer = consumerValue;
|
629
|
+
params = paramsValue;
|
630
|
+
document.addEventListener("DOMContentLoaded", (() => {
|
631
|
+
active = false;
|
632
|
+
connectionStatusClass();
|
633
|
+
if (Deprecate.enabled && consumerValue) console.warn("Deprecation warning: the next version of StimulusReflex will obtain a reference to consumer via the Stimulus application object.\nPlease add 'application.consumer = consumer' to your index.js after your Stimulus application has been established, and remove the consumer key from your StimulusReflex initialize() options object.");
|
634
|
+
}));
|
635
|
+
document.addEventListener("turbolinks:load", connectionStatusClass);
|
636
|
+
document.addEventListener("turbo:load", connectionStatusClass);
|
637
|
+
};
|
638
|
+
const subscribe = controller => {
|
639
|
+
if (subscription) return;
|
640
|
+
consumer = consumer || controller.application.consumer || actioncable.createConsumer();
|
641
|
+
const {channel: channel} = controller.StimulusReflex;
|
642
|
+
const request = {
|
643
|
+
channel: channel,
|
644
|
+
...params
|
645
|
+
};
|
646
|
+
const identifier = JSON.stringify(request);
|
647
|
+
subscription = consumer.subscriptions.findAll(identifier)[0] || consumer.subscriptions.create(request, {
|
648
|
+
received: received,
|
649
|
+
connected: connected,
|
650
|
+
rejected: rejected,
|
651
|
+
disconnected: disconnected
|
652
|
+
});
|
653
|
+
};
|
654
|
+
const connected = () => {
|
655
|
+
active = true;
|
656
|
+
connectionStatusClass();
|
657
|
+
emitEvent("stimulus-reflex:connected");
|
658
|
+
Object.values(reflexes.queued).forEach((reflex => {
|
659
|
+
subscription.send(reflex.data);
|
660
|
+
dispatchLifecycleEvent(reflex, "delivered");
|
661
|
+
}));
|
662
|
+
};
|
663
|
+
const rejected = () => {
|
664
|
+
active = false;
|
665
|
+
connectionStatusClass();
|
666
|
+
emitEvent("stimulus-reflex:rejected");
|
667
|
+
if (Debug.enabled) console.warn("Channel subscription was rejected.");
|
668
|
+
};
|
669
|
+
const disconnected = willAttemptReconnect => {
|
670
|
+
active = false;
|
671
|
+
connectionStatusClass();
|
672
|
+
emitEvent("stimulus-reflex:disconnected", willAttemptReconnect);
|
673
|
+
};
|
674
|
+
const deliver = reflex => {
|
675
|
+
if (active) {
|
676
|
+
subscription.send(reflex.data);
|
677
|
+
dispatchLifecycleEvent(reflex, "delivered");
|
678
|
+
} else dispatchLifecycleEvent(reflex, "queued");
|
679
|
+
};
|
680
|
+
const connectionStatusClass = () => {
|
681
|
+
const list = document.body.classList;
|
682
|
+
if (!(list.contains("stimulus-reflex-connected") || list.contains("stimulus-reflex-disconnected"))) {
|
683
|
+
list.add(active ? "stimulus-reflex-connected" : "stimulus-reflex-disconnected");
|
684
|
+
return;
|
685
|
+
}
|
686
|
+
if (active) {
|
687
|
+
list.replace("stimulus-reflex-disconnected", "stimulus-reflex-connected");
|
688
|
+
} else {
|
689
|
+
list.replace("stimulus-reflex-connected", "stimulus-reflex-disconnected");
|
190
690
|
}
|
191
|
-
|
691
|
+
};
|
692
|
+
var ActionCableTransport = {
|
693
|
+
subscribe: subscribe,
|
694
|
+
deliver: deliver,
|
695
|
+
initialize: initialize$1
|
696
|
+
};
|
697
|
+
const request = reflex => {
|
698
|
+
if (Debug$1.disabled || reflex.data.suppressLogging) return;
|
699
|
+
console.log(`↑ stimulus ↑ ${reflex.target}`, {
|
700
|
+
id: reflex.id,
|
701
|
+
args: reflex.data.args,
|
702
|
+
controller: reflex.controller.identifier,
|
703
|
+
element: reflex.element,
|
704
|
+
controllerElement: reflex.controller.element
|
705
|
+
});
|
706
|
+
};
|
707
|
+
const success = reflex => {
|
708
|
+
if (Debug$1.disabled || reflex.data.suppressLogging) return;
|
709
|
+
const output = {
|
710
|
+
id: reflex.id,
|
711
|
+
morph: reflex.morph,
|
712
|
+
payload: reflex.payload
|
713
|
+
};
|
714
|
+
if (reflex.operation !== "dispatch_event") output.operation = reflex.operation;
|
715
|
+
console.log(`↓ reflex ↓ ${reflex.target} → ${reflex.selector || "∞"}${progress(reflex)} ${duration(reflex)}`, output);
|
716
|
+
};
|
717
|
+
const halted$1 = reflex => {
|
718
|
+
if (Debug$1.disabled || reflex.data.suppressLogging) return;
|
719
|
+
console.log(`↓ reflex ↓ ${reflex.target} ${duration(reflex)} %cHALTED`, "color: #ffa500;", {
|
720
|
+
id: reflex.id,
|
721
|
+
payload: reflex.payload
|
722
|
+
});
|
723
|
+
};
|
724
|
+
const forbidden$1 = reflex => {
|
725
|
+
if (Debug$1.disabled || reflex.data.suppressLogging) return;
|
726
|
+
console.log(`↓ reflex ↓ ${reflex.target} ${duration(reflex)} %cFORBIDDEN`, "color: #BF40BF;", {
|
727
|
+
id: reflex.id,
|
728
|
+
payload: reflex.payload
|
729
|
+
});
|
730
|
+
};
|
731
|
+
const error$1 = reflex => {
|
732
|
+
if (Debug$1.disabled || reflex.data.suppressLogging) return;
|
733
|
+
console.log(`↓ reflex ↓ ${reflex.target} ${duration(reflex)} %cERROR: ${reflex.error}`, "color: #f00;", {
|
734
|
+
id: reflex.id,
|
735
|
+
payload: reflex.payload
|
736
|
+
});
|
737
|
+
};
|
738
|
+
const duration = reflex => !reflex.cloned ? `in ${new Date - reflex.timestamp}ms` : "CLONED";
|
739
|
+
const progress = reflex => reflex.totalOperations > 1 ? ` ${reflex.completedOperations}/${reflex.totalOperations}` : "";
|
740
|
+
var Log = {
|
741
|
+
request: request,
|
742
|
+
success: success,
|
743
|
+
halted: halted$1,
|
744
|
+
forbidden: forbidden$1,
|
745
|
+
error: error$1
|
192
746
|
};
|
193
747
|
const multipleInstances = element => {
|
194
748
|
if ([ "checkbox", "radio" ].includes(element.type)) {
|
@@ -198,8 +752,8 @@
|
|
198
752
|
};
|
199
753
|
const collectCheckedOptions = element => Array.from(element.querySelectorAll("option:checked")).concat(Array.from(document.querySelectorAll(`input[type="${element.type}"][name="${element.name}"]`)).filter((elem => elem.checked))).map((o => o.value));
|
200
754
|
const attributeValue = (values = []) => {
|
201
|
-
const value = values.filter((v => v && String(v).length)).map((v => v.trim())).join(" ").trim();
|
202
|
-
return value.length ? value : null;
|
755
|
+
const value = Array.from(new Set(values.filter((v => v && String(v).length)).map((v => v.trim())))).join(" ").trim();
|
756
|
+
return value.length > 0 ? value : null;
|
203
757
|
};
|
204
758
|
const attributeValues = value => {
|
205
759
|
if (!value) return [];
|
@@ -307,217 +861,78 @@
|
|
307
861
|
}
|
308
862
|
return attrs;
|
309
863
|
};
|
310
|
-
|
311
|
-
var
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
864
|
+
var name = "stimulus_reflex";
|
865
|
+
var version = "3.5.0-rc1";
|
866
|
+
var description = "Build reactive applications with the Rails tooling you already know and love.";
|
867
|
+
var keywords = [ "ruby", "rails", "websockets", "actioncable", "turbolinks", "reactive", "cable", "ujs", "ssr", "stimulus", "reflex", "stimulus_reflex", "dom", "morphdom" ];
|
868
|
+
var homepage = "https://docs.stimulusreflex.com";
|
869
|
+
var bugs = "https://github.com/stimulusreflex/stimulus_reflex/issues";
|
870
|
+
var repository = "https://github.com/stimulusreflex/stimulus_reflex";
|
871
|
+
var license = "MIT";
|
872
|
+
var author = "Nathan Hopkins <natehop@gmail.com>";
|
873
|
+
var contributors = [ "Andrew Mason <andrewmcodes@protonmail.com>", "Julian Rubisch <julian@julianrubisch.at>", "Marco Roth <marco.roth@intergga.ch>", "Nathan Hopkins <natehop@gmail.com>" ];
|
874
|
+
var main = "./dist/stimulus_reflex.js";
|
875
|
+
var module = "./dist/stimulus_reflex.js";
|
876
|
+
var browser = "./dist/stimulus_reflex.js";
|
877
|
+
var unpkg = "./dist/stimulus_reflex.umd.js";
|
878
|
+
var umd = "./dist/stimulus_reflex.umd.js";
|
879
|
+
var files = [ "dist/*", "javascript/*" ];
|
880
|
+
var scripts = {
|
881
|
+
lint: "yarn run format --check",
|
882
|
+
format: "yarn run prettier-standard ./javascript/**/*.js rollup.config.mjs",
|
883
|
+
build: "yarn rollup -c",
|
884
|
+
"build:watch": "yarn rollup -wc",
|
885
|
+
watch: "yarn build:watch",
|
886
|
+
test: "web-test-runner javascript/test/**/*.test.js",
|
887
|
+
"test:watch": "yarn test --watch",
|
888
|
+
"docs:dev": "vitepress dev docs",
|
889
|
+
"docs:build": "vitepress build docs && cp docs/_redirects docs/.vitepress/dist",
|
890
|
+
"docs:preview": "vitepress preview docs"
|
318
891
|
};
|
319
|
-
|
320
|
-
|
321
|
-
const controller = controllerElement.reflexController[reflexId];
|
322
|
-
const reflex = controllerElement.reflexData[reflexId].target;
|
323
|
-
const reflexMethodName = reflex.split("#")[1];
|
324
|
-
const specificLifecycleMethodName = [ "before", "after", "finalize" ].includes(stage) ? `${stage}${camelize(reflexMethodName)}` : `${camelize(reflexMethodName, false)}${camelize(stage)}`;
|
325
|
-
const specificLifecycleMethod = controller[specificLifecycleMethodName];
|
326
|
-
const genericLifecycleMethodName = [ "before", "after", "finalize" ].includes(stage) ? `${stage}Reflex` : `reflex${camelize(stage)}`;
|
327
|
-
const genericLifecycleMethod = controller[genericLifecycleMethodName];
|
328
|
-
if (typeof specificLifecycleMethod === "function") {
|
329
|
-
specificLifecycleMethod.call(controller, reflexElement, reflex, controllerElement.reflexError[reflexId], reflexId, payload);
|
330
|
-
}
|
331
|
-
if (typeof genericLifecycleMethod === "function") {
|
332
|
-
genericLifecycleMethod.call(controller, reflexElement, reflex, controllerElement.reflexError[reflexId], reflexId, payload);
|
333
|
-
}
|
334
|
-
if (reflexes[reflexId] && stage === reflexes[reflexId].finalStage) {
|
335
|
-
Reflect.deleteProperty(controllerElement.reflexController, reflexId);
|
336
|
-
Reflect.deleteProperty(controllerElement.reflexData, reflexId);
|
337
|
-
Reflect.deleteProperty(controllerElement.reflexError, reflexId);
|
338
|
-
}
|
892
|
+
var peerDependencies = {
|
893
|
+
"@hotwired/stimulus": ">= 3.0"
|
339
894
|
};
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
}), true);
|
345
|
-
document.addEventListener("stimulus-reflex:nothing", (event => {
|
346
|
-
dispatchLifecycleEvent("success", event.detail.element, event.detail.controller.element, event.detail.reflexId, event.detail.payload);
|
347
|
-
}), true);
|
348
|
-
document.addEventListener("stimulus-reflex:error", (event => {
|
349
|
-
invokeLifecycleMethod("error", event.detail.element, event.detail.controller.element, event.detail.reflexId, event.detail.payload);
|
350
|
-
dispatchLifecycleEvent("after", event.detail.element, event.detail.controller.element, event.detail.reflexId, event.detail.payload);
|
351
|
-
}), true);
|
352
|
-
document.addEventListener("stimulus-reflex:halted", (event => invokeLifecycleMethod("halted", event.detail.element, event.detail.controller.element, event.detail.reflexId, event.detail.payload)), true);
|
353
|
-
document.addEventListener("stimulus-reflex:after", (event => invokeLifecycleMethod("after", event.detail.element, event.detail.controller.element, event.detail.reflexId, event.detail.payload)), true);
|
354
|
-
document.addEventListener("stimulus-reflex:finalize", (event => invokeLifecycleMethod("finalize", event.detail.element, event.detail.controller.element, event.detail.reflexId, event.detail.payload)), true);
|
355
|
-
const dispatchLifecycleEvent = (stage, reflexElement, controllerElement, reflexId, payload) => {
|
356
|
-
if (!controllerElement) {
|
357
|
-
if (Debug$1.enabled && !reflexes[reflexId].warned) {
|
358
|
-
console.warn(`StimulusReflex was not able execute callbacks or emit events for "${stage}" or later life-cycle stages for this Reflex. The StimulusReflex Controller Element is no longer present in the DOM. Could you move the StimulusReflex Controller to an element higher in your DOM?`);
|
359
|
-
reflexes[reflexId].warned = true;
|
360
|
-
}
|
361
|
-
return;
|
362
|
-
}
|
363
|
-
if (!controllerElement.reflexController || controllerElement.reflexController && !controllerElement.reflexController[reflexId]) {
|
364
|
-
if (Debug$1.enabled && !reflexes[reflexId].warned) {
|
365
|
-
console.warn(`StimulusReflex detected that the StimulusReflex Controller responsible for this Reflex has been replaced with a new instance. Callbacks and events for "${stage}" or later life-cycle stages cannot be executed.`);
|
366
|
-
reflexes[reflexId].warned = true;
|
367
|
-
}
|
368
|
-
return;
|
369
|
-
}
|
370
|
-
const {target: target} = controllerElement.reflexData[reflexId] || {};
|
371
|
-
const controller = controllerElement.reflexController[reflexId] || {};
|
372
|
-
const event = `stimulus-reflex:${stage}`;
|
373
|
-
const action = `${event}:${target.split("#")[1]}`;
|
374
|
-
const detail = {
|
375
|
-
reflex: target,
|
376
|
-
controller: controller,
|
377
|
-
reflexId: reflexId,
|
378
|
-
element: reflexElement,
|
379
|
-
payload: payload
|
380
|
-
};
|
381
|
-
const options = {
|
382
|
-
bubbles: true,
|
383
|
-
cancelable: false,
|
384
|
-
detail: detail
|
385
|
-
};
|
386
|
-
controllerElement.dispatchEvent(new CustomEvent(event, options));
|
387
|
-
controllerElement.dispatchEvent(new CustomEvent(action, options));
|
388
|
-
if (window.jQuery) {
|
389
|
-
window.jQuery(controllerElement).trigger(event, detail);
|
390
|
-
window.jQuery(controllerElement).trigger(action, detail);
|
391
|
-
}
|
895
|
+
var dependencies = {
|
896
|
+
"@hotwired/stimulus": "^3",
|
897
|
+
"@rails/actioncable": "^6 || ^7",
|
898
|
+
cable_ready: "5.0.0-rc1"
|
392
899
|
};
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
900
|
+
var devDependencies = {
|
901
|
+
"@open-wc/testing": "^3.1.7",
|
902
|
+
"@rollup/plugin-json": "^6.0.0",
|
903
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
904
|
+
"@rollup/plugin-terser": "^0.4.0",
|
905
|
+
"@web/dev-server-esbuild": "^0.3.3",
|
906
|
+
"@web/dev-server-rollup": "^0.3.21",
|
907
|
+
"@web/test-runner": "^0.15.1",
|
908
|
+
"prettier-standard": "^16.4.1",
|
909
|
+
rollup: "^3.19.1",
|
910
|
+
"toastify-js": "^1.12.0",
|
911
|
+
vitepress: "^1.0.0-alpha.56"
|
405
912
|
};
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
913
|
+
var packageInfo = {
|
914
|
+
name: name,
|
915
|
+
version: version,
|
916
|
+
description: description,
|
917
|
+
keywords: keywords,
|
918
|
+
homepage: homepage,
|
919
|
+
bugs: bugs,
|
920
|
+
repository: repository,
|
921
|
+
license: license,
|
922
|
+
author: author,
|
923
|
+
contributors: contributors,
|
924
|
+
main: main,
|
925
|
+
module: module,
|
926
|
+
browser: browser,
|
927
|
+
import: "./dist/stimulus_reflex.js",
|
928
|
+
unpkg: unpkg,
|
929
|
+
umd: umd,
|
930
|
+
files: files,
|
931
|
+
scripts: scripts,
|
932
|
+
peerDependencies: peerDependencies,
|
933
|
+
dependencies: dependencies,
|
934
|
+
devDependencies: devDependencies
|
412
935
|
};
|
413
|
-
const received = data => {
|
414
|
-
if (!data.cableReady) return;
|
415
|
-
if (data.version.replace(".pre", "-pre") !== CableReady__default["default"].version) {
|
416
|
-
if (Debug$1.enabled) console.error(`Reflex failed due to cable_ready 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\ncable_ready gem: ${data.version}\ncable_ready NPM: ${CableReady__default["default"].version}`);
|
417
|
-
return;
|
418
|
-
}
|
419
|
-
let reflexOperations = [];
|
420
|
-
for (let i = data.operations.length - 1; i >= 0; i--) {
|
421
|
-
if (data.operations[i].stimulusReflex) {
|
422
|
-
reflexOperations.push(data.operations[i]);
|
423
|
-
data.operations.splice(i, 1);
|
424
|
-
}
|
425
|
-
}
|
426
|
-
if (reflexOperations.some((operation => operation.stimulusReflex.url !== location.href))) {
|
427
|
-
return;
|
428
|
-
}
|
429
|
-
let reflexData;
|
430
|
-
if (reflexOperations.length) {
|
431
|
-
reflexData = reflexOperations[0].stimulusReflex;
|
432
|
-
reflexData.payload = reflexOperations[0].payload;
|
433
|
-
}
|
434
|
-
if (reflexData) {
|
435
|
-
const {reflexId: reflexId, payload: payload} = reflexData;
|
436
|
-
if (!reflexes[reflexId] && IsolationMode.disabled) {
|
437
|
-
const controllerElement = XPathToElement(reflexData.xpathController);
|
438
|
-
const reflexElement = XPathToElement(reflexData.xpathElement);
|
439
|
-
controllerElement.reflexController = controllerElement.reflexController || {};
|
440
|
-
controllerElement.reflexData = controllerElement.reflexData || {};
|
441
|
-
controllerElement.reflexError = controllerElement.reflexError || {};
|
442
|
-
controllerElement.reflexController[reflexId] = reflexes.app.getControllerForElementAndIdentifier(controllerElement, reflexData.reflexController);
|
443
|
-
controllerElement.reflexData[reflexId] = reflexData;
|
444
|
-
dispatchLifecycleEvent("before", reflexElement, controllerElement, reflexId, payload);
|
445
|
-
registerReflex(reflexData);
|
446
|
-
}
|
447
|
-
if (reflexes[reflexId]) {
|
448
|
-
reflexes[reflexId].totalOperations = reflexOperations.length;
|
449
|
-
reflexes[reflexId].pendingOperations = reflexOperations.length;
|
450
|
-
reflexes[reflexId].completedOperations = 0;
|
451
|
-
reflexes[reflexId].piggybackOperations = data.operations;
|
452
|
-
CableReady__default["default"].perform(reflexOperations);
|
453
|
-
}
|
454
|
-
} else {
|
455
|
-
if (data.operations.length && reflexes[data.operations[0].reflexId]) {
|
456
|
-
CableReady__default["default"].perform(data.operations);
|
457
|
-
}
|
458
|
-
}
|
459
|
-
};
|
460
|
-
const registerReflex = data => {
|
461
|
-
const {reflexId: reflexId} = data;
|
462
|
-
reflexes[reflexId] = {
|
463
|
-
finalStage: "finalize"
|
464
|
-
};
|
465
|
-
const promise = new Promise(((resolve, reject) => {
|
466
|
-
reflexes[reflexId].promise = {
|
467
|
-
resolve: resolve,
|
468
|
-
reject: reject,
|
469
|
-
data: data
|
470
|
-
};
|
471
|
-
}));
|
472
|
-
promise.reflexId = reflexId;
|
473
|
-
if (Debug$1.enabled) promise.catch((() => {}));
|
474
|
-
return promise;
|
475
|
-
};
|
476
|
-
const getReflexRoots = element => {
|
477
|
-
let list = [];
|
478
|
-
while (list.length === 0 && element) {
|
479
|
-
let reflexRoot = element.getAttribute(Schema.reflexRoot);
|
480
|
-
if (reflexRoot) {
|
481
|
-
if (reflexRoot.length === 0 && element.id) reflexRoot = `#${element.id}`;
|
482
|
-
const selectors = reflexRoot.split(",").filter((s => s.trim().length));
|
483
|
-
if (Debug$1.enabled && selectors.length === 0) {
|
484
|
-
console.error(`No value found for ${Schema.reflexRoot}. Add an #id to the element or provide a value for ${Schema.reflexRoot}.`, element);
|
485
|
-
}
|
486
|
-
list = list.concat(selectors.filter((s => document.querySelector(s))));
|
487
|
-
}
|
488
|
-
element = element.parentElement ? element.parentElement.closest(`[${Schema.reflexRoot}]`) : null;
|
489
|
-
}
|
490
|
-
return list;
|
491
|
-
};
|
492
|
-
const setupDeclarativeReflexes = debounce((() => {
|
493
|
-
document.querySelectorAll(`[${Schema.reflex}]`).forEach((element => {
|
494
|
-
const controllers = attributeValues(element.getAttribute(Schema.controller));
|
495
|
-
const reflexAttributeNames = attributeValues(element.getAttribute(Schema.reflex));
|
496
|
-
const actions = attributeValues(element.getAttribute(Schema.action));
|
497
|
-
reflexAttributeNames.forEach((reflexName => {
|
498
|
-
const controller = findControllerByReflexName(reflexName, allReflexControllers(reflexes.app, element));
|
499
|
-
let action;
|
500
|
-
if (controller) {
|
501
|
-
action = `${reflexName.split("->")[0]}->${controller.identifier}#__perform`;
|
502
|
-
if (!actions.includes(action)) actions.push(action);
|
503
|
-
} else {
|
504
|
-
action = `${reflexName.split("->")[0]}->stimulus-reflex#__perform`;
|
505
|
-
if (!controllers.includes("stimulus-reflex")) {
|
506
|
-
controllers.push("stimulus-reflex");
|
507
|
-
}
|
508
|
-
if (!actions.includes(action)) actions.push(action);
|
509
|
-
}
|
510
|
-
}));
|
511
|
-
const controllerValue = attributeValue(controllers);
|
512
|
-
const actionValue = attributeValue(actions);
|
513
|
-
if (controllerValue && element.getAttribute(Schema.controller) != controllerValue) {
|
514
|
-
element.setAttribute(Schema.controller, controllerValue);
|
515
|
-
}
|
516
|
-
if (actionValue && element.getAttribute(Schema.action) != actionValue) element.setAttribute(Schema.action, actionValue);
|
517
|
-
}));
|
518
|
-
emitEvent("stimulus-reflex:ready");
|
519
|
-
}), 20);
|
520
|
-
var version = "3.5.0-pre9";
|
521
936
|
class ReflexData {
|
522
937
|
constructor(options, reflexElement, controllerElement, reflexController, permanentAttributeName, target, args, url, tabId) {
|
523
938
|
this.options = options;
|
@@ -534,9 +949,9 @@
|
|
534
949
|
this._attrs = this._attrs || this.options["attrs"] || extractElementAttributes(this.reflexElement);
|
535
950
|
return this._attrs;
|
536
951
|
}
|
537
|
-
get
|
538
|
-
this.
|
539
|
-
return this.
|
952
|
+
get id() {
|
953
|
+
this._id = this._id || this.options["id"] || uuidv4();
|
954
|
+
return this._id;
|
540
955
|
}
|
541
956
|
get selectors() {
|
542
957
|
this._selectors = this._selectors || this.options["selectors"] || getReflexRoots(this.reflexElement);
|
@@ -581,7 +996,7 @@
|
|
581
996
|
attrs: this.attrs,
|
582
997
|
dataset: this.dataset,
|
583
998
|
selectors: this.selectors,
|
584
|
-
|
999
|
+
id: this.id,
|
585
1000
|
resolveLate: this.resolveLate,
|
586
1001
|
suppressLogging: this.suppressLogging,
|
587
1002
|
xpathController: this.xpathController,
|
@@ -595,198 +1010,207 @@
|
|
595
1010
|
args: this.args,
|
596
1011
|
url: this.url,
|
597
1012
|
tabId: this.tabId,
|
598
|
-
version: version
|
1013
|
+
version: packageInfo.version
|
599
1014
|
};
|
600
1015
|
}
|
601
1016
|
}
|
602
|
-
let
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
consumer = consumer || controller.application.consumer || actioncable.createConsumer();
|
607
|
-
const {channel: channel} = controller.StimulusReflex;
|
608
|
-
const subscription = {
|
609
|
-
channel: channel,
|
610
|
-
...params
|
611
|
-
};
|
612
|
-
const identifier = JSON.stringify(subscription);
|
613
|
-
controller.StimulusReflex.subscription = consumer.subscriptions.findAll(identifier)[0] || consumer.subscriptions.create(subscription, {
|
614
|
-
received: received,
|
615
|
-
connected: connected,
|
616
|
-
rejected: rejected,
|
617
|
-
disconnected: disconnected
|
618
|
-
});
|
619
|
-
};
|
620
|
-
const connected = () => {
|
621
|
-
subscriptionActive = true;
|
622
|
-
document.body.classList.replace("stimulus-reflex-disconnected", "stimulus-reflex-connected");
|
623
|
-
emitEvent("stimulus-reflex:connected");
|
624
|
-
emitEvent("stimulus-reflex:action-cable:connected");
|
625
|
-
};
|
626
|
-
const rejected = () => {
|
627
|
-
subscriptionActive = false;
|
628
|
-
document.body.classList.replace("stimulus-reflex-connected", "stimulus-reflex-disconnected");
|
629
|
-
emitEvent("stimulus-reflex:rejected");
|
630
|
-
emitEvent("stimulus-reflex:action-cable:rejected");
|
631
|
-
if (Debug.enabled) console.warn("Channel subscription was rejected.");
|
632
|
-
};
|
633
|
-
const disconnected = willAttemptReconnect => {
|
634
|
-
subscriptionActive = false;
|
635
|
-
document.body.classList.replace("stimulus-reflex-connected", "stimulus-reflex-disconnected");
|
636
|
-
emitEvent("stimulus-reflex:disconnected", willAttemptReconnect);
|
637
|
-
emitEvent("stimulus-reflex:action-cable:disconnected", willAttemptReconnect);
|
638
|
-
};
|
639
|
-
var ActionCableTransport = {
|
640
|
-
consumer: consumer,
|
641
|
-
params: params,
|
642
|
-
get subscriptionActive() {
|
643
|
-
return subscriptionActive;
|
1017
|
+
let transport = {};
|
1018
|
+
var Transport = {
|
1019
|
+
get plugin() {
|
1020
|
+
return transport;
|
644
1021
|
},
|
645
|
-
|
646
|
-
|
647
|
-
rejected: rejected,
|
648
|
-
disconnected: disconnected,
|
649
|
-
set(consumerValue, paramsValue) {
|
650
|
-
consumer = consumerValue;
|
651
|
-
params = paramsValue;
|
1022
|
+
set(newTransport) {
|
1023
|
+
transport = newTransport;
|
652
1024
|
}
|
653
1025
|
};
|
654
1026
|
const beforeDOMUpdate = event => {
|
655
|
-
const {stimulusReflex: stimulusReflex
|
1027
|
+
const {stimulusReflex: stimulusReflex} = event.detail || {};
|
656
1028
|
if (!stimulusReflex) return;
|
657
|
-
const
|
658
|
-
const controllerElement = XPathToElement(xpathController);
|
659
|
-
const reflexElement = XPathToElement(xpathElement);
|
660
|
-
const reflex = reflexes[reflexId];
|
661
|
-
const {promise: promise} = reflex;
|
1029
|
+
const reflex = reflexes[stimulusReflex.id];
|
662
1030
|
reflex.pendingOperations--;
|
663
1031
|
if (reflex.pendingOperations > 0) return;
|
664
|
-
if (!stimulusReflex.resolveLate) setTimeout((() => promise.resolve({
|
665
|
-
element:
|
1032
|
+
if (!stimulusReflex.resolveLate) setTimeout((() => reflex.promise.resolve({
|
1033
|
+
element: reflex.element,
|
666
1034
|
event: event,
|
667
|
-
data:
|
668
|
-
payload: payload,
|
669
|
-
|
1035
|
+
data: reflex.data,
|
1036
|
+
payload: reflex.payload,
|
1037
|
+
id: reflex.id,
|
670
1038
|
toString: () => ""
|
671
1039
|
})));
|
672
|
-
setTimeout((() => dispatchLifecycleEvent("success"
|
1040
|
+
setTimeout((() => dispatchLifecycleEvent(reflex, "success")));
|
673
1041
|
};
|
674
1042
|
const afterDOMUpdate = event => {
|
675
|
-
const {stimulusReflex: stimulusReflex
|
1043
|
+
const {stimulusReflex: stimulusReflex} = event.detail || {};
|
676
1044
|
if (!stimulusReflex) return;
|
677
|
-
const
|
678
|
-
const controllerElement = XPathToElement(xpathController);
|
679
|
-
const reflexElement = XPathToElement(xpathElement);
|
680
|
-
const reflex = reflexes[reflexId];
|
681
|
-
const {promise: promise} = reflex;
|
1045
|
+
const reflex = reflexes[stimulusReflex.id];
|
682
1046
|
reflex.completedOperations++;
|
683
|
-
|
1047
|
+
reflex.selector = event.detail.selector;
|
1048
|
+
reflex.morph = event.detail.stimulusReflex.morph;
|
1049
|
+
reflex.operation = event.type.split(":")[1].split("-").slice(1).join("_");
|
1050
|
+
Log.success(reflex);
|
684
1051
|
if (reflex.completedOperations < reflex.totalOperations) return;
|
685
|
-
if (stimulusReflex.resolveLate) setTimeout((() => promise.resolve({
|
686
|
-
element:
|
1052
|
+
if (stimulusReflex.resolveLate) setTimeout((() => reflex.promise.resolve({
|
1053
|
+
element: reflex.element,
|
687
1054
|
event: event,
|
688
|
-
data:
|
689
|
-
payload: payload,
|
690
|
-
|
1055
|
+
data: reflex.data,
|
1056
|
+
payload: reflex.payload,
|
1057
|
+
id: reflex.id,
|
691
1058
|
toString: () => ""
|
692
1059
|
})));
|
693
|
-
setTimeout((() => dispatchLifecycleEvent("finalize"
|
694
|
-
if (reflex.piggybackOperations.length)
|
1060
|
+
setTimeout((() => dispatchLifecycleEvent(reflex, "finalize")));
|
1061
|
+
if (reflex.piggybackOperations.length) CableReady.perform(reflex.piggybackOperations);
|
695
1062
|
};
|
696
1063
|
const routeReflexEvent = event => {
|
697
|
-
const {stimulusReflex: stimulusReflex,
|
1064
|
+
const {stimulusReflex: stimulusReflex, name: name} = event.detail || {};
|
698
1065
|
const eventType = name.split("-")[2];
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
if (
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
1066
|
+
const eventTypes = {
|
1067
|
+
nothing: nothing,
|
1068
|
+
halted: halted,
|
1069
|
+
forbidden: forbidden,
|
1070
|
+
error: error
|
1071
|
+
};
|
1072
|
+
if (!stimulusReflex || !Object.keys(eventTypes).includes(eventType)) return;
|
1073
|
+
const reflex = reflexes[stimulusReflex.id];
|
1074
|
+
reflex.completedOperations++;
|
1075
|
+
reflex.pendingOperations--;
|
1076
|
+
reflex.selector = event.detail.selector;
|
1077
|
+
reflex.morph = event.detail.stimulusReflex.morph;
|
1078
|
+
reflex.operation = event.type.split(":")[1].split("-").slice(1).join("_");
|
1079
|
+
if (eventType === "error") reflex.error = event.detail.error;
|
1080
|
+
eventTypes[eventType](reflex, event);
|
1081
|
+
setTimeout((() => dispatchLifecycleEvent(reflex, eventType)));
|
1082
|
+
if (reflex.piggybackOperations.length) CableReady.perform(reflex.piggybackOperations);
|
1083
|
+
};
|
1084
|
+
const nothing = (reflex, event) => {
|
1085
|
+
Log.success(reflex);
|
1086
|
+
setTimeout((() => reflex.promise.resolve({
|
1087
|
+
data: reflex.data,
|
1088
|
+
element: reflex.element,
|
1089
|
+
event: event,
|
1090
|
+
payload: reflex.payload,
|
1091
|
+
id: reflex.id,
|
1092
|
+
toString: () => ""
|
1093
|
+
})));
|
1094
|
+
};
|
1095
|
+
const halted = (reflex, event) => {
|
1096
|
+
Log.halted(reflex, event);
|
1097
|
+
setTimeout((() => reflex.promise.resolve({
|
1098
|
+
data: reflex.data,
|
1099
|
+
element: reflex.element,
|
731
1100
|
event: event,
|
732
|
-
payload: payload,
|
733
|
-
|
1101
|
+
payload: reflex.payload,
|
1102
|
+
id: reflex.id,
|
734
1103
|
toString: () => ""
|
735
1104
|
})));
|
736
1105
|
};
|
737
|
-
const
|
738
|
-
reflex
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
element: reflexElement,
|
1106
|
+
const forbidden = (reflex, event) => {
|
1107
|
+
Log.forbidden(reflex, event);
|
1108
|
+
setTimeout((() => reflex.promise.resolve({
|
1109
|
+
data: reflex.data,
|
1110
|
+
element: reflex.element,
|
743
1111
|
event: event,
|
744
|
-
payload: payload,
|
745
|
-
|
1112
|
+
payload: reflex.payload,
|
1113
|
+
id: reflex.id,
|
746
1114
|
toString: () => ""
|
747
1115
|
})));
|
748
1116
|
};
|
749
|
-
const error = (
|
750
|
-
reflex
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
element: reflexElement,
|
1117
|
+
const error = (reflex, event) => {
|
1118
|
+
Log.error(reflex, event);
|
1119
|
+
setTimeout((() => reflex.promise.reject({
|
1120
|
+
data: reflex.data,
|
1121
|
+
element: reflex.element,
|
755
1122
|
event: event,
|
756
|
-
payload: payload,
|
757
|
-
|
758
|
-
error:
|
759
|
-
toString: () =>
|
1123
|
+
payload: reflex.payload,
|
1124
|
+
id: reflex.id,
|
1125
|
+
error: reflex.error,
|
1126
|
+
toString: () => reflex.error
|
760
1127
|
})));
|
761
1128
|
};
|
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
|
+
};
|
1134
|
+
const allReflexControllers = element => {
|
1135
|
+
let controllers = [];
|
1136
|
+
while (element) {
|
1137
|
+
controllers = controllers.concat(localReflexControllers(element));
|
1138
|
+
element = element.parentElement;
|
1139
|
+
}
|
1140
|
+
return controllers;
|
1141
|
+
};
|
1142
|
+
const findControllerByReflexName = (reflexName, controllers) => {
|
1143
|
+
const controller = controllers.find((controller => {
|
1144
|
+
if (!controller || !controller.identifier) return;
|
1145
|
+
const identifier = reflexNameToControllerIdentifier(extractReflexName(reflexName));
|
1146
|
+
return identifier === controller.identifier;
|
1147
|
+
}));
|
1148
|
+
return controller || controllers[0];
|
1149
|
+
};
|
1150
|
+
const scanForReflexes = debounce((() => {
|
1151
|
+
const reflexElements = document.querySelectorAll(`[${Schema.reflex}]`);
|
1152
|
+
reflexElements.forEach((element => scanForReflexesOnElement(element)));
|
1153
|
+
}), 20);
|
1154
|
+
const scanForReflexesOnElement = (element, controller = null) => {
|
1155
|
+
const controllerAttribute = element.getAttribute(Schema.controller);
|
1156
|
+
const controllers = attributeValues(controllerAttribute).filter((controller => controller !== "stimulus-reflex"));
|
1157
|
+
const reflexAttribute = element.getAttribute(Schema.reflex);
|
1158
|
+
const reflexAttributeNames = attributeValues(reflexAttribute);
|
1159
|
+
const actionAttribute = element.getAttribute(Schema.action);
|
1160
|
+
const actions = attributeValues(actionAttribute).filter((action => !action.includes("#__perform")));
|
1161
|
+
reflexAttributeNames.forEach((reflexName => {
|
1162
|
+
const potentialControllers = [ controller ].concat(allReflexControllers(element));
|
1163
|
+
controller = findControllerByReflexName(reflexName, potentialControllers);
|
1164
|
+
const controllerName = controller ? controller.identifier : "stimulus-reflex";
|
1165
|
+
actions.push(`${reflexName.split("->")[0]}->${controllerName}#__perform`);
|
1166
|
+
const parentControllerElement = element.closest(`[data-controller~=${controllerName}]`);
|
1167
|
+
if (!parentControllerElement) {
|
1168
|
+
controllers.push(controllerName);
|
1169
|
+
}
|
1170
|
+
}));
|
1171
|
+
const controllerValue = attributeValue(controllers);
|
1172
|
+
const actionValue = attributeValue(actions);
|
1173
|
+
let emitReadyEvent = false;
|
1174
|
+
if (controllerValue && element.getAttribute(Schema.controller) != controllerValue) {
|
1175
|
+
element.setAttribute(Schema.controller, controllerValue);
|
1176
|
+
emitReadyEvent = true;
|
1177
|
+
}
|
1178
|
+
if (actionValue && element.getAttribute(Schema.action) != actionValue) {
|
1179
|
+
element.setAttribute(Schema.action, actionValue);
|
1180
|
+
emitReadyEvent = true;
|
1181
|
+
}
|
1182
|
+
if (emitReadyEvent) {
|
1183
|
+
dispatch(element, "stimulus-reflex:ready", {
|
1184
|
+
reflex: reflexAttribute,
|
1185
|
+
controller: controllerValue,
|
1186
|
+
action: actionValue,
|
1187
|
+
element: element
|
1188
|
+
});
|
1189
|
+
}
|
1190
|
+
};
|
762
1191
|
class StimulusReflexController extends stimulus.Controller {
|
763
1192
|
constructor(...args) {
|
764
1193
|
super(...args);
|
765
1194
|
register(this);
|
766
1195
|
}
|
767
1196
|
}
|
768
|
-
const
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
document.body.classList.add("stimulus-reflex-disconnected");
|
773
|
-
if (Deprecate.enabled && consumer) console.warn("Deprecation warning: the next version of StimulusReflex will obtain a reference to consumer via the Stimulus application object.\nPlease add 'application.consumer = consumer' to your index.js after your Stimulus application has been established, and remove the consumer key from your StimulusReflex initialize() options object.");
|
774
|
-
if (Deprecate.enabled && IsolationMode.disabled) console.warn("Deprecation warning: the next version of StimulusReflex will standardize isolation mode, and the isolate option will be removed.\nPlease update your applications to assume that every tab will be isolated.");
|
775
|
-
}), {
|
776
|
-
once: true
|
777
|
-
});
|
1197
|
+
const tabId = uuidv4();
|
1198
|
+
const initialize = (application, {controller: controller, consumer: consumer, debug: debug, params: params, isolate: isolate, deprecate: deprecate, transport: transport} = {}) => {
|
1199
|
+
Transport.set(transport || ActionCableTransport);
|
1200
|
+
Transport.plugin.initialize(consumer, params);
|
778
1201
|
IsolationMode.set(!!isolate);
|
779
|
-
|
1202
|
+
App.set(application);
|
780
1203
|
Schema.set(application);
|
781
|
-
|
1204
|
+
App.app.register("stimulus-reflex", controller || StimulusReflexController);
|
782
1205
|
Debug$1.set(!!debug);
|
783
1206
|
if (typeof deprecate !== "undefined") Deprecate.set(deprecate);
|
784
|
-
const observer = new MutationObserver(
|
1207
|
+
const observer = new MutationObserver(scanForReflexes);
|
785
1208
|
observer.observe(document.documentElement, {
|
786
1209
|
attributeFilter: [ Schema.reflex, Schema.action ],
|
787
1210
|
childList: true,
|
788
1211
|
subtree: true
|
789
1212
|
});
|
1213
|
+
emitEvent("stimulus-reflex:initialized");
|
790
1214
|
};
|
791
1215
|
const register = (controller, options = {}) => {
|
792
1216
|
const channel = "StimulusReflex::Channel";
|
@@ -794,38 +1218,32 @@
|
|
794
1218
|
...options,
|
795
1219
|
channel: channel
|
796
1220
|
};
|
797
|
-
|
1221
|
+
Transport.plugin.subscribe(controller);
|
798
1222
|
Object.assign(controller, {
|
799
|
-
isActionCableConnectionOpen() {
|
800
|
-
return this.StimulusReflex.subscription.consumer.connection.isOpen();
|
801
|
-
},
|
802
1223
|
stimulate() {
|
803
1224
|
const url = location.href;
|
1225
|
+
const controllerElement = this.element;
|
804
1226
|
const args = Array.from(arguments);
|
805
1227
|
const target = args.shift() || "StimulusReflex::Reflex#default_reflex";
|
806
|
-
const
|
807
|
-
|
808
|
-
if (reflexElement.type === "number" && reflexElement.validity && reflexElement.validity.badInput) {
|
1228
|
+
const reflexElement = getReflexElement(args, controllerElement);
|
1229
|
+
if (elementInvalid(reflexElement)) {
|
809
1230
|
if (Debug$1.enabled) console.warn("Reflex aborted: invalid numeric input");
|
810
1231
|
return;
|
811
1232
|
}
|
812
|
-
const options =
|
813
|
-
if (args[0] && typeof args[0] === "object" && Object.keys(args[0]).filter((key => [ "attrs", "selectors", "reflexId", "resolveLate", "serializeForm", "suppressLogging", "includeInnerHTML", "includeTextContent" ].includes(key))).length) {
|
814
|
-
const opts = args.shift();
|
815
|
-
Object.keys(opts).forEach((o => options[o] = opts[o]));
|
816
|
-
}
|
1233
|
+
const options = getReflexOptions(args);
|
817
1234
|
const reflexData = new ReflexData(options, reflexElement, controllerElement, this.identifier, Schema.reflexPermanent, target, args, url, tabId);
|
818
|
-
const
|
819
|
-
if (!this.isActionCableConnectionOpen()) throw "The ActionCable connection is not open! `this.isActionCableConnectionOpen()` must return true before calling `this.stimulate()`";
|
820
|
-
if (!ActionCableTransport.subscriptionActive) throw "The ActionCable channel subscription for StimulusReflex was rejected.";
|
1235
|
+
const id = reflexData.id;
|
821
1236
|
controllerElement.reflexController = controllerElement.reflexController || {};
|
822
1237
|
controllerElement.reflexData = controllerElement.reflexData || {};
|
823
1238
|
controllerElement.reflexError = controllerElement.reflexError || {};
|
824
|
-
controllerElement.reflexController[
|
825
|
-
controllerElement.reflexData[
|
826
|
-
|
1239
|
+
controllerElement.reflexController[id] = this;
|
1240
|
+
controllerElement.reflexData[id] = reflexData.valueOf();
|
1241
|
+
const reflex = new Reflex(reflexData, this);
|
1242
|
+
reflexes[id] = reflex;
|
1243
|
+
this.lastReflex = reflex;
|
1244
|
+
dispatchLifecycleEvent(reflex, "before");
|
827
1245
|
setTimeout((() => {
|
828
|
-
const {params: params} = controllerElement.reflexData[
|
1246
|
+
const {params: params} = controllerElement.reflexData[id] || {};
|
829
1247
|
const check = reflexElement.attributes[Schema.reflexSerializeForm];
|
830
1248
|
if (check) {
|
831
1249
|
options["serializeForm"] = check.value !== "false";
|
@@ -835,16 +1253,16 @@
|
|
835
1253
|
const formData = options["serializeForm"] === false ? "" : serializeForm(form, {
|
836
1254
|
element: reflexElement
|
837
1255
|
});
|
838
|
-
|
1256
|
+
reflex.data = {
|
839
1257
|
...reflexData.valueOf(),
|
840
1258
|
params: params,
|
841
1259
|
formData: formData
|
842
1260
|
};
|
843
|
-
|
1261
|
+
controllerElement.reflexData[id] = reflex.data;
|
1262
|
+
Transport.plugin.deliver(reflex);
|
844
1263
|
}));
|
845
|
-
|
846
|
-
|
847
|
-
return promise;
|
1264
|
+
Log.request(reflex);
|
1265
|
+
return reflex.getPromise;
|
848
1266
|
},
|
849
1267
|
__perform(event) {
|
850
1268
|
let element = event.target;
|
@@ -861,8 +1279,23 @@
|
|
861
1279
|
}
|
862
1280
|
}
|
863
1281
|
});
|
1282
|
+
if (!controller.reflexes) Object.defineProperty(controller, "reflexes", {
|
1283
|
+
get() {
|
1284
|
+
return new Proxy(reflexes, {
|
1285
|
+
get: function(target, prop) {
|
1286
|
+
if (prop === "last") return this.lastReflex;
|
1287
|
+
return Object.fromEntries(Object.entries(target[prop]).filter((([_, reflex]) => reflex.controller === this)));
|
1288
|
+
}.bind(this)
|
1289
|
+
});
|
1290
|
+
}
|
1291
|
+
});
|
1292
|
+
scanForReflexesOnElement(controller.element, controller);
|
1293
|
+
emitEvent("stimulus-reflex:controller-registered", {
|
1294
|
+
detail: {
|
1295
|
+
controller: controller
|
1296
|
+
}
|
1297
|
+
});
|
864
1298
|
};
|
865
|
-
const tabId = uuidv4();
|
866
1299
|
const useReflex = (controller, options = {}) => {
|
867
1300
|
register(controller, options);
|
868
1301
|
};
|
@@ -871,14 +1304,22 @@
|
|
871
1304
|
document.addEventListener("cable-ready:before-morph", beforeDOMUpdate);
|
872
1305
|
document.addEventListener("cable-ready:after-inner-html", afterDOMUpdate);
|
873
1306
|
document.addEventListener("cable-ready:after-morph", afterDOMUpdate);
|
874
|
-
|
1307
|
+
document.addEventListener("readystatechange", (() => {
|
1308
|
+
if (document.readyState === "complete") {
|
1309
|
+
scanForReflexes();
|
1310
|
+
}
|
1311
|
+
}));
|
875
1312
|
var StimulusReflex = Object.freeze({
|
876
1313
|
__proto__: null,
|
877
1314
|
initialize: initialize,
|
1315
|
+
reflexes: reflexes,
|
878
1316
|
register: register,
|
1317
|
+
scanForReflexes: scanForReflexes,
|
1318
|
+
scanForReflexesOnElement: scanForReflexesOnElement,
|
879
1319
|
useReflex: useReflex
|
880
1320
|
});
|
881
1321
|
const global = {
|
1322
|
+
version: packageInfo.version,
|
882
1323
|
...StimulusReflex,
|
883
1324
|
get debug() {
|
884
1325
|
return Debug$1.value;
|
@@ -894,9 +1335,12 @@
|
|
894
1335
|
}
|
895
1336
|
};
|
896
1337
|
window.StimulusReflex = global;
|
897
|
-
exports
|
1338
|
+
exports.default = global;
|
898
1339
|
exports.initialize = initialize;
|
1340
|
+
exports.reflexes = reflexes;
|
899
1341
|
exports.register = register;
|
1342
|
+
exports.scanForReflexes = scanForReflexes;
|
1343
|
+
exports.scanForReflexesOnElement = scanForReflexesOnElement;
|
900
1344
|
exports.useReflex = useReflex;
|
901
1345
|
Object.defineProperty(exports, "__esModule", {
|
902
1346
|
value: true
|