Dev #2

Merged
w-vandal merged 24 commits from dev into main 2026-08-27 13:00:44 +00:00
2 changed files with 64 additions and 4 deletions
Showing only changes of commit 943bf265de - Show all commits
+5
View File
@@ -206,6 +206,11 @@ body.builderBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden; d
.floatPanel--left{ left:24px; width:280px; }
.floatPanel--right{ right:24px; width:340px; }
.floatPanel--center{ left:50%; width:560px; max-width:calc(100vw - 48px); transform:translateX(-50%); }
/* Plein écran (voir makeFloatPanelFullscreenable() dans game_dashboard.html)
— juste un repère visuel (bordure accent) sur le panneau agrandi, tout le
positionnement réel est posé directement en style inline par le JS (pour
pouvoir revenir exactement à la position/taille d'avant en sortant). */
.floatPanel--fullscreen{ border-color:var(--accent); }
.floatPanelHeader{
display:flex; align-items:center; justify-content:space-between; gap:8px;
padding:8px 10px; border-bottom:1px solid var(--border); background:var(--panel2);
+59 -4
View File
@@ -221,6 +221,7 @@
<div class="floatPanel floatPanel--center hidden" id="newObjectPanel">
<div class="floatPanelHeader" id="newObjectPanelHeader">
<span class="floatPanelTitle">⋮⋮ Nouvel objet</span>
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
<button type="button" class="button is-small" onclick="closeNewObjectPanel()">✕</button>
</div>
<div class="floatPanelBody">
@@ -261,6 +262,7 @@
<div class="floatPanel floatPanel--center hidden objectEditPanel" data-definition-id="{{ d.id }}" id="objectEditPanel-{{ d.id }}">
<div class="floatPanelHeader">
<span class="floatPanelTitle">⋮⋮ {{ definition.name }}</span>
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
<button type="button" class="button is-small" onclick="closeObjectEditPanel({{ d.id }})">✕</button>
</div>
<div class="floatPanelBody">
@@ -458,6 +460,7 @@
<div class="floatPanel floatPanel--center hidden addFieldPanel" data-definition-id="{{ d.id }}" id="addFieldPanel-{{ d.id }}">
<div class="floatPanelHeader">
<span class="floatPanelTitle">⋮⋮ Ajouter un champ — {{ definition.name }}</span>
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
<button type="button" class="button is-small" onclick="closeAddFieldPanel({{ d.id }})">✕</button>
</div>
<div class="floatPanelBody">
@@ -509,6 +512,7 @@
<div class="floatPanel floatPanel--center hidden addEntryPanel" data-definition-id="{{ d.id }}" id="addEntryPanel-{{ d.id }}">
<div class="floatPanelHeader">
<span class="floatPanelTitle">⋮⋮ Ajouter une entrée — {{ definition.name }}</span>
<button type="button" class="button is-small floatPanelFullscreenBtn" title="Plein écran">⛶</button>
<button type="button" class="button is-small" onclick="closeAddEntryPanel({{ d.id }})">✕</button>
</div>
<div class="floatPanelBody">
@@ -628,10 +632,15 @@ function makeFloatPanelDraggable(panel, header) {
header.addEventListener('mousedown', function (e) {
if (e.target.closest('button')) return;
dragging = true;
// Glisser un panneau en plein écran doit d'abord l'en faire sortir —
// sinon left/top posés juste en dessous seraient aussitôt repris en
// main par bottom/right encore actifs (voir makeFloatPanelFullscreenable).
if (panel.classList.contains('floatPanel--fullscreen')) panel._fsToggle.exit();
var rect = panel.getBoundingClientRect();
panel.style.left = rect.left + 'px';
panel.style.top = rect.top + 'px';
panel.style.right = 'auto';
panel.style.bottom = 'auto';
panel.style.transform = 'none';
offsetX = e.clientX - rect.left;
offsetY = e.clientY - rect.top;
@@ -651,6 +660,10 @@ function makeFloatPanelResizable(panel, handle) {
var resizing = false, startX = 0, startY = 0, startW = 0, startH = 0;
handle.addEventListener('mousedown', function (e) {
resizing = true;
// Même remarque que pour le glisser-déposer : sortir du plein écran
// d'abord, sinon bottom/right encore actifs reprendraient la main sur
// la largeur/hauteur posées ci-dessous.
if (panel.classList.contains('floatPanel--fullscreen')) panel._fsToggle.exit();
var rect = panel.getBoundingClientRect();
startX = e.clientX; startY = e.clientY;
startW = rect.width; startH = rect.height;
@@ -673,13 +686,50 @@ function makeFloatPanelResizable(panel, handle) {
document.body.style.userSelect = '';
});
}
// Plein écran (voir switchDashTab pour l'esprit général : chaque panneau
// s'ouvre en plein écran par défaut — plus pratique dès qu'il y a plus de
// quelques champs — avec un bouton pour revenir à sa taille/position
// précédente, mémorisée le temps de la session (pas persistée). Renvoie un
// objet {enter, exit} et pose panel._fsToggle dessus, pour que le code qui
// OUVRE le panneau (openXxxPanel ci-dessous) puisse appeler enter() sans
// avoir à re-chercher le bouton.
function makeFloatPanelFullscreenable(panel, toggleBtn) {
var saved = null;
function enter() {
saved = {
left: panel.style.left, top: panel.style.top, right: panel.style.right,
width: panel.style.width, height: panel.style.height,
maxWidth: panel.style.maxWidth, transform: panel.style.transform,
};
panel.classList.add('floatPanel--fullscreen');
panel.style.left = '12px'; panel.style.top = '12px'; panel.style.right = '12px'; panel.style.bottom = '12px';
panel.style.width = 'auto'; panel.style.height = 'auto'; panel.style.maxWidth = 'none'; panel.style.transform = 'none';
toggleBtn.title = 'Quitter le plein écran';
}
function exit() {
panel.classList.remove('floatPanel--fullscreen');
panel.style.bottom = '';
if (saved) {
panel.style.left = saved.left; panel.style.top = saved.top; panel.style.right = saved.right;
panel.style.width = saved.width; panel.style.height = saved.height;
panel.style.maxWidth = saved.maxWidth; panel.style.transform = saved.transform;
}
toggleBtn.title = 'Plein écran';
}
toggleBtn.addEventListener('click', function () {
if (panel.classList.contains('floatPanel--fullscreen')) exit(); else enter();
});
panel._fsToggle = { enter: enter, exit: exit };
return panel._fsToggle;
}
// ---------- Panneau déplaçable "Nouvel objet" ----------
(function () {
var panel = document.getElementById('newObjectPanel');
makeFloatPanelDraggable(panel, document.getElementById('newObjectPanelHeader'));
makeFloatPanelResizable(panel, document.getElementById('newObjectPanelResizeHandle'));
window.openNewObjectPanel = function () { panel.classList.remove('hidden'); };
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
window.openNewObjectPanel = function () { panel.classList.remove('hidden'); panel._fsToggle.enter(); };
window.closeNewObjectPanel = function () { panel.classList.add('hidden'); };
})();
@@ -688,10 +738,13 @@ function makeFloatPanelResizable(panel, handle) {
document.querySelectorAll('.objectEditPanel').forEach(function (panel) {
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
});
window.openObjectEditPanel = function (definitionId, subtab) {
document.querySelectorAll('.objectEditPanel').forEach(function (panel) {
panel.classList.toggle('hidden', panel.dataset.definitionId !== String(definitionId));
var isTarget = panel.dataset.definitionId === String(definitionId);
panel.classList.toggle('hidden', !isTarget);
if (isTarget) panel._fsToggle.enter();
});
if (subtab) {
var panel = document.querySelector('.objectEditPanel[data-definition-id="' + definitionId + '"]');
@@ -725,6 +778,7 @@ function makeFloatPanelResizable(panel, handle) {
document.querySelectorAll('.addFieldPanel').forEach(function (panel) {
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
var typeSelect = panel.querySelector('.fieldTypeSelect');
var relationTarget = panel.querySelector('.relationTarget');
@@ -739,11 +793,12 @@ function makeFloatPanelResizable(panel, handle) {
document.querySelectorAll('.addEntryPanel').forEach(function (panel) {
makeFloatPanelDraggable(panel, panel.querySelector('.floatPanelHeader'));
makeFloatPanelResizable(panel, panel.querySelector('.floatPanelResizeHandle'));
makeFloatPanelFullscreenable(panel, panel.querySelector('.floatPanelFullscreenBtn'));
});
window.openAddFieldPanel = function (definitionId) {
var panel = document.querySelector('.addFieldPanel[data-definition-id="' + definitionId + '"]');
if (panel) panel.classList.remove('hidden');
if (panel) { panel.classList.remove('hidden'); panel._fsToggle.enter(); }
};
window.closeAddFieldPanel = function (definitionId) {
var panel = document.querySelector('.addFieldPanel[data-definition-id="' + definitionId + '"]');
@@ -751,7 +806,7 @@ function makeFloatPanelResizable(panel, handle) {
};
window.openAddEntryPanel = function (definitionId) {
var panel = document.querySelector('.addEntryPanel[data-definition-id="' + definitionId + '"]');
if (panel) panel.classList.remove('hidden');
if (panel) { panel.classList.remove('hidden'); panel._fsToggle.enter(); }
};
window.closeAddEntryPanel = function (definitionId) {
var panel = document.querySelector('.addEntryPanel[data-definition-id="' + definitionId + '"]');