spina 2.19.0 → 2.21.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.
- checksums.yaml +4 -4
- data/Rakefile +0 -2
- data/app/assets/builds/spina/tailwind.css +3338 -3725
- data/app/assets/config/spina/manifest.js +2 -2
- data/app/assets/javascripts/spina/application.js +1 -1
- data/app/assets/javascripts/spina/controllers/confetti_controller.js +1 -1
- data/app/assets/javascripts/spina/controllers/confirm_controller.js +2 -2
- data/app/assets/javascripts/spina/controllers/data_binding_controller.js +234 -1
- data/app/assets/javascripts/spina/controllers/form_controller.js +1 -2
- data/app/assets/javascripts/spina/controllers/hotkeys_controller.js +1 -1
- data/app/assets/javascripts/spina/controllers/navigation_controller.js +4 -4
- data/app/assets/javascripts/spina/controllers/reveal_controller.js +424 -1
- data/app/assets/javascripts/spina/controllers/sortable_controller.js +1 -2
- data/app/assets/javascripts/spina/libraries/canvas-confetti.js +1 -1
- data/app/assets/javascripts/spina/libraries/hotkeys.js +1 -1
- data/app/assets/javascripts/spina/libraries/sortablejs.js +1 -1
- data/app/assets/javascripts/spina/libraries/trix.js +1 -1
- data/app/assets/stylesheets/spina/application.tailwind.css +105 -62
- data/app/assets/stylesheets/spina/fonts-propshaft.css +114 -0
- data/app/components/spina/forms/switch_component.html.erb +2 -2
- data/app/components/spina/forms/trix_toolbar_component.html.erb +16 -33
- data/app/components/spina/media_picker/modal_component.html.erb +1 -1
- data/app/components/spina/media_picker/modal_component.rb +2 -2
- data/app/components/spina/pages/actions_component.html.erb +4 -4
- data/app/components/spina/pages/location_component.html.erb +2 -2
- data/app/components/spina/pages/new_page_button_component.html.erb +2 -2
- data/app/components/spina/pages/page_component.html.erb +1 -1
- data/app/components/spina/pages/page_component.rb +2 -2
- data/app/components/spina/pages/translations_component.html.erb +3 -3
- data/app/components/spina/pages/translations_component.rb +1 -1
- data/app/components/spina/user_interface/modal_component.html.erb +2 -2
- data/app/components/spina/user_interface/tab_link_component.rb +1 -1
- data/app/components/spina/user_interface/translations_component.html.erb +2 -2
- data/app/components/spina/user_interface/translations_component.rb +1 -1
- data/app/controllers/concerns/spina/current_spina_account.rb +1 -1
- data/app/controllers/spina/admin/page_select_options_controller.rb +1 -1
- data/app/controllers/spina/admin/resource_select_options_controller.rb +1 -1
- data/app/controllers/spina/application_controller.rb +1 -1
- data/app/helpers/spina/admin/pages_helper.rb +23 -4
- data/app/jobs/spina/replace_signed_id_job.rb +12 -9
- data/app/models/concerns/spina/attachable.rb +1 -1
- data/app/models/concerns/spina/translated_content.rb +1 -1
- data/app/models/spina/account.rb +2 -2
- data/app/models/spina/embeds/youtube.rb +1 -1
- data/app/models/spina/resource.rb +3 -1
- data/app/models/spina/setting.rb +2 -0
- data/app/presenters/spina/menu_presenter.rb +7 -12
- data/app/views/layouts/spina/admin/application.html.erb +9 -2
- data/app/views/spina/admin/embeds/new.html.erb +4 -4
- data/app/views/spina/admin/images/_image.html.erb +1 -1
- data/app/views/spina/admin/layout/edit.html.erb +2 -2
- data/app/views/spina/admin/move_pages/new.html.erb +2 -2
- data/app/views/spina/admin/navigation_items/_navigation_item.html.erb +5 -5
- data/app/views/spina/admin/pages/_form.html.erb +1 -1
- data/app/views/spina/admin/pages/_form_advanced.html.erb +1 -1
- data/app/views/spina/admin/pages/edit_template.html.erb +2 -2
- data/app/views/spina/admin/pages/index.html.erb +1 -1
- data/app/views/spina/admin/parts/image_collections/_fields.html.erb +1 -1
- data/app/views/spina/admin/parts/images/_form.html.erb +1 -1
- data/app/views/spina/admin/parts/page_links/_form.html.erb +2 -2
- data/app/views/spina/admin/parts/repeaters/_form.html.erb +1 -1
- data/app/views/spina/admin/parts/resource_links/_form.html.erb +1 -1
- data/app/views/spina/admin/parts/texts/_form.html.erb +2 -2
- data/app/views/spina/admin/settings/_wysiwyg_field.html.erb +3 -3
- data/app/views/spina/admin/shared/_navigation.html.erb +1 -1
- data/app/views/spina/admin/users/index.html.erb +2 -2
- data/app/views/spina/sitemaps/show.xml.builder +1 -1
- data/config/locales/de.yml +2 -0
- data/config/routes.rb +2 -2
- data/db/migrate/13_add_json_attributes_to_spina_accounts.rb +1 -1
- data/db/migrate/14_add_json_attributes_to_spina_pages.rb +1 -1
- data/db/migrate/15_add_slug_to_spina_resources.rb +1 -1
- data/db/migrate/18_change_default_spina_resources_slug.rb +9 -0
- data/db/migrate/7_create_spina_settings.rb +1 -1
- data/lib/generators/spina/tailwind_config_generator.rb +1 -1
- data/lib/generators/spina/templates/app/assets/stylesheets/spina/application.tailwind.css.tt +232 -0
- data/lib/generators/spina/templates/app/views/demo/shared/_languages.html.erb +2 -2
- data/lib/spina/engine.rb +1 -2
- data/lib/spina/railtie.rb +4 -1
- data/lib/spina/version.rb +1 -1
- data/lib/spina.rb +63 -83
- data/lib/tasks/install.rake +1 -1
- data/lib/tasks/tailwind.rake +2 -3
- metadata +17 -49
- data/app/assets/javascripts/spina/libraries/form-request-submit-polyfill.js +0 -1
- data/app/assets/javascripts/spina/libraries/form-request-submit-polyfill@2.0.0.js +0 -27
- data/app/assets/javascripts/spina/libraries/stimulus-data-bindings@1.3.2.js +0 -234
- data/app/assets/javascripts/spina/libraries/stimulus-reveal@1.4.2.js +0 -424
- data/lib/generators/spina/templates/app/assets/config/spina/tailwind.config.js.tt +0 -23
- /data/app/assets/stylesheets/spina/{fonts.css.erb → fonts-sprockets.css.erb} +0 -0
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
(function(prototype) {
|
|
2
|
-
if (typeof prototype.requestSubmit == "function")
|
|
3
|
-
return;
|
|
4
|
-
prototype.requestSubmit = function(submitter) {
|
|
5
|
-
if (submitter) {
|
|
6
|
-
validateSubmitter(submitter, this);
|
|
7
|
-
submitter.click();
|
|
8
|
-
} else {
|
|
9
|
-
submitter = document.createElement("input");
|
|
10
|
-
submitter.type = "submit";
|
|
11
|
-
submitter.hidden = true;
|
|
12
|
-
this.appendChild(submitter);
|
|
13
|
-
submitter.click();
|
|
14
|
-
this.removeChild(submitter);
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
function validateSubmitter(submitter, form) {
|
|
18
|
-
submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'");
|
|
19
|
-
submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button");
|
|
20
|
-
submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError");
|
|
21
|
-
}
|
|
22
|
-
function raise(errorConstructor, message, name) {
|
|
23
|
-
throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name);
|
|
24
|
-
}
|
|
25
|
-
})(HTMLFormElement.prototype);
|
|
26
|
-
export default null;
|
|
27
|
-
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { Controller } from '@hotwired/stimulus'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* One way data and visibility bindings for inputs
|
|
5
|
-
* @extends Controller
|
|
6
|
-
*/
|
|
7
|
-
export default class DataBindingController extends Controller {
|
|
8
|
-
/**
|
|
9
|
-
* Initialize bindings on connection to the DOM
|
|
10
|
-
*/
|
|
11
|
-
connect() {
|
|
12
|
-
if (this.element.dataset.bindingDebug === "true") {
|
|
13
|
-
this.debugMode = true
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
this._debug("stimulus-data-binding: connecting to wrapper:", this.element)
|
|
17
|
-
|
|
18
|
-
const sourceElements = Array.from(this.element.querySelectorAll('[data-binding-target]'))
|
|
19
|
-
if (this.element.dataset.bindingTarget) sourceElements.unshift(this.element)
|
|
20
|
-
|
|
21
|
-
if (sourceElements.length === 0) this._debug("No source elements found. Did you set data-binding-target on your source elements?")
|
|
22
|
-
|
|
23
|
-
for (const sourceElement of sourceElements) {
|
|
24
|
-
if (this.debugMode) console.group("stimulus-data-binding: Source element")
|
|
25
|
-
this._debug("Source element found", sourceElement)
|
|
26
|
-
|
|
27
|
-
if (sourceElement.dataset.bindingInitial !== 'false') {
|
|
28
|
-
this._debug("Running initial binding on source element")
|
|
29
|
-
this._runBindings(sourceElement)
|
|
30
|
-
} else {
|
|
31
|
-
this._debug("%cNot running initial binding on source element as binding-initial is set to false", "color: rgba(150,150,150,0.8);")
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (this.debugMode) console.groupEnd()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Updates bindings for the current element.
|
|
40
|
-
* @param {Event} e - an event with a currentTarget DOMElement
|
|
41
|
-
*/
|
|
42
|
-
update(e) {
|
|
43
|
-
this._runBindings(e.currentTarget)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* @private
|
|
48
|
-
* @param {DOMElement} source
|
|
49
|
-
*/
|
|
50
|
-
_runBindings(source) {
|
|
51
|
-
this._debug("Searching for targets for source: ", source)
|
|
52
|
-
for (const targetRef of source.dataset.bindingTarget.split(' ')) {
|
|
53
|
-
const targetElements = this._bindingElements(targetRef)
|
|
54
|
-
|
|
55
|
-
if (targetElements.length === 0) this._debug(`Could not find any target elements for ref ${targetRef}. Have you set data-target-ref="${targetRef}" on your target elements?`)
|
|
56
|
-
|
|
57
|
-
for (const target of targetElements) {
|
|
58
|
-
if (this.debugMode) console.group("stimulus-data-binding: Target Element")
|
|
59
|
-
this._debug("Target found. Running bindings for target: ", target)
|
|
60
|
-
|
|
61
|
-
const bindingCondition = this._getDatum('bindingCondition', source, target)
|
|
62
|
-
|
|
63
|
-
if (bindingCondition) {
|
|
64
|
-
this._debug(`Evaluating binding condition: '${bindingCondition}'`)
|
|
65
|
-
} else {
|
|
66
|
-
this._debug(`%cNo binding condition set. Evaluating as true. To add a condition set 'data-binding-condition="..."'`, "color: rgba(150,150,150,0.8);")
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const conditionPassed = this._evaluate(
|
|
70
|
-
bindingCondition,
|
|
71
|
-
{
|
|
72
|
-
source,
|
|
73
|
-
target
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
if (conditionPassed) {
|
|
78
|
-
this._debug(`Condition evaluated to: `, conditionPassed)
|
|
79
|
-
} else {
|
|
80
|
-
this._debug(`Condition evaluated to: `, conditionPassed)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const bindingValue = this._getDatum('bindingValue', source, target)
|
|
84
|
-
|
|
85
|
-
if (bindingValue) {
|
|
86
|
-
this._debug(`Evaluating binding value: '${bindingValue}'`)
|
|
87
|
-
} else {
|
|
88
|
-
this._debug(`%cNo binding value set, evaluating as true. to set a value for the attribute / property on your target elements set 'data-binding-value="..."'`, "color: rgba(150,150,150,0.8);")
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const value = this._evaluate(
|
|
92
|
-
bindingValue,
|
|
93
|
-
{
|
|
94
|
-
source,
|
|
95
|
-
target
|
|
96
|
-
}
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
this._debug(`Value evaluated to: '${value}'`)
|
|
100
|
-
|
|
101
|
-
const bindingAttribute = this._getDatum(
|
|
102
|
-
'bindingAttribute',
|
|
103
|
-
source,
|
|
104
|
-
target
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
if (!bindingAttribute) {
|
|
108
|
-
this._debug(`%cNo binding attribute set. To add attributes to your target element set 'data-binding-attribute="..."'`, "color: rgba(150,150,150,0.8);")
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (bindingAttribute) {
|
|
112
|
-
for (const attribute of bindingAttribute.split(' ')) {
|
|
113
|
-
if (conditionPassed) {
|
|
114
|
-
this._debug(`Condition passed so setting attribute '${attribute}' to '${value}'`)
|
|
115
|
-
target.setAttribute(attribute, value)
|
|
116
|
-
} else {
|
|
117
|
-
this._debug(`Condition failed so removing attribute '${attribute}'`)
|
|
118
|
-
target.removeAttribute(attribute)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const bindingProperty = this._getDatum(
|
|
124
|
-
'bindingProperty',
|
|
125
|
-
source,
|
|
126
|
-
target
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
if (!bindingProperty) {
|
|
130
|
-
this._debug(`%cNo binding property set. To add properties to your target element set 'data-binding-property="..."'`, "color: rgba(150,150,150,0.8);")
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (bindingProperty) {
|
|
134
|
-
for (const prop of bindingProperty.split(' ')) {
|
|
135
|
-
const propertyValue = conditionPassed ? value : ''
|
|
136
|
-
if (target[prop] != propertyValue) { target.dataset.hasChanged = true }
|
|
137
|
-
|
|
138
|
-
if (conditionPassed) {
|
|
139
|
-
this._debug(`Condition passed so setting property '${prop}' from ${target[prop]} to '${value}'`)
|
|
140
|
-
} else {
|
|
141
|
-
this._debug(`Condition failed so setting property '${prop}' from ${target[prop]} to '' (empty string)`)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
target[prop] = propertyValue
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const bindingClass = this._getDatum(
|
|
149
|
-
'bindingClass',
|
|
150
|
-
source,
|
|
151
|
-
target
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
if (!bindingClass) {
|
|
155
|
-
this._debug(`%cNo binding class set. To add classes to your target element set 'data-binding-class="..."'`, "color: rgba(150,150,150,0.8);")
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (bindingClass) {
|
|
159
|
-
for (const klass of bindingClass.split(' ')) {
|
|
160
|
-
if (conditionPassed) {
|
|
161
|
-
this._debug(`Condition passed so adding class '${klass}'`)
|
|
162
|
-
target.classList.add(klass)
|
|
163
|
-
} else {
|
|
164
|
-
this._debug(`Condition failed so removing class '${klass}'`)
|
|
165
|
-
target.classList.remove(klass)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const bindingEvent = this._getDatum('bindingEvent', source, target)
|
|
171
|
-
|
|
172
|
-
if (!bindingEvent) {
|
|
173
|
-
this._debug(`%cNo binding event set. To dispatch events on property change to your target element set 'data-binding-event="..."'`, "color: rgba(150,150,150,0.8);")
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (bindingEvent) {
|
|
177
|
-
for (const event of bindingEvent.split(' ')) {
|
|
178
|
-
if (target.dataset.hasChanged) {
|
|
179
|
-
this._debug(`Target has changed so dispatching event ${event}`)
|
|
180
|
-
target.dispatchEvent(new Event(event, { cancelable: true, bubbles: true }))
|
|
181
|
-
delete target.dataset.hasChanged
|
|
182
|
-
} else {
|
|
183
|
-
this._debug(`No changes to target properties so not dispatching '${event}'`)
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (this.debugMode) console.groupEnd()
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* @private
|
|
195
|
-
* @param {String} name - the name of the binding reference
|
|
196
|
-
*/
|
|
197
|
-
_bindingElements(name) {
|
|
198
|
-
return this.element.querySelectorAll(`[data-binding-ref="${name}"]`)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* @private
|
|
203
|
-
* @param {String} attribute - the attribute to fetch from the source / target dataaset
|
|
204
|
-
* @param {String} source - The source element to get the attribute from, only loads if target doesnt have it
|
|
205
|
-
* @param {String} target - The target element to get the attribute from, has precedence over the source
|
|
206
|
-
*/
|
|
207
|
-
_getDatum(attribute, source, target) {
|
|
208
|
-
return target.dataset[attribute] || source.dataset[attribute]
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* @private
|
|
213
|
-
* @param {String} expression - expression to safe eval
|
|
214
|
-
* @param {Object} variables - variables to be present when evaluating the given expression
|
|
215
|
-
*/
|
|
216
|
-
_evaluate(expression, variables = {}) {
|
|
217
|
-
if (!expression) return true
|
|
218
|
-
return new Function(
|
|
219
|
-
Object.keys(variables).map((v) => `$${v}`),
|
|
220
|
-
`return ${expression.trim()}`
|
|
221
|
-
)(...Object.values(variables))
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* @private
|
|
226
|
-
* @param {String} expression - expression to safe eval
|
|
227
|
-
* @param {Object} variables - variables to be present when evaluating the given expression
|
|
228
|
-
*/
|
|
229
|
-
_debug(...args) {
|
|
230
|
-
if (this.debugMode) {
|
|
231
|
-
console.log(...args)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
@@ -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
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
content: [
|
|
3
|
-
<%= Spina.config.tailwind_content.map{|path|"'#{path}'"}.join(",\n") %>
|
|
4
|
-
],
|
|
5
|
-
theme: {
|
|
6
|
-
fontFamily: {
|
|
7
|
-
body: ['Metropolis'],
|
|
8
|
-
mono: ['ui-monospace', 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', "Liberation Mono", "Courier New", 'monospace']
|
|
9
|
-
},
|
|
10
|
-
extend: {
|
|
11
|
-
colors: {
|
|
12
|
-
spina: {
|
|
13
|
-
light: '#797ab8',
|
|
14
|
-
DEFAULT: '#6865b4',
|
|
15
|
-
dark: '#3a3a70'
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
plugins: [
|
|
21
|
-
<%= Spina.config.tailwind_plugins.map {|plugin|"require('#{plugin}')"}.join(",\n\t") %>
|
|
22
|
-
]
|
|
23
|
-
}
|
|
File without changes
|