@csedl/svelte-on-rails 10.0.4 → 10.1.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 +4 -34
- package/index.js +5 -2
- package/package.json +6 -7
- package/src/config.js +53 -19
- package/src/hydrate-build/cleanupSvelteComponent.js +5 -4
- package/src/hydrate-build/initializeSvelteComponent.js +3 -12
- package/src/hydrate-build/svelte-on-rails-controller.js +1 -1
- package/src/logger.js +2 -10
- package/src/streams/componentStreamListener.js +1 -2
- package/src/streams/dispatch-event.js +10 -10
- package/src/streams/turbo-stream-controller.js +2 -2
- package/.idea/modules.xml +0 -8
- package/.idea/node-module.iml +0 -12
- package/.idea/vcs.xml +0 -6
package/README.md
CHANGED
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
# @csedl/svelte-on-rails
|
|
2
2
|
|
|
3
|
-
Works together with the [svelte-on-rails](https://svelte-on-rails.dev) gem.
|
|
4
|
-
|
|
5
|
-
Versions here do not have many updates here, and are more dependend on the versions from the gem.
|
|
6
|
-
So, i added no releases here.
|
|
7
|
-
Checkout Release Notes on the gems repository.
|
|
8
|
-
|
|
9
|
-
## Prerequisites
|
|
10
|
-
|
|
11
|
-
- Please follow the [gem](https://svelte-on-rails.dev) instructions.
|
|
12
|
-
- Svelte >= 5
|
|
13
|
-
- tested with ruby 3.2.2 and rails 7.1
|
|
14
|
-
|
|
15
3
|
## Installation
|
|
16
4
|
|
|
17
5
|
```
|
|
@@ -24,32 +12,14 @@ Add to your entrypoint file, like `application.js`
|
|
|
24
12
|
import '@csedl/svelte-on-rails';
|
|
25
13
|
```
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```javascript
|
|
30
|
-
import { SvelteOnRails } from '@csedl/svelte-on-rails'
|
|
31
|
-
SvelteOnRails.debug = true
|
|
32
|
-
|
|
33
|
-
// source for svelte components for hydration
|
|
34
|
-
// by default svelte components are mapped by sourceCodeDir from vite.json
|
|
35
|
-
// which usually is app/frontend/**/*.svelte
|
|
36
|
-
SvelteOnRails.includeRailsViews = true
|
|
37
|
-
// when set to true, additionaly, app/views/**/*.svelte is mapped
|
|
38
|
-
// => this is a 2016 new introduced feature, status: experimental
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
The `SvelteOnRails` Object is accessible by `window.SvelteOnRails`
|
|
42
|
-
|
|
43
|
-
## What it contains or does
|
|
15
|
+
## What it does
|
|
44
16
|
|
|
45
17
|
- It includes a stimulus controller that handles the initializing event of the svelte component,
|
|
46
18
|
rendered by the ruby gem. Initializing means that the component is mounted or hydrated, together
|
|
47
19
|
with the properties given by the ruby gem.
|
|
48
|
-
- After disappearing, the component is unmounted by the disconnect event of stimulus.
|
|
49
20
|
|
|
50
|
-
|
|
21
|
+
## Description
|
|
51
22
|
|
|
52
|
-
|
|
53
|
-
on Svelte Components.
|
|
54
|
-
- Helper for adding eventListeners on Svelte Components.
|
|
23
|
+
Please follow [svelte-on-rails docs](https://svelte-on-rails.dev) for more information.
|
|
55
24
|
|
|
25
|
+
The repository is shared with the gem [svelte-on-rails](https://gitlab.com/sedl/svelte-on-rails) (monorepo).
|
package/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import SvelteOnRails from "./src/config.js";
|
|
2
2
|
import {Application} from "@hotwired/stimulus"
|
|
3
3
|
import {dispatchSvelteStreamEvent} from "./src/streams/dispatch-event.js";
|
|
4
|
-
import {
|
|
4
|
+
import {streamDebugLog} from "./src/logger.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
//console.error('test-error')
|
|
5
8
|
|
|
6
9
|
if (!window.Stimulus) {
|
|
7
10
|
window.Stimulus = Application.start()
|
|
@@ -19,4 +22,4 @@ import turboStreamController from "./src/streams/turbo-stream-controller.js";
|
|
|
19
22
|
|
|
20
23
|
Stimulus.register('svelte-on-rails-turbo-stream', turboStreamController)
|
|
21
24
|
|
|
22
|
-
export { SvelteOnRails, dispatchSvelteStreamEvent,
|
|
25
|
+
export { SvelteOnRails, dispatchSvelteStreamEvent, streamDebugLog };
|
package/package.json
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@csedl/svelte-on-rails",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.1.1",
|
|
4
4
|
"description": "Hydrates Svelte components from the svelte-on-rails gem and can handle Actions received by Web Socket.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./index.js",
|
|
9
9
|
"./src/streams/componentStreamListener": "./src/streams/componentStreamListener.js",
|
|
10
|
-
"./src/dispatch-event": "./src/streams/dispatch-event.js"
|
|
10
|
+
"./src/streams/dispatch-event.js": "./src/streams/dispatch-event.js",
|
|
11
|
+
"./src/logger.js": "./src/logger.js",
|
|
12
|
+
"./src/config.js": "./src/config.js"
|
|
11
13
|
},
|
|
12
14
|
"peerDependencies": {
|
|
13
15
|
"@hotwired/stimulus": "^3.2.2",
|
|
14
16
|
"svelte": "^5.50.0"
|
|
15
17
|
},
|
|
16
|
-
"scripts": {
|
|
17
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
18
|
-
},
|
|
19
18
|
"repository": {
|
|
20
19
|
"type": "git",
|
|
21
|
-
"url": "
|
|
20
|
+
"url": "https://gitlab.com/sedl/svelte-on-rails"
|
|
22
21
|
},
|
|
23
22
|
"keywords": [
|
|
24
23
|
"svelte",
|
|
@@ -28,7 +27,7 @@
|
|
|
28
27
|
"author": "Christian Sedlmair",
|
|
29
28
|
"license": "LICENSE.md",
|
|
30
29
|
"bugs": {
|
|
31
|
-
"url": "https://gitlab.com/sedl/
|
|
30
|
+
"url": "https://gitlab.com/sedl/svelte-on-rails/-/issues"
|
|
32
31
|
},
|
|
33
32
|
"homepage": "https://svelte-on-rails.dev"
|
|
34
33
|
}
|
package/src/config.js
CHANGED
|
@@ -1,11 +1,62 @@
|
|
|
1
|
+
import {streamDebugLog} from "./logger.js";
|
|
1
2
|
// src/config.js
|
|
2
3
|
let _debug = false;
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
let _lazyComponents = {}
|
|
6
|
+
let _defaultComponents = import.meta.glob("/**/*.svelte", { eager: false, import: "default" });
|
|
5
7
|
|
|
6
8
|
import {debugLog} from "./logger.js";
|
|
7
9
|
|
|
8
10
|
const SvelteOnRails = {
|
|
11
|
+
|
|
12
|
+
async loadComponent(componentKey) {
|
|
13
|
+
|
|
14
|
+
// fetch loader from store
|
|
15
|
+
|
|
16
|
+
let components
|
|
17
|
+
if (Object.keys(_lazyComponents).length === 0) {
|
|
18
|
+
debugLog("lazyComponents not set: falling back to built-in «import.meta.glob(['/**/*.svelte'], {eager: false, import: 'default'})»");
|
|
19
|
+
components = _defaultComponents;
|
|
20
|
+
} else {
|
|
21
|
+
debugLog(`[svelte-on-rails] using given lazyComponents`);
|
|
22
|
+
components = _lazyComponents
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
const loader = components[componentKey];
|
|
27
|
+
console.log(`[svelte-on-rails:debug] loader`, loader);
|
|
28
|
+
if (!loader) {
|
|
29
|
+
throw new Error(`[svelte-on-rails] Component not found: ${componentKey} (relative to vites sourceCodeDir / frontend-folder)`);
|
|
30
|
+
//return;
|
|
31
|
+
} else {
|
|
32
|
+
console.log(`[svelte-on-rails] Component found: ${componentKey}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// load and validate component
|
|
36
|
+
|
|
37
|
+
let comp;
|
|
38
|
+
if (loader.prototype) {
|
|
39
|
+
console.warn(`[svelte-on-rails] Components should be lazy loaded. Did you use vite.meta.glob(..., {eager: true})?`);
|
|
40
|
+
comp = loader;
|
|
41
|
+
} else {
|
|
42
|
+
comp = await loader();
|
|
43
|
+
if (typeof comp !== 'function') {
|
|
44
|
+
throw new Error(`[svelte-on-rails] Component is not a function: ${componentKey}\nYou may need to use vite.meta.glob(..., {...import: "default"})`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// finish
|
|
49
|
+
|
|
50
|
+
console.log(`[svelte-on-rails:debug] Component loaded:`, comp);
|
|
51
|
+
return comp;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
set lazyComponents(value) {
|
|
55
|
+
console.log(`[svelte-on-rails:debug] lazyComponents set:`, value);
|
|
56
|
+
_lazyComponents = value;
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
|
|
9
60
|
get debug() {
|
|
10
61
|
return _debug;
|
|
11
62
|
},
|
|
@@ -13,23 +64,6 @@ const SvelteOnRails = {
|
|
|
13
64
|
_debug = !!value;
|
|
14
65
|
debugLog(`Debug mode: ${_debug ? "enabled" : "disabled"}`);
|
|
15
66
|
},
|
|
16
|
-
|
|
17
|
-
// includeRailsViews
|
|
18
|
-
get includeRailsViews() { // ← clearer, reads like a question
|
|
19
|
-
return _includeRailsViews;
|
|
20
|
-
},
|
|
21
|
-
set includeRailsViews(value) {
|
|
22
|
-
_includeRailsViews = !!value;
|
|
23
|
-
debugLog(`Include components within app/views: ${_includeRailsViews ? "enabled" : "disabled"}`);
|
|
24
|
-
if (_includeRailsViews) {
|
|
25
|
-
const _viewComponents = import.meta.glob("/../../app/views/**/*.svelte", {eager: false, import: "default"});
|
|
26
|
-
Object.assign(_componentModules, _viewComponents);
|
|
27
|
-
debugLog(`loaded view-components: `);
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
get components() {
|
|
31
|
-
return(_componentModules);
|
|
32
|
-
}
|
|
33
67
|
};
|
|
34
68
|
|
|
35
69
|
window.SvelteOnRails = SvelteOnRails;
|
|
@@ -7,19 +7,20 @@ const svelteInstances = new WeakMap();
|
|
|
7
7
|
/**
|
|
8
8
|
* Cleans up all initialized Svelte component instances.
|
|
9
9
|
*/
|
|
10
|
-
export function cleanupSvelteComponent(element
|
|
10
|
+
export function cleanupSvelteComponent(element) {
|
|
11
11
|
try {
|
|
12
12
|
const instance = svelteInstances.get(element);
|
|
13
13
|
if (instance) {
|
|
14
14
|
unmount(instance); // Destroy the Svelte component instance in Svelte 5
|
|
15
|
-
debugLog(`Successfully unmounted Svelte component for element:`, element
|
|
15
|
+
debugLog(`Successfully unmounted Svelte component for element:`, element);
|
|
16
16
|
element.removeAttribute('data-svelte-initialized'); // Reset initialized state
|
|
17
17
|
svelteInstances.delete(element); // Remove from WeakMap
|
|
18
18
|
} else {
|
|
19
|
-
|
|
19
|
+
let comps = document.getElementsByClassName('svelte-component')
|
|
20
|
+
debugLog(`Actual ${comps.length} components on the page. No Svelte instance found`, element);
|
|
20
21
|
}
|
|
21
22
|
} catch (e) {
|
|
22
|
-
console.error(`[
|
|
23
|
+
console.error(`[svelte-on-rails:stream] Error unmounting Svelte component for element:`, e);
|
|
23
24
|
// Fallback: Clear element content to prevent stale content
|
|
24
25
|
element.innerHTML = '';
|
|
25
26
|
}
|
|
@@ -17,20 +17,11 @@ export async function initializeSvelteComponent(element) {
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
debugLog(`start
|
|
20
|
+
debugLog(`start ${action} for ${componentKey}`);
|
|
21
21
|
|
|
22
22
|
// load the component from lazy import
|
|
23
23
|
|
|
24
|
-
const
|
|
25
|
-
if (!loader) {
|
|
26
|
-
console.error(`[svelte-on-rails] Component not found: ${componentKey} (relative to vites sourceCodeDir / frontend-folder)`);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
debugLog(`found: ${componentKey} from lazy-imported components`);
|
|
30
|
-
|
|
31
|
-
const Component = await loader();
|
|
32
|
-
debugLog(`loaded successfully: ${componentKey}`);
|
|
33
|
-
|
|
24
|
+
const Component = await SvelteOnRails.loadComponent(componentKey);
|
|
34
25
|
|
|
35
26
|
// Parse props (unchanged)
|
|
36
27
|
let props = {};
|
|
@@ -39,7 +30,7 @@ export async function initializeSvelteComponent(element) {
|
|
|
39
30
|
try {
|
|
40
31
|
props = JSON.parse(propsString);
|
|
41
32
|
} catch (e) {
|
|
42
|
-
console.error(`Error parsing data-props for ${componentKey}:`, e);
|
|
33
|
+
console.error(`[svelte-on-rails] Error parsing data-props for ${componentKey}:`, e);
|
|
43
34
|
}
|
|
44
35
|
}
|
|
45
36
|
|
|
@@ -8,7 +8,7 @@ export default class extends Controller {
|
|
|
8
8
|
const stat = this.element.getAttribute('data-svelte-status');
|
|
9
9
|
if (stat === 'do-not-hydrate-build-me') return;
|
|
10
10
|
|
|
11
|
-
initializeSvelteComponent(this.element, false);
|
|
11
|
+
initializeSvelteComponent(this.element, false).then(r => {});
|
|
12
12
|
|
|
13
13
|
}
|
|
14
14
|
|
package/src/logger.js
CHANGED
|
@@ -4,16 +4,8 @@ export function debugLog(message, object, object2) {
|
|
|
4
4
|
log( null, message, object, object2);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function receiveStreamEventDebugLog(message, object, object2) {
|
|
12
|
-
log( 'receive-stream-event', message, object, object2);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function actionCableDebugLog(message, object, object2) {
|
|
16
|
-
log( 'action-cable', message, object, object2);
|
|
7
|
+
export function streamDebugLog(message, object, object2) {
|
|
8
|
+
log( 'stream', message, object, object2);
|
|
17
9
|
}
|
|
18
10
|
|
|
19
11
|
function log(namespace, message, object, object2) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
///import {receiveStreamEventDebugLog} from "./logger.js";
|
|
2
1
|
|
|
3
2
|
// componentStreamListener.js (in your npm package)
|
|
4
3
|
export function addComponentStreamListener(node, callback) {
|
|
@@ -7,7 +6,7 @@ export function addComponentStreamListener(node, callback) {
|
|
|
7
6
|
const wrapper = node.closest('.svelte-component');
|
|
8
7
|
|
|
9
8
|
if (!wrapper) {
|
|
10
|
-
console.error('[svelte-on-rails:
|
|
9
|
+
console.error('[svelte-on-rails:stream] No wrapping element with class .svelte-component found!');
|
|
11
10
|
return;
|
|
12
11
|
}
|
|
13
12
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {streamDebugLog} from "../logger.js";
|
|
2
2
|
|
|
3
3
|
export function dispatchSvelteStreamEvent(args) {
|
|
4
4
|
|
|
@@ -9,7 +9,7 @@ export function dispatchSvelteStreamEvent(args) {
|
|
|
9
9
|
throw new Error(`[svelte-on-rails:dispatch-event] Invalid keys found: ${invalidKeys.join(', ')}. Allowed keys are: ${allowedKeys.join(', ')}.`);
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
streamDebugLog(`parsed arguments:`, args)
|
|
13
13
|
|
|
14
14
|
const eventName = args.event || 'stream-action'
|
|
15
15
|
const customEvent = new CustomEvent(eventName, {detail: args['eventDetail']})
|
|
@@ -27,12 +27,12 @@ function dispatchByComponent(args, event) {
|
|
|
27
27
|
// find components
|
|
28
28
|
let components
|
|
29
29
|
if (args.component) {
|
|
30
|
-
const componentsSelector = `[data-
|
|
30
|
+
const componentsSelector = `[data-component="${args.component}"]`
|
|
31
31
|
components = document.querySelectorAll(componentsSelector)
|
|
32
|
-
|
|
32
|
+
streamDebugLog(`found ${components.length} components by selector «${componentsSelector}»`, components)
|
|
33
33
|
} else {
|
|
34
34
|
components = Array.from(document.getElementsByClassName('svelte-component'))
|
|
35
|
-
|
|
35
|
+
streamDebugLog(`found ${components.length} components by class-name «svelte-component» (no components selector given)`, components)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// dispatch elements
|
|
@@ -42,14 +42,14 @@ function dispatchByComponent(args, event) {
|
|
|
42
42
|
if (args.selector) {
|
|
43
43
|
const elements = component.querySelectorAll(args.selector)
|
|
44
44
|
if (elements.length === 0) {
|
|
45
|
-
|
|
45
|
+
streamDebugLog(`no elements found by selector «${args.selector}», within:`, component)
|
|
46
46
|
}
|
|
47
47
|
elements.forEach(element => {
|
|
48
|
-
|
|
48
|
+
streamDebugLog(`dispatch event «${event.type}» on element:`, element)
|
|
49
49
|
element.dispatchEvent(event)
|
|
50
50
|
})
|
|
51
51
|
} else {
|
|
52
|
-
|
|
52
|
+
streamDebugLog(`dispatch event «${event.type}» on components wrapper:`, component)
|
|
53
53
|
component.dispatchEvent(event)
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -64,12 +64,12 @@ function dispatchBySelector(args, event) {
|
|
|
64
64
|
const elements = document.querySelectorAll(args.selector)
|
|
65
65
|
|
|
66
66
|
if (elements.length === 0) {
|
|
67
|
-
|
|
67
|
+
streamDebugLog(`no elements found by selector «${args.selector}»`)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
elements.forEach(element => {
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
streamDebugLog(`dispatch event «${event.type}» on element:`, element)
|
|
73
73
|
element.dispatchEvent(event)
|
|
74
74
|
|
|
75
75
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {Controller} from "@hotwired/stimulus"
|
|
2
|
-
import {
|
|
2
|
+
import {streamDebugLog} from "../logger.js";
|
|
3
3
|
import {dispatchSvelteStreamEvent} from "./dispatch-event.js";
|
|
4
4
|
|
|
5
5
|
export default class extends Controller {
|
|
@@ -7,7 +7,7 @@ export default class extends Controller {
|
|
|
7
7
|
connect() {
|
|
8
8
|
|
|
9
9
|
const argsBase64 = this.element.getAttribute('data-args')
|
|
10
|
-
|
|
10
|
+
streamDebugLog('turbo-stream received with base-64 encoded string:', argsBase64)
|
|
11
11
|
|
|
12
12
|
const decodedString = this.decodeBase64(argsBase64)
|
|
13
13
|
|
package/.idea/modules.xml
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<project version="4">
|
|
3
|
-
<component name="ProjectModuleManager">
|
|
4
|
-
<modules>
|
|
5
|
-
<module fileurl="file://$PROJECT_DIR$/.idea/node-module.iml" filepath="$PROJECT_DIR$/.idea/node-module.iml" />
|
|
6
|
-
</modules>
|
|
7
|
-
</component>
|
|
8
|
-
</project>
|
package/.idea/node-module.iml
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="WEB_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager">
|
|
4
|
-
<content url="file://$MODULE_DIR$">
|
|
5
|
-
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
6
|
-
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
7
|
-
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
8
|
-
</content>
|
|
9
|
-
<orderEntry type="inheritedJdk" />
|
|
10
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
11
|
-
</component>
|
|
12
|
-
</module>
|