kingkont 0.18.6 → 0.18.7
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/renderer/board.js +22 -5
- package/renderer/settings.js +42 -0
- package/renderer/styles.css +32 -1
package/package.json
CHANGED
package/renderer/board.js
CHANGED
|
@@ -2461,11 +2461,16 @@ async function createNodeEl(node) {
|
|
|
2461
2461
|
el.dataset.id = node.id;
|
|
2462
2462
|
el.style.left = node.x + 'px';
|
|
2463
2463
|
el.style.top = node.y + 'px';
|
|
2464
|
-
// Label
|
|
2465
|
-
//
|
|
2466
|
-
//
|
|
2467
|
-
//
|
|
2468
|
-
if (node.type
|
|
2464
|
+
// Label-ноды: высоту НЕ применяем (auto по контенту), но ширину — ДА,
|
|
2465
|
+
// если юзер явно её задал через label-width-handle. Это позволяет
|
|
2466
|
+
// сделать многострочный label («ширина задаёт перенос»). Без width
|
|
2467
|
+
// → auto-width по тексту (как раньше).
|
|
2468
|
+
if (node.type === 'label') {
|
|
2469
|
+
if (node.width) {
|
|
2470
|
+
el.style.width = node.width + 'px';
|
|
2471
|
+
el.dataset.fixedWidth = '1'; // CSS: разрешаем label-text занять 100%
|
|
2472
|
+
}
|
|
2473
|
+
} else {
|
|
2469
2474
|
if (node.width) el.style.width = node.width + 'px';
|
|
2470
2475
|
if (node.height) el.style.height = node.height + 'px';
|
|
2471
2476
|
}
|
|
@@ -2514,6 +2519,18 @@ async function createNodeEl(node) {
|
|
|
2514
2519
|
el.appendChild(rh);
|
|
2515
2520
|
attachResize(el, node, rh);
|
|
2516
2521
|
|
|
2522
|
+
// Label-ноды получают ВТОРОЙ хендл — на правом краю — для управления
|
|
2523
|
+
// только ШИРИНОЙ (юзер просил: «ноде лейбл позволь менять ширину
|
|
2524
|
+
// отдельно, чтобы менялось количество строк если текст длинный»).
|
|
2525
|
+
// Существующий .resize-handle (правый-нижний угол) меняет fontSize.
|
|
2526
|
+
if (node.type === 'label') {
|
|
2527
|
+
const wh = document.createElement('div');
|
|
2528
|
+
wh.className = 'label-width-handle';
|
|
2529
|
+
wh.title = 'Тяни — ширина (для переноса строк)';
|
|
2530
|
+
el.appendChild(wh);
|
|
2531
|
+
attachLabelWidthResize(el, node, wh);
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2517
2534
|
const anchor = document.createElement('div');
|
|
2518
2535
|
anchor.className = 'anchor';
|
|
2519
2536
|
anchor.title = 'Тяни, чтобы сослаться или сгенерировать ноду со ссылкой';
|
package/renderer/settings.js
CHANGED
|
@@ -746,6 +746,48 @@ async function openGenerateForRef(fromNode, clientX, clientY, forceKind) {
|
|
|
746
746
|
}, 50);
|
|
747
747
|
}
|
|
748
748
|
|
|
749
|
+
// Width-only resize для label-нод. Юзер тянет хендл на правом краю —
|
|
750
|
+
// устанавливаем node.width, label-text оборачивается. Высота auto.
|
|
751
|
+
// Двойной клик по хендлу — снять width (вернуть auto-width по тексту).
|
|
752
|
+
function attachLabelWidthResize(el, node, handle) {
|
|
753
|
+
handle.addEventListener('mousedown', e => {
|
|
754
|
+
e.preventDefault();
|
|
755
|
+
e.stopPropagation();
|
|
756
|
+
const startX = e.clientX;
|
|
757
|
+
const startW = el.offsetWidth;
|
|
758
|
+
const labelText = el.querySelector('.label-text');
|
|
759
|
+
const onMove = ev => {
|
|
760
|
+
const dx = (ev.clientX - startX) / state.zoom;
|
|
761
|
+
const newW = Math.max(80, Math.min(2000, startW + dx));
|
|
762
|
+
node.width = Math.round(newW);
|
|
763
|
+
el.style.width = node.width + 'px';
|
|
764
|
+
el.dataset.fixedWidth = '1';
|
|
765
|
+
// Force label-text to fill — иначе inline-block остаётся узким.
|
|
766
|
+
if (labelText) labelText.style.width = '100%';
|
|
767
|
+
renderConnections();
|
|
768
|
+
};
|
|
769
|
+
const onUp = () => {
|
|
770
|
+
document.removeEventListener('mousemove', onMove);
|
|
771
|
+
document.removeEventListener('mouseup', onUp);
|
|
772
|
+
scheduleSave();
|
|
773
|
+
};
|
|
774
|
+
document.addEventListener('mousemove', onMove);
|
|
775
|
+
document.addEventListener('mouseup', onUp);
|
|
776
|
+
});
|
|
777
|
+
// dblclick — сбросить ширину (вернуть auto-size).
|
|
778
|
+
handle.addEventListener('dblclick', e => {
|
|
779
|
+
e.preventDefault();
|
|
780
|
+
e.stopPropagation();
|
|
781
|
+
delete node.width;
|
|
782
|
+
el.style.width = '';
|
|
783
|
+
delete el.dataset.fixedWidth;
|
|
784
|
+
const labelText = el.querySelector('.label-text');
|
|
785
|
+
if (labelText) labelText.style.width = '';
|
|
786
|
+
renderConnections();
|
|
787
|
+
scheduleSave();
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
|
|
749
791
|
function attachResize(el, node, handle) {
|
|
750
792
|
handle.addEventListener('mousedown', e => {
|
|
751
793
|
e.preventDefault();
|
package/renderer/styles.css
CHANGED
|
@@ -519,6 +519,12 @@
|
|
|
519
519
|
overflow: hidden;
|
|
520
520
|
}
|
|
521
521
|
.welcome-card-thumb {
|
|
522
|
+
/* position:absolute + inset:0 — заполняем всю карточку (4:3).
|
|
523
|
+
БАДЖИ внутри (cloud/bg) тоже absolute → этот thumb работает как
|
|
524
|
+
positioning context для них. РАНЬШЕ ниже было `.welcome-card-thumb
|
|
525
|
+
{ position: relative; }` — оно переопределяло absolute → thumb
|
|
526
|
+
shrink'ался до размера контента (символ «+» / «☁» / «🎬») и
|
|
527
|
+
прибивался к верху карточки. Слились в один rule. */
|
|
522
528
|
position: absolute; inset: 0;
|
|
523
529
|
background: #1a1a1a;
|
|
524
530
|
display: flex; align-items: center; justify-content: center;
|
|
@@ -528,7 +534,6 @@
|
|
|
528
534
|
.welcome-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
529
535
|
/* ☁-бейдж в углу обложки облачного проекта. Делает cloud/folder-проекты
|
|
530
536
|
визуально различимыми в общем grid'е (без необходимости второго рядa). */
|
|
531
|
-
.welcome-card-thumb { position: relative; }
|
|
532
537
|
.welcome-card-cloud-badge {
|
|
533
538
|
position: absolute; right: 6px; bottom: 6px;
|
|
534
539
|
background: rgba(20, 30, 50, 0.85); color: #9cf;
|
|
@@ -764,6 +769,32 @@
|
|
|
764
769
|
}
|
|
765
770
|
.node.label-node:hover .resize-handle,
|
|
766
771
|
.node.label-node:focus-within .resize-handle { opacity: 1; }
|
|
772
|
+
/* Width-only handle на правом краю — отдельно от font-size handle.
|
|
773
|
+
Тянуть → меняется ширина label, текст переносится. dblclick →
|
|
774
|
+
сбросить ширину обратно к auto. */
|
|
775
|
+
.node.label-node .label-width-handle {
|
|
776
|
+
position: absolute;
|
|
777
|
+
right: -3px; top: 50%;
|
|
778
|
+
transform: translateY(-50%);
|
|
779
|
+
width: 6px; height: 36px;
|
|
780
|
+
background: rgba(90,168,255,0.7);
|
|
781
|
+
border: 1px solid rgba(255,255,255,0.35);
|
|
782
|
+
border-radius: 3px;
|
|
783
|
+
cursor: ew-resize;
|
|
784
|
+
opacity: 0; transition: opacity 0.15s;
|
|
785
|
+
z-index: 11;
|
|
786
|
+
}
|
|
787
|
+
.node.label-node:hover .label-width-handle,
|
|
788
|
+
.node.label-node:focus-within .label-width-handle { opacity: 1; }
|
|
789
|
+
/* Когда label имеет explicit width (data-fixed-width="1") — внутренний
|
|
790
|
+
label-text должен ЗАПОЛНЯТЬ родителя, иначе inline-block остаётся
|
|
791
|
+
узким и текст не переносится. Сбрасываем min/max-width inner'a. */
|
|
792
|
+
.node.label-node[data-fixed-width="1"] .label-text {
|
|
793
|
+
width: 100%;
|
|
794
|
+
min-width: 0;
|
|
795
|
+
max-width: none;
|
|
796
|
+
box-sizing: border-box;
|
|
797
|
+
}
|
|
767
798
|
|
|
768
799
|
/* Body — wrapper без визуального вклада. */
|
|
769
800
|
.node.label-node .node-body {
|