kingkont 0.7.86 → 0.7.87

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kingkont",
3
- "version": "0.7.86",
3
+ "version": "0.7.87",
4
4
  "description": "KingKont · Chatium — нод-редактор сцен с AI-генерацией (картинки/видео/голос/SFX/музыка/текст)",
5
5
  "main": "main.js",
6
6
  "bin": {
package/renderer/board.js CHANGED
@@ -1111,25 +1111,35 @@ function askName(title, placeholder = '', initialValue = '', opts = {}) {
1111
1111
  // Возвращает выбранную строку или null если юзер закрыл.
1112
1112
  // window.prompt() в Electron renderer молча возвращает null — поэтому
1113
1113
  // нельзя использовать его для select-подобных диалогов.
1114
- function askChoice(title, options, currentValue) {
1114
+ // askChoice(title, options, currentValue, opts?)
1115
+ // opts:
1116
+ // vertical: bool — стэкаем кнопки вертикально (по умолчанию — flex-wrap)
1117
+ // optionStyles: { [opt]: 'css-string' } — кастомный CSS на кнопку (для preview-эффектов,
1118
+ // напр. рендер опции «Карандашом» в самом шрифте Karandashom)
1119
+ function askChoice(title, options, currentValue, opts = {}) {
1115
1120
  return new Promise(resolve => {
1116
1121
  const overlay = document.createElement('div');
1117
1122
  overlay.className = 'modal';
1118
1123
  overlay.style.cssText = 'position:fixed; inset:0; background:rgba(0,0,0,0.55); display:flex; align-items:center; justify-content:center; z-index:9999;';
1119
1124
  const box = document.createElement('div');
1120
- box.style.cssText = 'background:#222; border:1px solid #444; border-radius:8px; padding:18px 20px; min-width:360px; box-shadow:0 8px 32px rgba(0,0,0,0.6);';
1125
+ box.style.cssText = 'background:#222; border:1px solid #444; border-radius:8px; padding:18px 20px; min-width:360px; max-height:80vh; overflow-y:auto; box-shadow:0 8px 32px rgba(0,0,0,0.6);';
1121
1126
  const h = document.createElement('h3');
1122
1127
  h.textContent = title;
1123
1128
  h.style.cssText = 'margin:0 0 12px; font-size:14px; color:#e0e0e0;';
1124
1129
  box.append(h);
1125
1130
  const grid = document.createElement('div');
1126
- grid.style.cssText = 'display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px;';
1131
+ grid.style.cssText = opts.vertical
1132
+ ? 'display:flex; flex-direction:column; gap:6px; margin-bottom:14px;'
1133
+ : 'display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px;';
1127
1134
  const close = (val) => { overlay.remove(); resolve(val); };
1128
1135
  for (const opt of options) {
1129
1136
  const b = document.createElement('button');
1130
1137
  b.textContent = opt;
1131
- b.style.cssText = 'padding:6px 12px; background:#1a1a1a; color:#e0e0e0; border:1px solid #444; border-radius:4px; font-size:13px; cursor:pointer;' +
1132
- (opt === currentValue ? 'border-color:#7c3aed; background:#2a1a3a;' : '');
1138
+ let css = 'padding:6px 12px; background:#1a1a1a; color:#e0e0e0; border:1px solid #444; border-radius:4px; font-size:13px; cursor:pointer;';
1139
+ if (opts.vertical) css += 'text-align:left;';
1140
+ if (opt === currentValue) css += 'border-color:#7c3aed; background:#2a1a3a;';
1141
+ if (opts.optionStyles?.[opt]) css += opts.optionStyles[opt];
1142
+ b.style.cssText = css;
1133
1143
  b.addEventListener('click', () => close(opt));
1134
1144
  grid.append(b);
1135
1145
  }
@@ -1781,7 +1791,18 @@ function showNodeContextMenu(node, clientX, clientY) {
1781
1791
  const ts = node.textStyle;
1782
1792
  const curFont = LABEL_FONTS.find(f => f.id === ts.fontFamily) || LABEL_FONTS[0];
1783
1793
  add(`🔤 Шрифт: ${curFont.label}`, async () => {
1784
- const choice = await askChoice('Шрифт label-ноды', LABEL_FONTS.map(f => f.label), curFont.label);
1794
+ // Каждая опция в picker'е рендерится в собственно её шрифте — юзер
1795
+ // сразу видит как «Карандашом» / «Прописью» / «Кистью» выглядят.
1796
+ const fontStyles = {};
1797
+ for (const f of LABEL_FONTS) {
1798
+ fontStyles[f.label] = `font-family: ${getLabelFontFamily(f.id)}; font-size: 22px; padding: 8px 14px; line-height: 1.3;`;
1799
+ }
1800
+ const choice = await askChoice(
1801
+ 'Шрифт label-ноды',
1802
+ LABEL_FONTS.map(f => f.label),
1803
+ curFont.label,
1804
+ { vertical: true, optionStyles: fontStyles },
1805
+ );
1785
1806
  if (!choice) return;
1786
1807
  const picked = LABEL_FONTS.find(f => f.label === choice);
1787
1808
  if (!picked) return;
@@ -1790,7 +1811,19 @@ function showNodeContextMenu(node, clientX, clientY) {
1790
1811
  await refreshNodeDOM(node.id);
1791
1812
  });
1792
1813
  add(`📏 Размер: ${ts.fontSize || 32}px`, async () => {
1793
- const choice = await askChoice('Размер шрифта', LABEL_FONT_SIZES.map(s => s + 'px'), (ts.fontSize || 32) + 'px');
1814
+ // Каждый размер в picker'е рендерится в реальном размере лимитом),
1815
+ // чтобы юзер чувствовал «насколько крупно». Также вертикально.
1816
+ const sizeStyles = {};
1817
+ for (const s of LABEL_FONT_SIZES) {
1818
+ const previewSize = Math.min(s, 36); // не растим окно — лимит превью
1819
+ sizeStyles[s + 'px'] = `font-size: ${previewSize}px; line-height: 1.2; padding: 6px 14px;`;
1820
+ }
1821
+ const choice = await askChoice(
1822
+ 'Размер шрифта',
1823
+ LABEL_FONT_SIZES.map(s => s + 'px'),
1824
+ (ts.fontSize || 32) + 'px',
1825
+ { vertical: true, optionStyles: sizeStyles },
1826
+ );
1794
1827
  if (!choice) return;
1795
1828
  const n = parseInt(choice, 10);
1796
1829
  if (Number.isFinite(n)) {
@@ -85,6 +85,27 @@ function applyLabelStyle(ed, style) {
85
85
  ed.dataset.font = style.fontFamily || 'default';
86
86
  }
87
87
 
88
+ // Соответствие label-font-id → CSS font-family stack. Используется для
89
+ // preview-кнопок в picker'e шрифта (askChoice показывает каждую опцию
90
+ // в собственно её шрифте, чтобы юзер видел как выглядит). Семейства
91
+ // должны совпадать с теми, что заданы в .label-text[data-font="..."]
92
+ // в renderer/styles.css.
93
+ function getLabelFontFamily(id) {
94
+ const map = {
95
+ default: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
96
+ pencil: "'KK Neucha', 'Marker Felt', 'Comic Sans MS', cursive",
97
+ handwritten: "'KK Caveat', 'Caveat', 'Marker Felt', cursive",
98
+ brush: "'KK BadScript', 'Bad Script', 'Snell Roundhand', cursive",
99
+ marker: "'KK Pacifico', 'Pacifico', 'Marker Felt', cursive",
100
+ display: "'KK Lobster', 'Lobster', Georgia, serif",
101
+ elegant: "'KK YesevaOne', 'Yeseva One', Georgia, serif",
102
+ rounded: "'KK Comfortaa', 'Comfortaa', -apple-system, sans-serif",
103
+ serif: "'KK PTSerif', 'PT Serif', Georgia, serif",
104
+ mono: "'KK PTMono', 'PT Mono', ui-monospace, Menlo, monospace",
105
+ };
106
+ return map[id] || map.default;
107
+ }
108
+
88
109
  function renderLabelNodeBody(node, body) {
89
110
  if (!node.textStyle) node.textStyle = { ...LABEL_DEFAULT_STYLE };
90
111