@csedl/hotwire-svelte-helpers 4.2.0 → 4.3.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.
- package/README.md +4 -2
- package/package.json +1 -1
- package/src/lib/floating-ui-functions.js +1 -1
- package/src/lib/initializers.js +5 -3
- package/src/lib/utils.js +20 -7
- package/src/stimulus/modal-controller.js +34 -0
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ to your application.js. This will check for detached instances and unmount them.
|
|
|
45
45
|
## Dropdown Example
|
|
46
46
|
|
|
47
47
|
```html
|
|
48
|
-
<div data-controller="
|
|
48
|
+
<div data-controller="hotwire-svelte-helpers-dropdown" data-panel-id="dropdown-panel-3h5k7l4">
|
|
49
49
|
Button
|
|
50
50
|
</div>
|
|
51
51
|
<div id="dropdown-panel-3h5k7l4" class="dropdownSvelte-panel-example-class" style="display: none;">
|
|
@@ -59,6 +59,8 @@ If `#overlays-box` does not exist, it is created automatically.
|
|
|
59
59
|
This keeps overlays at the root level to avoid most z-index and clipping issues,
|
|
60
60
|
while keeping the DOM cleaner than mounting panels directly into `body`.
|
|
61
61
|
|
|
62
|
+
This aligns to the behaviour of the [stimulus side](https://gitlab.com/sedl/stimulus-overlay-helpers)
|
|
63
|
+
|
|
62
64
|
## Svelte Dropdowns
|
|
63
65
|
|
|
64
66
|
There are some default components included, which can be used to build Svelte Dropdowns.
|
|
@@ -147,7 +149,7 @@ What these helpers mainly do is to find all the dropdowns by the `has-open-panel
|
|
|
147
149
|
## Tooltip
|
|
148
150
|
|
|
149
151
|
```html
|
|
150
|
-
<span data-controller="
|
|
152
|
+
<span data-controller="hotwire-svelte-helpers-tooltip" data-panel-id="tooltip-123" data-delay="0.2">
|
|
151
153
|
Text-with-tooltip
|
|
152
154
|
</span>
|
|
153
155
|
<div id="tooltip-123" class="tooltip-panel" style="display: none;">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csedl/hotwire-svelte-helpers",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"description": "Hotwire + Svelte helpers for Rails: Stimulus floating dropdowns/toolips + Svelte global panels/modals + RTurbo-friendly utilities. Build together with the rubygem svelte-on-rails and its npm-package.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,7 +21,7 @@ export function getAllOpenPanels(scopeElement) {
|
|
|
21
21
|
const elements = []
|
|
22
22
|
|
|
23
23
|
for (const button of buttons) {
|
|
24
|
-
if (button.getAttribute('data-controller') === '
|
|
24
|
+
if (button.getAttribute('data-controller') === 'hotwire-svelte-helpers-dropdown') {
|
|
25
25
|
const getOrSetPanelId = button.getAttribute('data-panel-id')
|
|
26
26
|
const panel = document.getElementById(getOrSetPanelId)
|
|
27
27
|
elements.push([button, panel])
|
package/src/lib/initializers.js
CHANGED
|
@@ -2,6 +2,7 @@ import {debugLog} from "./utils.js";
|
|
|
2
2
|
import {Application} from "@hotwired/stimulus"
|
|
3
3
|
import dc from '../stimulus/dropdown-controller'
|
|
4
4
|
import ttc from '../stimulus/tooltip-controller'
|
|
5
|
+
import mod from '../stimulus/modal-controller'
|
|
5
6
|
import ppc from '../stimulus/move-panels-controller'
|
|
6
7
|
|
|
7
8
|
|
|
@@ -30,9 +31,10 @@ const HotwireSvelteHelpers = {
|
|
|
30
31
|
|
|
31
32
|
const Stimulus = Application.start()
|
|
32
33
|
|
|
33
|
-
Stimulus.register('
|
|
34
|
-
Stimulus.register('
|
|
35
|
-
Stimulus.register('
|
|
34
|
+
Stimulus.register('hotwire-svelte-helpers-modal', mod)
|
|
35
|
+
Stimulus.register('hotwire-svelte-helpers-dropdown', dc)
|
|
36
|
+
Stimulus.register('hotwire-svelte-helpers-tooltip', ttc)
|
|
37
|
+
Stimulus.register('hotwire-svelte-helpers-move-panels', ppc)
|
|
36
38
|
|
|
37
39
|
debugLog('Overlays active, driven by Stimulus')
|
|
38
40
|
|
package/src/lib/utils.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {positionPanelSelf, positionPanelByButton, positionPanel} from "./floating-ui-functions.js";
|
|
2
2
|
|
|
3
3
|
// Fetch content from server based on panel's data-src attribute and update content
|
|
4
|
+
|
|
4
5
|
export function openDropdownPanel(buttonElement, panelElement, options = {}) {
|
|
5
6
|
|
|
6
7
|
if (buttonElement.classList.contains('has-open-panel')) {
|
|
@@ -10,11 +11,13 @@ export function openDropdownPanel(buttonElement, panelElement, options = {}) {
|
|
|
10
11
|
|
|
11
12
|
// link button and panel, initialize
|
|
12
13
|
panelElement.id = getOrSetPanelId(buttonElement);
|
|
13
|
-
initializeDropdown(buttonElement)
|
|
14
|
-
debugLog(`opening panel ${panelElement.id.split('-').pop()}
|
|
15
|
-
panelElement.style.display = 'block';
|
|
14
|
+
initializeDropdown(buttonElement, options)
|
|
15
|
+
debugLog(`opening panel ${panelElement.id.split('-').pop()}`, options)
|
|
16
|
+
panelElement.style.display = (options.isModal ? 'flex' : 'block');
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
if (!options.isModal) {
|
|
19
|
+
positionPanel(buttonElement, panelElement);
|
|
20
|
+
}
|
|
18
21
|
|
|
19
22
|
// Set focus to input element
|
|
20
23
|
if (panelElement.hasAttribute('data-set-focus')) {
|
|
@@ -48,10 +51,10 @@ export function openDropdownPanel(buttonElement, panelElement, options = {}) {
|
|
|
48
51
|
const buttonElement = document.querySelector(`[data-panel-id="${panelElement.id}"]`);
|
|
49
52
|
const ctrl = buttonElement.getAttribute('data-controller');
|
|
50
53
|
|
|
51
|
-
if (ctrl === '
|
|
54
|
+
if (ctrl === 'hotwire-svelte-helpers-dropdown') {
|
|
52
55
|
const wrapper = panelElement.querySelector('.content');
|
|
53
56
|
wrapper.innerHTML = xhr.response;
|
|
54
|
-
} else if (ctrl === '
|
|
57
|
+
} else if (ctrl === 'hotwire-svelte-helpers-tooltip') {
|
|
55
58
|
const wrapper = panelElement.querySelector('.content');
|
|
56
59
|
wrapper.innerHTML = xhr.response;
|
|
57
60
|
} else {
|
|
@@ -69,6 +72,7 @@ export function openDropdownPanel(buttonElement, panelElement, options = {}) {
|
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
// Handle panel closing
|
|
75
|
+
|
|
72
76
|
export function closePanel(button) {
|
|
73
77
|
|
|
74
78
|
const panel = findPanelOrThrow(button);
|
|
@@ -95,6 +99,7 @@ export function closePanel(button) {
|
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
// Close panels when clicking outside
|
|
102
|
+
|
|
98
103
|
export function closeOnOutsideClick(clickedElement) {
|
|
99
104
|
|
|
100
105
|
// set button
|
|
@@ -148,7 +153,8 @@ export function closeOnOutsideClick(clickedElement) {
|
|
|
148
153
|
}
|
|
149
154
|
|
|
150
155
|
// Add panel functionality, including close event listeners
|
|
151
|
-
|
|
156
|
+
|
|
157
|
+
export function initializeDropdown(button, options = {}) {
|
|
152
158
|
|
|
153
159
|
// find panel
|
|
154
160
|
const panel_id = button.getAttribute('data-panel-id');
|
|
@@ -183,6 +189,12 @@ export function initializeDropdown(button) {
|
|
|
183
189
|
debugLog('initializeDropdown: panel already initialized:', panel.id.split('-').pop())
|
|
184
190
|
}
|
|
185
191
|
|
|
192
|
+
// return if isModal
|
|
193
|
+
|
|
194
|
+
if (options.isModal) {
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
186
198
|
// initialize the button
|
|
187
199
|
if (!button.hasAttribute('data-hsh-initialized')) {
|
|
188
200
|
button.setAttribute('data-hsh-initialized', 'true');
|
|
@@ -227,6 +239,7 @@ export function debugLog(message, object) {
|
|
|
227
239
|
}
|
|
228
240
|
|
|
229
241
|
// find or add the data-panel-id attribute of a button and return it
|
|
242
|
+
|
|
230
243
|
export function getOrSetPanelId(buttonTag) {
|
|
231
244
|
let id = buttonTag.getAttribute('data-panel-id')
|
|
232
245
|
if (id) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
import { openDropdownPanel, closePanel, findPanelOrThrow } from "../lib/utils.js";
|
|
3
|
+
import { debugLog } from "../lib/utils.js";
|
|
4
|
+
|
|
5
|
+
export default class extends Controller {
|
|
6
|
+
|
|
7
|
+
connect() {
|
|
8
|
+
|
|
9
|
+
this.element.addEventListener('click', (e) => this.toggle(e))
|
|
10
|
+
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
toggle(e) {
|
|
15
|
+
if (this.element.getAttribute('data-prevent-default')) {
|
|
16
|
+
e.preventDefault()
|
|
17
|
+
}
|
|
18
|
+
e.stopPropagation()
|
|
19
|
+
debugLog('toggle panel', e)
|
|
20
|
+
|
|
21
|
+
const panel = findPanelOrThrow(this.element)
|
|
22
|
+
if (panel.style.display === 'block') {
|
|
23
|
+
closePanel(this.element)
|
|
24
|
+
} else {
|
|
25
|
+
openDropdownPanel(this.element, panel, {isModal: true})
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|