@doyosi/laraisy 1.0.2 → 1.0.4
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/package.json +1 -1
- package/src/DSSvgFetch.js +69 -69
- package/src/DSTabs.js +46 -17
package/package.json
CHANGED
package/src/DSSvgFetch.js
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DSSvgFetch
|
|
3
|
-
* Fetches SVG files and injects them inline.
|
|
4
|
-
* Replaces <svg> classes with those defined in data-class.
|
|
5
|
-
*/
|
|
6
|
-
export
|
|
7
|
-
constructor(options = {}) {
|
|
8
|
-
this.config = {
|
|
9
|
-
selector: '.icon-fetch-web',
|
|
10
|
-
attribute: 'data-svg',
|
|
11
|
-
classAttribute: 'data-class', // New config for the class data
|
|
12
|
-
...options
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
this.svgCache = new Map();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
init() {
|
|
19
|
-
const elements = document.querySelectorAll(this.config.selector);
|
|
20
|
-
|
|
21
|
-
elements.forEach(element => {
|
|
22
|
-
if (element.dataset.svgProcessed) return;
|
|
23
|
-
this.processElement(element);
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async processElement(element) {
|
|
28
|
-
const url = element.getAttribute(this.config.attribute);
|
|
29
|
-
const customClasses = element.getAttribute(this.config.classAttribute);
|
|
30
|
-
|
|
31
|
-
if (!url) return;
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
element.dataset.svgProcessed = 'true';
|
|
35
|
-
|
|
36
|
-
// 1. Fetch content (or get from cache)
|
|
37
|
-
const svgContent = await this.fetchSvg(url);
|
|
38
|
-
|
|
39
|
-
// 2. Inject HTML
|
|
40
|
-
element.innerHTML = svgContent;
|
|
41
|
-
|
|
42
|
-
// 3. Apply custom classes if data-class exists
|
|
43
|
-
if (customClasses) {
|
|
44
|
-
const svg = element.querySelector('svg');
|
|
45
|
-
if (svg) {
|
|
46
|
-
// setAttribute overwrites the entire 'class' attribute,
|
|
47
|
-
// effectively removing old classes and adding the new ones.
|
|
48
|
-
svg.setAttribute('class', customClasses);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
} catch (error) {
|
|
53
|
-
console.error(`DSSvgFetch: Failed to load ${url}`, error);
|
|
54
|
-
delete element.dataset.svgProcessed;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async fetchSvg(url) {
|
|
59
|
-
if (this.svgCache.has(url)) {
|
|
60
|
-
return this.svgCache.get(url);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const response = await fetch(url);
|
|
64
|
-
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
65
|
-
|
|
66
|
-
const text = await response.text();
|
|
67
|
-
this.svgCache.set(url, text);
|
|
68
|
-
return text;
|
|
69
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* DSSvgFetch
|
|
3
|
+
* Fetches SVG files and injects them inline.
|
|
4
|
+
* Replaces <svg> classes with those defined in data-class.
|
|
5
|
+
*/
|
|
6
|
+
export class DSSvgFetch {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.config = {
|
|
9
|
+
selector: '.icon-fetch-web',
|
|
10
|
+
attribute: 'data-svg',
|
|
11
|
+
classAttribute: 'data-class', // New config for the class data
|
|
12
|
+
...options
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
this.svgCache = new Map();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
init() {
|
|
19
|
+
const elements = document.querySelectorAll(this.config.selector);
|
|
20
|
+
|
|
21
|
+
elements.forEach(element => {
|
|
22
|
+
if (element.dataset.svgProcessed) return;
|
|
23
|
+
this.processElement(element);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async processElement(element) {
|
|
28
|
+
const url = element.getAttribute(this.config.attribute);
|
|
29
|
+
const customClasses = element.getAttribute(this.config.classAttribute);
|
|
30
|
+
|
|
31
|
+
if (!url) return;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
element.dataset.svgProcessed = 'true';
|
|
35
|
+
|
|
36
|
+
// 1. Fetch content (or get from cache)
|
|
37
|
+
const svgContent = await this.fetchSvg(url);
|
|
38
|
+
|
|
39
|
+
// 2. Inject HTML
|
|
40
|
+
element.innerHTML = svgContent;
|
|
41
|
+
|
|
42
|
+
// 3. Apply custom classes if data-class exists
|
|
43
|
+
if (customClasses) {
|
|
44
|
+
const svg = element.querySelector('svg');
|
|
45
|
+
if (svg) {
|
|
46
|
+
// setAttribute overwrites the entire 'class' attribute,
|
|
47
|
+
// effectively removing old classes and adding the new ones.
|
|
48
|
+
svg.setAttribute('class', customClasses);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(`DSSvgFetch: Failed to load ${url}`, error);
|
|
54
|
+
delete element.dataset.svgProcessed;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async fetchSvg(url) {
|
|
59
|
+
if (this.svgCache.has(url)) {
|
|
60
|
+
return this.svgCache.get(url);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const response = await fetch(url);
|
|
64
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
65
|
+
|
|
66
|
+
const text = await response.text();
|
|
67
|
+
this.svgCache.set(url, text);
|
|
68
|
+
return text;
|
|
69
|
+
}
|
|
70
70
|
}
|
package/src/DSTabs.js
CHANGED
|
@@ -139,24 +139,33 @@ export class DSTabs {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
_cacheElements() {
|
|
142
|
-
// Find
|
|
142
|
+
// 1. Find Buttons (always in main container)
|
|
143
143
|
this.buttons = Array.from(this.container.querySelectorAll(this.cfg.buttonSelector));
|
|
144
144
|
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (this.tabsContainer) {
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
// 2. Determine Scope for Content/Radios
|
|
146
|
+
// If tabsContainer is configured AND exists, strictly scope to it.
|
|
147
|
+
// Otherwise, search within the entire main container (flexible mode).
|
|
148
|
+
let searchScope = this.container;
|
|
149
|
+
if (this.cfg.tabsContainer) {
|
|
150
|
+
const scopedEl = this.container.querySelector(this.cfg.tabsContainer);
|
|
151
|
+
if (scopedEl) {
|
|
152
|
+
this.tabsContainer = scopedEl;
|
|
153
|
+
searchScope = scopedEl;
|
|
154
|
+
} else {
|
|
155
|
+
this.tabsContainer = null;
|
|
156
|
+
}
|
|
152
157
|
} else {
|
|
153
|
-
this.
|
|
154
|
-
this.contents = [];
|
|
158
|
+
this.tabsContainer = null;
|
|
155
159
|
}
|
|
156
160
|
|
|
157
|
-
//
|
|
161
|
+
// 3. Find Radios and Content within that scope
|
|
162
|
+
this.radios = Array.from(searchScope.querySelectorAll(this.cfg.radioSelector));
|
|
163
|
+
this.contents = Array.from(searchScope.querySelectorAll(this.cfg.contentSelector));
|
|
164
|
+
|
|
165
|
+
// 4. Initialize Map
|
|
158
166
|
this._tabMap = new Map();
|
|
159
167
|
|
|
168
|
+
// Group buttons by tab name
|
|
160
169
|
this.buttons.forEach(button => {
|
|
161
170
|
const tabName = button.dataset.tab;
|
|
162
171
|
if (!this._tabMap.has(tabName)) {
|
|
@@ -165,15 +174,35 @@ export class DSTabs {
|
|
|
165
174
|
this._tabMap.get(tabName).buttons.push(button);
|
|
166
175
|
});
|
|
167
176
|
|
|
168
|
-
// Associate
|
|
169
|
-
this.radios.forEach(
|
|
177
|
+
// Associate Radios (by data-tab)
|
|
178
|
+
this.radios.forEach(radio => {
|
|
170
179
|
const tabName = radio.dataset.tab;
|
|
171
180
|
if (this._tabMap.has(tabName)) {
|
|
172
181
|
this._tabMap.get(tabName).radio = radio;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Associate Content (Improved Logic)
|
|
186
|
+
// Strategy: Match by data-tab first. If content lacks data-tab, fall back to index/order.
|
|
187
|
+
const unmappedContents = [...this.contents]; // Copy to track what's used
|
|
188
|
+
|
|
189
|
+
// Pass 1: Link content elements that explicitly have data-tab="..."
|
|
190
|
+
this._tabMap.forEach((data, name) => {
|
|
191
|
+
const matchIndex = unmappedContents.findIndex(c => c.dataset.tab === name);
|
|
192
|
+
if (matchIndex > -1) {
|
|
193
|
+
data.content = unmappedContents[matchIndex];
|
|
194
|
+
unmappedContents[matchIndex] = null; // Mark as used
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Pass 2: Link remaining content to remaining tabs by order (legacy support)
|
|
199
|
+
let remainingIndex = 0;
|
|
200
|
+
const remainingContents = unmappedContents.filter(c => c !== null);
|
|
201
|
+
|
|
202
|
+
this._tabMap.forEach((data) => {
|
|
203
|
+
if (!data.content && remainingContents[remainingIndex]) {
|
|
204
|
+
data.content = remainingContents[remainingIndex];
|
|
205
|
+
remainingIndex++;
|
|
177
206
|
}
|
|
178
207
|
});
|
|
179
208
|
}
|