nocopyrightsounds-widget 1.1.1 → 1.3.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/README.md +53 -62
- package/package.json +1 -1
- package/src/genres.js +71 -0
- package/src/index.js +57 -33
package/README.md
CHANGED
|
@@ -7,18 +7,19 @@ Un lecteur musical flottant, élégant et hautement personnalisable pour intégr
|
|
|
7
7
|
|
|
8
8
|
Conçu pour les développeurs modernes : léger, persistant entre les changements de pages, et entièrement paramétrable via JavaScript et CSS.
|
|
9
9
|
|
|
10
|
-
 *(Ajoutez une capture d'écran de votre widget dans votre dépôt GitHub et remplacez ce lien
|
|
10
|
+
 *(Ajoutez une capture d'écran de votre widget dans votre dépôt GitHub et remplacez ce lien !)*
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## ✨ Fonctionnalités
|
|
15
15
|
|
|
16
|
-
* ⚡ **Zéro Latence :** Algorithme de préchargement (buffering)
|
|
17
|
-
* 💾 **Persistance d'état :** Mémorise la piste en cours, le volume, la progression et l'état
|
|
18
|
-
* 🎨 **
|
|
19
|
-
* 🎛️ **Contrôles Complets :** Boutons Suivant/Précédent avec historique, contrôle du volume, Mute, et barre de progression
|
|
20
|
-
* 🎵
|
|
21
|
-
*
|
|
16
|
+
* ⚡ **Zéro Latence :** Algorithme de préchargement (buffering) en arrière-plan pour des transitions instantanées.
|
|
17
|
+
* 💾 **Persistance d'état :** Mémorise la piste en cours, le volume, la progression et l'état du widget d'une page à l'autre via `localStorage`.
|
|
18
|
+
* 🎨 **Design Premium & Glassmorphism :** Support natif des modes clair/sombre, personnalisation des couleurs et effet de verre dépoli.
|
|
19
|
+
* 🎛️ **Contrôles Complets :** Boutons Suivant/Précédent avec historique, contrôle du volume, Mute, et barre de progression.
|
|
20
|
+
* 🎵 **Catalogue Complet :** Navigation aléatoire intelligente parmi les 60+ genres historiques de NCS.
|
|
21
|
+
* 🔘 **Bouton Réduit Sur Mesure :** Transformez l'icône flottante en cercle, en carré, changez l'émoji ou mettez-y du texte !
|
|
22
|
+
* 🔌 **Prêt à l'emploi (Plug & Play) :** API backend officielle intégrée par défaut. Zéro configuration requise !
|
|
22
23
|
|
|
23
24
|
---
|
|
24
25
|
|
|
@@ -40,78 +41,70 @@ npm install nocopyrightsounds-widget
|
|
|
40
41
|
|
|
41
42
|
## 🚀 Utilisation Rapide
|
|
42
43
|
|
|
43
|
-
### Exemple
|
|
44
|
+
### Exemple basique (Zéro configuration)
|
|
44
45
|
\`\`\`html
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
</script>
|
|
52
|
-
</body>
|
|
46
|
+
<script type="module">
|
|
47
|
+
import NCSWidget from 'https://cdn.jsdelivr.net/npm/nocopyrightsounds-widget@latest/src/index.js';
|
|
48
|
+
|
|
49
|
+
// Le widget s'occupe de tout avec les paramètres par défaut !
|
|
50
|
+
const player = new NCSWidget();
|
|
51
|
+
</script>
|
|
53
52
|
\`\`\`
|
|
54
53
|
|
|
55
|
-
### Exemple
|
|
56
|
-
\`\`\`
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
};
|
|
73
|
-
}, []);
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<div>
|
|
77
|
-
<h1>Mon Super Site</h1>
|
|
78
|
-
</div>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
54
|
+
### Exemple Avancé (Design sur mesure)
|
|
55
|
+
\`\`\`javascript
|
|
56
|
+
const widget = new NCSWidget({
|
|
57
|
+
position: 'bottom-left',
|
|
58
|
+
theme: 'dark',
|
|
59
|
+
primaryColor: '#ff0055',
|
|
60
|
+
glassmorphism: true,
|
|
61
|
+
borderRadius: '12px',
|
|
62
|
+
defaultGenre: '10', // Démarre sur la House (ID: 10)
|
|
63
|
+
|
|
64
|
+
// 🔥 Personnalisation du bouton réduit
|
|
65
|
+
minimizedIcon: '🎵 Play', // Texte au lieu d'un émoji
|
|
66
|
+
minimizedSize: '80px', // Bouton plus large
|
|
67
|
+
minimizedRadius: '12px', // Bords arrondis (au lieu d'un cercle parfait)
|
|
68
|
+
minimizedBg: '#222222', // Fond sombre
|
|
69
|
+
minimizedColor: '#ff0055' // Texte coloré
|
|
70
|
+
});
|
|
81
71
|
\`\`\`
|
|
82
72
|
|
|
83
73
|
---
|
|
84
74
|
|
|
85
|
-
## ⚙️ Configuration (Options
|
|
86
|
-
|
|
87
|
-
Vous pouvez passer un objet d'options au constructeur pour personnaliser le comportement du widget :
|
|
75
|
+
## ⚙️ Configuration Détaillée (Options)
|
|
88
76
|
|
|
89
77
|
| Option | Type | Défaut | Description |
|
|
90
78
|
| :--- | :--- | :--- | :--- |
|
|
91
|
-
| \`position\` | String | \`'bottom-right'\` | Position
|
|
79
|
+
| \`position\` | String | \`'bottom-right'\` | Position (\`bottom-right\`, \`bottom-left\`, \`top-right\`, \`top-left\`). |
|
|
92
80
|
| \`offset\` | String | \`'25px'\` | Marge par rapport au bord de l'écran. |
|
|
93
81
|
| \`theme\` | String | \`'dark'\` | Thème de base de l'interface (\`'dark'\` ou \`'light'\`). |
|
|
94
|
-
| \`primaryColor\` | String | \`'#1DB954'\` | Couleur principale (
|
|
82
|
+
| \`primaryColor\` | String | \`'#1DB954'\` | Couleur principale (Sliders, visualizer). |
|
|
83
|
+
| \`glassmorphism\`| Boolean | \`false\` | Active un fond semi-transparent avec flou d'arrière-plan. |
|
|
84
|
+
| \`borderRadius\` | String | \`'16px'\` | Rayon des bordures du lecteur étendu. |
|
|
85
|
+
| \`fontFamily\` | String | \`'system-ui...'\`| Typographie utilisée dans tout le widget. |
|
|
86
|
+
| \`minimizedIcon\`| String | \`'🎧'\` | Icône ou texte du bouton réduit. |
|
|
87
|
+
| \`minimizedSize\`| String | \`'55px'\` | Largeur/Hauteur du bouton réduit. |
|
|
88
|
+
| \`minimizedRadius\`| String| \`'50%'\` | Arrondi du bouton réduit (\`50%\` = rond, \`8px\` = carré arrondi). |
|
|
89
|
+
| \`minimizedBg\` | String | *primaryColor*| Couleur de fond spécifique au bouton réduit. |
|
|
90
|
+
| \`minimizedColor\`| String| \`'#ffffff'\` | Couleur de l'icône/texte du bouton réduit. |
|
|
91
|
+
| \`hideDownload\` | Boolean | \`false\` | Masque l'icône de téléchargement direct. |
|
|
92
|
+
| \`hideVisualizer\`| Boolean | \`false\` | Masque les barres animées à côté du titre. |
|
|
93
|
+
| \`autoOpen\` | Boolean | \`false\` | Déploie le widget automatiquement à la 1ère visite. |
|
|
95
94
|
| \`defaultGenre\` | String | \`'all'\` | L'ID du genre au démarrage (ex: \`'10'\` pour House). |
|
|
96
|
-
| \`startVolume\` | Number | \`0.5\` | Volume initial entre 0.0 et 1.0
|
|
97
|
-
| \`zIndex\` | Number | \`99999\` | Profondeur d'affichage CSS (z-index). |
|
|
98
|
-
| \`apiUrl\` | String | *https://www.wordreference.com/definition/interne* | URL de l'API Backend. Vous pouvez héberger la vôtre si besoin. |
|
|
95
|
+
| \`startVolume\` | Number | \`0.5\` | Volume initial entre 0.0 et 1.0. |
|
|
99
96
|
|
|
100
97
|
---
|
|
101
98
|
|
|
102
99
|
## 🎨 Personnalisation CSS Avancée
|
|
103
100
|
|
|
104
|
-
|
|
101
|
+
Le widget expose des **Variables CSS** (Custom Properties) rattachées à l'ID `#ncs-persistent-widget`. Vous pouvez les surcharger directement dans la feuille de style de votre site :
|
|
105
102
|
|
|
106
103
|
\`\`\`css
|
|
107
|
-
/* Dans le fichier style.css de votre site web */
|
|
108
104
|
#ncs-persistent-widget {
|
|
109
|
-
--ncs-bg: #000000; /* Fond du widget
|
|
105
|
+
--ncs-bg: #000000; /* Fond du widget */
|
|
110
106
|
--ncs-border: #333333; /* Couleur de la bordure */
|
|
111
|
-
--ncs-
|
|
112
|
-
--ncs-panel-bg: #111111; /* Fond des éléments internes (images, selects) */
|
|
113
|
-
font-family: 'Roboto', sans-serif; /* Changement de police */
|
|
114
|
-
border-radius: 0px; /* Retirer les coins arrondis */
|
|
107
|
+
--ncs-panel-bg: #111111; /* Fond des listes et des images */
|
|
115
108
|
}
|
|
116
109
|
\`\`\`
|
|
117
110
|
|
|
@@ -119,10 +112,8 @@ Si les options du constructeur ne suffisent pas, le widget expose des **Variable
|
|
|
119
112
|
|
|
120
113
|
## 🏗️ Architecture & Backend
|
|
121
114
|
|
|
122
|
-
En raison des restrictions CORS strictes sur le web moderne, un navigateur web ne peut pas interroger directement le site de NCS.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
*Note : Une API publique par défaut est fournie avec ce widget pour un usage immédiat. Pour des environnements de production à fort trafic, il est recommandé de déployer votre propre instance du serveur relais.*
|
|
115
|
+
En raison des restrictions CORS strictes sur le web moderne, un navigateur web ne peut pas interroger directement le site de NCS. Ce widget s'appuie donc sur une API Backend Node.js.
|
|
116
|
+
**Une instance publique hébergée sur Render est configurée par défaut dans le widget pour un usage "Plug & Play".**
|
|
126
117
|
|
|
127
118
|
---
|
|
128
119
|
|
|
@@ -130,4 +121,4 @@ Ce widget s'appuie donc sur une API Backend Node.js qui sert de relais de donné
|
|
|
130
121
|
|
|
131
122
|
Distribué sous la licence MIT. Voir `LICENSE` pour plus d'informations.
|
|
132
123
|
|
|
133
|
-
**Avertissement :** Ce projet n'est pas affilié à NoCopyrightSounds. Toutes les musiques diffusées
|
|
124
|
+
**Avertissement :** Ce projet n'est pas affilié à NoCopyrightSounds. Toutes les musiques diffusées appartiennent à leurs créateurs respectifs et à NCS.
|
package/package.json
CHANGED
package/src/genres.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/genres.js
|
|
2
|
+
|
|
3
|
+
export const ncsGenres = [
|
|
4
|
+
{ value: "all", label: "🌍 Tous les genres" },
|
|
5
|
+
{ value: "31", label: "Alternative Dance" },
|
|
6
|
+
{ value: "32", label: "Alternative Hip-Hop" },
|
|
7
|
+
{ value: "33", label: "Alternative Pop" },
|
|
8
|
+
{ value: "23", label: "Ambient" },
|
|
9
|
+
{ value: "34", label: "Anti-Pop" },
|
|
10
|
+
{ value: "1", label: "Bass" },
|
|
11
|
+
{ value: "18", label: "Bass House" },
|
|
12
|
+
{ value: "78", label: "Bass Music" },
|
|
13
|
+
{ value: "26", label: "Brazilian Phonk" },
|
|
14
|
+
{ value: "27", label: "Breakbeat" },
|
|
15
|
+
{ value: "2", label: "Chill" },
|
|
16
|
+
{ value: "24", label: "Chill Bass" },
|
|
17
|
+
{ value: "35", label: "Chill Pop" },
|
|
18
|
+
{ value: "85", label: "Colour Bass" },
|
|
19
|
+
{ value: "65", label: "Complextro" },
|
|
20
|
+
{ value: "36", label: "Dance-Pop" },
|
|
21
|
+
{ value: "66", label: "Deep House" },
|
|
22
|
+
{ value: "45", label: "Disco" },
|
|
23
|
+
{ value: "46", label: "Disco House" },
|
|
24
|
+
{ value: "3", label: "Drum & Bass" },
|
|
25
|
+
{ value: "4", label: "Drumstep" },
|
|
26
|
+
{ value: "5", label: "Dubstep" },
|
|
27
|
+
{ value: "6", label: "EDM" },
|
|
28
|
+
{ value: "47", label: "Electro" },
|
|
29
|
+
{ value: "48", label: "Electro House" },
|
|
30
|
+
{ value: "7", label: "Electronic" },
|
|
31
|
+
{ value: "39", label: "Electronic Pop" },
|
|
32
|
+
{ value: "83", label: "Electronic Rock" },
|
|
33
|
+
{ value: "17", label: "Future Bass" },
|
|
34
|
+
{ value: "68", label: 'Future Bounce' },
|
|
35
|
+
{ value: "50", label: "Future Funk" },
|
|
36
|
+
{ value: "8", label: "Future House" },
|
|
37
|
+
{ value: "69", label: "Future Rave" },
|
|
38
|
+
{ value: "57", label: "Future Trap" },
|
|
39
|
+
{ value: "40", label: "Futurepop" },
|
|
40
|
+
{ value: "51", label: "Garage" },
|
|
41
|
+
{ value: "15", label: "Glitch Hop" },
|
|
42
|
+
{ value: "82", label: "Hardcore" },
|
|
43
|
+
{ value: "9", label: "Hardstyle" },
|
|
44
|
+
{ value: "10", label: "House" },
|
|
45
|
+
{ value: "41", label: "Hyperpop" },
|
|
46
|
+
{ value: "11", label: "Indie Dance" },
|
|
47
|
+
{ value: "91", label: "J-Pop" },
|
|
48
|
+
{ value: "84", label: "Jersey Club" },
|
|
49
|
+
{ value: "28", label: "Jump-Up" },
|
|
50
|
+
{ value: "29", label: "Liquid DnB" },
|
|
51
|
+
{ value: "60", label: "Lofi Hip-Hop" },
|
|
52
|
+
{ value: "12", label: "Melodic Dubstep" },
|
|
53
|
+
{ value: "54", label: "Melodic House" },
|
|
54
|
+
{ value: "22", label: "Midtempo Bass" },
|
|
55
|
+
{ value: "30", label: "Neurofunk" },
|
|
56
|
+
{ value: "87", label: "Nu-Jazz" },
|
|
57
|
+
{ value: "16", label: "Phonk" },
|
|
58
|
+
{ value: "86", label: "Pluggnb" },
|
|
59
|
+
{ value: "19", label: "Pop" },
|
|
60
|
+
{ value: "55", label: "Progressive House" },
|
|
61
|
+
{ value: "88", label: "RnB" },
|
|
62
|
+
{ value: "89", label: "Speed Garage" },
|
|
63
|
+
{ value: "73", label: "Tech House" },
|
|
64
|
+
{ value: "80", label: "Techno" },
|
|
65
|
+
{ value: "81", label: "Trance" },
|
|
66
|
+
{ value: "14", label: "Trap" },
|
|
67
|
+
{ value: "74", label: "Tribal House" },
|
|
68
|
+
{ value: "21", label: "UKG" },
|
|
69
|
+
{ value: "92", label: "Wave" },
|
|
70
|
+
{ value: "90", label: "Witch House" }
|
|
71
|
+
];
|
package/src/index.js
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
|
+
import { ncsGenres } from './genres.js';
|
|
2
|
+
|
|
1
3
|
class NCSWidget {
|
|
2
4
|
constructor(userOptions = {}) {
|
|
3
|
-
// 🛠️ 1. Configurations par défaut (Fusionnées avec les choix de l'utilisateur)
|
|
4
5
|
const defaultOptions = {
|
|
5
6
|
position: 'bottom-right',
|
|
6
|
-
apiUrl: 'https://
|
|
7
|
-
theme: 'dark',
|
|
8
|
-
primaryColor: '#1DB954',
|
|
7
|
+
apiUrl: 'https://ncs-backend-api.onrender.com', // 🔗 Votre API officielle fixée !
|
|
8
|
+
theme: 'dark',
|
|
9
|
+
primaryColor: '#1DB954',
|
|
9
10
|
defaultGenre: 'all',
|
|
10
11
|
startVolume: 0.5,
|
|
11
|
-
offset: '25px',
|
|
12
|
-
zIndex: 99999
|
|
12
|
+
offset: '25px',
|
|
13
|
+
zIndex: 99999,
|
|
14
|
+
glassmorphism: false,
|
|
15
|
+
borderRadius: '16px',
|
|
16
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
17
|
+
hideDownload: false,
|
|
18
|
+
hideVisualizer: false,
|
|
19
|
+
autoOpen: false,
|
|
20
|
+
|
|
21
|
+
// --- 🎛️ NOUVEAUTÉS V1.3.0 : Bouton Réduit ---
|
|
22
|
+
minimizedIcon: '🎧', // L'icône par défaut
|
|
23
|
+
minimizedSize: '55px', // Taille du bouton
|
|
24
|
+
minimizedRadius: '50%', // Arrondi (50% = rond, 10px = carré arrondi)
|
|
25
|
+
minimizedBg: null, // Surcharger la couleur de fond (utilise primaryColor sinon)
|
|
26
|
+
minimizedColor: '#ffffff' // Couleur de l'icône
|
|
13
27
|
};
|
|
14
28
|
|
|
15
29
|
this.options = { ...defaultOptions, ...userOptions };
|
|
@@ -33,7 +47,13 @@ class NCSWidget {
|
|
|
33
47
|
this.savedCover = localStorage.getItem('ncs_currentCover') || null;
|
|
34
48
|
this.savedTitle = localStorage.getItem('ncs_currentTitle') || null;
|
|
35
49
|
this.savedArtists = localStorage.getItem('ncs_currentArtists') || null;
|
|
36
|
-
|
|
50
|
+
|
|
51
|
+
const savedState = localStorage.getItem('ncs_isOpen');
|
|
52
|
+
if (savedState !== null) {
|
|
53
|
+
this.isWidgetOpen = savedState === 'true';
|
|
54
|
+
} else {
|
|
55
|
+
this.isWidgetOpen = this.options.autoOpen;
|
|
56
|
+
}
|
|
37
57
|
}
|
|
38
58
|
|
|
39
59
|
this.initDOM();
|
|
@@ -43,7 +63,6 @@ class NCSWidget {
|
|
|
43
63
|
this.restoreTrack();
|
|
44
64
|
this.fillQueue(this.genreSelect.value);
|
|
45
65
|
} else {
|
|
46
|
-
// Utiliser le genre par défaut défini dans les options
|
|
47
66
|
this.genreSelect.value = this.options.defaultGenre;
|
|
48
67
|
this.changeGenre(this.options.defaultGenre);
|
|
49
68
|
}
|
|
@@ -55,14 +74,16 @@ class NCSWidget {
|
|
|
55
74
|
this.container = document.createElement('div');
|
|
56
75
|
this.container.id = 'ncs-persistent-widget';
|
|
57
76
|
|
|
58
|
-
// 🎨 2. Application du thème (Variables CSS dynamiques)
|
|
59
77
|
const isLight = this.options.theme === 'light';
|
|
78
|
+
const baseBgColor = isLight ? '255, 255, 255' : '24, 24, 24';
|
|
79
|
+
const finalBg = this.options.glassmorphism ? `rgba(${baseBgColor}, 0.75)` : (isLight ? '#ffffff' : '#181818');
|
|
80
|
+
const backdropFilter = this.options.glassmorphism ? 'blur(12px)' : 'none';
|
|
81
|
+
|
|
60
82
|
const colors = {
|
|
61
|
-
bg: isLight ? '#ffffff' : '#181818',
|
|
62
83
|
text: isLight ? '#222222' : '#ffffff',
|
|
63
84
|
textMuted: isLight ? '#666666' : '#b3b3b3',
|
|
64
|
-
border: isLight ? '#e0e0e0' : '#282828',
|
|
65
|
-
panelBg: isLight ? '#f5f5f5' : '#282828',
|
|
85
|
+
border: this.options.glassmorphism ? `rgba(${isLight ? '0,0,0' : '255,255,255'}, 0.1)` : (isLight ? '#e0e0e0' : '#282828'),
|
|
86
|
+
panelBg: this.options.glassmorphism ? `rgba(${isLight ? '0,0,0' : '255,255,255'}, 0.05)` : (isLight ? '#f5f5f5' : '#282828'),
|
|
66
87
|
sliderBg: isLight ? '#d3d3d3' : '#535353',
|
|
67
88
|
btnBg: isLight ? '#222222' : '#ffffff',
|
|
68
89
|
btnColor: isLight ? '#ffffff' : '#000000'
|
|
@@ -71,9 +92,8 @@ class NCSWidget {
|
|
|
71
92
|
const style = document.createElement('style');
|
|
72
93
|
style.textContent = `
|
|
73
94
|
#ncs-persistent-widget {
|
|
74
|
-
/* Variables CSS exposées pour les développeurs */
|
|
75
95
|
--ncs-primary: ${this.options.primaryColor};
|
|
76
|
-
--ncs-bg: ${
|
|
96
|
+
--ncs-bg: ${finalBg};
|
|
77
97
|
--ncs-text: ${colors.text};
|
|
78
98
|
--ncs-text-muted: ${colors.textMuted};
|
|
79
99
|
--ncs-border: ${colors.border};
|
|
@@ -81,19 +101,27 @@ class NCSWidget {
|
|
|
81
101
|
--ncs-slider-bg: ${colors.sliderBg};
|
|
82
102
|
--ncs-btn-bg: ${colors.btnBg};
|
|
83
103
|
--ncs-btn-color: ${colors.btnColor};
|
|
104
|
+
--ncs-radius: ${this.options.borderRadius};
|
|
105
|
+
--ncs-font: ${this.options.fontFamily};
|
|
106
|
+
|
|
107
|
+
/* Variables Bouton Réduit */
|
|
108
|
+
--ncs-min-size: ${this.options.minimizedSize};
|
|
109
|
+
--ncs-min-radius: ${this.options.minimizedRadius};
|
|
110
|
+
--ncs-min-bg: ${this.options.minimizedBg || this.options.primaryColor};
|
|
111
|
+
--ncs-min-color: ${this.options.minimizedColor};
|
|
84
112
|
|
|
85
113
|
position: fixed;
|
|
86
114
|
${this.getPositionStyles()}
|
|
87
115
|
z-index: ${this.options.zIndex};
|
|
88
|
-
font-family:
|
|
116
|
+
font-family: var(--ncs-font);
|
|
89
117
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
90
118
|
}
|
|
91
119
|
|
|
92
|
-
.ncs-minimized { width:
|
|
93
|
-
.ncs-minimized:hover { transform: scale(1.
|
|
120
|
+
.ncs-minimized { width: var(--ncs-min-size); height: var(--ncs-min-size); 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(var(--ncs-min-size) * 0.45); transition: transform 0.2s; color: var(--ncs-min-color); }
|
|
121
|
+
.ncs-minimized:hover { transform: scale(1.05); }
|
|
94
122
|
.ncs-minimized.hidden { display: none; }
|
|
95
123
|
|
|
96
|
-
.ncs-expanded { width: 320px; background: var(--ncs-bg); color: var(--ncs-text); border-radius:
|
|
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); display: none; border: 1px solid var(--ncs-border); backdrop-filter: ${backdropFilter}; -webkit-backdrop-filter: ${backdropFilter}; }
|
|
97
125
|
.ncs-expanded.active { display: block; animation: ncsFadeIn 0.3s ease; }
|
|
98
126
|
|
|
99
127
|
.ncs-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; }
|
|
@@ -101,7 +129,7 @@ class NCSWidget {
|
|
|
101
129
|
.ncs-close-btn { background: transparent; border: none; color: var(--ncs-text-muted); font-size: 18px; cursor: pointer; padding: 0; transition: color 0.2s; }
|
|
102
130
|
.ncs-close-btn:hover { color: var(--ncs-text); }
|
|
103
131
|
|
|
104
|
-
.ncs-visualizer { display: flex; gap: 2px; height: 12px; align-items: flex-end; opacity: 0; transition: opacity 0.3s; }
|
|
132
|
+
.ncs-visualizer { display: ${this.options.hideVisualizer ? 'none' : 'flex'}; gap: 2px; height: 12px; align-items: flex-end; opacity: 0; transition: opacity 0.3s; }
|
|
105
133
|
.ncs-visualizer.playing { opacity: 1; }
|
|
106
134
|
.ncs-bar { width: 3px; background: var(--ncs-primary); border-radius: 2px; animation: bounce 0.5s infinite alternate; }
|
|
107
135
|
.ncs-bar:nth-child(2) { animation-delay: 0.15s; }
|
|
@@ -109,7 +137,7 @@ class NCSWidget {
|
|
|
109
137
|
@keyframes bounce { from { height: 3px; } to { height: 12px; } }
|
|
110
138
|
|
|
111
139
|
.ncs-track-info { display: flex; align-items: center; margin-bottom: 15px; }
|
|
112
|
-
.ncs-cover { width: 65px; height: 65px; border-radius:
|
|
140
|
+
.ncs-cover { width: 65px; height: 65px; border-radius: calc(var(--ncs-radius) / 2); background: var(--ncs-panel-bg); margin-right: 15px; object-fit: cover; box-shadow: 0 4px 10px rgba(0,0,0,0.1); }
|
|
113
141
|
.ncs-details { flex: 1; overflow: hidden; display: flex; flex-direction: column; justify-content: center; }
|
|
114
142
|
#ncs-track-name { font-size: 14px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px; }
|
|
115
143
|
#ncs-artists { font-size: 11px; color: var(--ncs-text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 8px; }
|
|
@@ -132,14 +160,19 @@ class NCSWidget {
|
|
|
132
160
|
.ncs-volume-container { display: flex; align-items: center; gap: 8px; color: var(--ncs-text-muted); flex: 1; margin-right: 15px; }
|
|
133
161
|
#ncs-mute-btn { cursor: pointer; transition: transform 0.1s; user-select: none; }
|
|
134
162
|
#ncs-mute-btn:hover { transform: scale(1.1); }
|
|
135
|
-
|
|
163
|
+
|
|
164
|
+
.ncs-download-btn { display: ${this.options.hideDownload ? 'none' : 'block'}; color: var(--ncs-text-muted); text-decoration: none; font-size: 18px; transition: color 0.2s; }
|
|
136
165
|
.ncs-download-btn:hover { color: var(--ncs-primary); }
|
|
137
166
|
|
|
138
167
|
@keyframes ncsFadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
|
|
139
168
|
`;
|
|
140
169
|
|
|
170
|
+
const genresOptionsHTML = ncsGenres.map(genre =>
|
|
171
|
+
`<option value="${genre.value}">${genre.label}</option>`
|
|
172
|
+
).join('');
|
|
173
|
+
|
|
141
174
|
this.container.innerHTML = `
|
|
142
|
-
<div class="ncs-minimized ${this.isWidgetOpen ? 'hidden' : ''}"
|
|
175
|
+
<div class="ncs-minimized ${this.isWidgetOpen ? 'hidden' : ''}">${this.options.minimizedIcon}</div>
|
|
143
176
|
<div class="ncs-expanded ${this.isWidgetOpen ? 'active' : ''}">
|
|
144
177
|
<div class="ncs-header">
|
|
145
178
|
<strong>NCS Player
|
|
@@ -156,16 +189,8 @@ class NCSWidget {
|
|
|
156
189
|
<div id="ncs-track-name">Chargement...</div>
|
|
157
190
|
<div id="ncs-artists">Artiste(s)</div>
|
|
158
191
|
<select id="ncs-genre">
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
<option value="10">House</option>
|
|
162
|
-
<option value="2">Chill</option>
|
|
163
|
-
<option value="5">Dubstep</option>
|
|
164
|
-
<option value="7">Electronic</option>
|
|
165
|
-
<option value="3">Drum & Bass</option>
|
|
166
|
-
<option value="9">Hardstyle</option>
|
|
167
|
-
<option value="14">Trap</option>
|
|
168
|
-
</select>
|
|
192
|
+
${genresOptionsHTML}
|
|
193
|
+
</select>
|
|
169
194
|
</div>
|
|
170
195
|
</div>
|
|
171
196
|
|
|
@@ -194,7 +219,6 @@ class NCSWidget {
|
|
|
194
219
|
document.head.appendChild(style);
|
|
195
220
|
document.body.appendChild(this.container);
|
|
196
221
|
|
|
197
|
-
// Références
|
|
198
222
|
this.minimized = this.container.querySelector('.ncs-minimized');
|
|
199
223
|
this.expanded = this.container.querySelector('.ncs-expanded');
|
|
200
224
|
this.playBtn = this.container.querySelector('#ncs-play-pause');
|