spina 2.19.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/spina/manifest.js +2 -2
  3. data/app/assets/javascripts/spina/application.js +1 -1
  4. data/app/assets/javascripts/spina/controllers/confetti_controller.js +1 -1
  5. data/app/assets/javascripts/spina/controllers/data_binding_controller.js +234 -1
  6. data/app/assets/javascripts/spina/controllers/form_controller.js +1 -2
  7. data/app/assets/javascripts/spina/controllers/hotkeys_controller.js +1 -1
  8. data/app/assets/javascripts/spina/controllers/reveal_controller.js +424 -1
  9. data/app/assets/javascripts/spina/controllers/sortable_controller.js +1 -2
  10. data/app/assets/javascripts/spina/libraries/canvas-confetti.js +1 -1
  11. data/app/assets/javascripts/spina/libraries/hotkeys.js +1 -1
  12. data/app/assets/javascripts/spina/libraries/sortablejs.js +1 -1
  13. data/app/assets/javascripts/spina/libraries/trix.js +1 -1
  14. data/app/assets/stylesheets/spina/fonts-propshaft.css +114 -0
  15. data/app/helpers/spina/admin/pages_helper.rb +23 -4
  16. data/app/models/spina/embeds/youtube.rb +1 -1
  17. data/app/views/layouts/spina/admin/application.html.erb +9 -2
  18. data/config/locales/de.yml +2 -0
  19. data/db/migrate/18_change_default_spina_resources_slug.rb +9 -0
  20. data/lib/spina/engine.rb +0 -1
  21. data/lib/spina/railtie.rb +4 -1
  22. data/lib/spina/version.rb +1 -1
  23. metadata +11 -27
  24. data/app/assets/javascripts/spina/libraries/form-request-submit-polyfill.js +0 -1
  25. data/app/assets/javascripts/spina/libraries/form-request-submit-polyfill@2.0.0.js +0 -27
  26. data/app/assets/javascripts/spina/libraries/stimulus-data-bindings@1.3.2.js +0 -234
  27. data/app/assets/javascripts/spina/libraries/stimulus-reveal@1.4.2.js +0 -424
  28. /data/app/assets/stylesheets/spina/{fonts.css.erb → fonts-sprockets.css.erb} +0 -0
@@ -1,424 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus";
2
-
3
- /**
4
- * Stimulus controller to toggle element visibility
5
- * @extends Controller
6
- */
7
- export default class RevealController extends Controller {
8
- static values = {
9
- open: Boolean,
10
- transitioning: Boolean,
11
- targetSelector: String,
12
- toggleKeys: String,
13
- showKeys: String,
14
- hideKeys: String,
15
- away: Boolean,
16
- debug: Boolean,
17
- };
18
-
19
- connect() {
20
- this._initCloseKeypressListener();
21
- this._initToggleKeypressListener();
22
- this._initShowKeypressListener();
23
- this._awayHandler = this._awayHandler.bind(this);
24
- }
25
-
26
- disconnect() {
27
- this._teardown();
28
- }
29
-
30
- /**
31
- * Shows elements connected to the controller.
32
- * @param {Event} event - an event with a currentTarget DOMElement
33
- */
34
- show(event) {
35
- if (this.openValue || this.transitioningValue) return;
36
-
37
- this._init(event, true);
38
- }
39
-
40
- /**
41
- * Hides elements connected to the controller.
42
- * @param {Event} event - an event with a currentTarget DOMElement
43
- */
44
- hide(event) {
45
- if (!this.openValue || this.transitioningValue) return;
46
-
47
- this._init(event, false);
48
- }
49
-
50
- /**
51
- * Toggles elements connected to the controller.
52
- * @param {Event} event - an event with a currentTarget DOMElement
53
- */
54
- toggle(event) {
55
- if (this.transitioningValue) return;
56
-
57
- this._init(event, !this.openValue);
58
- }
59
-
60
- /**
61
- * Stops event propagation of elements connected to the controller.
62
- * @param {Event} event - an event with a currentTarget DOMElement
63
- */
64
- stop(event) {
65
- event.stopPropagation();
66
- }
67
-
68
- // Private methods
69
-
70
- /**
71
- * @private
72
- * @param {Event} event
73
- * @param {Event} shouldOpen
74
- */
75
- async _init(event, shouldOpen) {
76
- if (event && event.currentTarget && event.currentTarget.dataset) {
77
- if ("revealPreventDefault" in event.currentTarget.dataset) {
78
- event.preventDefault();
79
- }
80
- if ("revealStopPropagation" in event.currentTarget.dataset) {
81
- event.stopPropagation();
82
- }
83
- }
84
- // start stuff
85
- const startSelector = `${this.selector}[data-${shouldOpen ? "enter" : "leave"
86
- }-start]`;
87
- const startPromises = this._didInitWithPromise(startSelector, shouldOpen);
88
- await Promise.all(startPromises);
89
-
90
- const defaultSelector = `${this.selector}:not([data-${shouldOpen ? "enter" : "leave"
91
- }-start]):not([data-${shouldOpen ? "enter" : "leave"}-end])`;
92
- const defaultPromises = this._didInitWithPromise(
93
- defaultSelector,
94
- shouldOpen
95
- );
96
- await Promise.all(defaultPromises);
97
-
98
- // end stuff
99
- const endSelector = `${this.selector}[data-${shouldOpen ? "enter" : "leave"
100
- }-end]`;
101
- const endPromises = this._didInitWithPromise(endSelector, shouldOpen);
102
- await Promise.all(endPromises);
103
- }
104
-
105
- /**
106
- * @private
107
- */
108
- _teardown() {
109
- if (this.hasAwayValue) {
110
- document.removeEventListener("click", this._awayHandler);
111
- }
112
- }
113
-
114
- _didInitWithPromise(selector, shouldOpen) {
115
- this._debug("selecting", selector, this._fetchElements(selector));
116
- return this._fetchElements(selector).map((element) => {
117
- return this._doInitTransition(element, shouldOpen);
118
- });
119
- }
120
-
121
- /**
122
- * @private
123
- */
124
- _initCloseKeypressListener() {
125
- if (this.hasHideKeysValue) {
126
- document.addEventListener("keydown", (event) => {
127
- if (!this.openValue) return;
128
- if (!this.hideKeysValue.split(",").includes(event.key.toLowerCase())) {
129
- return;
130
- }
131
-
132
- event.stopPropagation();
133
- this.toggle(event);
134
- });
135
- }
136
- }
137
-
138
- /**
139
- * @private
140
- */
141
- _initToggleKeypressListener() {
142
- if (this.hasToggleKeysValue) {
143
- document.addEventListener("keydown", (event) => {
144
- if (
145
- !this.toggleKeysValue.split(",").includes(event.key.toLowerCase())
146
- ) {
147
- return;
148
- }
149
-
150
- event.stopPropagation();
151
-
152
- this.toggle(event);
153
- });
154
- }
155
- }
156
-
157
- /**
158
- * @private
159
- */
160
- _initShowKeypressListener() {
161
- if (this.hasShowKeysValue) {
162
- document.addEventListener("keydown", (event) => {
163
- if (this.openValue) return;
164
- if (!this.showKeysValue.split(",").includes(event.key.toLowerCase())) {
165
- return;
166
- }
167
-
168
- event.stopPropagation();
169
-
170
- this.toggle(event);
171
- });
172
- }
173
- }
174
-
175
- /**
176
- * @private
177
- */
178
- _awayHandler(event) {
179
- if (!this.element.contains(event.target)) {
180
- document.removeEventListener("click", this._awayHandler);
181
- this.hide(event);
182
- }
183
- return true;
184
- }
185
-
186
- /**
187
- * @private
188
- * @param {DOMElement} target
189
- * @param {boolean} openState
190
- */
191
- _doInitTransition(target, openState) {
192
- this._debug("init transition", `${openState ? "open" : "closed"}`, target);
193
- this._debug(
194
- "dispatching event",
195
- `reveal:${openState ? "show" : "hide"}`,
196
- target
197
- );
198
- target.dispatchEvent(
199
- new Event(`reveal:${openState ? "show" : "hide"}`, {
200
- bubbles: true,
201
- cancelable: false,
202
- })
203
- );
204
-
205
- return new Promise((resolve, reject) => {
206
- if (
207
- "transition" in target.dataset &&
208
- this.element.offsetParent !== null
209
- ) {
210
- requestAnimationFrame(() => {
211
- this._transitionSetup(target, openState);
212
- const _didEndTransition = this._didEndTransition.bind(this);
213
-
214
- target.addEventListener(
215
- "transitionend",
216
- function _didEndTransitionHandler() {
217
- _didEndTransition(target, openState);
218
- target.removeEventListener(
219
- "transitionend",
220
- _didEndTransitionHandler
221
- );
222
- resolve();
223
- }
224
- );
225
-
226
- requestAnimationFrame(() => {
227
- this._doStartTransition(target, openState);
228
- });
229
- });
230
- } else {
231
- if (openState) {
232
- this._debug(
233
- "force hidden - init",
234
- `${openState ? "open" : "closed"}`,
235
- target
236
- );
237
- target.hidden = !target.hidden;
238
- }
239
- this._doCompleteTransition(target, openState);
240
- resolve();
241
- }
242
- });
243
- }
244
-
245
- /**
246
- * @private
247
- * @param {DOMElement} target
248
- */
249
- _doStartTransition(target, openState) {
250
- this._debug("start transition", `${openState ? "open" : "closed"}`, target);
251
- this.transitioningValue = true;
252
- if (target.dataset.useTransitionClasses === "true") {
253
- const transitionClasses = this._transitionClasses(
254
- target,
255
- this.transitionType
256
- );
257
- target.classList.add(...transitionClasses.end.split(" "));
258
- target.classList.remove(...transitionClasses.start.split(" "));
259
- } else {
260
- const transitions = this._transitionDefaults(openState);
261
- target.style.transformOrigin = transitions.origin;
262
- target.style.transitionProperty = "opacity transform";
263
- target.style.transitionDuration = `${transitions.duration / 1000}s`;
264
- target.style.transitionTimingFunction = "cubic-bezier(0.4, 0.0, 0.2, 1)";
265
-
266
- target.style.opacity = transitions.to.opacity;
267
- target.style.transform = `scale(${transitions.to.scale / 100})`;
268
- }
269
- }
270
-
271
- /**
272
- * @private
273
- * @param {DOMElement} target
274
- * @param {boolean} openState
275
- */
276
- _didEndTransition(target, openState) {
277
- this._debug("end transition", `${openState ? "open" : "closed"}`, target);
278
- if (target.dataset.useTransitionClasses === "true") {
279
- const transitionClasses = this._transitionClasses(
280
- target,
281
- this.transitionType
282
- );
283
- target.classList.remove(...transitionClasses.before.split(" "));
284
- } else {
285
- target.style.opacity = target.dataset.opacityCache;
286
- target.style.transform = target.dataset.transformCache;
287
- target.style.transformOrigin = target.dataset.transformOriginCache;
288
- }
289
- this._doCompleteTransition(target, openState);
290
- }
291
-
292
- /**
293
- * @private
294
- * @param {DOMElement} target
295
- * @param {boolean} openState
296
- */
297
- _doCompleteTransition(target, openState) {
298
- this._debug(
299
- "complete transition",
300
- `${openState ? "open" : "closed"}`,
301
- target
302
- );
303
- this.transitioningValue = false;
304
-
305
- if (!openState) {
306
- this._debug(
307
- "force hidden - complete",
308
- `${openState ? "open" : "closed"}`,
309
- target
310
- );
311
- target.hidden = !target.hidden;
312
- }
313
- this.openValue = openState;
314
-
315
- this._debug(
316
- "dispatching event",
317
- `reveal:${openState ? "shown" : "hidden"}`,
318
- target
319
- );
320
- target.dispatchEvent(
321
- new Event(`reveal:${openState ? "shown" : "hidden"}`, {
322
- bubbles: true,
323
- cancelable: false,
324
- })
325
- );
326
-
327
- if (this.hasAwayValue && openState) {
328
- document.addEventListener("click", this._awayHandler);
329
- }
330
-
331
- this._debug("dispatching event", "reveal:complete", target);
332
- target.dispatchEvent(
333
- new Event("reveal:complete", { bubbles: true, cancelable: false })
334
- );
335
- }
336
-
337
- /**
338
- * @private
339
- * @param {DOMElement} target
340
- * @param {boolean} openState
341
- */
342
- _transitionSetup(target, openState) {
343
- this.transitionType = openState ? "transitionEnter" : "transitionLeave";
344
-
345
- if (this.transitionType in target.dataset) {
346
- target.dataset.useTransitionClasses = true;
347
- const transitionClasses = this._transitionClasses(
348
- target,
349
- this.transitionType
350
- );
351
- target.classList.add(...transitionClasses.before.split(" "));
352
- target.classList.add(...transitionClasses.start.split(" "));
353
- } else {
354
- target.dataset.useTransitionClasses = false;
355
- const transitions = this._transitionDefaults(openState);
356
- target.dataset.opacityCache = target.style.opacity;
357
- target.dataset.transformCache = target.style.transform;
358
- target.dataset.transformOriginCache = target.style.transformOrigin;
359
-
360
- target.style.opacity = transitions.from.opacity;
361
- target.style.transform = `scale(${transitions.from.scale / 100})`;
362
- }
363
- if (openState) {
364
- this._debug("opening with transition", target);
365
- target.hidden = !target.hidden;
366
- }
367
- }
368
-
369
- /**
370
- * @private
371
- * @param {boolean} openState
372
- */
373
- _transitionDefaults(openState) {
374
- return {
375
- duration: openState ? 200 : 150,
376
- origin: "center",
377
- from: {
378
- opacity: openState ? 0 : 1,
379
- scale: openState ? 95 : 100,
380
- },
381
- to: {
382
- opacity: openState ? 1 : 0,
383
- scale: openState ? 100 : 95,
384
- },
385
- };
386
- }
387
-
388
- /**
389
- * @private
390
- * @param {DOMElement} target
391
- * @param {string} transitionType
392
- */
393
- _transitionClasses(target, transitionType) {
394
- return {
395
- before: target.dataset[transitionType],
396
- start: target.dataset[`${transitionType}Start`],
397
- end: target.dataset[`${transitionType}End`],
398
- };
399
- }
400
-
401
- /**
402
- * @private
403
- * @param {String} selector
404
- */
405
- _fetchElements(selector) {
406
- return [this.element, ...this.element.querySelectorAll(selector)].filter(
407
- (el) => el.matches(selector)
408
- );
409
- }
410
-
411
- /**
412
- * @private
413
- * @param {Array} args
414
- */
415
- _debug(...args) {
416
- if (this.debugValue) console.log(...args);
417
- }
418
-
419
- get selector() {
420
- return this.hasTargetSelectorValue
421
- ? this.targetSelectorValue
422
- : "[data-reveal]";
423
- }
424
- }