data-primals-engine 1.0.11 → 1.1.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.
Files changed (166) hide show
  1. package/client/README.md +8 -0
  2. package/client/index.html +31 -0
  3. package/client/index.js +25 -0
  4. package/client/package-lock.json +11664 -0
  5. package/client/package.json +70 -0
  6. package/client/public/demo/26899917-d1ba-4df4-bb33-48d09a8778da.jpg +0 -0
  7. package/client/public/demo/4b9894c7-12cd-466d-8fd3-a2757b09ec96.jpg +0 -0
  8. package/client/public/demo/7ed369ac-a1a2-4b45-b0cd-4fd5bcf5a75a.jpg +0 -0
  9. package/client/public/doc/API.postman_collection.json +214 -0
  10. package/client/public/github.svg +1 -0
  11. package/client/public/profilCompany.jpg +0 -0
  12. package/client/public/profilDeveloper.jpg +0 -0
  13. package/client/public/profilEngineer.jpg +0 -0
  14. package/client/public/profilPersonal.jpg +0 -0
  15. package/client/public/profils .psd +0 -0
  16. package/client/public/react.svg +9 -0
  17. package/client/src/APIInfo.jsx +328 -0
  18. package/client/src/AddWidgetTypeModal.jsx +44 -0
  19. package/client/src/AddWidgetTypeModal.scss +87 -0
  20. package/client/src/App.css +42 -0
  21. package/client/src/App.jsx +586 -0
  22. package/client/src/App.scss +1466 -0
  23. package/client/src/AssistantChat.jsx +280 -0
  24. package/client/src/AssistantChat.scss +229 -0
  25. package/client/src/Button.jsx +12 -0
  26. package/client/src/Button.scss +197 -0
  27. package/client/src/CalculationBuilder.jsx +338 -0
  28. package/client/src/CalculationStepRow.jsx +199 -0
  29. package/client/src/CalendarConfigModal.jsx +49 -0
  30. package/client/src/ChartConfigModal.jsx +402 -0
  31. package/client/src/ConditionBuilder.jsx +622 -0
  32. package/client/src/ConditionBuilder.scss +672 -0
  33. package/client/src/ConditionBuilder2.jsx +757 -0
  34. package/client/src/ContentView.jsx +274 -0
  35. package/client/src/CronBuilder.jsx +126 -0
  36. package/client/src/CronBuilder.scss +128 -0
  37. package/client/src/CronPartBuilder.jsx +150 -0
  38. package/client/src/Dashboard.jsx +210 -0
  39. package/client/src/Dashboard.scss +445 -0
  40. package/client/src/DashboardChart.jsx +362 -0
  41. package/client/src/DashboardFlexViewItem.jsx +129 -0
  42. package/client/src/DashboardView.jsx +554 -0
  43. package/client/src/DataChart.jsx +349 -0
  44. package/client/src/DataEditor.jsx +556 -0
  45. package/client/src/DataLayout.jsx +709 -0
  46. package/client/src/DataTable.jsx +996 -0
  47. package/client/src/DataTable.scss +73 -0
  48. package/client/src/Dialog.jsx +90 -0
  49. package/client/src/Dialog.scss +117 -0
  50. package/client/src/DisplayFlexNodeRenderer.jsx +115 -0
  51. package/client/src/DocumentationPageLayout.jsx +93 -0
  52. package/client/src/DocumentationPageLayout.scss +262 -0
  53. package/client/src/Draggable.jsx +222 -0
  54. package/client/src/Draggable.scss +49 -0
  55. package/client/src/ExportDialog.jsx +172 -0
  56. package/client/src/Field.jsx +1558 -0
  57. package/client/src/FlexBuilder.jsx +269 -0
  58. package/client/src/FlexBuilder.scss +226 -0
  59. package/client/src/FlexBuilderControls.jsx +170 -0
  60. package/client/src/FlexBuilderModal.jsx +75 -0
  61. package/client/src/FlexBuilderModal.scss +109 -0
  62. package/client/src/FlexBuilderPreview.jsx +48 -0
  63. package/client/src/FlexBuilderUtils.js +84 -0
  64. package/client/src/FlexDataRenderer.jsx +170 -0
  65. package/client/src/FlexDataRenderer.scss +80 -0
  66. package/client/src/FlexNode.jsx +290 -0
  67. package/client/src/FlexTreeUtils.js +129 -0
  68. package/client/src/HiddenableCell.jsx +46 -0
  69. package/client/src/HiddenableCell.scss +36 -0
  70. package/client/src/KPIDialog.jsx +39 -0
  71. package/client/src/KPIWidget.jsx +139 -0
  72. package/client/src/KanbanCard.jsx +92 -0
  73. package/client/src/KanbanColumn.jsx +29 -0
  74. package/client/src/KanbanConfigModal.jsx +115 -0
  75. package/client/src/KanbanView.jsx +113 -0
  76. package/client/src/KanbanView.scss +107 -0
  77. package/client/src/MessageRotator.jsx +77 -0
  78. package/client/src/MessageRotator.scss +14 -0
  79. package/client/src/ModelCreator.jsx +640 -0
  80. package/client/src/ModelCreator.scss +154 -0
  81. package/client/src/ModelCreatorField.jsx +810 -0
  82. package/client/src/ModelImporter.jsx +120 -0
  83. package/client/src/ModelList.jsx +205 -0
  84. package/client/src/Notification.jsx +137 -0
  85. package/client/src/Notification.scss +126 -0
  86. package/client/src/NotificationProvider.jsx +73 -0
  87. package/client/src/PackGallery.jsx +211 -0
  88. package/client/src/PackGallery.scss +156 -0
  89. package/client/src/Pagination.jsx +141 -0
  90. package/client/src/RTE.jsx +415 -0
  91. package/client/src/RTETrans.jsx +103 -0
  92. package/client/src/RelationField.jsx +247 -0
  93. package/client/src/RelationValue.jsx +230 -0
  94. package/client/src/RestoreConfirmationModal.jsx +183 -0
  95. package/client/src/RestoreDialog.jsx +134 -0
  96. package/client/src/RestoreDialog.scss +67 -0
  97. package/client/src/RichTextEditorModal.jsx +34 -0
  98. package/client/src/RichTextEditorModal.scss +54 -0
  99. package/client/src/TourSpotlight.jsx +234 -0
  100. package/client/src/TourSpotlight.scss +100 -0
  101. package/client/src/TutorialsMenu.jsx +83 -0
  102. package/client/src/TutorialsMenu.scss +217 -0
  103. package/client/src/TutorialsRewardModal.jsx +65 -0
  104. package/client/src/Utils.jsx +78 -0
  105. package/client/src/ViewSwitcher.jsx +54 -0
  106. package/client/src/ViewSwitcher.scss +74 -0
  107. package/client/src/Webpage.jsx +69 -0
  108. package/client/src/_variables.scss +21 -0
  109. package/client/src/assets/react.svg +1 -0
  110. package/client/src/constants.js +68 -0
  111. package/client/src/contexts/AuthContext.jsx +28 -0
  112. package/client/src/contexts/ModelContext.jsx +328 -0
  113. package/client/src/contexts/UIContext.jsx +52 -0
  114. package/client/src/core/data.js +35 -0
  115. package/client/src/entry-client.jsx +15 -0
  116. package/client/src/entry-server.jsx +13 -0
  117. package/client/src/filter.js +222 -0
  118. package/client/src/hooks/data.js +101 -0
  119. package/client/src/hooks/useDebounce.js +20 -0
  120. package/client/src/hooks/useDragAndDrop.js +59 -0
  121. package/client/src/hooks/useLocalStorage.js +100 -0
  122. package/client/src/hooks/useMount.js +42 -0
  123. package/client/src/hooks/useTutorials.jsx +227 -0
  124. package/client/src/hooks/useWindowSize.js +24 -0
  125. package/client/src/i18n.js +47 -0
  126. package/client/src/index.css +90 -0
  127. package/client/src/index.js +10 -0
  128. package/client/src/main.jsx +11 -0
  129. package/client/src/translations.js +15940 -0
  130. package/client/src/tutorials.js +112 -0
  131. package/client/vite.config.js +30 -0
  132. package/eslint.config.js +50 -0
  133. package/package.json +48 -27
  134. package/server.js +9 -0
  135. package/src/constants.js +12 -23
  136. package/src/core.js +9 -8
  137. package/src/data.js +81 -80
  138. package/src/defaultModels.js +114 -115
  139. package/src/email.js +8 -9
  140. package/src/engine.js +5 -5
  141. package/src/events.js +1 -2
  142. package/src/i18n.js +212 -211
  143. package/src/middlewares/middleware-mongodb.js +94 -93
  144. package/src/migrate.js +24 -24
  145. package/src/modules/assistant.js +55 -55
  146. package/src/modules/bucket.js +10 -9
  147. package/src/modules/data.js +387 -357
  148. package/src/modules/file.js +3 -6
  149. package/src/modules/mongodb.js +6 -7
  150. package/src/modules/user.js +24 -47
  151. package/src/modules/workflow.js +68 -67
  152. package/src/openai.jobs.js +2 -2
  153. package/src/packs.js +30 -31
  154. package/src/providers.js +101 -3
  155. package/src/setenv.js +1 -1
  156. package/src/user.js +0 -17
  157. package/src/workers/crypto-worker.js +21 -20
  158. package/src/workers/import-export-worker.js +18 -18
  159. package/test/data.backup.integration.test.js +7 -12
  160. package/test/data.integration.test.js +27 -25
  161. package/test/globalSetup.js +2 -2
  162. package/test/import_export.integration.test.js +6 -6
  163. package/test/model.integration.test.js +21 -22
  164. package/test/workflow.integration.test.js +2 -5
  165. package/test/workflow.robustness.test.js +6 -13
  166. package/vitest.config.js +2 -2
@@ -0,0 +1,262 @@
1
+ // C:/Dev/hackersonline-engine/client/src/DocumentationPageLayout.scss
2
+ @import "_variables";
3
+
4
+ .documentation-layout {
5
+ display: flex;
6
+ // Ajustez 60px en fonction de la hauteur réelle de votre topBarMenu si elle est fixe
7
+ // Sinon, vous pourriez avoir besoin de JavaScript pour calculer la hauteur disponible
8
+ // ou utiliser des techniques CSS plus avancées comme Grid/Flexbox pour le layout global de la page.
9
+ // Pour l'instant, on part sur une hauteur qui remplit le reste de la vue.
10
+ height: calc(100vh - 70px); // Exemple de hauteur, ajustez selon votre TopBar
11
+ margin-top: 1rem; // Un peu d'espace sous la TopBar si elle est fixe et que ce layout est en dessous
12
+
13
+ .documentation-sidebar {
14
+ width: 100%;
15
+ flex:0.4;
16
+ min-width: 220px; // Largeur minimale
17
+ background-color: #f8f9fa; // Couleur de fond claire pour le menu
18
+ padding: 20px;
19
+ border-right: 1px solid #dee2e6; // Bordure de séparation
20
+ overflow-y: auto; // Permet le défilement si le contenu du menu est trop long
21
+ height: 100%; // Prend toute la hauteur disponible dans .documentation-layout
22
+ box-sizing: border-box;
23
+ .documentation-menu {
24
+ // Styles pour le conteneur nav de DocumentationMenu.jsx
25
+ .doc-menu-group {
26
+ margin-bottom: 1.25rem; // Espace entre les groupes de menu
27
+
28
+ .doc-menu-group-title {
29
+ font-weight: bold;
30
+ font-size: 1.1em;
31
+ color: #343a40; // Couleur de texte foncée pour les titres de groupe
32
+ margin-bottom: 0.75rem;
33
+ cursor: pointer;
34
+ background: none;
35
+ border: none;
36
+ padding: 8px;
37
+ width: 100%;
38
+ text-align: left;
39
+ display: flex;
40
+ align-items: center;
41
+ transition: color 0.2s ease-in-out;
42
+
43
+ svg {
44
+ margin-right: 10px; // Espace entre l'icône et le texte
45
+ font-size: 0.8em; // Taille de l'icône chevron
46
+ transition: transform 0.2s ease-in-out; // Animation douce pour la rotation
47
+ }
48
+
49
+ &:hover {
50
+ color: $primary-color; // Utilise votre variable de couleur primaire ou un bleu par défaut
51
+ }
52
+ }
53
+
54
+ .doc-menu-sublist {
55
+ list-style: none;
56
+ padding-left: 8px; // Indentation pour les sous-éléments, alignée avec l'icône
57
+ margin-top: 0.5rem;
58
+ border-left: 2px solid #e0e0e0; // Ligne verticale discrète pour l'indentation
59
+ margin-left: 4px; // Pour aligner la bordure avec le centre de l'icône
60
+
61
+ li {
62
+ margin-bottom: 2px; // Petit espace entre les liens
63
+ }
64
+
65
+ .doc-menu-item {
66
+ display: block;
67
+ padding: 10px 15px; // Padding confortable
68
+ text-decoration: none;
69
+ color: #495057; // Couleur de texte pour les liens
70
+ border-radius: 5px; // Coins arrondis
71
+ font-size: 0.95em;
72
+ transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
73
+
74
+ &:hover {
75
+ background-color: #e9ecef; // Fond au survol
76
+ color: $primary-color-darker; // Couleur de texte plus foncée au survol
77
+ }
78
+
79
+ &.active {
80
+ background-color: $primary-color; // Couleur primaire pour l'élément actif
81
+ color: white; // Texte blanc pour l'élément actif
82
+ font-weight: 500; // Un peu plus gras pour l'élément actif
83
+
84
+ &:hover {
85
+ background-color: $primary-color-darker; // Couleur primaire plus foncée au survol de l'actif
86
+ }
87
+
88
+ }
89
+
90
+ position: relative;
91
+ a {
92
+ color: inherit;
93
+ display: block;
94
+ position: absolute;
95
+ top: 0;
96
+ left: 0;
97
+ width: 100%;
98
+ height: 100%;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ .documentation-content {
107
+ width: 100%;
108
+ box-sizing: border-box;
109
+ flex: 1; // Prend le reste de la largeur
110
+ padding: 25px 40px; // Bon padding intérieur
111
+ overflow-y: auto; // Permet le défilement du contenu principal
112
+ background-color: #ffffff; // Fond blanc pour le contenu
113
+ height: 100%; // Prend toute la hauteur disponible
114
+
115
+ // Styles de base pour le contenu de la documentation
116
+ h1, h2, h3, h4 {
117
+ color: #212529; // Couleur de texte foncée pour les titres
118
+ margin-top: 1.5em; // Espace au-dessus des titres
119
+ margin-bottom: 0.8em;
120
+ padding-bottom: 0.4em;
121
+ border-bottom: 1px solid #eaecef; // Ligne de séparation sous les titres
122
+
123
+ &:first-child {
124
+ margin-top: 0; // Pas de marge en haut pour le premier titre de la page
125
+ }
126
+ }
127
+ h1 { font-size: 2.2em; font-weight: 600; }
128
+ h2 { font-size: 1.8em; font-weight: 600; }
129
+ h3 { font-size: 1.5em; font-weight: 600; }
130
+ h4 { font-size: 1.25em; font-weight: 600; }
131
+
132
+ p, li {
133
+ line-height: 1.75; // Bonne lisibilité pour les paragraphes et listes
134
+ margin-bottom: 1.1em;
135
+ color: #333; // Couleur de texte principale
136
+ font-size: 1em; // Taille de police standard
137
+ }
138
+
139
+ li > p {
140
+ display: inline;
141
+ }
142
+
143
+ ul, ol {
144
+ padding-left: 30px; // Indentation pour les listes
145
+ ul, ol {
146
+ margin-top: 0.5em; // Espace pour les listes imbriquées
147
+ }
148
+ }
149
+
150
+ a {
151
+ color: $primary-color; // Couleur des liens
152
+ text-decoration: none;
153
+ font-weight: 500;
154
+
155
+ &:hover {
156
+ text-decoration: underline;
157
+ color: $primary-color-darker;
158
+ }
159
+ }
160
+
161
+ pre {
162
+ background-color: #2d2d2d; // Fond sombre pour les blocs de code
163
+ color: #f8f8f2; // Texte clair pour les blocs de code
164
+ padding: 1.2em 1.5em;
165
+ border-radius: 6px;
166
+ overflow-x: auto; // Permet le défilement horizontal si le code est trop long
167
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
168
+ font-size: 0.9em;
169
+ line-height: 1.6;
170
+ margin-bottom: 1.8rem;
171
+ white-space: pre-wrap; // Gère les retours à la ligne dans le code
172
+ word-wrap: break-word; // Coupe les mots longs si nécessaire
173
+
174
+ code {
175
+ background-color: transparent; // Pas de fond pour le code dans un <pre>
176
+ padding: 0;
177
+ color: inherit; // Hérite de la couleur du <pre>
178
+ font-size: 1em; // Taille normale dans le <pre>
179
+ }
180
+ }
181
+
182
+ blockquote {
183
+ border-left: 5px solid #dfe2e5; // Bordure pour les citations
184
+ padding: 10px 20px;
185
+ margin: 1.5em 0;
186
+ color: #586069; // Couleur de texte pour les citations
187
+ background-color: #f8f9fa; // Fond léger pour les citations
188
+ font-style: italic;
189
+
190
+ p {
191
+ margin-bottom: 0; // Pas de marge en bas pour le dernier paragraphe dans une citation
192
+ }
193
+ }
194
+
195
+ img {
196
+ max-width: 100%; // Assure que les images sont responsives
197
+ height: auto;
198
+ border-radius: 4px; // Coins arrondis pour les images
199
+ margin: 1em 0;
200
+ }
201
+
202
+ hr {
203
+ border: 0;
204
+ height: 1px;
205
+ background-color: #e0e0e0;
206
+ margin: 2em 0;
207
+ }
208
+
209
+ // Classes utilitaires que vous pourriez vouloir ajouter
210
+ .doc-note {
211
+ background-color: #fff3cd;
212
+ border-left: 4px solid #ffeeba;
213
+ padding: 15px;
214
+ margin: 1.5em 0;
215
+ border-radius: 4px;
216
+ color: #856404;
217
+ }
218
+
219
+ .doc-tip {
220
+ background-color: #d1ecf1;
221
+ border-left: 4px solid #bee5eb;
222
+ padding: 15px;
223
+ margin: 1.5em 0;
224
+ border-radius: 4px;
225
+ color: #0c5460;
226
+ }
227
+
228
+ .doc-warning {
229
+ background-color: #f8d7da;
230
+ border-left: 4px solid #f5c6cb;
231
+ padding: 15px;
232
+ margin: 1.5em 0;
233
+ border-radius: 4px;
234
+ color: #721c24;
235
+ }
236
+ }
237
+ }
238
+
239
+ @media only screen and (min-width: 1024Fpx){
240
+ .documentation-sidebar{
241
+ max-width: 360px; // Largeur fixe pour le menu latéral
242
+ }
243
+ }
244
+ // Styles responsives optionnels
245
+ @media (max-width: 768px) {
246
+ .documentation-layout {
247
+ flex-direction: column; // Empile le menu et le contenu sur petits écrans
248
+ height: auto; // Hauteur automatique pour permettre le défilement de toute la page
249
+
250
+ .documentation-sidebar {
251
+ width: 100%; // Prend toute la largeur
252
+ height: auto; // Hauteur basée sur le contenu
253
+ border-right: none;
254
+ border-bottom: 1px solid #dee2e6; // Bordure en bas à la place de droite
255
+ margin-bottom: 20px; // Espace avant le contenu principal
256
+ }
257
+
258
+ .documentation-content {
259
+ padding: 20px; // Moins de padding sur petits écrans
260
+ }
261
+ }
262
+ }
@@ -0,0 +1,222 @@
1
+ import React, { useState, useRef, useEffect } from 'react';
2
+ import './Draggable.scss'; // Fichier pour les styles (à créer)
3
+
4
+ function Draggable({ items: initialItems = [], renderItem, onChange }) {
5
+ const [items, setItems] = useState(initialItems);
6
+ const [draggedIndex, setDraggedIndex] = useState(null);
7
+ const [overIndex, setOverIndex] = useState(null);
8
+
9
+ const itemRefs = useRef([]); // Pour stocker les refs des éléments li
10
+
11
+ // Mettre à jour l'état interne si les items initiaux changent
12
+ useEffect(() => {
13
+ setItems(initialItems);
14
+ // Rnitialiser les refs si la longueur change
15
+ itemRefs.current = itemRefs.current.slice(0, initialItems.length);
16
+ }, [initialItems]);
17
+
18
+ // --- Gestionnaires d'événements Drag & Drop (Bureau) ---
19
+
20
+ const handleDragStart = (e, index) => {
21
+ setDraggedIndex(index);
22
+ // Optionnel: Ajouter une classe pour le style de l'élément glissé
23
+ e.currentTarget.classList.add('dragging');
24
+ // Nécessaire pour Firefox
25
+ e.dataTransfer.effectAllowed = 'move';
26
+ // On peut mettre l'ID ou l'index dans dataTransfer si besoin, mais on utilise l'état ici
27
+ e.dataTransfer.setData('text/plain', index);
28
+ };
29
+
30
+ const handleDragEnter = (e, index) => {
31
+ e.preventDefault(); // Important pour permettre le drop
32
+ if (index !== draggedIndex) {
33
+ setOverIndex(index); // Pour le style de la cible potentielle
34
+
35
+ // Logique de réorganisation immédiate (optionnel, pour feedback visuel)
36
+ // Décommenter si vous voulez voir l'élément bouger pendant le drag
37
+ /*
38
+ if (draggedIndex !== null) {
39
+ const newItems = [...items];
40
+ const [draggedItem] = newItems.splice(draggedIndex, 1);
41
+ newItems.splice(index, 0, draggedItem);
42
+ setItems(newItems);
43
+ setDraggedIndex(index); // Mettre à jour l'index aprs déplacement
44
+ }
45
+ */
46
+ } else {
47
+ setOverIndex(null);
48
+ }
49
+ };
50
+
51
+ const handleDragOver = (e) => {
52
+ e.preventDefault(); // Doit être présent pour que onDrop fonctionne
53
+ };
54
+
55
+ const handleDragLeave = (e) => {
56
+ // Optionnel: Réinitialiser overIndex si on quitte la zone sans dropper
57
+ // setOverIndex(null);
58
+ };
59
+
60
+ const handleDrop = (e, index) => {
61
+ e.preventDefault();
62
+ if (draggedIndex === null || draggedIndex === index) {
63
+ setOverIndex(null);
64
+ return; // Ne rien faire si on drop sur soi-même ou si rien n'est glissé
65
+ }
66
+
67
+ const newItems = [...items];
68
+ const [draggedItem] = newItems.splice(draggedIndex, 1);
69
+ newItems.splice(index, 0, draggedItem);
70
+
71
+ setItems(newItems);
72
+ setOverIndex(null);
73
+
74
+ // Appeler le callback onChange avec la nouvelle liste triée
75
+ if (onChange) {
76
+ onChange(newItems);
77
+ }
78
+ };
79
+
80
+ const handleDragEnd = (e) => {
81
+ // Nettoyer l'état et les styles
82
+ e.currentTarget.classList.remove('dragging');
83
+ setDraggedIndex(null);
84
+ setOverIndex(null);
85
+ };
86
+
87
+ // --- Gestionnaires d'événements Tactiles (Mobile) ---
88
+
89
+ const touchStartY = useRef(0);
90
+ const currentTouchY = useRef(0);
91
+ const initialScrollTop = useRef(0); // Pour gérer le scroll pendant le drag tactile
92
+
93
+ const handleTouchStart = (e, index) => {
94
+ setDraggedIndex(index);
95
+ touchStartY.current = e.touches[0].clientY;
96
+ currentTouchY.current = touchStartY.current;
97
+ initialScrollTop.current = e.currentTarget.closest('.draggable-list')?.scrollTop || 0; // Stocker le scroll initial du conteneur
98
+
99
+ // Ajouter un style visuel
100
+ const target = itemRefs.current[index];
101
+ if (target) {
102
+ target.classList.add('dragging-touch');
103
+ }
104
+ // Empcher le scroll de la page pendant le drag de l'élément
105
+ // Attention: cela peut être trop agressif selon l'UX souhaitée
106
+ // document.body.style.overflow = 'hidden';
107
+ };
108
+
109
+ const handleTouchMove = (e) => {
110
+ if (draggedIndex === null) return;
111
+
112
+ currentTouchY.current = e.touches[0].clientY;
113
+ const draggedElement = itemRefs.current[draggedIndex];
114
+
115
+ if (draggedElement) {
116
+ // Déplacer visuellement l'élément (simple translation pour le feedback)
117
+ // Une implémentation plus robuste utiliserait une copie ou un placeholder
118
+ const deltaY = currentTouchY.current - touchStartY.current;
119
+ draggedElement.style.transform = `translateY(${deltaY}px)`;
120
+ draggedElement.style.zIndex = '100'; // Mettre au-dessus des autres
121
+
122
+ // Déterminer sur quel élément on survole
123
+ let newOverIndex = null;
124
+ itemRefs.current.forEach((ref, index) => {
125
+ if (ref && index !== draggedIndex) {
126
+ const rect = ref.getBoundingClientRect();
127
+ // Si le centre vertical du doigt est dans les limites de l'élément
128
+ if (currentTouchY.current > rect.top && currentTouchY.current < rect.bottom) {
129
+ newOverIndex = index;
130
+ ref.classList.add('drag-over'); // Style pour la cible
131
+ } else {
132
+ ref.classList.remove('drag-over');
133
+ }
134
+ }
135
+ });
136
+
137
+ // Si on survole un nouvel élément, mettre à jour l'état overIndex
138
+ if (newOverIndex !== null && newOverIndex !== overIndex) {
139
+ setOverIndex(newOverIndex);
140
+ } else if (newOverIndex === null) {
141
+ setOverIndex(null);
142
+ }
143
+
144
+ // --- Auto-scroll (optionnel mais utile sur mobile) ---
145
+ const listElement = draggedElement.closest('.draggable-list');
146
+ if (listElement) {
147
+ const listRect = listElement.getBoundingClientRect();
148
+ const touchOffsetInList = currentTouchY.current - listRect.top;
149
+ const scrollThreshold = 50; // Pixels près du bord pour déclencher le scroll
150
+
151
+ if (touchOffsetInList < scrollThreshold) {
152
+ // Scroller vers le haut
153
+ listElement.scrollTop -= 10;
154
+ } else if (touchOffsetInList > listRect.height - scrollThreshold) {
155
+ // Scroller vers le bas
156
+ listElement.scrollTop += 10;
157
+ }
158
+ }
159
+ }
160
+ };
161
+
162
+ const handleTouchEnd = (e) => {
163
+ if (draggedIndex === null) return;
164
+
165
+ const draggedElement = itemRefs.current[draggedIndex];
166
+ if (draggedElement) {
167
+ // Réinitialiser le style visuel
168
+ draggedElement.style.transform = '';
169
+ draggedElement.style.zIndex = '';
170
+ draggedElement.classList.remove('dragging-touch');
171
+ }
172
+ itemRefs.current.forEach(ref => ref?.classList.remove('drag-over'));
173
+ // document.body.style.overflow = ''; // Ractile
174
+ if (overIndex !== null && overIndex !== draggedIndex) {
175
+ const newItems = [...items];
176
+ const [draggedItem] = newItems.splice(draggedIndex, 1);
177
+ newItems.splice(overIndex, 0, draggedItem);
178
+
179
+ setItems(newItems);
180
+
181
+ // Appeler le callback onChange
182
+ if (onChange) {
183
+ onChange(newItems);
184
+ }
185
+ }
186
+
187
+ // Nettoyer l'état
188
+ setDraggedIndex(null);
189
+ setOverIndex(null);
190
+ touchStartY.current = 0;
191
+ currentTouchY.current = 0;
192
+ initialScrollTop.current = 0;
193
+ };
194
+
195
+ return (
196
+ <ul className="draggable-list">
197
+ {items.map((item, index) => (
198
+ <li
199
+ key={item.id} // Assurez-vous que chaque item a un id unique
200
+ ref={el => itemRefs.current[index] = el} // Stocker la ref
201
+ draggable={true} // Activer le drag natif
202
+ onDragStart={(e) => handleDragStart(e, index)}
203
+ onDragEnter={(e) => handleDragEnter(e, index)}
204
+ onDragOver={handleDragOver}
205
+ onDragLeave={handleDragLeave}
206
+ onDrop={(e) => handleDrop(e, index)}
207
+ onDragEnd={handleDragEnd}
208
+ onTouchStart={(e) => handleTouchStart(e, index)}
209
+ onTouchMove={handleTouchMove}
210
+ onTouchEnd={handleTouchEnd}
211
+ className={`draggable-item ${index === overIndex ? 'drag-over' : ''}`}
212
+ style={{ opacity: index === draggedIndex ? 0.5 : 1 }} // Style simple pour l'élément glissé
213
+ >
214
+ {/* Rendre le contenu de l'item via la fonction renderItem */}
215
+ {renderItem ? renderItem(item, index) : JSON.stringify(item)}
216
+ </li>
217
+ ))}
218
+ </ul>
219
+ );
220
+ }
221
+
222
+ export default Draggable;
@@ -0,0 +1,49 @@
1
+ .draggable-list {
2
+ list-style: none;
3
+ padding: 0;
4
+ margin: 0;
5
+ user-select: none; /* Empêche la sélection de texte pendant le drag */
6
+ overflow-y: auto; /* Important pour l'auto-scroll tactile */
7
+ // max-height: 400px; /* Définir une hauteur si nécessaire pour le scroll */
8
+ width: 100%;
9
+ }
10
+
11
+ .draggable-item {
12
+ padding: 8px 12px;
13
+ margin: 5px 0;
14
+ background-color: #f9f9f9;
15
+ border: 1px solid #eee;
16
+ cursor: grab;
17
+ transition: background-color 0.2s ease, opacity 0.2s ease, transform 0.1s linear; /* Transition pour transform (touch) */
18
+ position: relative; /* Pour z-index */
19
+
20
+ &:active {
21
+ cursor: grabbing;
22
+ }
23
+
24
+ // Style pour l'élément en cours de drag (bureau)
25
+ &.dragging {
26
+ opacity: 0.5;
27
+ background-color: #e0e0e0;
28
+ }
29
+
30
+ // Style pour l'élément en cours de drag (tactile)
31
+ &.dragging-touch {
32
+ // background-color: #d3eaff; // Couleur différente si besoin
33
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
34
+ // opacity: 0.8; // Peut être redondant avec le style opacity inline
35
+ }
36
+
37
+ // Style pour la zone où l'élément peut être déposé
38
+ &.drag-over {
39
+ background-color: #d3eaff;
40
+ border-style: dashed;
41
+ }
42
+ }
43
+
44
+ // Optionnel: Cacher l'élément fantôme natif pendant le drag (peut améliorer l'UX)
45
+ // .draggable-item.dragging {
46
+ // color: transparent; // Rend le texte invisible
47
+ // background: lightgrey; // Garde une forme visible
48
+ // }
49
+ // * Attention: Cacher complètement peut perturber le drag sur certains navigateurs.