@sequent-org/moodboard 1.4.32 → 1.4.34
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 +5 -1
- package/src/assets/fonts/inter/inter-cyrillic-400-normal.woff2 +0 -0
- package/src/assets/fonts/inter/inter-cyrillic-500-normal.woff2 +0 -0
- package/src/assets/fonts/inter/inter-latin-400-normal.woff2 +0 -0
- package/src/assets/fonts/inter/inter-latin-500-normal.woff2 +0 -0
- package/src/assets/icons/attachments.svg +3 -1
- package/src/assets/icons/comments.svg +2 -2
- package/src/assets/icons/connector.svg +6 -0
- package/src/assets/icons/emoji.svg +6 -1
- package/src/assets/icons/frame.svg +4 -1
- package/src/assets/icons/image.svg +5 -1
- package/src/assets/icons/laser.svg +1 -0
- package/src/assets/icons/lasso.svg +5 -0
- package/src/assets/icons/mindmap.svg +10 -2
- package/src/assets/icons/note.svg +4 -1
- package/src/assets/icons/pan.svg +5 -2
- package/src/assets/icons/pencil.svg +4 -1
- package/src/assets/icons/reactions.svg +5 -0
- package/src/assets/icons/redo.svg +3 -2
- package/src/assets/icons/select.svg +2 -8
- package/src/assets/icons/shapes.svg +5 -1
- package/src/assets/icons/text-add.svg +15 -1
- package/src/assets/icons/undo.svg +3 -2
- package/src/assets/reactions/1f44d.svg +20 -0
- package/src/assets/reactions/1f44e.svg +20 -0
- package/src/assets/reactions/2705.svg +20 -0
- package/src/assets/reactions/274c.svg +19 -0
- package/src/assets/reactions/2753.svg +20 -0
- package/src/assets/reactions/2764.svg +22 -0
- package/src/assets/reactions/2b50.svg +19 -0
- package/src/assets/reactions/plus-one.svg +25 -0
- package/src/core/PixiEngine.js +23 -0
- package/src/core/bootstrap/CoreInitializer.js +43 -0
- package/src/core/commands/GroupDeleteCommand.js +13 -1
- package/src/core/commands/UpdateShapeStyleCommand.js +121 -0
- package/src/core/commands/UpdateTextStyleCommand.js +17 -6
- package/src/core/commands/index.js +3 -0
- package/src/core/events/Events.js +22 -0
- package/src/core/flows/LayerAndViewportFlow.js +1 -0
- package/src/core/flows/ObjectLifecycleFlow.js +155 -7
- package/src/core/index.js +28 -1
- package/src/grid/CrossGridZoomPhases.js +3 -3
- package/src/initNoBundler.js +1 -1
- package/src/moodboard/DataManager.js +28 -0
- package/src/moodboard/MoodBoard.js +27 -0
- package/src/moodboard/bootstrap/MoodBoardInitializer.js +69 -1
- package/src/moodboard/bootstrap/MoodBoardUiFactory.js +22 -4
- package/src/moodboard/integration/MoodBoardEventBindings.js +5 -1
- package/src/moodboard/integration/MoodBoardLoadApi.js +10 -1
- package/src/moodboard/lifecycle/MoodBoardDestroyer.js +9 -0
- package/src/objects/ConnectorObject.js +2 -2
- package/src/objects/FrameObject.js +119 -59
- package/src/objects/ShapeObject.js +49 -74
- package/src/objects/shape/ShapeDrawer.js +210 -0
- package/src/services/ConnectorBindingResolver.js +112 -0
- package/src/services/ConnectorRouter.js +210 -0
- package/src/services/ai/ChatSessionController.js +14 -8
- package/src/services/comments/CommentService.js +344 -0
- package/src/tools/object-tools/CommentTool.js +85 -0
- package/src/tools/object-tools/DrawingTool.js +110 -10
- package/src/tools/object-tools/LaserPointerTool.js +121 -0
- package/src/tools/object-tools/SelectTool.js +25 -1
- package/src/tools/object-tools/TextTool.js +6 -1
- package/src/tools/object-tools/connector/ConnectorDragController.js +50 -3
- package/src/tools/object-tools/connector/connectorGesture.js +33 -19
- package/src/tools/object-tools/placement/PlacementInputRouter.js +22 -1
- package/src/tools/object-tools/selection/BoxSelectController.js +24 -2
- package/src/tools/object-tools/selection/FrameTitleInlineEditorController.js +139 -0
- package/src/tools/object-tools/selection/InlineEditorController.js +12 -0
- package/src/tools/object-tools/selection/InlineEditorDomFactory.js +36 -0
- package/src/tools/object-tools/selection/LassoSelectController.js +125 -0
- package/src/tools/object-tools/selection/MindmapInlineEditorController.js +1 -0
- package/src/tools/object-tools/selection/SelectInputRouter.js +64 -5
- package/src/tools/object-tools/selection/SelectToolLifecycleController.js +11 -1
- package/src/tools/object-tools/selection/SelectToolSetup.js +13 -1
- package/src/tools/object-tools/selection/TextEditorInteractionController.js +46 -12
- package/src/tools/object-tools/selection/TextEditorSyncService.js +1 -0
- package/src/tools/object-tools/selection/TextInlineEditorController.js +65 -6
- package/src/ui/CommentPopover.js +6 -0
- package/src/ui/CommentsBar.js +91 -0
- package/src/ui/ConnectorPropertiesPanel.js +150 -0
- package/src/ui/ContextMenu.js +25 -0
- package/src/ui/DrawingPropertiesPanel.js +362 -0
- package/src/ui/FilePropertiesPanel.js +5 -0
- package/src/ui/FramePropertiesPanel.js +5 -0
- package/src/ui/HtmlTextLayer.js +246 -66
- package/src/ui/NotePropertiesPanel.js +6 -0
- package/src/ui/ShapePropertiesPanel.js +307 -0
- package/src/ui/TextPropertiesPanel.js +100 -1
- package/src/ui/Toolbar.js +25 -2
- package/src/ui/Topbar.js +2 -2
- package/src/ui/animation/HoverLiftController.js +6 -7
- package/src/ui/chat/ChatComposer.js +63 -9
- package/src/ui/chat/ChatWindow.js +329 -166
- package/src/ui/comments/CommentListPanel.js +213 -0
- package/src/ui/comments/CommentPinLayer.js +448 -0
- package/src/ui/comments/CommentThreadPopover.js +539 -0
- package/src/ui/comments/commentFormat.js +32 -0
- package/src/ui/connector-properties/ConnectorPropertiesPanelBindings.js +223 -0
- package/src/ui/connector-properties/ConnectorPropertiesPanelEventBridge.js +114 -0
- package/src/ui/connector-properties/ConnectorPropertiesPanelMapper.js +144 -0
- package/src/ui/connector-properties/ConnectorPropertiesPanelRenderer.js +447 -0
- package/src/ui/connector-properties/ConnectorPropertiesPanelState.js +61 -0
- package/src/ui/connectors/ConnectionAnchorsLayer.js +1 -0
- package/src/ui/connectors/ConnectorHandlesLayer.js +321 -0
- package/src/ui/connectors/ConnectorLabelLayer.js +334 -0
- package/src/ui/connectors/ConnectorLayer.js +264 -57
- package/src/ui/handles/HandlesDomRenderer.js +5 -13
- package/src/ui/handles/HandlesEventBridge.js +1 -0
- package/src/ui/handles/SingleSelectionHandlesController.js +4 -0
- package/src/ui/mindmap/MindmapCollapseLayer.js +1 -0
- package/src/ui/mindmap/MindmapConnectionLayer.js +1 -0
- package/src/ui/mindmap/MindmapHtmlTextLayer.js +6 -0
- package/src/ui/shape-properties/ShapePropertiesPanelDom.js +533 -0
- package/src/ui/shape-properties/ShapePropertiesPanelSync.js +132 -0
- package/src/ui/styles/chat.css +710 -18
- package/src/ui/styles/index.css +1 -0
- package/src/ui/styles/panels.css +112 -2
- package/src/ui/styles/shape-properties-panel.css +250 -0
- package/src/ui/styles/toolbar.css +7 -2
- package/src/ui/styles/topbar.css +1 -1
- package/src/ui/styles/workspace.css +257 -6
- package/src/ui/text-properties/TextFormatControls.js +88 -0
- package/src/ui/text-properties/TextListRenderer.js +137 -0
- package/src/ui/text-properties/TextPropertiesPanelBindings.js +27 -0
- package/src/ui/text-properties/TextPropertiesPanelEventBridge.js +3 -1
- package/src/ui/text-properties/TextPropertiesPanelMapper.js +56 -0
- package/src/ui/text-properties/TextPropertiesPanelRenderer.js +24 -0
- package/src/ui/text-properties/TextPropertiesPanelState.js +8 -0
- package/src/ui/toolbar/ReactionsPopupController.js +88 -0
- package/src/ui/toolbar/ToolbarActionRouter.js +71 -5
- package/src/ui/toolbar/ToolbarPopupsController.js +120 -118
- package/src/ui/toolbar/ToolbarRenderer.js +9 -1
- package/src/ui/toolbar/ToolbarStateController.js +4 -1
- package/src/utils/iconLoader.js +17 -16
- package/src/utils/markdown.js +14 -0
- package/src/utils/richText.js +125 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FONT_OPTIONS,
|
|
3
|
+
FONT_SIZE_OPTIONS,
|
|
4
|
+
TEXT_COLOR_PRESETS,
|
|
5
|
+
} from '../text-properties/TextPropertiesPanelMapper.js';
|
|
6
|
+
|
|
7
|
+
// ── Константы ─────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
export const FILL_COLORS = [
|
|
10
|
+
{ name: 'Белый', hex: '#FFFFFF', pixi: 0xFFFFFF },
|
|
11
|
+
{ name: 'Светлый серый', hex: '#F5F5F5', pixi: 0xF5F5F5 },
|
|
12
|
+
{ name: 'Голубой', hex: '#DBEAFE', pixi: 0xDBEAFE },
|
|
13
|
+
{ name: 'Зеленый', hex: '#DCFCE7', pixi: 0xDCFCE7 },
|
|
14
|
+
{ name: 'Желтый', hex: '#FEF9C3', pixi: 0xFEF9C3 },
|
|
15
|
+
{ name: 'Розовый', hex: '#FCE7F3', pixi: 0xFCE7F3 },
|
|
16
|
+
{ name: 'Синий', hex: '#BFDBFE', pixi: 0xBFDBFE },
|
|
17
|
+
{ name: 'Оранжевый', hex: '#FED7AA', pixi: 0xFED7AA },
|
|
18
|
+
{ name: 'Красный', hex: '#FECACA', pixi: 0xFECACA },
|
|
19
|
+
{ name: 'Черный', hex: '#1A1A1A', pixi: 0x1A1A1A },
|
|
20
|
+
{ name: 'Темно-серый', hex: '#404040', pixi: 0x404040 },
|
|
21
|
+
{ name: 'Темно-синий', hex: '#1E3A5F', pixi: 0x1E3A5F },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const BORDER_COLORS = [
|
|
25
|
+
{ name: 'Серый', hex: '#D4D4D4', pixi: 0xD4D4D4 },
|
|
26
|
+
{ name: 'Темно-серый', hex: '#737373', pixi: 0x737373 },
|
|
27
|
+
{ name: 'Черный', hex: '#1A1A1A', pixi: 0x1A1A1A },
|
|
28
|
+
{ name: 'Синий', hex: '#2563EB', pixi: 0x2563EB },
|
|
29
|
+
{ name: 'Красный', hex: '#EF4444', pixi: 0xEF4444 },
|
|
30
|
+
{ name: 'Зеленый', hex: '#22C55E', pixi: 0x22C55E },
|
|
31
|
+
{ name: 'Желтый', hex: '#EAB308', pixi: 0xEAB308 },
|
|
32
|
+
{ name: 'Фиолетовый', hex: '#A855F7', pixi: 0xA855F7 },
|
|
33
|
+
{ name: 'Белый', hex: '#FFFFFF', pixi: 0xFFFFFF },
|
|
34
|
+
{ name: 'Прозрачный', hex: '#E5E7EB', pixi: 0xE5E7EB },
|
|
35
|
+
{ name: 'Оранжевый', hex: '#F97316', pixi: 0xF97316 },
|
|
36
|
+
{ name: 'Розовый', hex: '#EC4899', pixi: 0xEC4899 },
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export const SHAPE_KINDS = [
|
|
40
|
+
{ kind: 'square', label: 'Прямоугольник' },
|
|
41
|
+
{ kind: 'rounded', label: 'Скруглённый' },
|
|
42
|
+
{ kind: 'circle', label: 'Эллипс' },
|
|
43
|
+
{ kind: 'triangle', label: 'Треугольник' },
|
|
44
|
+
{ kind: 'diamond', label: 'Ромб' },
|
|
45
|
+
{ kind: 'parallelogram', label: 'Параллелограмм' },
|
|
46
|
+
{ kind: 'arrow', label: 'Стрелка' },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export const SHAPE_ICONS = {
|
|
50
|
+
square: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><rect x="2" y="2" width="18" height="18" rx="0" stroke="currentColor" stroke-width="1.5"/></svg>',
|
|
51
|
+
rounded: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><rect x="2" y="2" width="18" height="18" rx="5" stroke="currentColor" stroke-width="1.5"/></svg>',
|
|
52
|
+
circle: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><ellipse cx="11" cy="11" rx="9" ry="9" stroke="currentColor" stroke-width="1.5"/></svg>',
|
|
53
|
+
triangle: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><polygon points="11,2 21,20 1,20" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>',
|
|
54
|
+
diamond: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><polygon points="11,2 21,11 11,20 1,11" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>',
|
|
55
|
+
parallelogram: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><polygon points="5,18 19,18 17,4 3,4" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>',
|
|
56
|
+
arrow: '<svg width="22" height="22" viewBox="0 0 22 22" fill="none"><polygon points="2,8 2,14 13,14 13,18 21,11 13,4 13,8" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/></svg>',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const CARET_SVG = '<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5l3 3 3-3" stroke="#888" stroke-width="1.5" stroke-linecap="round"/></svg>';
|
|
60
|
+
|
|
61
|
+
// ── Строители секций ──────────────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
export function sep() {
|
|
64
|
+
const s = document.createElement('div');
|
|
65
|
+
s.className = 'spp-sep';
|
|
66
|
+
return s;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function buildColorGrid(container, colors, onPick, swatchesOut) {
|
|
70
|
+
const grid = document.createElement('div');
|
|
71
|
+
grid.className = 'spp-color-grid';
|
|
72
|
+
colors.forEach((color) => {
|
|
73
|
+
const btn = document.createElement('button');
|
|
74
|
+
btn.type = 'button';
|
|
75
|
+
btn.className = 'spp-color-swatch' +
|
|
76
|
+
(color.hex.toUpperCase() === '#FFFFFF' ? ' spp-color-swatch--white' : '');
|
|
77
|
+
btn.style.backgroundColor = color.hex;
|
|
78
|
+
btn.title = color.name;
|
|
79
|
+
btn.dataset.colorHex = color.hex.toUpperCase();
|
|
80
|
+
const tick = document.createElement('span');
|
|
81
|
+
tick.className = 'spp-tick';
|
|
82
|
+
btn.appendChild(tick);
|
|
83
|
+
btn.addEventListener('click', () => {
|
|
84
|
+
swatchesOut.forEach(s => s.classList.remove('spp-color-swatch--active'));
|
|
85
|
+
btn.classList.add('spp-color-swatch--active');
|
|
86
|
+
onPick(color);
|
|
87
|
+
});
|
|
88
|
+
grid.appendChild(btn);
|
|
89
|
+
swatchesOut.push(btn);
|
|
90
|
+
});
|
|
91
|
+
container.appendChild(grid);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function buildShapeGroup(inst) {
|
|
95
|
+
const trigger = document.createElement('button');
|
|
96
|
+
trigger.className = 'spp-trigger';
|
|
97
|
+
trigger.title = 'Форма';
|
|
98
|
+
trigger.innerHTML = SHAPE_ICONS['square'] + CARET_SVG;
|
|
99
|
+
inst._kindTrigger = trigger;
|
|
100
|
+
|
|
101
|
+
const popover = document.createElement('div');
|
|
102
|
+
popover.className = 'spp-popover';
|
|
103
|
+
Object.assign(popover.style, { top: '100%', left: '0', marginTop: '4px' });
|
|
104
|
+
|
|
105
|
+
const grid = document.createElement('div');
|
|
106
|
+
grid.className = 'spp-kind-grid';
|
|
107
|
+
|
|
108
|
+
inst._kindButtons = {};
|
|
109
|
+
SHAPE_KINDS.forEach(({ kind, label }) => {
|
|
110
|
+
const btn = document.createElement('button');
|
|
111
|
+
btn.className = 'spp-kind-btn';
|
|
112
|
+
btn.title = label;
|
|
113
|
+
btn.dataset.kind = kind;
|
|
114
|
+
btn.innerHTML = (SHAPE_ICONS[kind] || '') +
|
|
115
|
+
`<span>${label.length > 8 ? label.slice(0, 7) + '\u2026' : label}</span>`;
|
|
116
|
+
btn.addEventListener('click', () => {
|
|
117
|
+
inst._emit({ updates: { properties: { kind } } });
|
|
118
|
+
inst._closePopover();
|
|
119
|
+
});
|
|
120
|
+
grid.appendChild(btn);
|
|
121
|
+
inst._kindButtons[kind] = btn;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
popover.appendChild(grid);
|
|
125
|
+
inst._kindPopover = popover;
|
|
126
|
+
|
|
127
|
+
const wrap = document.createElement('div');
|
|
128
|
+
wrap.style.position = 'relative';
|
|
129
|
+
wrap.appendChild(trigger);
|
|
130
|
+
wrap.appendChild(popover);
|
|
131
|
+
|
|
132
|
+
trigger.addEventListener('click', (e) => {
|
|
133
|
+
e.stopPropagation();
|
|
134
|
+
inst._togglePopover(popover);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return wrap;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function buildFillGroup(inst) {
|
|
141
|
+
const label = document.createElement('span');
|
|
142
|
+
label.className = 'spp-label';
|
|
143
|
+
label.textContent = 'Заливка:';
|
|
144
|
+
|
|
145
|
+
const btn = document.createElement('button');
|
|
146
|
+
btn.className = 'spp-color-btn';
|
|
147
|
+
btn.style.backgroundColor = '#FFFFFF';
|
|
148
|
+
btn.title = 'Цвет заливки';
|
|
149
|
+
inst._fillColorBtn = btn;
|
|
150
|
+
inst._fillSwatches = [];
|
|
151
|
+
|
|
152
|
+
const popover = document.createElement('div');
|
|
153
|
+
popover.className = 'spp-popover';
|
|
154
|
+
Object.assign(popover.style, { top: '100%', left: '0', marginTop: '4px' });
|
|
155
|
+
buildColorGrid(popover, FILL_COLORS, (color) => {
|
|
156
|
+
inst._fillColorBtn.style.backgroundColor = color.hex;
|
|
157
|
+
inst._emit({ updates: { color: color.pixi } });
|
|
158
|
+
inst._closePopover();
|
|
159
|
+
}, inst._fillSwatches);
|
|
160
|
+
inst._fillPopover = popover;
|
|
161
|
+
|
|
162
|
+
const wrap = document.createElement('div');
|
|
163
|
+
wrap.style.position = 'relative';
|
|
164
|
+
wrap.appendChild(btn);
|
|
165
|
+
wrap.appendChild(popover);
|
|
166
|
+
|
|
167
|
+
btn.addEventListener('click', (e) => {
|
|
168
|
+
e.stopPropagation();
|
|
169
|
+
inst._togglePopover(popover);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return [label, wrap];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function buildBorderGroup(inst) {
|
|
176
|
+
const trigger = document.createElement('button');
|
|
177
|
+
trigger.className = 'spp-trigger';
|
|
178
|
+
trigger.title = 'Рамка';
|
|
179
|
+
trigger.innerHTML =
|
|
180
|
+
'<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="1.5" y="1.5" width="13" height="13" rx="1" stroke="currentColor" stroke-width="1.5"/></svg>' +
|
|
181
|
+
'<span style="font-size:11px;color:#555">Рамка</span>' + CARET_SVG;
|
|
182
|
+
inst._borderTrigger = trigger;
|
|
183
|
+
|
|
184
|
+
const popover = document.createElement('div');
|
|
185
|
+
popover.className = 'spp-popover';
|
|
186
|
+
Object.assign(popover.style, { top: '100%', left: '0', marginTop: '4px' });
|
|
187
|
+
|
|
188
|
+
const group = document.createElement('div');
|
|
189
|
+
group.className = 'spp-border-group';
|
|
190
|
+
|
|
191
|
+
// Стиль линии
|
|
192
|
+
const styleRow = _borderRow('Стиль:');
|
|
193
|
+
const styleBtns = document.createElement('div');
|
|
194
|
+
styleBtns.className = 'spp-style-btns';
|
|
195
|
+
inst._borderStyleBtns = {};
|
|
196
|
+
[
|
|
197
|
+
{ value: 'solid', svg: '<svg width="22" height="14" viewBox="0 0 22 14"><line x1="1" y1="7" x2="21" y2="7" stroke="currentColor" stroke-width="2"/></svg>' },
|
|
198
|
+
{ value: 'dashed', svg: '<svg width="22" height="14" viewBox="0 0 22 14"><line x1="1" y1="7" x2="21" y2="7" stroke="currentColor" stroke-width="2" stroke-dasharray="4 3"/></svg>' },
|
|
199
|
+
{ value: 'dotted', svg: '<svg width="22" height="14" viewBox="0 0 22 14"><line x1="1" y1="7" x2="21" y2="7" stroke="currentColor" stroke-width="2" stroke-dasharray="2 3" stroke-linecap="round"/></svg>' },
|
|
200
|
+
].forEach(({ value, svg }) => {
|
|
201
|
+
const b = document.createElement('button');
|
|
202
|
+
b.className = 'spp-btn';
|
|
203
|
+
b.title = value;
|
|
204
|
+
b.innerHTML = svg;
|
|
205
|
+
b.dataset.style = value;
|
|
206
|
+
b.addEventListener('click', () => {
|
|
207
|
+
inst._emit({ updates: { properties: { borderStyle: value } } });
|
|
208
|
+
inst._updateBorderStyleBtns(value);
|
|
209
|
+
});
|
|
210
|
+
styleBtns.appendChild(b);
|
|
211
|
+
inst._borderStyleBtns[value] = b;
|
|
212
|
+
});
|
|
213
|
+
styleRow.appendChild(styleBtns);
|
|
214
|
+
group.appendChild(styleRow);
|
|
215
|
+
|
|
216
|
+
// Толщина
|
|
217
|
+
const [widthRow, widthSlider, widthVal] = _sliderRow('Толщина:', 0, 10, 0.5, 1);
|
|
218
|
+
inst._borderWidthSlider = widthSlider;
|
|
219
|
+
inst._borderWidthVal = widthVal;
|
|
220
|
+
widthSlider.addEventListener('input', () => {
|
|
221
|
+
const v = parseFloat(widthSlider.value);
|
|
222
|
+
widthVal.textContent = String(v);
|
|
223
|
+
inst._emit({ updates: { properties: { borderWidth: v } } });
|
|
224
|
+
});
|
|
225
|
+
group.appendChild(widthRow);
|
|
226
|
+
|
|
227
|
+
// Прозрачность
|
|
228
|
+
const [opacityRow, opacitySlider, opacityVal] = _sliderRow('Прозрачность:', 0, 100, 1, 100, '%');
|
|
229
|
+
inst._borderOpacitySlider = opacitySlider;
|
|
230
|
+
inst._borderOpacityVal = opacityVal;
|
|
231
|
+
opacitySlider.addEventListener('input', () => {
|
|
232
|
+
const pct = parseInt(opacitySlider.value, 10);
|
|
233
|
+
opacityVal.textContent = `${pct}%`;
|
|
234
|
+
inst._emit({ updates: { properties: { borderOpacity: pct / 100 } } });
|
|
235
|
+
});
|
|
236
|
+
group.appendChild(opacityRow);
|
|
237
|
+
|
|
238
|
+
// Цвет рамки
|
|
239
|
+
const colorRow = _borderRow('Цвет рамки:');
|
|
240
|
+
const colorSwatch = document.createElement('button');
|
|
241
|
+
colorSwatch.className = 'spp-color-btn';
|
|
242
|
+
colorSwatch.style.backgroundColor = '#D4D4D4';
|
|
243
|
+
colorSwatch.title = 'Цвет рамки';
|
|
244
|
+
inst._borderColorBtn = colorSwatch;
|
|
245
|
+
inst._borderSwatches = [];
|
|
246
|
+
|
|
247
|
+
const bcPopover = document.createElement('div');
|
|
248
|
+
bcPopover.className = 'spp-popover';
|
|
249
|
+
Object.assign(bcPopover.style, { top: '100%', left: '0', marginTop: '4px', position: 'absolute' });
|
|
250
|
+
buildColorGrid(bcPopover, BORDER_COLORS, (color) => {
|
|
251
|
+
inst._borderColorBtn.style.backgroundColor = color.hex;
|
|
252
|
+
inst._emit({ updates: { properties: { borderColor: color.pixi } } });
|
|
253
|
+
inst._closePopover();
|
|
254
|
+
}, inst._borderSwatches);
|
|
255
|
+
inst._borderColorPopover = bcPopover;
|
|
256
|
+
|
|
257
|
+
const cWrap = document.createElement('div');
|
|
258
|
+
cWrap.style.position = 'relative';
|
|
259
|
+
cWrap.appendChild(colorSwatch);
|
|
260
|
+
cWrap.appendChild(bcPopover);
|
|
261
|
+
colorSwatch.addEventListener('click', (e) => {
|
|
262
|
+
e.stopPropagation();
|
|
263
|
+
inst._togglePopover(bcPopover);
|
|
264
|
+
});
|
|
265
|
+
colorRow.appendChild(cWrap);
|
|
266
|
+
group.appendChild(colorRow);
|
|
267
|
+
|
|
268
|
+
popover.appendChild(group);
|
|
269
|
+
inst._borderPopover = popover;
|
|
270
|
+
|
|
271
|
+
const wrap = document.createElement('div');
|
|
272
|
+
wrap.style.position = 'relative';
|
|
273
|
+
wrap.appendChild(trigger);
|
|
274
|
+
wrap.appendChild(popover);
|
|
275
|
+
|
|
276
|
+
trigger.addEventListener('click', (e) => {
|
|
277
|
+
e.stopPropagation();
|
|
278
|
+
inst._togglePopover(popover);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
return wrap;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function buildRadiusGroup(inst) {
|
|
285
|
+
const label = document.createElement('span');
|
|
286
|
+
label.className = 'spp-label';
|
|
287
|
+
label.textContent = 'Угол:';
|
|
288
|
+
|
|
289
|
+
const group = document.createElement('div');
|
|
290
|
+
group.className = 'spp-radius-group';
|
|
291
|
+
|
|
292
|
+
const slider = document.createElement('input');
|
|
293
|
+
slider.type = 'range';
|
|
294
|
+
slider.min = '0';
|
|
295
|
+
slider.max = '50';
|
|
296
|
+
slider.step = '1';
|
|
297
|
+
slider.value = '0';
|
|
298
|
+
slider.className = 'spp-radius-slider';
|
|
299
|
+
slider.title = 'Радиус скругления';
|
|
300
|
+
inst._radiusSlider = slider;
|
|
301
|
+
|
|
302
|
+
const valLabel = document.createElement('span');
|
|
303
|
+
valLabel.className = 'spp-label';
|
|
304
|
+
valLabel.textContent = '0';
|
|
305
|
+
valLabel.style.minWidth = '20px';
|
|
306
|
+
inst._radiusVal = valLabel;
|
|
307
|
+
|
|
308
|
+
slider.addEventListener('input', () => {
|
|
309
|
+
const v = parseInt(slider.value, 10);
|
|
310
|
+
valLabel.textContent = String(v);
|
|
311
|
+
inst._emit({ updates: { properties: { cornerRadius: v } } });
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
group.appendChild(slider);
|
|
315
|
+
group.appendChild(valLabel);
|
|
316
|
+
return [label, group];
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function buildTextGroup(inst) {
|
|
320
|
+
const nodes = [];
|
|
321
|
+
|
|
322
|
+
// Шрифт
|
|
323
|
+
const fontLabel = document.createElement('span');
|
|
324
|
+
fontLabel.className = 'spp-label';
|
|
325
|
+
fontLabel.textContent = 'Шрифт:';
|
|
326
|
+
nodes.push(fontLabel);
|
|
327
|
+
|
|
328
|
+
const fontSelect = document.createElement('select');
|
|
329
|
+
fontSelect.className = 'spp-select spp-select--font';
|
|
330
|
+
FONT_OPTIONS.forEach(({ value, name }) => {
|
|
331
|
+
const opt = document.createElement('option');
|
|
332
|
+
opt.value = value;
|
|
333
|
+
opt.textContent = name;
|
|
334
|
+
opt.style.fontFamily = value;
|
|
335
|
+
fontSelect.appendChild(opt);
|
|
336
|
+
});
|
|
337
|
+
fontSelect.addEventListener('change', () => {
|
|
338
|
+
inst._emit({ updates: { properties: { text: { fontFamily: fontSelect.value } } } });
|
|
339
|
+
});
|
|
340
|
+
inst._fontSelect = fontSelect;
|
|
341
|
+
nodes.push(fontSelect);
|
|
342
|
+
|
|
343
|
+
// Размер
|
|
344
|
+
const sizeLabel = document.createElement('span');
|
|
345
|
+
sizeLabel.className = 'spp-label';
|
|
346
|
+
sizeLabel.textContent = 'Р:';
|
|
347
|
+
nodes.push(sizeLabel);
|
|
348
|
+
|
|
349
|
+
const sizeSelect = document.createElement('select');
|
|
350
|
+
sizeSelect.className = 'spp-select spp-select--size';
|
|
351
|
+
FONT_SIZE_OPTIONS.forEach((sz) => {
|
|
352
|
+
const opt = document.createElement('option');
|
|
353
|
+
opt.value = sz;
|
|
354
|
+
opt.textContent = String(sz);
|
|
355
|
+
sizeSelect.appendChild(opt);
|
|
356
|
+
});
|
|
357
|
+
sizeSelect.value = '16';
|
|
358
|
+
sizeSelect.addEventListener('change', () => {
|
|
359
|
+
inst._emit({ updates: { properties: { text: { fontSize: parseInt(sizeSelect.value, 10) } } } });
|
|
360
|
+
});
|
|
361
|
+
inst._sizeSelect = sizeSelect;
|
|
362
|
+
nodes.push(sizeSelect);
|
|
363
|
+
|
|
364
|
+
nodes.push(sep());
|
|
365
|
+
|
|
366
|
+
// Цвет текста
|
|
367
|
+
const tcLabel = document.createElement('span');
|
|
368
|
+
tcLabel.className = 'spp-label';
|
|
369
|
+
tcLabel.textContent = 'Цвет:';
|
|
370
|
+
nodes.push(tcLabel);
|
|
371
|
+
|
|
372
|
+
const tcBtn = document.createElement('button');
|
|
373
|
+
tcBtn.className = 'spp-color-btn';
|
|
374
|
+
tcBtn.style.backgroundColor = '#111111';
|
|
375
|
+
tcBtn.title = 'Цвет текста';
|
|
376
|
+
inst._textColorBtn = tcBtn;
|
|
377
|
+
inst._textColorSwatches = [];
|
|
378
|
+
|
|
379
|
+
const tcPopover = document.createElement('div');
|
|
380
|
+
tcPopover.className = 'spp-popover';
|
|
381
|
+
Object.assign(tcPopover.style, { top: '100%', left: '0', marginTop: '4px' });
|
|
382
|
+
_buildTextColorGrid(tcPopover, inst);
|
|
383
|
+
inst._textColorPopover = tcPopover;
|
|
384
|
+
|
|
385
|
+
const tcWrap = document.createElement('div');
|
|
386
|
+
tcWrap.style.position = 'relative';
|
|
387
|
+
tcWrap.appendChild(tcBtn);
|
|
388
|
+
tcWrap.appendChild(tcPopover);
|
|
389
|
+
tcBtn.addEventListener('click', (e) => {
|
|
390
|
+
e.stopPropagation();
|
|
391
|
+
inst._togglePopover(tcPopover);
|
|
392
|
+
});
|
|
393
|
+
nodes.push(tcWrap);
|
|
394
|
+
|
|
395
|
+
nodes.push(sep());
|
|
396
|
+
|
|
397
|
+
// Bold
|
|
398
|
+
const boldBtn = document.createElement('button');
|
|
399
|
+
boldBtn.className = 'spp-btn';
|
|
400
|
+
boldBtn.title = 'Жирный';
|
|
401
|
+
boldBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14"><text x="2" y="12" font-family="Arial" font-size="13" font-weight="bold" fill="currentColor">B</text></svg>';
|
|
402
|
+
boldBtn.addEventListener('click', () => {
|
|
403
|
+
const cur = boldBtn.classList.contains('spp-btn--active');
|
|
404
|
+
boldBtn.classList.toggle('spp-btn--active', !cur);
|
|
405
|
+
inst._emit({ updates: { properties: { text: { bold: !cur } } } });
|
|
406
|
+
});
|
|
407
|
+
inst._boldBtn = boldBtn;
|
|
408
|
+
nodes.push(boldBtn);
|
|
409
|
+
|
|
410
|
+
nodes.push(sep());
|
|
411
|
+
|
|
412
|
+
// Выравнивание
|
|
413
|
+
inst._alignBtns = {};
|
|
414
|
+
[
|
|
415
|
+
{ value: 'left', svg: '<svg width="16" height="14" viewBox="0 0 16 14"><line x1="1" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="7" x2="10" y2="7" stroke="currentColor" stroke-width="1.5"/><line x1="1" y1="11" x2="13" y2="11" stroke="currentColor" stroke-width="1.5"/></svg>', title: 'По левому краю' },
|
|
416
|
+
{ value: 'center', svg: '<svg width="16" height="14" viewBox="0 0 16 14"><line x1="1" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="7" x2="13" y2="7" stroke="currentColor" stroke-width="1.5"/><line x1="2" y1="11" x2="14" y2="11" stroke="currentColor" stroke-width="1.5"/></svg>', title: 'По центру' },
|
|
417
|
+
{ value: 'right', svg: '<svg width="16" height="14" viewBox="0 0 16 14"><line x1="1" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5"/><line x1="6" y1="7" x2="15" y2="7" stroke="currentColor" stroke-width="1.5"/><line x1="3" y1="11" x2="15" y2="11" stroke="currentColor" stroke-width="1.5"/></svg>', title: 'По правому краю' },
|
|
418
|
+
].forEach(({ value, svg, title }) => {
|
|
419
|
+
const b = document.createElement('button');
|
|
420
|
+
b.className = 'spp-btn';
|
|
421
|
+
b.title = title;
|
|
422
|
+
b.innerHTML = svg;
|
|
423
|
+
b.dataset.align = value;
|
|
424
|
+
b.addEventListener('click', () => {
|
|
425
|
+
inst._setAlign(value);
|
|
426
|
+
inst._emit({ updates: { properties: { text: { textAlign: value } } } });
|
|
427
|
+
});
|
|
428
|
+
inst._alignBtns[value] = b;
|
|
429
|
+
nodes.push(b);
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
nodes.push(sep());
|
|
433
|
+
|
|
434
|
+
// Список
|
|
435
|
+
const listBtn = document.createElement('button');
|
|
436
|
+
listBtn.className = 'spp-btn';
|
|
437
|
+
listBtn.title = 'Маркированный список';
|
|
438
|
+
listBtn.innerHTML =
|
|
439
|
+
'<svg width="16" height="14" viewBox="0 0 16 14">' +
|
|
440
|
+
'<circle cx="2" cy="3" r="1.5" fill="currentColor"/><line x1="5" y1="3" x2="15" y2="3" stroke="currentColor" stroke-width="1.5"/>' +
|
|
441
|
+
'<circle cx="2" cy="7" r="1.5" fill="currentColor"/><line x1="5" y1="7" x2="15" y2="7" stroke="currentColor" stroke-width="1.5"/>' +
|
|
442
|
+
'<circle cx="2" cy="11" r="1.5" fill="currentColor"/><line x1="5" y1="11" x2="15" y2="11" stroke="currentColor" stroke-width="1.5"/>' +
|
|
443
|
+
'</svg>';
|
|
444
|
+
listBtn.addEventListener('click', () => {
|
|
445
|
+
const cur = listBtn.classList.contains('spp-btn--active');
|
|
446
|
+
listBtn.classList.toggle('spp-btn--active', !cur);
|
|
447
|
+
inst._emit({ updates: { properties: { text: { list: cur ? 'none' : 'bullet' } } } });
|
|
448
|
+
});
|
|
449
|
+
inst._listBtn = listBtn;
|
|
450
|
+
nodes.push(listBtn);
|
|
451
|
+
|
|
452
|
+
nodes.push(sep());
|
|
453
|
+
|
|
454
|
+
// Межстрочный интервал
|
|
455
|
+
const lhLabel = document.createElement('span');
|
|
456
|
+
lhLabel.className = 'spp-label';
|
|
457
|
+
lhLabel.textContent = 'Интервал:';
|
|
458
|
+
nodes.push(lhLabel);
|
|
459
|
+
|
|
460
|
+
const lhSelect = document.createElement('select');
|
|
461
|
+
lhSelect.className = 'spp-select';
|
|
462
|
+
lhSelect.style.minWidth = '60px';
|
|
463
|
+
[1.0, 1.2, 1.4, 1.6, 2.0].forEach((v) => {
|
|
464
|
+
const opt = document.createElement('option');
|
|
465
|
+
opt.value = String(v);
|
|
466
|
+
opt.textContent = String(v);
|
|
467
|
+
if (v === 1.4) opt.selected = true;
|
|
468
|
+
lhSelect.appendChild(opt);
|
|
469
|
+
});
|
|
470
|
+
lhSelect.addEventListener('change', () => {
|
|
471
|
+
inst._emit({ updates: { properties: { text: { lineHeight: parseFloat(lhSelect.value) } } } });
|
|
472
|
+
});
|
|
473
|
+
inst._lhSelect = lhSelect;
|
|
474
|
+
nodes.push(lhSelect);
|
|
475
|
+
|
|
476
|
+
return nodes;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// ── Внутренние утилиты ────────────────────────────────────────────────────────
|
|
480
|
+
|
|
481
|
+
function _borderRow(labelText) {
|
|
482
|
+
const row = document.createElement('div');
|
|
483
|
+
row.className = 'spp-border-row';
|
|
484
|
+
const lbl = document.createElement('span');
|
|
485
|
+
lbl.className = 'spp-border-label';
|
|
486
|
+
lbl.textContent = labelText;
|
|
487
|
+
row.appendChild(lbl);
|
|
488
|
+
return row;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function _sliderRow(labelText, min, max, step, defVal, suffix = '') {
|
|
492
|
+
const row = _borderRow(labelText);
|
|
493
|
+
const slider = document.createElement('input');
|
|
494
|
+
slider.type = 'range';
|
|
495
|
+
slider.min = String(min);
|
|
496
|
+
slider.max = String(max);
|
|
497
|
+
slider.step = String(step);
|
|
498
|
+
slider.value = String(defVal);
|
|
499
|
+
slider.className = 'spp-slider-full';
|
|
500
|
+
const valLabel = document.createElement('span');
|
|
501
|
+
valLabel.className = 'spp-slider-value';
|
|
502
|
+
valLabel.textContent = `${defVal}${suffix}`;
|
|
503
|
+
row.appendChild(slider);
|
|
504
|
+
row.appendChild(valLabel);
|
|
505
|
+
return [row, slider, valLabel];
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function _buildTextColorGrid(container, inst) {
|
|
509
|
+
const grid = document.createElement('div');
|
|
510
|
+
grid.className = 'spp-color-grid';
|
|
511
|
+
TEXT_COLOR_PRESETS.forEach(({ color, name }) => {
|
|
512
|
+
const btn = document.createElement('button');
|
|
513
|
+
btn.type = 'button';
|
|
514
|
+
btn.className = 'spp-color-swatch' +
|
|
515
|
+
(color === '#ffffff' ? ' spp-color-swatch--white' : '');
|
|
516
|
+
btn.style.backgroundColor = color;
|
|
517
|
+
btn.title = name;
|
|
518
|
+
btn.dataset.colorHex = color.toUpperCase();
|
|
519
|
+
const tick = document.createElement('span');
|
|
520
|
+
tick.className = 'spp-tick';
|
|
521
|
+
btn.appendChild(tick);
|
|
522
|
+
btn.addEventListener('click', () => {
|
|
523
|
+
inst._textColorSwatches.forEach(s => s.classList.remove('spp-color-swatch--active'));
|
|
524
|
+
btn.classList.add('spp-color-swatch--active');
|
|
525
|
+
inst._textColorBtn.style.backgroundColor = color;
|
|
526
|
+
inst._emit({ updates: { properties: { text: { color } } } });
|
|
527
|
+
inst._closePopover();
|
|
528
|
+
});
|
|
529
|
+
grid.appendChild(btn);
|
|
530
|
+
inst._textColorSwatches.push(btn);
|
|
531
|
+
});
|
|
532
|
+
container.appendChild(grid);
|
|
533
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { FONT_OPTIONS, FONT_SIZE_OPTIONS } from '../text-properties/TextPropertiesPanelMapper.js';
|
|
2
|
+
import { SHAPE_ICONS } from './ShapePropertiesPanelDom.js';
|
|
3
|
+
|
|
4
|
+
const CARET_SVG = '<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 3.5l3 3 3-3" stroke="#888" stroke-width="1.5" stroke-linecap="round"/></svg>';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Синхронизирует все контролы панели с текущим состоянием объекта.
|
|
8
|
+
* Читает данные через core.getObjectData(id).
|
|
9
|
+
*/
|
|
10
|
+
export function updateControlsFromObject(inst) {
|
|
11
|
+
if (!inst.currentId) return;
|
|
12
|
+
const data = inst.core?.getObjectData?.(inst.currentId);
|
|
13
|
+
if (!data) return;
|
|
14
|
+
|
|
15
|
+
const props = data.properties || {};
|
|
16
|
+
|
|
17
|
+
_syncKind(inst, props.kind || 'square');
|
|
18
|
+
_syncRadius(inst, props.cornerRadius ?? 0);
|
|
19
|
+
_syncFillColor(inst, data.color ?? 0xFFFFFF);
|
|
20
|
+
_syncBorder(inst, props);
|
|
21
|
+
_syncText(inst, props.text || {});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function updateBorderStyleBtns(inst, active) {
|
|
25
|
+
if (!inst._borderStyleBtns) return;
|
|
26
|
+
Object.entries(inst._borderStyleBtns).forEach(([val, btn]) => {
|
|
27
|
+
btn.classList.toggle('spp-btn--active', val === active);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function setAlign(inst, value) {
|
|
32
|
+
if (!inst._alignBtns) return;
|
|
33
|
+
Object.entries(inst._alignBtns).forEach(([val, btn]) => {
|
|
34
|
+
btn.classList.toggle('spp-btn--active', val === value);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function syncSwatches(swatches, hexUpper) {
|
|
39
|
+
if (!swatches) return;
|
|
40
|
+
swatches.forEach(s => {
|
|
41
|
+
const match = (s.dataset.colorHex || '').toUpperCase() === hexUpper.toUpperCase();
|
|
42
|
+
s.classList.toggle('spp-color-swatch--active', match);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function pixiToHex(pixi) {
|
|
47
|
+
return `#${(pixi >>> 0).toString(16).padStart(6, '0').toUpperCase()}`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ── Приватные хелперы ─────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
function _syncKind(inst, kind) {
|
|
53
|
+
if (inst._kindButtons) {
|
|
54
|
+
Object.values(inst._kindButtons).forEach(b =>
|
|
55
|
+
b.classList.toggle('spp-kind-btn--active', b.dataset.kind === kind));
|
|
56
|
+
}
|
|
57
|
+
if (inst._kindTrigger && SHAPE_ICONS[kind]) {
|
|
58
|
+
inst._kindTrigger.innerHTML = SHAPE_ICONS[kind] + CARET_SVG;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function _syncRadius(inst, cr) {
|
|
63
|
+
if (inst._radiusSlider) {
|
|
64
|
+
inst._radiusSlider.value = String(cr);
|
|
65
|
+
if (inst._radiusVal) inst._radiusVal.textContent = String(cr);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function _syncFillColor(inst, fillPixi) {
|
|
70
|
+
if (inst._fillColorBtn) {
|
|
71
|
+
inst._fillColorBtn.style.backgroundColor = pixiToHex(fillPixi);
|
|
72
|
+
}
|
|
73
|
+
syncSwatches(inst._fillSwatches, pixiToHex(fillPixi));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function _syncBorder(inst, props) {
|
|
77
|
+
const bw = props.borderWidth ?? 1;
|
|
78
|
+
if (inst._borderWidthSlider) {
|
|
79
|
+
inst._borderWidthSlider.value = String(bw);
|
|
80
|
+
if (inst._borderWidthVal) inst._borderWidthVal.textContent = String(bw);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const bop = typeof props.borderOpacity === 'number' ? props.borderOpacity : 1;
|
|
84
|
+
if (inst._borderOpacitySlider) {
|
|
85
|
+
inst._borderOpacitySlider.value = String(Math.round(bop * 100));
|
|
86
|
+
if (inst._borderOpacityVal) inst._borderOpacityVal.textContent = `${Math.round(bop * 100)}%`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
updateBorderStyleBtns(inst, props.borderStyle || 'solid');
|
|
90
|
+
|
|
91
|
+
const bcPixi = props.borderColor ?? 0xD4D4D4;
|
|
92
|
+
if (inst._borderColorBtn) {
|
|
93
|
+
inst._borderColorBtn.style.backgroundColor = pixiToHex(bcPixi);
|
|
94
|
+
}
|
|
95
|
+
syncSwatches(inst._borderSwatches, pixiToHex(bcPixi));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function _syncText(inst, text) {
|
|
99
|
+
if (inst._fontSelect) {
|
|
100
|
+
const family = text.fontFamily || FONT_OPTIONS[0].value;
|
|
101
|
+
if ([...inst._fontSelect.options].some(o => o.value === family)) {
|
|
102
|
+
inst._fontSelect.value = family;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (inst._sizeSelect) {
|
|
107
|
+
const fsStr = String(text.fontSize || 16);
|
|
108
|
+
if ([...inst._sizeSelect.options].some(o => o.value === fsStr)) {
|
|
109
|
+
inst._sizeSelect.value = fsStr;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (inst._textColorBtn) {
|
|
114
|
+
inst._textColorBtn.style.backgroundColor = text.color || '#111111';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (inst._boldBtn) {
|
|
118
|
+
inst._boldBtn.classList.toggle('spp-btn--active', !!text.bold);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setAlign(inst, text.textAlign || 'center');
|
|
122
|
+
|
|
123
|
+
if (inst._listBtn) {
|
|
124
|
+
inst._listBtn.classList.toggle('spp-btn--active', text.list === 'bullet');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (inst._lhSelect) {
|
|
128
|
+
const lhStr = String(text.lineHeight || 1.4);
|
|
129
|
+
const found = [...inst._lhSelect.options].find(o => o.value === lhStr);
|
|
130
|
+
if (found) inst._lhSelect.value = lhStr;
|
|
131
|
+
}
|
|
132
|
+
}
|