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 +1 -1
- package/renderer/board.js +40 -7
- package/renderer/settings.js +21 -0
package/package.json
CHANGED
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
|
-
|
|
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 =
|
|
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
|
-
|
|
1132
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)) {
|
package/renderer/settings.js
CHANGED
|
@@ -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
|
|