kingkont 0.20.54 → 0.20.56
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 +4 -1
- package/renderer/settings.js +18 -13
- package/renderer/styles.css +18 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kingkont",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.56",
|
|
4
4
|
"description": "KingKont \u00b7 Chatium \u2014 \u043d\u043e\u0434-\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0446\u0435\u043d \u0441 AI-\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 (\u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438/\u0432\u0438\u0434\u0435\u043e/\u0433\u043e\u043b\u043e\u0441/SFX/\u043c\u0443\u0437\u044b\u043a\u0430/\u0442\u0435\u043a\u0441\u0442)",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"bin": {
|
package/renderer/board.js
CHANGED
|
@@ -4110,7 +4110,10 @@ async function createNodeEl(node) {
|
|
|
4110
4110
|
// (ensureNodeDescriptionEl идемпотентно создаёт/обновляет/удаляет).
|
|
4111
4111
|
// Вызывается ЗДЕСЬ, чтобы покрыть все вызовы createNodeEl: renderCanvas
|
|
4112
4112
|
// / generate.js (новые ноды) / timeline.js / drawings.js / chat.js.
|
|
4113
|
-
|
|
4113
|
+
// Передаём el-hint — .node ещё не в canvas DOM (caller сделает appendChild
|
|
4114
|
+
// после return), и без hint'а measure'а .node-footer не сработает →
|
|
4115
|
+
// placeholder перекрыл бы regen-кнопки.
|
|
4116
|
+
if (typeof ensureNodeDescriptionEl === 'function') ensureNodeDescriptionEl(node, el);
|
|
4114
4117
|
return el;
|
|
4115
4118
|
}
|
|
4116
4119
|
// =================== Контекстное меню ноды (ПКМ) ===================
|
package/renderer/settings.js
CHANGED
|
@@ -587,7 +587,7 @@ async function renderNodeBody(node, body) {
|
|
|
587
587
|
// «попробуем показать описание ВНЕ этой ноды, но так чтобы оно с ней
|
|
588
588
|
// перемещалось… совпадало с ней по ширине, а высота — сколько займет текст».
|
|
589
589
|
// Идемпотентно: пересоздаёт DOM, если описание изменилось/добавилось/удалилось.
|
|
590
|
-
function ensureNodeDescriptionEl(node) {
|
|
590
|
+
function ensureNodeDescriptionEl(node, nodeElHint) {
|
|
591
591
|
if (!node) return null;
|
|
592
592
|
const canvasEl = document.getElementById('canvas');
|
|
593
593
|
if (!canvasEl) return null;
|
|
@@ -638,24 +638,29 @@ function ensureNodeDescriptionEl(node) {
|
|
|
638
638
|
el.classList.remove('empty');
|
|
639
639
|
if (el.textContent !== text) el.textContent = text;
|
|
640
640
|
}
|
|
641
|
-
positionNodeDescriptionEl(node, el);
|
|
641
|
+
positionNodeDescriptionEl(node, el, nodeElHint);
|
|
642
|
+
// Если в этот момент .node ещё не вставлен в canvas — querySelector
|
|
643
|
+
// вернёт null → footerH=0 → placeholder сел поверх footer'а. Через rAF
|
|
644
|
+
// делаем повторный pass: к этому моменту caller сделал appendChild,
|
|
645
|
+
// footer измерим, sidecar сдвинется чуть выше.
|
|
646
|
+
requestAnimationFrame(() => positionNodeDescriptionEl(node, el));
|
|
642
647
|
return el;
|
|
643
648
|
}
|
|
644
|
-
function positionNodeDescriptionEl(node, el) {
|
|
649
|
+
function positionNodeDescriptionEl(node, el, nodeElHint) {
|
|
645
650
|
if (!el) el = document.querySelector(`.node-description-outside[data-desc-for="${node.id}"]`);
|
|
646
651
|
if (!el) return;
|
|
647
652
|
const w = node.width || 280;
|
|
648
653
|
const h = node.height || 200;
|
|
649
|
-
//
|
|
650
|
-
//
|
|
651
|
-
//
|
|
652
|
-
//
|
|
653
|
-
//
|
|
654
|
-
|
|
655
|
-
|
|
654
|
+
// У image/video с node.generated есть .node-footer (regen-btn, история ←/→)
|
|
655
|
+
// — она у нижней грани. Поднимаем sidecar НАД footer'ом на footerH+2
|
|
656
|
+
// выше — иначе placeholder «Добавить описание» перекрывал бы regen-кнопки
|
|
657
|
+
// (юзер: «после появления кнопки добавить описание из ноды пропал ряд
|
|
658
|
+
// кнопок который делал перегенерацию»).
|
|
659
|
+
const nodeEl = nodeElHint || document.querySelector(`.node[data-id="${node.id}"]`);
|
|
660
|
+
const footerH = nodeEl?.querySelector('.node-footer')?.offsetHeight || 0;
|
|
656
661
|
const descH = el.offsetHeight || 0;
|
|
657
662
|
el.style.left = node.x + 'px';
|
|
658
|
-
el.style.top = (node.y + h - descH - 2) + 'px';
|
|
663
|
+
el.style.top = (node.y + h - footerH - descH - 2) + 'px';
|
|
659
664
|
el.style.width = w + 'px';
|
|
660
665
|
}
|
|
661
666
|
function removeNodeDescriptionEl(nodeId) {
|
|
@@ -690,13 +695,13 @@ function fitNodeHeightToMedia(node, nodeEl, mediaEl) {
|
|
|
690
695
|
if (Math.abs(newH - (node.height || 0)) <= 2) {
|
|
691
696
|
// Высоту не меняем, но позицию sidecar'а всё равно обновим — а вдруг
|
|
692
697
|
// описание появилось/изменилось до того как media догрузилось.
|
|
693
|
-
positionNodeDescriptionEl(node);
|
|
698
|
+
positionNodeDescriptionEl(node, null, nodeEl);
|
|
694
699
|
return;
|
|
695
700
|
}
|
|
696
701
|
node.height = newH;
|
|
697
702
|
nodeEl.style.height = newH + 'px';
|
|
698
703
|
if (typeof renderConnections === 'function') renderConnections();
|
|
699
|
-
positionNodeDescriptionEl(node);
|
|
704
|
+
positionNodeDescriptionEl(node, null, nodeEl);
|
|
700
705
|
scheduleSave();
|
|
701
706
|
}
|
|
702
707
|
|
package/renderer/styles.css
CHANGED
|
@@ -1908,7 +1908,10 @@
|
|
|
1908
1908
|
.modal.hidden { display: none; }
|
|
1909
1909
|
.modal-card {
|
|
1910
1910
|
background: #2a2a2a; border: 1px solid #444; border-radius: 12px;
|
|
1911
|
-
padding:
|
|
1911
|
+
/* padding-bottom=0: .modal-actions сама даёт нижний паддинг через свой
|
|
1912
|
+
padding-bottom — нужно чтобы sticky-bottom:0 ровно совпал с краем
|
|
1913
|
+
модалки. */
|
|
1914
|
+
padding: 24px 24px 0; width: 540px; max-width: 92vw; max-height: 90vh;
|
|
1912
1915
|
overflow-y: auto; display: flex; flex-direction: column; gap: 14px;
|
|
1913
1916
|
position: relative;
|
|
1914
1917
|
}
|
|
@@ -1928,7 +1931,20 @@
|
|
|
1928
1931
|
}
|
|
1929
1932
|
.modal-card input:focus, .modal-card textarea:focus, .modal-card select:focus { border-color: #6a8aaa; }
|
|
1930
1933
|
.modal-card textarea { resize: vertical; min-height: 100px; }
|
|
1931
|
-
|
|
1934
|
+
/* Кнопки внизу модалки залипают к её низу — юзер: «сделай чтобы кнопки
|
|
1935
|
+
прилипали к нижней части модалки и были всегда видны, во всех модалках».
|
|
1936
|
+
Sticky bottom:0 пинит к нижнему краю scroll-контейнера (modal-card),
|
|
1937
|
+
negative margin-left/right компенсирует padding modal-card'а (24px),
|
|
1938
|
+
padding 14px 24px 24px даёт собственный bottom-pad. */
|
|
1939
|
+
.modal-actions {
|
|
1940
|
+
display: flex; gap: 8px; align-items: center;
|
|
1941
|
+
position: sticky; bottom: 0;
|
|
1942
|
+
margin: 14px -24px 0;
|
|
1943
|
+
padding: 14px 24px 24px;
|
|
1944
|
+
background: #2a2a2a;
|
|
1945
|
+
border-top: 1px solid #383838;
|
|
1946
|
+
z-index: 5;
|
|
1947
|
+
}
|
|
1932
1948
|
.modal-actions .spacer { flex: 1; }
|
|
1933
1949
|
.seg-control { display: flex; }
|
|
1934
1950
|
.seg-control .seg { flex: 1; background: #1e1e1e; border: 1px solid #383838; border-radius: 0; }
|