slicejs-web-framework 2.3.3 → 2.3.5
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/Slice/Components/Structural/ContextManager/ContextManagerDebugger.js +39 -0
- package/Slice/Components/Structural/EventManager/EventManagerDebugger.js +131 -8
- package/api/index.js +0 -6
- package/package.json +1 -1
- package/src/Components/Visual/Link/Link.css +8 -0
- package/src/Components/Visual/Link/Link.html +1 -0
- package/src/Components/Visual/Link/Link.js +63 -0
- package/src/Components/components.js +2 -2
- package/src/sliceConfig.json +68 -60
- package/src/Components/Service/Link/Link.js +0 -26
|
@@ -17,6 +17,7 @@ export default class ContextManagerDebugger extends HTMLElement {
|
|
|
17
17
|
slice.stylesManager.registerComponentStyles('ContextManagerDebugger', this.renderStyles());
|
|
18
18
|
this.cacheElements();
|
|
19
19
|
this.bindEvents();
|
|
20
|
+
this.makeDraggable();
|
|
20
21
|
this.renderList();
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -53,6 +54,7 @@ export default class ContextManagerDebugger extends HTMLElement {
|
|
|
53
54
|
|
|
54
55
|
cacheElements() {
|
|
55
56
|
this.container = this.querySelector('#context-debugger');
|
|
57
|
+
this.header = this.querySelector('.context-header');
|
|
56
58
|
this.list = this.querySelector('#context-list');
|
|
57
59
|
this.filterInput = this.querySelector('#context-filter');
|
|
58
60
|
this.countLabel = this.querySelector('#context-count');
|
|
@@ -69,6 +71,42 @@ export default class ContextManagerDebugger extends HTMLElement {
|
|
|
69
71
|
});
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
makeDraggable() {
|
|
75
|
+
if (!this.header || !this.container) return;
|
|
76
|
+
|
|
77
|
+
let offset = { x: 0, y: 0 };
|
|
78
|
+
let isDragging = false;
|
|
79
|
+
|
|
80
|
+
this.header.style.cursor = 'grab';
|
|
81
|
+
|
|
82
|
+
this.header.addEventListener('mousedown', (event) => {
|
|
83
|
+
if (event.target.closest('.btn')) return;
|
|
84
|
+
isDragging = true;
|
|
85
|
+
offset.x = event.clientX - this.container.getBoundingClientRect().left;
|
|
86
|
+
offset.y = event.clientY - this.container.getBoundingClientRect().top;
|
|
87
|
+
this.header.style.cursor = 'grabbing';
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
document.addEventListener('mousemove', (event) => {
|
|
91
|
+
if (!isDragging) return;
|
|
92
|
+
const rect = this.container.getBoundingClientRect();
|
|
93
|
+
const maxX = window.innerWidth - rect.width;
|
|
94
|
+
const maxY = window.innerHeight - rect.height;
|
|
95
|
+
const x = Math.min(Math.max(event.clientX - offset.x, 0), maxX);
|
|
96
|
+
const y = Math.min(Math.max(event.clientY - offset.y, 0), maxY);
|
|
97
|
+
this.container.style.left = `${x}px`;
|
|
98
|
+
this.container.style.top = `${y}px`;
|
|
99
|
+
this.container.style.right = 'auto';
|
|
100
|
+
this.container.style.bottom = 'auto';
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
document.addEventListener('mouseup', () => {
|
|
104
|
+
if (!isDragging) return;
|
|
105
|
+
isDragging = false;
|
|
106
|
+
this.header.style.cursor = 'grab';
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
72
110
|
renderList() {
|
|
73
111
|
if (!slice?.context?.contexts) {
|
|
74
112
|
this.list.textContent = 'ContextManager not available.';
|
|
@@ -165,6 +203,7 @@ export default class ContextManagerDebugger extends HTMLElement {
|
|
|
165
203
|
padding: 12px 14px;
|
|
166
204
|
background: var(--tertiary-background-color);
|
|
167
205
|
border-bottom: 1px solid var(--medium-color);
|
|
206
|
+
user-select: none;
|
|
168
207
|
}
|
|
169
208
|
|
|
170
209
|
.context-header .title {
|
|
@@ -18,6 +18,7 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
18
18
|
slice.stylesManager.registerComponentStyles('EventManagerDebugger', this.renderStyles());
|
|
19
19
|
this.cacheElements();
|
|
20
20
|
this.bindEvents();
|
|
21
|
+
this.makeDraggable();
|
|
21
22
|
this.renderList();
|
|
22
23
|
}
|
|
23
24
|
|
|
@@ -54,6 +55,7 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
54
55
|
|
|
55
56
|
cacheElements() {
|
|
56
57
|
this.container = this.querySelector('#events-debugger');
|
|
58
|
+
this.header = this.querySelector('.events-header');
|
|
57
59
|
this.list = this.querySelector('#events-list');
|
|
58
60
|
this.filterInput = this.querySelector('#events-filter');
|
|
59
61
|
this.countLabel = this.querySelector('#events-count');
|
|
@@ -70,6 +72,42 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
makeDraggable() {
|
|
76
|
+
if (!this.header || !this.container) return;
|
|
77
|
+
|
|
78
|
+
let offset = { x: 0, y: 0 };
|
|
79
|
+
let isDragging = false;
|
|
80
|
+
|
|
81
|
+
this.header.style.cursor = 'grab';
|
|
82
|
+
|
|
83
|
+
this.header.addEventListener('mousedown', (event) => {
|
|
84
|
+
if (event.target.closest('.btn')) return;
|
|
85
|
+
isDragging = true;
|
|
86
|
+
offset.x = event.clientX - this.container.getBoundingClientRect().left;
|
|
87
|
+
offset.y = event.clientY - this.container.getBoundingClientRect().top;
|
|
88
|
+
this.header.style.cursor = 'grabbing';
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
document.addEventListener('mousemove', (event) => {
|
|
92
|
+
if (!isDragging) return;
|
|
93
|
+
const rect = this.container.getBoundingClientRect();
|
|
94
|
+
const maxX = window.innerWidth - rect.width;
|
|
95
|
+
const maxY = window.innerHeight - rect.height;
|
|
96
|
+
const x = Math.min(Math.max(event.clientX - offset.x, 0), maxX);
|
|
97
|
+
const y = Math.min(Math.max(event.clientY - offset.y, 0), maxY);
|
|
98
|
+
this.container.style.left = `${x}px`;
|
|
99
|
+
this.container.style.top = `${y}px`;
|
|
100
|
+
this.container.style.right = 'auto';
|
|
101
|
+
this.container.style.bottom = 'auto';
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
document.addEventListener('mouseup', () => {
|
|
105
|
+
if (!isDragging) return;
|
|
106
|
+
isDragging = false;
|
|
107
|
+
this.header.style.cursor = 'grab';
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
73
111
|
renderList() {
|
|
74
112
|
if (!slice?.events?.subscriptions) {
|
|
75
113
|
this.list.textContent = 'EventManager not available.';
|
|
@@ -79,11 +117,23 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
79
117
|
|
|
80
118
|
const items = [];
|
|
81
119
|
slice.events.subscriptions.forEach((subs, eventName) => {
|
|
82
|
-
const
|
|
120
|
+
const entries = Array.from(subs.entries()).map(([id, sub]) => {
|
|
121
|
+
const componentSliceId = sub.componentSliceId || null;
|
|
122
|
+
const component = componentSliceId ? slice.controller.getComponent(componentSliceId) : null;
|
|
123
|
+
const componentName = component?.constructor?.name || null;
|
|
124
|
+
return {
|
|
125
|
+
id,
|
|
126
|
+
once: sub.once,
|
|
127
|
+
componentSliceId,
|
|
128
|
+
componentName
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
|
|
83
132
|
if (this.filterText && !eventName.toLowerCase().includes(this.filterText)) {
|
|
84
133
|
return;
|
|
85
134
|
}
|
|
86
|
-
|
|
135
|
+
|
|
136
|
+
items.push({ eventName, count: subs.size, entries });
|
|
87
137
|
});
|
|
88
138
|
|
|
89
139
|
items.sort((a, b) => a.eventName.localeCompare(b.eventName));
|
|
@@ -91,11 +141,29 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
91
141
|
this.countLabel.textContent = String(items.length);
|
|
92
142
|
this.list.innerHTML = items.length
|
|
93
143
|
? items.map((item) => {
|
|
144
|
+
const details = item.entries.map((entry) => {
|
|
145
|
+
const label = entry.componentName
|
|
146
|
+
? `${entry.componentName} (${entry.componentSliceId})`
|
|
147
|
+
: entry.componentSliceId || 'Global';
|
|
148
|
+
const onceBadge = entry.once ? '<span class="badge">once</span>' : '';
|
|
149
|
+
return `
|
|
150
|
+
<div class="subscriber-row">
|
|
151
|
+
<div class="subscriber-name">${label}</div>
|
|
152
|
+
<div class="subscriber-meta">${entry.id}${onceBadge}</div>
|
|
153
|
+
</div>
|
|
154
|
+
`;
|
|
155
|
+
}).join('');
|
|
156
|
+
|
|
94
157
|
return `
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
158
|
+
<details class="event-row">
|
|
159
|
+
<summary>
|
|
160
|
+
<div class="event-name">${item.eventName}</div>
|
|
161
|
+
<div class="event-count">${item.count}</div>
|
|
162
|
+
</summary>
|
|
163
|
+
<div class="subscriber-list">
|
|
164
|
+
${details || '<div class="empty">No subscribers</div>'}
|
|
165
|
+
</div>
|
|
166
|
+
</details>
|
|
99
167
|
`;
|
|
100
168
|
}).join('')
|
|
101
169
|
: '<div class="empty">No events</div>';
|
|
@@ -153,6 +221,7 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
153
221
|
padding: 12px 14px;
|
|
154
222
|
background: var(--tertiary-background-color);
|
|
155
223
|
border-bottom: 1px solid var(--medium-color);
|
|
224
|
+
user-select: none;
|
|
156
225
|
}
|
|
157
226
|
|
|
158
227
|
.events-header .title {
|
|
@@ -202,13 +271,24 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
202
271
|
}
|
|
203
272
|
|
|
204
273
|
.event-row {
|
|
205
|
-
display:
|
|
206
|
-
justify-content: space-between;
|
|
274
|
+
display: block;
|
|
207
275
|
padding: 8px 10px;
|
|
208
276
|
background: var(--tertiary-background-color);
|
|
209
277
|
border-radius: 6px;
|
|
210
278
|
border: 1px solid var(--medium-color);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.event-row summary {
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: center;
|
|
284
|
+
justify-content: space-between;
|
|
211
285
|
gap: 8px;
|
|
286
|
+
cursor: pointer;
|
|
287
|
+
list-style: none;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.event-row summary::-webkit-details-marker {
|
|
291
|
+
display: none;
|
|
212
292
|
}
|
|
213
293
|
|
|
214
294
|
.event-name {
|
|
@@ -225,6 +305,49 @@ export default class EventManagerDebugger extends HTMLElement {
|
|
|
225
305
|
color: var(--primary-color);
|
|
226
306
|
}
|
|
227
307
|
|
|
308
|
+
.subscriber-list {
|
|
309
|
+
margin-top: 10px;
|
|
310
|
+
display: flex;
|
|
311
|
+
flex-direction: column;
|
|
312
|
+
gap: 8px;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.subscriber-row {
|
|
316
|
+
display: flex;
|
|
317
|
+
justify-content: space-between;
|
|
318
|
+
gap: 8px;
|
|
319
|
+
padding: 6px 8px;
|
|
320
|
+
border-radius: 6px;
|
|
321
|
+
background: var(--primary-background-color);
|
|
322
|
+
border: 1px solid var(--medium-color);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.subscriber-name {
|
|
326
|
+
font-size: 12px;
|
|
327
|
+
color: var(--font-primary-color);
|
|
328
|
+
overflow: hidden;
|
|
329
|
+
text-overflow: ellipsis;
|
|
330
|
+
white-space: nowrap;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.subscriber-meta {
|
|
334
|
+
font-size: 11px;
|
|
335
|
+
color: var(--font-secondary-color);
|
|
336
|
+
display: flex;
|
|
337
|
+
align-items: center;
|
|
338
|
+
gap: 6px;
|
|
339
|
+
white-space: nowrap;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.badge {
|
|
343
|
+
padding: 2px 6px;
|
|
344
|
+
border-radius: 999px;
|
|
345
|
+
background: var(--secondary-color);
|
|
346
|
+
color: var(--secondary-color-contrast);
|
|
347
|
+
font-size: 10px;
|
|
348
|
+
text-transform: uppercase;
|
|
349
|
+
}
|
|
350
|
+
|
|
228
351
|
.empty {
|
|
229
352
|
color: var(--font-secondary-color);
|
|
230
353
|
font-size: 12px;
|
package/api/index.js
CHANGED
|
@@ -97,12 +97,6 @@ function bundlesDirectoryExists() {
|
|
|
97
97
|
return fs.existsSync(bundleDir) && fs.statSync(bundleDir).isDirectory();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// Capturar todas las peticiones a bundles para debugging
|
|
101
|
-
app.use('/bundles/', (req, res, next) => {
|
|
102
|
-
console.log(`🔍 Bundle request: ${req.method} ${req.originalUrl}`);
|
|
103
|
-
next();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
100
|
// Middleware personalizado para archivos de bundles con MIME types correctos
|
|
107
101
|
// ⚠️ DEBE IR ANTES del middleware general para tener prioridad
|
|
108
102
|
app.use('/bundles/', (req, res, next) => {
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<a href="#" class="slice-link" data-route></a>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export default class Link extends HTMLElement {
|
|
2
|
+
static props = {
|
|
3
|
+
path: { type: 'string', default: '#' },
|
|
4
|
+
classes: { type: 'string', default: '' },
|
|
5
|
+
text: { type: 'string', default: '' }
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
constructor(props = {}) {
|
|
9
|
+
super();
|
|
10
|
+
slice.attachTemplate(this);
|
|
11
|
+
this.$anchor = this.querySelector('.slice-link');
|
|
12
|
+
|
|
13
|
+
slice.controller.setComponentProps(this, props);
|
|
14
|
+
this.debuggerProps = ['path', 'classes', 'text'];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async init() {
|
|
18
|
+
this.updateLink();
|
|
19
|
+
this.addEventListener('click', this.onClick.bind(this));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
updateLink() {
|
|
23
|
+
if (!this.$anchor) return;
|
|
24
|
+
this.$anchor.setAttribute('href', this.path || '#');
|
|
25
|
+
this.$anchor.textContent = this.text || '';
|
|
26
|
+
this.$anchor.className = `slice-link ${this.classes || ''}`.trim();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async onClick(event) {
|
|
30
|
+
event.preventDefault();
|
|
31
|
+
const path = this.path || this.$anchor?.getAttribute('href') || '#';
|
|
32
|
+
slice.router.navigate(path);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
set path(value) {
|
|
36
|
+
this._path = value;
|
|
37
|
+
this.updateLink();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get path() {
|
|
41
|
+
return this._path;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set classes(value) {
|
|
45
|
+
this._classes = value;
|
|
46
|
+
this.updateLink();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get classes() {
|
|
50
|
+
return this._classes;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
set text(value) {
|
|
54
|
+
this._text = value;
|
|
55
|
+
this.updateLink();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
get text() {
|
|
59
|
+
return this._text;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
customElements.define('slice-link', Link);
|
|
@@ -16,12 +16,12 @@ const components = {
|
|
|
16
16
|
"Navbar": "Visual",
|
|
17
17
|
"NotFound": "Visual",
|
|
18
18
|
"Route": "Visual",
|
|
19
|
+
"Link": "Visual",
|
|
19
20
|
"Select": "Visual",
|
|
20
21
|
"Switch": "Visual",
|
|
21
22
|
"TreeItem": "Visual",
|
|
22
23
|
"TreeView": "Visual",
|
|
23
24
|
"FetchManager": "Service",
|
|
24
25
|
"IndexedDbManager": "Service",
|
|
25
|
-
"Link": "Service",
|
|
26
26
|
"LocalStorageManager": "Service"
|
|
27
|
-
}; export default components;
|
|
27
|
+
}; export default components;
|
package/src/sliceConfig.json
CHANGED
|
@@ -1,60 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"server": {
|
|
3
|
-
"port": 3001,
|
|
4
|
-
"host": "localhost"
|
|
5
|
-
},
|
|
6
|
-
"debugger": {
|
|
7
|
-
"enabled": false,
|
|
8
|
-
"click": "right"
|
|
9
|
-
},
|
|
10
|
-
"events": {
|
|
11
|
-
"enabled": true
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"path": "/Components/
|
|
47
|
-
"type": "
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
{
|
|
2
|
+
"server": {
|
|
3
|
+
"port": 3001,
|
|
4
|
+
"host": "localhost"
|
|
5
|
+
},
|
|
6
|
+
"debugger": {
|
|
7
|
+
"enabled": false,
|
|
8
|
+
"click": "right"
|
|
9
|
+
},
|
|
10
|
+
"events": {
|
|
11
|
+
"enabled": true,
|
|
12
|
+
"ui": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"shortcut": "alt+shift+e"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"context": {
|
|
18
|
+
"enabled": true,
|
|
19
|
+
"ui": {
|
|
20
|
+
"enabled": true,
|
|
21
|
+
"shortcut": "alt+shift+c"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"stylesManager": {
|
|
25
|
+
"requestedStyles": ["sliceStyles"]
|
|
26
|
+
},
|
|
27
|
+
"themeManager": {
|
|
28
|
+
"enabled": true,
|
|
29
|
+
"defaultTheme": "Slice",
|
|
30
|
+
"saveThemeLocally": false,
|
|
31
|
+
"useBrowserTheme": false
|
|
32
|
+
},
|
|
33
|
+
"logger": {
|
|
34
|
+
"enabled": true,
|
|
35
|
+
"showLogs": {
|
|
36
|
+
"console": {
|
|
37
|
+
"error": true,
|
|
38
|
+
"warning": true,
|
|
39
|
+
"info": false
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"paths": {
|
|
44
|
+
"components": {
|
|
45
|
+
"AppComponents": {
|
|
46
|
+
"path": "/Components/AppComponents",
|
|
47
|
+
"type": "Visual"
|
|
48
|
+
},
|
|
49
|
+
"Visual": {
|
|
50
|
+
"path": "/Components/Visual",
|
|
51
|
+
"type": "Visual"
|
|
52
|
+
},
|
|
53
|
+
"Service": {
|
|
54
|
+
"path": "/Components/Service",
|
|
55
|
+
"type": "Service"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"themes": "/Themes",
|
|
59
|
+
"styles": "/Styles",
|
|
60
|
+
"routesFile": "/routes.js"
|
|
61
|
+
},
|
|
62
|
+
"router": {
|
|
63
|
+
"defaultRoute": "/"
|
|
64
|
+
},
|
|
65
|
+
"loading": {
|
|
66
|
+
"enabled": true
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export default class Link extends HTMLElement {
|
|
2
|
-
constructor(props = {}) {
|
|
3
|
-
super();
|
|
4
|
-
this.props = props;
|
|
5
|
-
this.innerHTML = this.getTemplate(props);
|
|
6
|
-
this.init();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
init() {
|
|
10
|
-
this.addEventListener('click', this.onClick);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async onClick(event) {
|
|
14
|
-
event.preventDefault();
|
|
15
|
-
const path = this.querySelector('a').getAttribute('href');
|
|
16
|
-
const routeTargets = document.querySelectorAll('slice-routetarget');
|
|
17
|
-
slice.router.navigate(path);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
getTemplate(props = {}) {
|
|
21
|
-
const { path = '#', classes = '', text = '' } = props;
|
|
22
|
-
return `<a href="${path}" class="${classes}" data-route>${text}</a>`;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
customElements.define('slice-link', Link);
|