@csedl/hotwire-svelte-helpers 4.1.0 → 4.2.1
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
CHANGED
|
@@ -14,7 +14,7 @@ A small toolkit for building more interactive Rails apps with Hotwire and Svelte
|
|
|
14
14
|
## Setup
|
|
15
15
|
|
|
16
16
|
```javascript
|
|
17
|
-
import { HotwireSvelteHelpers } from "@csedl/hotwire-svelte-helpers/
|
|
17
|
+
import { HotwireSvelteHelpers } from "@csedl/hotwire-svelte-helpers/setup"
|
|
18
18
|
HotwireSvelteHelpers.debug = true
|
|
19
19
|
HotwireSvelteHelpers.initializeOverlays()
|
|
20
20
|
```
|
|
@@ -52,6 +52,14 @@ to your application.js. This will check for detached instances and unmount them.
|
|
|
52
52
|
... any content
|
|
53
53
|
</div>
|
|
54
54
|
```
|
|
55
|
+
## `body#overlays-box` Tag
|
|
56
|
+
|
|
57
|
+
Svelte dropdown panels are mounted into `#overlays-box`, a shared overlay container appended directly to `document.body`.
|
|
58
|
+
If `#overlays-box` does not exist, it is created automatically.
|
|
59
|
+
This keeps overlays at the root level to avoid most z-index and clipping issues,
|
|
60
|
+
while keeping the DOM cleaner than mounting panels directly into `body`.
|
|
61
|
+
|
|
62
|
+
This aligns to the behaviour of the [stimulus side](https://gitlab.com/sedl/stimulus-overlay-helpers)
|
|
55
63
|
|
|
56
64
|
## Svelte Dropdowns
|
|
57
65
|
|
package/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
import { cleanMount, unmountAllDetached } from './src/svelte/cleanMount.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
initializeDropdown, openDropdownPanel,
|
|
5
|
+
getOrSetPanelId, debugLog, getCsrfToken, getOverlayTarget
|
|
6
|
+
} from './src/lib/utils.js'
|
|
4
7
|
|
|
5
8
|
export {
|
|
6
9
|
cleanMount, unmountAllDetached,
|
|
7
10
|
initializeDropdown, openDropdownPanel, getOrSetPanelId,
|
|
8
|
-
debugLog, getCsrfToken
|
|
11
|
+
debugLog, getCsrfToken, getOverlayTarget
|
|
9
12
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csedl/hotwire-svelte-helpers",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.2.1",
|
|
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": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"import": "./index.js",
|
|
12
12
|
"default": "./index.js"
|
|
13
13
|
},
|
|
14
|
-
"./
|
|
14
|
+
"./setup": {
|
|
15
15
|
"import": "./src/lib/initializers.js",
|
|
16
16
|
"default": "./src/lib/initializers.js"
|
|
17
17
|
},
|
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')) {
|
|
@@ -69,6 +70,7 @@ export function openDropdownPanel(buttonElement, panelElement, options = {}) {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
// Handle panel closing
|
|
73
|
+
|
|
72
74
|
export function closePanel(button) {
|
|
73
75
|
|
|
74
76
|
const panel = findPanelOrThrow(button);
|
|
@@ -95,6 +97,7 @@ export function closePanel(button) {
|
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
// Close panels when clicking outside
|
|
100
|
+
|
|
98
101
|
export function closeOnOutsideClick(clickedElement) {
|
|
99
102
|
|
|
100
103
|
// set button
|
|
@@ -148,6 +151,7 @@ export function closeOnOutsideClick(clickedElement) {
|
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
// Add panel functionality, including close event listeners
|
|
154
|
+
|
|
151
155
|
export function initializeDropdown(button) {
|
|
152
156
|
|
|
153
157
|
// find panel
|
|
@@ -213,10 +217,6 @@ export function findPanelOrThrow(button) {
|
|
|
213
217
|
return (panel)
|
|
214
218
|
}
|
|
215
219
|
|
|
216
|
-
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
217
|
-
// LOGGER
|
|
218
|
-
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
219
|
-
|
|
220
220
|
export function debugLog(message, object) {
|
|
221
221
|
if (window.HotwireSvelteHelpers.debug) {
|
|
222
222
|
|
|
@@ -230,13 +230,8 @@ export function debugLog(message, object) {
|
|
|
230
230
|
}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
-
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
234
|
-
// ADDITIONAL FUNCTIONS
|
|
235
|
-
// utils that are not used for the primary functions of this package itself, but helpful for building associated functions
|
|
236
|
-
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
237
|
-
|
|
238
|
-
|
|
239
233
|
// find or add the data-panel-id attribute of a button and return it
|
|
234
|
+
|
|
240
235
|
export function getOrSetPanelId(buttonTag) {
|
|
241
236
|
let id = buttonTag.getAttribute('data-panel-id')
|
|
242
237
|
if (id) {
|
|
@@ -259,5 +254,17 @@ function generateRandomHex(n) {
|
|
|
259
254
|
).join('');
|
|
260
255
|
}
|
|
261
256
|
|
|
257
|
+
const OVERLAY_TARGET_ID = 'overlays-box';
|
|
258
|
+
|
|
259
|
+
export function getOverlayTarget() {
|
|
260
|
+
let target = document.getElementById(OVERLAY_TARGET_ID);
|
|
262
261
|
|
|
262
|
+
if (!target) {
|
|
263
|
+
target = document.createElement('div');
|
|
264
|
+
target.id = OVERLAY_TARGET_ID;
|
|
265
|
+
document.body.appendChild(target);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return target;
|
|
269
|
+
}
|
|
263
270
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import DropdownPanel from "./DropdownPanel.svelte";
|
|
3
3
|
import { unmount } from 'svelte'
|
|
4
4
|
import { cleanMount } from "../cleanMount.js";
|
|
5
|
+
import { getOverlayTarget } from "../../lib/utils.js";
|
|
5
6
|
|
|
6
7
|
let { panelContent, panelTitle, panelClass, label, svgIcon, panelPlacement } = $props();
|
|
7
8
|
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
|
|
22
23
|
panelInstance = cleanMount(
|
|
23
24
|
DropdownPanel, {
|
|
24
|
-
target:
|
|
25
|
+
target: getOverlayTarget(),
|
|
25
26
|
props: {
|
|
26
27
|
title: panelTitle,
|
|
27
28
|
closeFunction: closeDropdown,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import Modal from './Modal.svelte';
|
|
3
|
-
import {unmount} from 'svelte'
|
|
4
|
-
import {cleanMount} from "../cleanMount.js";
|
|
3
|
+
import { unmount } from 'svelte'
|
|
4
|
+
import { cleanMount } from "../cleanMount.js";
|
|
5
|
+
import { getOverlayTarget } from "../../lib/utils.js";
|
|
5
6
|
|
|
6
7
|
let {panelTitle, panelContent, label, svgIcon} = $props()
|
|
7
8
|
let modalInstance;
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
function openModal() {
|
|
16
17
|
|
|
17
18
|
modalInstance = cleanMount(Modal, {
|
|
18
|
-
target:
|
|
19
|
+
target: getOverlayTarget(),
|
|
19
20
|
props: {
|
|
20
21
|
title: panelTitle,
|
|
21
22
|
content: panelContent,
|