doc-survival-kit 2.0.0 → 3.11.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.

Potentially problematic release.


This version of doc-survival-kit might be problematic. Click here for more details.

@@ -0,0 +1,236 @@
1
+ // ══════════════════════════════════════
2
+ // shape-ops.js — Manipulation des formes (outil, ajout, suppression, style, copie)
3
+ // ══════════════════════════════════════
4
+
5
+ // ── Outil actif ──
6
+ function setTool(tool) {
7
+ currentTool = tool;
8
+ document.querySelectorAll(".diagram-tool[id^='tool']").forEach(function (btn) {
9
+ btn.classList.remove("active");
10
+ });
11
+ var btnId = "tool" + tool.charAt(0).toUpperCase() + tool.slice(1);
12
+ var btn = document.getElementById(btnId);
13
+ if (btn) btn.classList.add("active");
14
+
15
+ arrowSrcId = null;
16
+ selectedIds = [];
17
+ document.getElementById("tempArrow").style.display = "none";
18
+ document.getElementById("canvas").setAttribute(
19
+ "data-tool", tool
20
+ );
21
+ if (tool !== "select") {
22
+ selectedId = null; selectedType = null;
23
+ document.getElementById("colorPanel").style.display = "none";
24
+ }
25
+ renderAll();
26
+ }
27
+
28
+ // ── Ajout d'une forme ──
29
+ function addShape(type, x, y) {
30
+ pushHistory();
31
+ var diag = getCurrentDiagram();
32
+ var size = DEFAULT_SIZES[type] || { w: 120, h: 50 };
33
+ var shape = {
34
+ id: "s" + Date.now(),
35
+ type: type,
36
+ x: Math.round(x - size.w / 2),
37
+ y: Math.round(y - size.h / 2),
38
+ w: size.w,
39
+ h: size.h,
40
+ text: "",
41
+ color: type === "postit" ? "t-amber" : DEFAULT_COLOR,
42
+ };
43
+ if (type === "table") {
44
+ shape.rows = 3; shape.cols = 3;
45
+ shape.cells = [["","",""],["","",""],["","",""]];
46
+ var initW = shape.w / 3;
47
+ shape.colWidths = [initW, initW, initW];
48
+ }
49
+ diag.shapes.push(shape);
50
+ saveDiagrammes();
51
+ selectedId = shape.id; selectedType = "shape";
52
+ selectedIds = [shape.id];
53
+ renderAll();
54
+ document.getElementById("colorPanel").style.display = "flex";
55
+ syncColorPanel();
56
+ if (type !== "table") startTextEdit(shape.id);
57
+ }
58
+
59
+ // ── Suppression ──
60
+ function deleteSelected() {
61
+ var diag = getCurrentDiagram();
62
+ if (selectedIds.length === 0 && !(selectedId && selectedType === "arrow")) return;
63
+ pushHistory();
64
+ if (selectedIds.length > 0) {
65
+ diag.shapes = diag.shapes.filter(function (s) { return selectedIds.indexOf(s.id) === -1; });
66
+ diag.arrows = diag.arrows.filter(function (a) {
67
+ return selectedIds.indexOf(a.from) === -1 && selectedIds.indexOf(a.to) === -1;
68
+ });
69
+ selectedIds = [];
70
+ selectedId = null; selectedType = null;
71
+ } else if (selectedId && selectedType === "arrow") {
72
+ diag.arrows = diag.arrows.filter(function (a) { return a.id !== selectedId; });
73
+ selectedId = null; selectedType = null;
74
+ } else {
75
+ return;
76
+ }
77
+ document.getElementById("colorPanel").style.display = "none";
78
+ saveDiagrammes();
79
+ renderAll();
80
+ }
81
+
82
+ // ── Couleur ──
83
+ function setShapeColor(color) {
84
+ if (selectedIds.length === 0) return;
85
+ pushHistory();
86
+ var diag = getCurrentDiagram();
87
+ selectedIds.forEach(function (id) {
88
+ var shape = diag.shapes.find(function (s) { return s.id === id; });
89
+ if (shape) shape.color = color;
90
+ });
91
+ saveDiagrammes();
92
+ renderAll();
93
+ document.getElementById("colorPanel").style.display = "flex";
94
+ }
95
+
96
+ function setShapeTextValign(valign) {
97
+ if (selectedIds.length === 0) return;
98
+ pushHistory();
99
+ var diag = getCurrentDiagram();
100
+ selectedIds.forEach(function (id) {
101
+ var shape = diag.shapes.find(function (s) { return s.id === id; });
102
+ if (shape) shape.textValign = valign;
103
+ });
104
+ saveDiagrammes();
105
+ renderAll();
106
+ document.getElementById("colorPanel").style.display = "flex";
107
+ }
108
+
109
+ function setShapeTextAlign(align) {
110
+ if (selectedIds.length === 0) return;
111
+ pushHistory();
112
+ var diag = getCurrentDiagram();
113
+ selectedIds.forEach(function (id) {
114
+ var shape = diag.shapes.find(function (s) { return s.id === id; });
115
+ if (shape) shape.textAlign = align;
116
+ });
117
+ saveDiagrammes();
118
+ renderAll();
119
+ document.getElementById("colorPanel").style.display = "flex";
120
+ }
121
+
122
+ function changeShapeFontSize(delta) {
123
+ if (selectedIds.length === 0) return;
124
+ pushHistory();
125
+ var diag = getCurrentDiagram();
126
+ selectedIds.forEach(function (id) {
127
+ var shape = diag.shapes.find(function (s) { return s.id === id; });
128
+ if (!shape) return;
129
+ var current = shape.fontSize || (shape.type === "text" ? 13 : 12);
130
+ shape.fontSize = Math.max(8, Math.min(28, current + delta));
131
+ });
132
+ saveDiagrammes();
133
+ renderAll();
134
+ document.getElementById("colorPanel").style.display = "flex";
135
+ }
136
+
137
+ // ── Copie de style (pick mode) ──
138
+ function startPickMode(mode) {
139
+ pickTargetIds = selectedIds.slice();
140
+ pickMode = mode;
141
+ document.getElementById("canvas").style.cursor = "crosshair";
142
+ document.getElementById("btnPickFont").classList.toggle("diagram-pick-active", mode === "fontSize");
143
+ document.getElementById("btnPickStyle").classList.toggle("diagram-pick-active", mode === "fullStyle");
144
+ }
145
+
146
+ function cancelPickMode() {
147
+ pickMode = null;
148
+ pickTargetIds = [];
149
+ document.getElementById("canvas").style.cursor = "";
150
+ document.getElementById("btnPickFont").classList.remove("diagram-pick-active");
151
+ document.getElementById("btnPickStyle").classList.remove("diagram-pick-active");
152
+ }
153
+
154
+ function applyPickMode(srcShape) {
155
+ pushHistory();
156
+ var diag = getCurrentDiagram();
157
+ pickTargetIds.forEach(function (id) {
158
+ if (id === srcShape.id) return;
159
+ var shape = diag.shapes.find(function (s) { return s.id === id; });
160
+ if (!shape) return;
161
+ if (pickMode === "fontSize") {
162
+ shape.fontSize = srcShape.fontSize || (srcShape.type === "text" ? 13 : 12);
163
+ } else if (pickMode === "fullStyle") {
164
+ shape.fontSize = srcShape.fontSize || (srcShape.type === "text" ? 13 : 12);
165
+ shape.color = srcShape.color;
166
+ shape.type = srcShape.type;
167
+ shape.w = srcShape.w;
168
+ shape.h = srcShape.h;
169
+ shape.textAlign = srcShape.textAlign || "center";
170
+ shape.textValign = srcShape.textValign || "middle";
171
+ shape.rotation = srcShape.rotation || 0;
172
+ }
173
+ });
174
+ selectedIds = pickTargetIds.slice();
175
+ saveDiagrammes();
176
+ renderAll();
177
+ document.getElementById("colorPanel").style.display = "flex";
178
+ }
179
+
180
+ function rotateShape(delta) {
181
+ var diag = getCurrentDiagram();
182
+ if (!diag || selectedIds.length === 0) return;
183
+ pushHistory();
184
+ selectedIds.forEach(function (id) {
185
+ var s = diag.shapes.find(function (sh) { return sh.id === id; });
186
+ if (!s || s.type === "image") return;
187
+ s.rotation = ((s.rotation || 0) + delta + 360) % 360;
188
+ });
189
+ saveDiagrammes();
190
+ renderAll();
191
+ }
192
+
193
+ function changeShapeOrder(delta) {
194
+ var diag = getCurrentDiagram();
195
+ if (!diag || selectedIds.length === 0) return;
196
+ pushHistory();
197
+ if (delta > 0) {
198
+ // Avancer : parcourir de la fin vers le début
199
+ for (var i = diag.shapes.length - 1; i >= 0; i--) {
200
+ if (selectedIds.indexOf(diag.shapes[i].id) !== -1 && i < diag.shapes.length - 1) {
201
+ var tmp = diag.shapes[i]; diag.shapes[i] = diag.shapes[i + 1]; diag.shapes[i + 1] = tmp;
202
+ }
203
+ }
204
+ } else {
205
+ // Reculer : parcourir du début vers la fin
206
+ for (var i = 0; i < diag.shapes.length; i++) {
207
+ if (selectedIds.indexOf(diag.shapes[i].id) !== -1 && i > 0) {
208
+ var tmp = diag.shapes[i]; diag.shapes[i] = diag.shapes[i - 1]; diag.shapes[i - 1] = tmp;
209
+ }
210
+ }
211
+ }
212
+ saveDiagrammes();
213
+ renderAll();
214
+ }
215
+
216
+ // ── Coller des formes ──
217
+ function pasteShapes() {
218
+ if (clipboard.length === 0) return;
219
+ pushHistory();
220
+ var diag = getCurrentDiagram();
221
+ var now = Date.now();
222
+ var pasted = clipboard.map(function (s, i) {
223
+ return Object.assign({}, JSON.parse(JSON.stringify(s)), {
224
+ id: "s" + (now + i),
225
+ x: s.x + 20,
226
+ y: s.y + 20,
227
+ });
228
+ });
229
+ pasted.forEach(function (s) { diag.shapes.push(s); });
230
+ selectedIds = pasted.map(function (s) { return s.id; });
231
+ selectedId = selectedIds[0]; selectedType = "shape";
232
+ clipboard = pasted.map(function (s) { return JSON.parse(JSON.stringify(s)); });
233
+ saveDiagrammes();
234
+ renderAll();
235
+ document.getElementById("colorPanel").style.display = "flex";
236
+ }
@@ -0,0 +1,292 @@
1
+ // ══════════════════════════════════════
2
+ // text-edit.js — Édition inline du texte et des cellules de tableau
3
+ // ══════════════════════════════════════
4
+
5
+ // ── Édition texte inline ──
6
+ function startTextEdit(shapeId) {
7
+ var diag = getCurrentDiagram();
8
+ var shape = diag.shapes.find(function (s) { return s.id === shapeId; });
9
+ if (!shape || shape.type === "image") return;
10
+ if (shape.type === "table") return;
11
+ editingShapeId = shapeId;
12
+
13
+ var svg = document.getElementById("canvas");
14
+ var sr = svg.getBoundingClientRect();
15
+ var sx = shape.x * viewTransform.scale + viewTransform.x + sr.left;
16
+ var sy = shape.y * viewTransform.scale + viewTransform.y + sr.top;
17
+ var sw = shape.w * viewTransform.scale;
18
+ var sh = shape.h * viewTransform.scale;
19
+ var c = COLORS[shape.color] || COLORS[DEFAULT_COLOR];
20
+
21
+ var useTextarea = shape.type === "postit" || shape.type === "rect" || shape.type === "rounded" || shape.type === "db" || shape.type === "cloud" || shape.type === "nuage";
22
+ if (useTextarea) {
23
+ var ta = document.getElementById("postitTextInput");
24
+ ta.value = shape.text || "";
25
+ var hpad = shape.type === "cloud" ? Math.round(sw * 0.15) : shape.type === "nuage" ? Math.round(sw * 0.14) : 8;
26
+ var vtop, vheight;
27
+ if (shape.type === "cloud") {
28
+ vtop = sy + Math.round(sh * 0.12);
29
+ vheight = sh - Math.round(sh * 0.12) * 2;
30
+ } else if (shape.type === "nuage") {
31
+ // Le nuage Bootstrap : haut visible ≈ y=2/16, bas de la zone texte ≈ y=10/16
32
+ var nuageTop = Math.round(sh * 2 / 16);
33
+ var nuageBot = Math.round(sh * 10 / 16);
34
+ vtop = sy + nuageTop;
35
+ vheight = nuageBot - nuageTop - 4;
36
+ } else if (shape.type === "db") {
37
+ var dbRy = Math.min(12, shape.h * 0.2) * viewTransform.scale;
38
+ vtop = sy + dbRy * 2 + 4;
39
+ vheight = sh - dbRy * 2 - 12;
40
+ } else {
41
+ vtop = sy + 8;
42
+ vheight = sh - 16;
43
+ }
44
+ ta.style.left = (sx + hpad) + "px";
45
+ ta.style.top = vtop + "px";
46
+ ta.style.width = (sw - hpad * 2) + "px";
47
+ ta.style.height = vheight + "px";
48
+ var editFs = shape.fontSize || (shape.type === "text" ? 13 : 12);
49
+ ta.style.fontSize = Math.max(10, editFs * viewTransform.scale) + "px";
50
+ ta.style.color = c.text;
51
+ ta.style.display = "block";
52
+ document.getElementById("shapeTextInput").style.display = "none";
53
+ document.getElementById("textOverlay").style.display = "block";
54
+ // Masquer le texte SVG pour éviter la double lecture
55
+ var sg = document.querySelector('#shapesLayer [data-id="' + shapeId + '"]');
56
+ if (sg) { var tx = sg.querySelector("text"); if (tx) tx.style.visibility = "hidden"; }
57
+ setTimeout(function () { ta.focus(); ta.select(); }, 10);
58
+ } else {
59
+ var input = document.getElementById("shapeTextInput");
60
+ input.value = shape.text || "";
61
+ if (shape.type === "actor") {
62
+ input.style.left = sx + "px";
63
+ input.style.top = (sy + sh * 0.84) + "px";
64
+ input.style.width = sw + "px";
65
+ } else {
66
+ input.style.left = (sx + sw * 0.08) + "px";
67
+ input.style.top = (sy + sh * 0.22) + "px";
68
+ input.style.width = (sw * 0.84) + "px";
69
+ }
70
+ var editFs2 = shape.fontSize || 13;
71
+ input.style.fontSize = Math.max(10, editFs2 * viewTransform.scale) + "px";
72
+ input.style.color = c.text;
73
+ input.style.display = "block";
74
+ document.getElementById("postitTextInput").style.display = "none";
75
+ document.getElementById("textOverlay").style.display = "block";
76
+ setTimeout(function () { input.focus(); input.select(); }, 10);
77
+ }
78
+ }
79
+
80
+ function confirmTextEdit() {
81
+ var input = document.getElementById("shapeTextInput");
82
+ var diag = getCurrentDiagram();
83
+ if (editingShapeId) {
84
+ var shape = diag.shapes.find(function (s) { return s.id === editingShapeId; });
85
+ if (shape) {
86
+ if (shape.type === "table" && editingTableCell !== null) {
87
+ var tval = document.getElementById("postitTextInput").value;
88
+ var oldCellVal = (shape.cells && shape.cells[editingTableCell.row] && shape.cells[editingTableCell.row][editingTableCell.col]) || "";
89
+ if (tval !== oldCellVal) pushHistory();
90
+ if (!shape.cells) shape.cells = [];
91
+ while (shape.cells.length <= editingTableCell.row) shape.cells.push([]);
92
+ shape.cells[editingTableCell.row][editingTableCell.col] = tval;
93
+ editingTableCell = null;
94
+ } else {
95
+ var usesTextarea = shape.type === "postit" || shape.type === "rect" || shape.type === "rounded" || shape.type === "db" || shape.type === "cloud" || shape.type === "nuage";
96
+ var val = usesTextarea
97
+ ? document.getElementById("postitTextInput").value
98
+ : input.value;
99
+ if (val !== (shape.text || "")) pushHistory();
100
+ shape.text = val;
101
+ }
102
+ saveDiagrammes();
103
+ renderAll();
104
+ }
105
+ editingShapeId = null;
106
+ } else if (editingArrowId) {
107
+ var arrow = (diag.arrows || []).find(function (a) { return a.id === editingArrowId; });
108
+ if (arrow) {
109
+ if (input.value !== (arrow.label || "")) pushHistory();
110
+ arrow.label = input.value; saveDiagrammes(); renderAll();
111
+ }
112
+ editingArrowId = null;
113
+ }
114
+ document.getElementById("textOverlay").style.display = "none";
115
+ document.getElementById("postitTextInput").style.display = "none";
116
+ document.getElementById("shapeTextInput").style.display = "block";
117
+ }
118
+
119
+ function startTableCellEdit(shapeId, row, col) {
120
+ var diag = getCurrentDiagram();
121
+ var shape = diag.shapes.find(function (s) { return s.id === shapeId; });
122
+ if (!shape) return;
123
+ editingShapeId = shapeId;
124
+ editingTableCell = { row: row, col: col };
125
+
126
+ var tRows = shape.rows || 3;
127
+ var scColWidths = getColWidths(shape);
128
+ var scColOffsets = getColOffsets(shape);
129
+ var cellW = scColWidths[col], cellH = shape.h / tRows;
130
+ var cellX = shape.x + scColOffsets[col], cellY = shape.y + row * cellH;
131
+
132
+ var svgEl = document.getElementById("canvas");
133
+ var sr = svgEl.getBoundingClientRect();
134
+ var csx = cellX * viewTransform.scale + viewTransform.x + sr.left;
135
+ var csy = cellY * viewTransform.scale + viewTransform.y + sr.top;
136
+ var csw = cellW * viewTransform.scale, csh = cellH * viewTransform.scale;
137
+ var cc = COLORS[shape.color] || COLORS[DEFAULT_COLOR];
138
+
139
+ var ta = document.getElementById("postitTextInput");
140
+ ta.value = (shape.cells && shape.cells[row] && shape.cells[row][col]) || "";
141
+ ta.style.left = (csx + 2) + "px";
142
+ ta.style.top = (csy + 2) + "px";
143
+ ta.style.width = (csw - 4) + "px";
144
+ ta.style.height = (csh - 4) + "px";
145
+ var tfs = shape.fontSize || 12;
146
+ ta.style.fontSize = Math.max(10, tfs * viewTransform.scale) + "px";
147
+ ta.style.color = cc.text;
148
+ ta.style.display = "block";
149
+ document.getElementById("shapeTextInput").style.display = "none";
150
+ document.getElementById("textOverlay").style.display = "block";
151
+ var sg = document.querySelector('#shapesLayer [data-id="' + shapeId + '"]');
152
+ if (sg) { var cellTx = sg.querySelector('text[data-cell="' + row + '-' + col + '"]'); if (cellTx) cellTx.style.visibility = "hidden"; }
153
+ setTimeout(function () { ta.focus(); ta.select(); }, 10);
154
+ }
155
+
156
+ function addTableRow() {
157
+ var diag = getCurrentDiagram();
158
+ var shape = selectedIds.length === 1 ? diag.shapes.find(function (s) { return s.id === selectedIds[0]; }) : null;
159
+ if (!shape || shape.type !== "table") return;
160
+ pushHistory();
161
+ shape.rows = (shape.rows || 3) + 1;
162
+ if (!shape.cells) shape.cells = [];
163
+ while (shape.cells.length < shape.rows) shape.cells.push([]);
164
+ shape.cells[shape.rows - 1] = new Array(shape.cols || 3).fill("");
165
+ saveDiagrammes(); renderAll();
166
+ document.getElementById("colorPanel").style.display = "flex";
167
+ syncColorPanel();
168
+ }
169
+
170
+ function removeTableRow() {
171
+ var diag = getCurrentDiagram();
172
+ var shape = selectedIds.length === 1 ? diag.shapes.find(function (s) { return s.id === selectedIds[0]; }) : null;
173
+ if (!shape || shape.type !== "table" || (shape.rows || 3) <= 1) return;
174
+ pushHistory();
175
+ shape.rows = (shape.rows || 3) - 1;
176
+ if (shape.cells && shape.cells.length > shape.rows) shape.cells.splice(shape.rows);
177
+ saveDiagrammes(); renderAll();
178
+ document.getElementById("colorPanel").style.display = "flex";
179
+ syncColorPanel();
180
+ }
181
+
182
+ function addTableCol() {
183
+ var diag = getCurrentDiagram();
184
+ var shape = selectedIds.length === 1 ? diag.shapes.find(function (s) { return s.id === selectedIds[0]; }) : null;
185
+ if (!shape || shape.type !== "table") return;
186
+ pushHistory();
187
+ var oldCols = shape.cols || 3;
188
+ shape.cols = oldCols + 1;
189
+ if (!shape.cells) shape.cells = [];
190
+ var rows = shape.rows || 3;
191
+ for (var ri = 0; ri < rows; ri++) {
192
+ if (!shape.cells[ri]) shape.cells[ri] = [];
193
+ shape.cells[ri].push("");
194
+ }
195
+ // Répartir la largeur : réduire les colonnes existantes proportionnellement
196
+ var oldWidths = getColWidths({ cols: oldCols, w: shape.w, colWidths: shape.colWidths });
197
+ var newColW = shape.w / shape.cols;
198
+ var scale = (shape.w - newColW) / shape.w;
199
+ shape.colWidths = oldWidths.map(function (w) { return w * scale; });
200
+ shape.colWidths.push(newColW);
201
+ saveDiagrammes(); renderAll();
202
+ document.getElementById("colorPanel").style.display = "flex";
203
+ syncColorPanel();
204
+ }
205
+
206
+ function removeTableCol() {
207
+ var diag = getCurrentDiagram();
208
+ var shape = selectedIds.length === 1 ? diag.shapes.find(function (s) { return s.id === selectedIds[0]; }) : null;
209
+ if (!shape || shape.type !== "table" || (shape.cols || 3) <= 1) return;
210
+ pushHistory();
211
+ var oldCols = shape.cols || 3;
212
+ shape.cols = oldCols - 1;
213
+ if (shape.cells) shape.cells.forEach(function (row) { if (row.length > shape.cols) row.splice(shape.cols); });
214
+ // Retirer la dernière colonne et rescaler les restantes pour remplir shape.w
215
+ var cw = getColWidths({ cols: oldCols, w: shape.w, colWidths: shape.colWidths });
216
+ cw.splice(shape.cols);
217
+ var total = cw.reduce(function (s, v) { return s + v; }, 0);
218
+ shape.colWidths = cw.map(function (w) { return w * shape.w / total; });
219
+ saveDiagrammes(); renderAll();
220
+ document.getElementById("colorPanel").style.display = "flex";
221
+ syncColorPanel();
222
+ }
223
+
224
+ // ── Overlay tableau (boutons +/− ligne/colonne sur le canvas) ──
225
+ function updateTableOverlay() {
226
+ var ids = ["tcBtnAddCol","tcBtnRemoveCol","tcBtnAddRow","tcBtnRemoveRow"];
227
+ var hide = function () { ids.forEach(function (id) { var el = document.getElementById(id); if (el) el.style.display = "none"; }); };
228
+ if (boardLocked || selectedIds.length !== 1 || selectedType !== "shape") { hide(); return; }
229
+ var diag = getCurrentDiagram();
230
+ if (!diag) { hide(); return; }
231
+ var shape = diag.shapes.find(function (s) { return s.id === selectedIds[0]; });
232
+ if (!shape || shape.type !== "table") { hide(); return; }
233
+
234
+ var svg = document.getElementById("canvas");
235
+ var sr = svg.getBoundingClientRect();
236
+ var sc = viewTransform.scale;
237
+ var tx = viewTransform.x, ty = viewTransform.y;
238
+ var right = (shape.x + shape.w) * sc + tx + sr.left;
239
+ var bottom = (shape.y + shape.h) * sc + ty + sr.top;
240
+ var rows = shape.rows || 3;
241
+ var cellH = shape.h * sc / rows;
242
+ var BW = 22, GAP = 4;
243
+
244
+ // +/− col : à droite de la dernière ligne, centrés verticalement dans cette ligne
245
+ var lastRowCy = bottom - cellH / 2;
246
+ var ac = document.getElementById("tcBtnAddCol");
247
+ var rc = document.getElementById("tcBtnRemoveCol");
248
+ ac.style.left = (right + GAP) + "px"; ac.style.top = (lastRowCy - BW - 2) + "px";
249
+ rc.style.left = (right + GAP) + "px"; rc.style.top = (lastRowCy + 2) + "px";
250
+ ac.style.display = rc.style.display = "flex";
251
+
252
+ // +/− row : sous la dernière ligne, alignés à droite de la table
253
+ var ar = document.getElementById("tcBtnAddRow");
254
+ var rr = document.getElementById("tcBtnRemoveRow");
255
+ ar.style.left = (right - BW * 2 - GAP) + "px"; ar.style.top = (bottom + GAP) + "px";
256
+ rr.style.left = (right - BW - 2) + "px"; rr.style.top = (bottom + GAP) + "px";
257
+ ar.style.display = rr.style.display = "flex";
258
+ }
259
+
260
+ // ── Édition du label d'une flèche ──
261
+ function startArrowTextEdit(arrowId) {
262
+ var diag = getCurrentDiagram();
263
+ var arrow = (diag.arrows || []).find(function (a) { return a.id === arrowId; });
264
+ if (!arrow) return;
265
+ var from = diag.shapes.find(function (s) { return s.id === arrow.from; });
266
+ var to = diag.shapes.find(function (s) { return s.id === arrow.to; });
267
+ if (!from || !to) return;
268
+
269
+ var toCx = to.x + to.w / 2, toCy = to.y + to.h / 2;
270
+ var frCx = from.x + from.w / 2, frCy = from.y + from.h / 2;
271
+ var fp = getEdgePoint(from, toCx, toCy);
272
+ var tp = getEdgePoint(to, frCx, frCy);
273
+ var mx = (fp.x + tp.x) / 2;
274
+ var my = (fp.y + tp.y) / 2;
275
+
276
+ var svg = document.getElementById("canvas");
277
+ var sr = svg.getBoundingClientRect();
278
+ var sx = mx * viewTransform.scale + viewTransform.x + sr.left;
279
+ var sy = my * viewTransform.scale + viewTransform.y + sr.top;
280
+
281
+ editingArrowId = arrowId;
282
+ var input = document.getElementById("shapeTextInput");
283
+ input.value = arrow.label || "";
284
+ input.style.left = (sx - 60) + "px";
285
+ input.style.top = (sy - 12) + "px";
286
+ input.style.width = "120px";
287
+ input.style.fontSize = Math.max(10, 11 * viewTransform.scale) + "px";
288
+ input.style.color = "#78716c";
289
+
290
+ document.getElementById("textOverlay").style.display = "block";
291
+ setTimeout(function () { input.focus(); input.select(); }, 10);
292
+ }
package/diagram.html CHANGED
@@ -318,6 +318,13 @@
318
318
  <script src="i18n/en.js"></script>
319
319
  <script src="i18n/i18n.js"></script>
320
320
  <script src="diagrammes.js"></script>
321
- <script src="diagram.js"></script>
321
+ <script src="diagram/globals.js"></script>
322
+ <script src="diagram/persistence.js"></script>
323
+ <script src="diagram/render.js"></script>
324
+ <script src="diagram/diagrams.js"></script>
325
+ <script src="diagram/shape-ops.js"></script>
326
+ <script src="diagram/text-edit.js"></script>
327
+ <script src="diagram/links.js"></script>
328
+ <script src="diagram/events.js"></script>
322
329
  </body>
323
330
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doc-survival-kit",
3
- "version": "2.0.0",
3
+ "version": "3.11.0",
4
4
  "description": "Dashboard personnel offline : diagrammes, tâches, notes et liens dans un seul fichier HTML — fonctionne sans serveur via file://",
5
5
  "bin": {
6
6
  "doc-survival-kit": "./bin/cli.js"
@@ -8,18 +8,18 @@
8
8
  "files": [
9
9
  "bin/",
10
10
  "i18n/",
11
- "index.html",
11
+ "images/",
12
+ "diagram/",
12
13
  "admin.html",
13
14
  "diagram.html",
14
- "style.css",
15
- "mesLiens.js",
16
- "mesNotes.js",
17
15
  "diagrammes.js",
16
+ "index.html",
18
17
  "liens.js",
19
- "taches.js",
18
+ "mesLiens.js",
19
+ "mesNotes.js",
20
20
  "notes.js",
21
- "diagram.js",
22
- "images/"
21
+ "style.css",
22
+ "taches.js"
23
23
  ],
24
24
  "engines": {
25
25
  "node": ">=16.7.0"