nocopyrightsounds-widget 1.3.0 → 1.4.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/package.json +1 -1
- package/src/index.js +50 -40
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -4,12 +4,13 @@ class NCSWidget {
|
|
|
4
4
|
constructor(userOptions = {}) {
|
|
5
5
|
const defaultOptions = {
|
|
6
6
|
position: 'bottom-right',
|
|
7
|
-
apiUrl: 'https://ncs-backend-api.onrender.com',
|
|
7
|
+
apiUrl: 'https://ncs-backend-api.onrender.com',
|
|
8
8
|
theme: 'dark',
|
|
9
9
|
primaryColor: '#1DB954',
|
|
10
10
|
defaultGenre: 'all',
|
|
11
11
|
startVolume: 0.5,
|
|
12
|
-
|
|
12
|
+
offsetX: '25px', // Séparé pour plus de précision (ex: gauche/droite)
|
|
13
|
+
offsetY: '25px', // Séparé (ex: haut/bas)
|
|
13
14
|
zIndex: 99999,
|
|
14
15
|
glassmorphism: false,
|
|
15
16
|
borderRadius: '16px',
|
|
@@ -18,12 +19,13 @@ class NCSWidget {
|
|
|
18
19
|
hideVisualizer: false,
|
|
19
20
|
autoOpen: false,
|
|
20
21
|
|
|
21
|
-
//
|
|
22
|
-
minimizedIcon: '🎧',
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
// 🎛️ Bouton Réduit Ultra-Configurable
|
|
23
|
+
minimizedIcon: '🎧',
|
|
24
|
+
minWidth: '55px', // Largeur séparée
|
|
25
|
+
minHeight: '55px', // Hauteur séparée
|
|
26
|
+
minRadius: '50%',
|
|
27
|
+
minBg: null,
|
|
28
|
+
minColor: '#ffffff'
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
this.options = { ...defaultOptions, ...userOptions };
|
|
@@ -49,11 +51,7 @@ class NCSWidget {
|
|
|
49
51
|
this.savedArtists = localStorage.getItem('ncs_currentArtists') || null;
|
|
50
52
|
|
|
51
53
|
const savedState = localStorage.getItem('ncs_isOpen');
|
|
52
|
-
|
|
53
|
-
this.isWidgetOpen = savedState === 'true';
|
|
54
|
-
} else {
|
|
55
|
-
this.isWidgetOpen = this.options.autoOpen;
|
|
56
|
-
}
|
|
54
|
+
this.isWidgetOpen = savedState !== null ? savedState === 'true' : this.options.autoOpen;
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
this.initDOM();
|
|
@@ -73,6 +71,8 @@ class NCSWidget {
|
|
|
73
71
|
|
|
74
72
|
this.container = document.createElement('div');
|
|
75
73
|
this.container.id = 'ncs-persistent-widget';
|
|
74
|
+
// Ajout d'une classe globale si le widget est ouvert dès le départ
|
|
75
|
+
if(this.isWidgetOpen) this.container.classList.add('ncs-is-open');
|
|
76
76
|
|
|
77
77
|
const isLight = this.options.theme === 'light';
|
|
78
78
|
const baseBgColor = isLight ? '255, 255, 255' : '24, 24, 24';
|
|
@@ -104,25 +104,27 @@ class NCSWidget {
|
|
|
104
104
|
--ncs-radius: ${this.options.borderRadius};
|
|
105
105
|
--ncs-font: ${this.options.fontFamily};
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
--ncs-min-
|
|
109
|
-
--ncs-min-radius: ${this.options.
|
|
110
|
-
--ncs-min-bg: ${this.options.
|
|
111
|
-
--ncs-min-color: ${this.options.
|
|
107
|
+
--ncs-min-w: ${this.options.minWidth};
|
|
108
|
+
--ncs-min-h: ${this.options.minHeight};
|
|
109
|
+
--ncs-min-radius: ${this.options.minRadius};
|
|
110
|
+
--ncs-min-bg: ${this.options.minBg || this.options.primaryColor};
|
|
111
|
+
--ncs-min-color: ${this.options.minColor};
|
|
112
|
+
--ncs-cover-img: url(''); /* Injecté en JS pour le design Vinyle */
|
|
112
113
|
|
|
113
114
|
position: fixed;
|
|
114
115
|
${this.getPositionStyles()}
|
|
115
116
|
z-index: ${this.options.zIndex};
|
|
116
117
|
font-family: var(--ncs-font);
|
|
117
|
-
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
.ncs-minimized { width: var(--ncs-min-
|
|
120
|
+
.ncs-minimized { width: var(--ncs-min-w); height: var(--ncs-min-h); border-radius: var(--ncs-min-radius); background: var(--ncs-min-bg); cursor: pointer; display: flex; justify-content: center; align-items: center; box-shadow: 0 6px 15px rgba(0,0,0, 0.2); font-size: calc(min(var(--ncs-min-w), var(--ncs-min-h)) * 0.45); transition: all 0.3s ease; color: var(--ncs-min-color); overflow: hidden; background-size: cover; background-position: center; }
|
|
121
121
|
.ncs-minimized:hover { transform: scale(1.05); }
|
|
122
|
-
|
|
122
|
+
/* Transition plus douce pour l'affichage */
|
|
123
|
+
.ncs-minimized.hidden { opacity: 0; pointer-events: none; position: absolute; }
|
|
123
124
|
|
|
124
|
-
.ncs-expanded { width: 320px; background: var(--ncs-bg); color: var(--ncs-text); border-radius: var(--ncs-radius); padding: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.15);
|
|
125
|
-
|
|
125
|
+
.ncs-expanded { width: 320px; background: var(--ncs-bg); color: var(--ncs-text); border-radius: var(--ncs-radius); padding: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.15); opacity: 0; pointer-events: none; position: absolute; bottom: 0; right: 0; border: 1px solid var(--ncs-border); backdrop-filter: ${backdropFilter}; -webkit-backdrop-filter: ${backdropFilter}; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); transform: translateY(20px) scale(0.95); }
|
|
126
|
+
/* Effet Tiroir par défaut lors de l'ouverture */
|
|
127
|
+
.ncs-expanded.active { opacity: 1; pointer-events: auto; position: relative; transform: translateY(0) scale(1); }
|
|
126
128
|
|
|
127
129
|
.ncs-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; }
|
|
128
130
|
.ncs-header strong { font-size: 14px; font-weight: 600; color: var(--ncs-text-muted); letter-spacing: 1px; text-transform: uppercase; display: flex; align-items: center; gap: 8px; }
|
|
@@ -160,19 +162,16 @@ class NCSWidget {
|
|
|
160
162
|
.ncs-volume-container { display: flex; align-items: center; gap: 8px; color: var(--ncs-text-muted); flex: 1; margin-right: 15px; }
|
|
161
163
|
#ncs-mute-btn { cursor: pointer; transition: transform 0.1s; user-select: none; }
|
|
162
164
|
#ncs-mute-btn:hover { transform: scale(1.1); }
|
|
163
|
-
|
|
164
165
|
.ncs-download-btn { display: ${this.options.hideDownload ? 'none' : 'block'}; color: var(--ncs-text-muted); text-decoration: none; font-size: 18px; transition: color 0.2s; }
|
|
165
166
|
.ncs-download-btn:hover { color: var(--ncs-primary); }
|
|
166
|
-
|
|
167
|
-
@keyframes ncsFadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
|
168
167
|
`;
|
|
169
168
|
|
|
170
|
-
const genresOptionsHTML = ncsGenres.map(genre =>
|
|
171
|
-
`<option value="${genre.value}">${genre.label}</option>`
|
|
172
|
-
).join('');
|
|
169
|
+
const genresOptionsHTML = ncsGenres.map(genre => `<option value="${genre.value}">${genre.label}</option>`).join('');
|
|
173
170
|
|
|
174
171
|
this.container.innerHTML = `
|
|
175
|
-
<div class="ncs-minimized ${this.isWidgetOpen ? 'hidden' : ''}"
|
|
172
|
+
<div class="ncs-minimized ${this.isWidgetOpen ? 'hidden' : ''}">
|
|
173
|
+
<span class="ncs-min-content">${this.options.minimizedIcon}</span>
|
|
174
|
+
</div>
|
|
176
175
|
<div class="ncs-expanded ${this.isWidgetOpen ? 'active' : ''}">
|
|
177
176
|
<div class="ncs-header">
|
|
178
177
|
<strong>NCS Player
|
|
@@ -188,9 +187,7 @@ class NCSWidget {
|
|
|
188
187
|
<div class="ncs-details">
|
|
189
188
|
<div id="ncs-track-name">Chargement...</div>
|
|
190
189
|
<div id="ncs-artists">Artiste(s)</div>
|
|
191
|
-
<select id="ncs-genre">
|
|
192
|
-
${genresOptionsHTML}
|
|
193
|
-
</select>
|
|
190
|
+
<select id="ncs-genre">${genresOptionsHTML}</select>
|
|
194
191
|
</div>
|
|
195
192
|
</div>
|
|
196
193
|
|
|
@@ -238,12 +235,13 @@ class NCSWidget {
|
|
|
238
235
|
}
|
|
239
236
|
|
|
240
237
|
getPositionStyles() {
|
|
241
|
-
const
|
|
238
|
+
const x = this.options.offsetX;
|
|
239
|
+
const y = this.options.offsetY;
|
|
242
240
|
const positions = {
|
|
243
|
-
'bottom-right': `bottom: ${
|
|
244
|
-
'bottom-left': `bottom: ${
|
|
245
|
-
'top-right': `top: ${
|
|
246
|
-
'top-left': `top: ${
|
|
241
|
+
'bottom-right': `bottom: ${y}; right: ${x};`,
|
|
242
|
+
'bottom-left': `bottom: ${y}; left: ${x};`,
|
|
243
|
+
'top-right': `top: ${y}; right: ${x};`,
|
|
244
|
+
'top-left': `top: ${y}; left: ${x};`
|
|
247
245
|
};
|
|
248
246
|
return positions[this.options.position] || positions['bottom-right'];
|
|
249
247
|
}
|
|
@@ -263,11 +261,13 @@ class NCSWidget {
|
|
|
263
261
|
this.playBtn.innerHTML = '⏸';
|
|
264
262
|
this.playBtn.classList.add('paused');
|
|
265
263
|
this.visualizer.classList.add('playing');
|
|
264
|
+
this.container.classList.add('ncs-is-playing'); // 🎵 CLASSE MAGIQUE POUR LES DESIGNERS
|
|
266
265
|
});
|
|
267
266
|
this.audio.addEventListener('pause', () => {
|
|
268
267
|
this.playBtn.innerHTML = '▶';
|
|
269
268
|
this.playBtn.classList.remove('paused');
|
|
270
269
|
this.visualizer.classList.remove('playing');
|
|
270
|
+
this.container.classList.remove('ncs-is-playing');
|
|
271
271
|
});
|
|
272
272
|
this.audio.addEventListener('timeupdate', () => this.updateProgress());
|
|
273
273
|
this.audio.addEventListener('loadedmetadata', () => {
|
|
@@ -320,9 +320,11 @@ class NCSWidget {
|
|
|
320
320
|
if (isOpen) {
|
|
321
321
|
this.minimized.classList.add('hidden');
|
|
322
322
|
this.expanded.classList.add('active');
|
|
323
|
+
this.container.classList.add('ncs-is-open');
|
|
323
324
|
} else {
|
|
324
325
|
this.minimized.classList.remove('hidden');
|
|
325
326
|
this.expanded.classList.remove('active');
|
|
327
|
+
this.container.classList.remove('ncs-is-open');
|
|
326
328
|
}
|
|
327
329
|
localStorage.setItem('ncs_isOpen', isOpen);
|
|
328
330
|
}
|
|
@@ -397,7 +399,11 @@ class NCSWidget {
|
|
|
397
399
|
this.audio.src = this.savedTrack;
|
|
398
400
|
this.trackName.innerText = this.savedTitle;
|
|
399
401
|
this.artistsName.innerText = this.savedArtists || "NCS Release";
|
|
400
|
-
if (this.savedCover)
|
|
402
|
+
if (this.savedCover) {
|
|
403
|
+
this.coverImg.src = this.savedCover;
|
|
404
|
+
// Injecter l'image dans le CSS pour les hackers de design !
|
|
405
|
+
this.container.style.setProperty('--ncs-cover-img', `url('${this.savedCover}')`);
|
|
406
|
+
}
|
|
401
407
|
this.downloadBtn.href = this.savedTrack;
|
|
402
408
|
|
|
403
409
|
this.trackHistory = [{
|
|
@@ -417,7 +423,11 @@ class NCSWidget {
|
|
|
417
423
|
this.artistsName.innerText = artistes;
|
|
418
424
|
this.artistsName.title = artistes;
|
|
419
425
|
|
|
420
|
-
if (track.coverUrl)
|
|
426
|
+
if (track.coverUrl) {
|
|
427
|
+
this.coverImg.src = track.coverUrl;
|
|
428
|
+
// 💿 INJECTION POUR LE HACK VINYLE :
|
|
429
|
+
this.container.style.setProperty('--ncs-cover-img', `url('${track.coverUrl}')`);
|
|
430
|
+
}
|
|
421
431
|
this.downloadBtn.href = track.audioUrl;
|
|
422
432
|
|
|
423
433
|
if (addToHistory) {
|