@operato/board 10.22.0 → 10.24.0
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/CHANGELOG.md +32 -0
- package/dist/src/modeller/component-toolbar/component-menu.js +5 -5
- package/dist/src/modeller/component-toolbar/component-menu.js.map +1 -1
- package/dist/src/modeller/component-toolbar/component-toolbar.d.ts +3 -5
- package/dist/src/modeller/component-toolbar/component-toolbar.js +114 -47
- package/dist/src/modeller/component-toolbar/component-toolbar.js.map +1 -1
- package/dist/src/modeller/edit-toolbar-style.js +47 -3
- package/dist/src/modeller/edit-toolbar-style.js.map +1 -1
- package/dist/src/modeller/edit-toolbar.d.ts +6 -0
- package/dist/src/modeller/edit-toolbar.js +71 -5
- package/dist/src/modeller/edit-toolbar.js.map +1 -1
- package/dist/src/modeller/selection-toolbar.d.ts +61 -0
- package/dist/src/modeller/selection-toolbar.js +402 -0
- package/dist/src/modeller/selection-toolbar.js.map +1 -0
- package/dist/src/ox-board-modeller.d.ts +4 -0
- package/dist/src/ox-board-modeller.js +24 -0
- package/dist/src/ox-board-modeller.js.map +1 -1
- package/dist/src/types.d.ts +1 -0
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -12
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
/**
|
|
3
|
+
* @license Copyright © HatioLab Inc. All rights reserved.
|
|
4
|
+
*/
|
|
5
|
+
import '@material/web/icon/icon.js';
|
|
6
|
+
import { css, html, nothing } from 'lit';
|
|
7
|
+
import { property, state } from 'lit/decorators.js';
|
|
8
|
+
import { EditToolbar } from './edit-toolbar.js';
|
|
9
|
+
/**
|
|
10
|
+
* The contextual toolbar: a small floating bar that sits just above whatever is selected and
|
|
11
|
+
* shows only the verbs that apply to it.
|
|
12
|
+
*
|
|
13
|
+
* ## Why
|
|
14
|
+
*
|
|
15
|
+
* Almost everything in the old 28-icon top toolbar is a verb about the selection - cut, align,
|
|
16
|
+
* distribute, order, group, font size. A verb about the selection belongs next to the selection,
|
|
17
|
+
* and only while there is one. With those gone, the top row keeps the handful of verbs about the
|
|
18
|
+
* board itself (undo, redo, fit, preview, fullscreen, panel), see EditToolbar's `compact`.
|
|
19
|
+
*
|
|
20
|
+
* ## What it shows
|
|
21
|
+
*
|
|
22
|
+
* one shape cut · copy · paste · delete │ forward · backward │ (text) A+ · A-
|
|
23
|
+
* │ ungroup when it is a group │ style copy · databind copy
|
|
24
|
+
* two shapes align (6) │ front · back │ group │ delete
|
|
25
|
+
* three or more + distribute (2)
|
|
26
|
+
*
|
|
27
|
+
* The root and layers never get a bar; a 3D board keeps the full top toolbar (its gizmo tools
|
|
28
|
+
* are not selection verbs in the same sense) and this bar stays out of the way.
|
|
29
|
+
*
|
|
30
|
+
* ## Where it sits
|
|
31
|
+
*
|
|
32
|
+
* Above the union of the selected shapes' screen boxes, centred, clamped to the canvas, and
|
|
33
|
+
* flipped below the selection when there is no room above. Screen boxes come from the scene:
|
|
34
|
+
* a shape's own corners → its root coordinates (`transcoordC2S` then the root's scale and
|
|
35
|
+
* translate) → canvas pixels (the root's scale and translate again), so rotation and nesting
|
|
36
|
+
* are both honoured. The position is refreshed on animation frames while a selection exists,
|
|
37
|
+
* which keeps the bar glued to a shape being dragged or a canvas being zoomed without wiring
|
|
38
|
+
* into every scene event.
|
|
39
|
+
*
|
|
40
|
+
* It reuses EditToolbar's handlers by inheritance, so every verb here is exactly the one the
|
|
41
|
+
* keyboard shortcut runs.
|
|
42
|
+
*/
|
|
43
|
+
export class SelectionToolbar extends EditToolbar {
|
|
44
|
+
constructor() {
|
|
45
|
+
super(...arguments);
|
|
46
|
+
/*
|
|
47
|
+
* floating: just above the selection, follows it, steps aside for a drag.
|
|
48
|
+
* docked: pinned top-centre of the canvas while something is selected - never over a handle,
|
|
49
|
+
* never over a neighbour, never moving under the hand. Same verbs either way.
|
|
50
|
+
*/
|
|
51
|
+
this.placement = 'floating';
|
|
52
|
+
this._left = 0;
|
|
53
|
+
this._top = 0;
|
|
54
|
+
this._visible = false;
|
|
55
|
+
this._frame = 0;
|
|
56
|
+
this._lastKey = '';
|
|
57
|
+
/*
|
|
58
|
+
* One frame at a time. The next frame is booked before the work, so a shape that throws while
|
|
59
|
+
* it is mid-change (being removed, undone, re-parented) costs one frame, not the loop.
|
|
60
|
+
*/
|
|
61
|
+
this._tick = () => {
|
|
62
|
+
this._frame = requestAnimationFrame(this._tick);
|
|
63
|
+
try {
|
|
64
|
+
this._place();
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
/* stale selection; the next frame sees the settled scene */
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
connectedCallback() {
|
|
72
|
+
super.connectedCallback();
|
|
73
|
+
this._tick();
|
|
74
|
+
/*
|
|
75
|
+
* Frames are the steady follow; these are the nudges. A throttled tab (background pane,
|
|
76
|
+
* battery saver) can starve animation frames, and the bar must still land after a click,
|
|
77
|
+
* a drag, a wheel zoom or a resize.
|
|
78
|
+
*/
|
|
79
|
+
const host = this.anchor || this.parentElement;
|
|
80
|
+
const nudge = () => this._place();
|
|
81
|
+
const events = ['pointerup', 'pointermove', 'wheel', 'keyup'];
|
|
82
|
+
events.forEach(name => host === null || host === void 0 ? void 0 : host.addEventListener(name, nudge, { passive: true }));
|
|
83
|
+
window.addEventListener('resize', nudge);
|
|
84
|
+
/* Step aside for a drag that starts on the canvas (not on the bar itself). */
|
|
85
|
+
const down = (e) => {
|
|
86
|
+
if (!e.composedPath().includes(this))
|
|
87
|
+
this.toggleAttribute('dragging', true);
|
|
88
|
+
};
|
|
89
|
+
const up = () => this.toggleAttribute('dragging', false);
|
|
90
|
+
host === null || host === void 0 ? void 0 : host.addEventListener('pointerdown', down, { passive: true });
|
|
91
|
+
window.addEventListener('pointerup', up, { passive: true });
|
|
92
|
+
window.addEventListener('pointercancel', up, { passive: true });
|
|
93
|
+
this._hostListeners = () => {
|
|
94
|
+
events.forEach(name => host === null || host === void 0 ? void 0 : host.removeEventListener(name, nudge));
|
|
95
|
+
window.removeEventListener('resize', nudge);
|
|
96
|
+
host === null || host === void 0 ? void 0 : host.removeEventListener('pointerdown', down);
|
|
97
|
+
window.removeEventListener('pointerup', up);
|
|
98
|
+
window.removeEventListener('pointercancel', up);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
disconnectedCallback() {
|
|
102
|
+
var _a;
|
|
103
|
+
super.disconnectedCallback();
|
|
104
|
+
cancelAnimationFrame(this._frame);
|
|
105
|
+
(_a = this._hostListeners) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
106
|
+
}
|
|
107
|
+
firstUpdated() {
|
|
108
|
+
/* The base wires the clipboard listener the paste verb reads from; keep it. */
|
|
109
|
+
super.firstUpdated();
|
|
110
|
+
}
|
|
111
|
+
updated(changes) {
|
|
112
|
+
super.updated(changes);
|
|
113
|
+
if (changes.has('_visible')) {
|
|
114
|
+
this.toggleAttribute('shown', this._visible);
|
|
115
|
+
}
|
|
116
|
+
if (changes.has('selected') || changes.has('scene')) {
|
|
117
|
+
/* The bar's width depends on what is selected; measure after it has rendered. */
|
|
118
|
+
this._lastKey = '';
|
|
119
|
+
requestAnimationFrame(() => this._place());
|
|
120
|
+
setTimeout(() => this._place(), 50);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
render() {
|
|
124
|
+
const selected = this.selected || [];
|
|
125
|
+
const count = selected.length;
|
|
126
|
+
const one = count === 1;
|
|
127
|
+
const many = count > 1;
|
|
128
|
+
const text = one && !!selected[0].hasTextProperty;
|
|
129
|
+
const group = one && selected[0].get('type') === 'group';
|
|
130
|
+
if (!this._visible) {
|
|
131
|
+
return html ``;
|
|
132
|
+
}
|
|
133
|
+
return html `
|
|
134
|
+
<div bar style="left:${this._left}px;top:${this._top}px;position:absolute">
|
|
135
|
+
${one
|
|
136
|
+
? html `
|
|
137
|
+
${this.button('content_cut', 'cut', () => this.onTapCut())}
|
|
138
|
+
${this.button('content_copy', 'copy', () => this.onTapCopy())}
|
|
139
|
+
${this.button('content_paste', 'paste', () => this.onTapPaste())}
|
|
140
|
+
<i></i>
|
|
141
|
+
${this.button('flip_to_front', 'bring forward', () => this.onTapZorder('forward'))}
|
|
142
|
+
${this.button('flip_to_back', 'send backward', () => this.onTapZorder('backward'))}
|
|
143
|
+
${text
|
|
144
|
+
? html `<i></i>
|
|
145
|
+
${this.button('text_increase', 'increase font size', () => this.onTapFontIncrease(undefined))}
|
|
146
|
+
${this.button('text_decrease', 'decrease font size', () => this.onTapFontDecrease(undefined))}`
|
|
147
|
+
: nothing}
|
|
148
|
+
${group ? html `<i></i>${this.button('deselect', 'ungroup', () => this.onTapUngroup())}` : nothing}
|
|
149
|
+
<i></i>
|
|
150
|
+
${this.button('format_paint', 'copy style to…', () => this.onStartStylePasteMode())}
|
|
151
|
+
${this.button('data_object', 'copy data binding to…', () => this.onStartDatabindPasteMode())}
|
|
152
|
+
`
|
|
153
|
+
: nothing}
|
|
154
|
+
${many
|
|
155
|
+
? html `
|
|
156
|
+
${this.button('align_horizontal_left', 'align left', () => this.onTapAlign('left'))}
|
|
157
|
+
${this.button('align_horizontal_center', 'align center', () => this.onTapAlign('center'))}
|
|
158
|
+
${this.button('align_horizontal_right', 'align right', () => this.onTapAlign('right'))}
|
|
159
|
+
${this.button('align_vertical_top', 'align top', () => this.onTapAlign('top'))}
|
|
160
|
+
${this.button('align_vertical_center', 'align middle', () => this.onTapAlign('middle'))}
|
|
161
|
+
${this.button('align_vertical_bottom', 'align bottom', () => this.onTapAlign('bottom'))}
|
|
162
|
+
${count > 2
|
|
163
|
+
? html `<i></i>
|
|
164
|
+
${this.button('horizontal_distribute', 'distribute horizontally', () => this.onTapDistribute('HORIZONTAL'))}
|
|
165
|
+
${this.button('vertical_distribute', 'distribute vertically', () => this.onTapDistribute('VERTICAL'))}`
|
|
166
|
+
: nothing}
|
|
167
|
+
<i></i>
|
|
168
|
+
${this.button('flip_to_front', 'bring to front', () => this.onTapZorder('front'))}
|
|
169
|
+
${this.button('flip_to_back', 'send to back', () => this.onTapZorder('back'))}
|
|
170
|
+
<i></i>
|
|
171
|
+
${this.button('select_all', 'group', () => this.onTapGroup())}
|
|
172
|
+
${this.button('content_copy', 'copy', () => this.onTapCopy())}
|
|
173
|
+
`
|
|
174
|
+
: nothing}
|
|
175
|
+
<i></i>
|
|
176
|
+
${this.button('delete', 'delete', () => this.onTapDelete(), true)}
|
|
177
|
+
</div>
|
|
178
|
+
`;
|
|
179
|
+
}
|
|
180
|
+
button(icon, title, handler, danger = false) {
|
|
181
|
+
return html `
|
|
182
|
+
<button
|
|
183
|
+
title=${title}
|
|
184
|
+
?danger=${danger}
|
|
185
|
+
@mousedown=${(e) => e.preventDefault()}
|
|
186
|
+
@click=${(e) => {
|
|
187
|
+
e.stopPropagation();
|
|
188
|
+
handler();
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
<md-icon>${icon}</md-icon>
|
|
192
|
+
</button>
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
_place() {
|
|
196
|
+
var _a;
|
|
197
|
+
/* A popup or dialog owns the screen while it is open; the bar must not show through it. */
|
|
198
|
+
const box = SelectionToolbar._overlayOpen() ? null : this._selectionBox();
|
|
199
|
+
if (!box) {
|
|
200
|
+
if (this._visible) {
|
|
201
|
+
this._visible = false;
|
|
202
|
+
this._lastKey = '';
|
|
203
|
+
}
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const host = this.anchor || this.parentElement;
|
|
207
|
+
const hostRect = host.getBoundingClientRect();
|
|
208
|
+
const BAR_HEIGHT = 36;
|
|
209
|
+
if (this.placement === 'docked') {
|
|
210
|
+
const key = `docked:${Math.round(hostRect.width)}`;
|
|
211
|
+
if (key === this._lastKey && this._visible)
|
|
212
|
+
return;
|
|
213
|
+
this._lastKey = key;
|
|
214
|
+
this._left = hostRect.width / 2;
|
|
215
|
+
this._top = 8;
|
|
216
|
+
this._visible = true;
|
|
217
|
+
this.toggleAttribute('below', false);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
/* Enough clearance for the top resize handle and the rotate handle that sits above it. */
|
|
221
|
+
const GAP = 26;
|
|
222
|
+
let left = (box.left + box.right) / 2 - hostRect.left;
|
|
223
|
+
let top = box.top - hostRect.top - BAR_HEIGHT - GAP;
|
|
224
|
+
let below = false;
|
|
225
|
+
/* Not enough room above: sit below the selection instead of on top of it. */
|
|
226
|
+
if (top < 8) {
|
|
227
|
+
top = box.bottom - hostRect.top + GAP;
|
|
228
|
+
below = true;
|
|
229
|
+
}
|
|
230
|
+
const barWidth = ((_a = this.renderRoot.querySelector('[bar]')) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 240;
|
|
231
|
+
left = Math.max(barWidth / 2 + 4, Math.min(hostRect.width - barWidth / 2 - 4, left));
|
|
232
|
+
top = Math.max(4, Math.min(hostRect.height - BAR_HEIGHT - 4, top));
|
|
233
|
+
const key = `${Math.round(left)}:${Math.round(top)}:${below}`;
|
|
234
|
+
if (key === this._lastKey && this._visible) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
this._lastKey = key;
|
|
238
|
+
this._left = left;
|
|
239
|
+
this._top = top;
|
|
240
|
+
this._visible = true;
|
|
241
|
+
this.toggleAttribute('below', below);
|
|
242
|
+
}
|
|
243
|
+
/* The union of the selected shapes' boxes, in viewport pixels; null when there is no bar to show. */
|
|
244
|
+
/* The shell mounts popups inside its header bar's shadow tree, so a plain query never sees them. */
|
|
245
|
+
static _overlayOpen() {
|
|
246
|
+
var _a, _b, _c;
|
|
247
|
+
const q = 'ox-floating-overlay, ox-popup, md-dialog[open]';
|
|
248
|
+
const app = document.querySelector('things-app');
|
|
249
|
+
const bar = (_a = app === null || app === void 0 ? void 0 : app.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('ox-header-bar');
|
|
250
|
+
return !!(document.querySelector(q) || ((_b = app === null || app === void 0 ? void 0 : app.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector(q)) || ((_c = bar === null || bar === void 0 ? void 0 : bar.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector(q)));
|
|
251
|
+
}
|
|
252
|
+
_selectionBox() {
|
|
253
|
+
var _a, _b;
|
|
254
|
+
const scene = this.scene;
|
|
255
|
+
const root = scene === null || scene === void 0 ? void 0 : scene.root;
|
|
256
|
+
const selected = (this.selected || []);
|
|
257
|
+
if (!(root === null || root === void 0 ? void 0 : root.element) || !selected.length) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
/* Only 2D boards; and never the root or a layer. */
|
|
261
|
+
if ((_b = (_a = scene.model_layer) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.threed) {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const scale = root.get('scale') || { x: 1, y: 1 };
|
|
265
|
+
const translate = root.get('translate') || { x: 0, y: 0 };
|
|
266
|
+
const canvas = root.element.getBoundingClientRect();
|
|
267
|
+
let left = Infinity;
|
|
268
|
+
let top = Infinity;
|
|
269
|
+
let right = -Infinity;
|
|
270
|
+
let bottom = -Infinity;
|
|
271
|
+
for (const component of selected) {
|
|
272
|
+
const c = component;
|
|
273
|
+
if (!c || (typeof c.isRootModel === 'function' && c.isRootModel()) || (typeof c.isLayer === 'function' && c.isLayer())) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
const b = c.bounds;
|
|
277
|
+
if (!b)
|
|
278
|
+
continue;
|
|
279
|
+
const corners = [
|
|
280
|
+
[b.left, b.top],
|
|
281
|
+
[b.left + b.width, b.top],
|
|
282
|
+
[b.left + b.width, b.top + b.height],
|
|
283
|
+
[b.left, b.top + b.height]
|
|
284
|
+
];
|
|
285
|
+
for (const [x, y] of corners) {
|
|
286
|
+
const p = c.transcoordC2S(x, y);
|
|
287
|
+
/* to root coordinates, then to canvas pixels */
|
|
288
|
+
const rx = p.x * scale.x + translate.x;
|
|
289
|
+
const ry = p.y * scale.y + translate.y;
|
|
290
|
+
const sx = rx * scale.x + translate.x + canvas.left;
|
|
291
|
+
const sy = ry * scale.y + translate.y + canvas.top;
|
|
292
|
+
left = Math.min(left, sx);
|
|
293
|
+
top = Math.min(top, sy);
|
|
294
|
+
right = Math.max(right, sx);
|
|
295
|
+
bottom = Math.max(bottom, sy);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (!Number.isFinite(left)) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
return { left, top, right, bottom };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
SelectionToolbar.styles = [
|
|
305
|
+
css `
|
|
306
|
+
:host {
|
|
307
|
+
position: absolute;
|
|
308
|
+
left: 0;
|
|
309
|
+
top: 0;
|
|
310
|
+
z-index: 20;
|
|
311
|
+
display: none;
|
|
312
|
+
pointer-events: none;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
:host([shown]) {
|
|
316
|
+
display: block;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* While the pointer is down on the canvas the floating bar steps aside; nothing must sit
|
|
320
|
+
* between the hand and a handle. It fades rather than pops so the eye is not pulled. */
|
|
321
|
+
:host([dragging]:not([placement='docked'])) [bar] {
|
|
322
|
+
opacity: 0;
|
|
323
|
+
pointer-events: none;
|
|
324
|
+
transition: opacity 0.08s ease-out;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
[bar] {
|
|
328
|
+
transition: opacity 0.12s ease-out;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
[bar] {
|
|
332
|
+
display: flex;
|
|
333
|
+
align-items: center;
|
|
334
|
+
gap: 2px;
|
|
335
|
+
padding: 3px;
|
|
336
|
+
border-radius: 8px;
|
|
337
|
+
background: var(--selection-toolbar-background, var(--md-sys-color-surface-container-highest));
|
|
338
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
339
|
+
border: 1px solid var(--md-sys-color-outline-variant);
|
|
340
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
|
|
341
|
+
pointer-events: auto;
|
|
342
|
+
white-space: nowrap;
|
|
343
|
+
transform: translateX(-50%);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
:host([below]) [bar] {
|
|
347
|
+
transform: translateX(-50%);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
[bar] button {
|
|
351
|
+
display: inline-flex;
|
|
352
|
+
align-items: center;
|
|
353
|
+
justify-content: center;
|
|
354
|
+
width: 28px;
|
|
355
|
+
height: 28px;
|
|
356
|
+
padding: 0;
|
|
357
|
+
border: 0;
|
|
358
|
+
border-radius: 6px;
|
|
359
|
+
background: transparent;
|
|
360
|
+
color: inherit;
|
|
361
|
+
cursor: pointer;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
[bar] button:hover {
|
|
365
|
+
background: var(--md-sys-color-secondary-container);
|
|
366
|
+
color: var(--md-sys-color-on-secondary-container);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
[bar] button[danger]:hover {
|
|
370
|
+
background: var(--md-sys-color-error-container, #f9dedc);
|
|
371
|
+
color: var(--md-sys-color-on-error-container, #410e0b);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
[bar] button md-icon {
|
|
375
|
+
--md-icon-size: 18px;
|
|
376
|
+
font-variation-settings: 'wght' 400;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
[bar] i {
|
|
380
|
+
width: 1px;
|
|
381
|
+
height: 18px;
|
|
382
|
+
margin: 0 3px;
|
|
383
|
+
background: var(--md-sys-color-outline-variant);
|
|
384
|
+
}
|
|
385
|
+
`
|
|
386
|
+
];
|
|
387
|
+
__decorate([
|
|
388
|
+
property({ attribute: false })
|
|
389
|
+
], SelectionToolbar.prototype, "anchor", void 0);
|
|
390
|
+
__decorate([
|
|
391
|
+
property({ type: String, reflect: true })
|
|
392
|
+
], SelectionToolbar.prototype, "placement", void 0);
|
|
393
|
+
__decorate([
|
|
394
|
+
state()
|
|
395
|
+
], SelectionToolbar.prototype, "_left", void 0);
|
|
396
|
+
__decorate([
|
|
397
|
+
state()
|
|
398
|
+
], SelectionToolbar.prototype, "_top", void 0);
|
|
399
|
+
__decorate([
|
|
400
|
+
state()
|
|
401
|
+
], SelectionToolbar.prototype, "_visible", void 0);
|
|
402
|
+
//# sourceMappingURL=selection-toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-toolbar.js","sourceRoot":"","sources":["../../../src/modeller/selection-toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\nimport '@material/web/icon/icon.js'\n\nimport { css, html, nothing, PropertyValues } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { Component } from '@hatiolab/things-scene'\n\nimport { EditToolbar } from './edit-toolbar.js'\n\n/**\n * The contextual toolbar: a small floating bar that sits just above whatever is selected and\n * shows only the verbs that apply to it.\n *\n * ## Why\n *\n * Almost everything in the old 28-icon top toolbar is a verb about the selection - cut, align,\n * distribute, order, group, font size. A verb about the selection belongs next to the selection,\n * and only while there is one. With those gone, the top row keeps the handful of verbs about the\n * board itself (undo, redo, fit, preview, fullscreen, panel), see EditToolbar's `compact`.\n *\n * ## What it shows\n *\n * one shape cut · copy · paste · delete │ forward · backward │ (text) A+ · A-\n * │ ungroup when it is a group │ style copy · databind copy\n * two shapes align (6) │ front · back │ group │ delete\n * three or more + distribute (2)\n *\n * The root and layers never get a bar; a 3D board keeps the full top toolbar (its gizmo tools\n * are not selection verbs in the same sense) and this bar stays out of the way.\n *\n * ## Where it sits\n *\n * Above the union of the selected shapes' screen boxes, centred, clamped to the canvas, and\n * flipped below the selection when there is no room above. Screen boxes come from the scene:\n * a shape's own corners → its root coordinates (`transcoordC2S` then the root's scale and\n * translate) → canvas pixels (the root's scale and translate again), so rotation and nesting\n * are both honoured. The position is refreshed on animation frames while a selection exists,\n * which keeps the bar glued to a shape being dragged or a canvas being zoomed without wiring\n * into every scene event.\n *\n * It reuses EditToolbar's handlers by inheritance, so every verb here is exactly the one the\n * keyboard shortcut runs.\n */\nexport class SelectionToolbar extends EditToolbar {\n static styles = [\n css`\n :host {\n position: absolute;\n left: 0;\n top: 0;\n z-index: 20;\n display: none;\n pointer-events: none;\n }\n\n :host([shown]) {\n display: block;\n }\n\n /* While the pointer is down on the canvas the floating bar steps aside; nothing must sit\n * between the hand and a handle. It fades rather than pops so the eye is not pulled. */\n :host([dragging]:not([placement='docked'])) [bar] {\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.08s ease-out;\n }\n\n [bar] {\n transition: opacity 0.12s ease-out;\n }\n\n [bar] {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n border-radius: 8px;\n background: var(--selection-toolbar-background, var(--md-sys-color-surface-container-highest));\n color: var(--md-sys-color-on-surface-variant);\n border: 1px solid var(--md-sys-color-outline-variant);\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);\n pointer-events: auto;\n white-space: nowrap;\n transform: translateX(-50%);\n }\n\n :host([below]) [bar] {\n transform: translateX(-50%);\n }\n\n [bar] button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n }\n\n [bar] button:hover {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n\n [bar] button[danger]:hover {\n background: var(--md-sys-color-error-container, #f9dedc);\n color: var(--md-sys-color-on-error-container, #410e0b);\n }\n\n [bar] button md-icon {\n --md-icon-size: 18px;\n font-variation-settings: 'wght' 400;\n }\n\n [bar] i {\n width: 1px;\n height: 18px;\n margin: 0 3px;\n background: var(--md-sys-color-outline-variant);\n }\n `\n ]\n\n /* The element whose box the bar is positioned in (the scene wrap); defaults to the parent. */\n @property({ attribute: false }) anchor?: HTMLElement\n /*\n * floating: just above the selection, follows it, steps aside for a drag.\n * docked: pinned top-centre of the canvas while something is selected - never over a handle,\n * never over a neighbour, never moving under the hand. Same verbs either way.\n */\n @property({ type: String, reflect: true }) placement: 'floating' | 'docked' = 'floating'\n\n @state() private _left = 0\n @state() private _top = 0\n @state() private _visible = false\n\n private _frame = 0\n private _lastKey = ''\n\n private _hostListeners?: () => void\n\n connectedCallback() {\n super.connectedCallback()\n this._tick()\n\n /*\n * Frames are the steady follow; these are the nudges. A throttled tab (background pane,\n * battery saver) can starve animation frames, and the bar must still land after a click,\n * a drag, a wheel zoom or a resize.\n */\n const host = this.anchor || (this.parentElement as HTMLElement)\n const nudge = () => this._place()\n const events = ['pointerup', 'pointermove', 'wheel', 'keyup']\n events.forEach(name => host?.addEventListener(name, nudge, { passive: true }))\n window.addEventListener('resize', nudge)\n\n /* Step aside for a drag that starts on the canvas (not on the bar itself). */\n const down = (e: Event) => {\n if (!e.composedPath().includes(this)) this.toggleAttribute('dragging', true)\n }\n const up = () => this.toggleAttribute('dragging', false)\n host?.addEventListener('pointerdown', down, { passive: true })\n window.addEventListener('pointerup', up, { passive: true })\n window.addEventListener('pointercancel', up, { passive: true })\n\n this._hostListeners = () => {\n events.forEach(name => host?.removeEventListener(name, nudge))\n window.removeEventListener('resize', nudge)\n host?.removeEventListener('pointerdown', down)\n window.removeEventListener('pointerup', up)\n window.removeEventListener('pointercancel', up)\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n cancelAnimationFrame(this._frame)\n this._hostListeners?.()\n }\n\n firstUpdated() {\n /* The base wires the clipboard listener the paste verb reads from; keep it. */\n super.firstUpdated()\n }\n\n updated(changes: PropertyValues<this>) {\n super.updated(changes)\n\n if ((changes as Map<string, unknown>).has('_visible')) {\n this.toggleAttribute('shown', this._visible)\n }\n\n if (changes.has('selected') || changes.has('scene')) {\n /* The bar's width depends on what is selected; measure after it has rendered. */\n this._lastKey = ''\n requestAnimationFrame(() => this._place())\n setTimeout(() => this._place(), 50)\n }\n }\n\n render() {\n const selected = this.selected || []\n const count = selected.length\n const one = count === 1\n const many = count > 1\n const text = one && !!(selected[0] as any).hasTextProperty\n const group = one && selected[0].get('type') === 'group'\n\n if (!this._visible) {\n return html``\n }\n\n return html`\n <div bar style=\"left:${this._left}px;top:${this._top}px;position:absolute\">\n ${one\n ? html`\n ${this.button('content_cut', 'cut', () => this.onTapCut())}\n ${this.button('content_copy', 'copy', () => this.onTapCopy())}\n ${this.button('content_paste', 'paste', () => this.onTapPaste())}\n <i></i>\n ${this.button('flip_to_front', 'bring forward', () => this.onTapZorder('forward'))}\n ${this.button('flip_to_back', 'send backward', () => this.onTapZorder('backward'))}\n ${text\n ? html`<i></i>\n ${this.button('text_increase', 'increase font size', () => this.onTapFontIncrease(undefined as any))}\n ${this.button('text_decrease', 'decrease font size', () => this.onTapFontDecrease(undefined as any))}`\n : nothing}\n ${group ? html`<i></i>${this.button('deselect', 'ungroup', () => this.onTapUngroup())}` : nothing}\n <i></i>\n ${this.button('format_paint', 'copy style to…', () => this.onStartStylePasteMode())}\n ${this.button('data_object', 'copy data binding to…', () => this.onStartDatabindPasteMode())}\n `\n : nothing}\n ${many\n ? html`\n ${this.button('align_horizontal_left', 'align left', () => this.onTapAlign('left'))}\n ${this.button('align_horizontal_center', 'align center', () => this.onTapAlign('center'))}\n ${this.button('align_horizontal_right', 'align right', () => this.onTapAlign('right'))}\n ${this.button('align_vertical_top', 'align top', () => this.onTapAlign('top'))}\n ${this.button('align_vertical_center', 'align middle', () => this.onTapAlign('middle'))}\n ${this.button('align_vertical_bottom', 'align bottom', () => this.onTapAlign('bottom'))}\n ${count > 2\n ? html`<i></i>\n ${this.button('horizontal_distribute', 'distribute horizontally', () => this.onTapDistribute('HORIZONTAL'))}\n ${this.button('vertical_distribute', 'distribute vertically', () => this.onTapDistribute('VERTICAL'))}`\n : nothing}\n <i></i>\n ${this.button('flip_to_front', 'bring to front', () => this.onTapZorder('front'))}\n ${this.button('flip_to_back', 'send to back', () => this.onTapZorder('back'))}\n <i></i>\n ${this.button('select_all', 'group', () => this.onTapGroup())}\n ${this.button('content_copy', 'copy', () => this.onTapCopy())}\n `\n : nothing}\n <i></i>\n ${this.button('delete', 'delete', () => this.onTapDelete(), true)}\n </div>\n `\n }\n\n private button(icon: string, title: string, handler: () => void, danger = false) {\n return html`\n <button\n title=${title}\n ?danger=${danger}\n @mousedown=${(e: Event) => e.preventDefault()}\n @click=${(e: Event) => {\n e.stopPropagation()\n handler()\n }}\n >\n <md-icon>${icon}</md-icon>\n </button>\n `\n }\n\n /*\n * One frame at a time. The next frame is booked before the work, so a shape that throws while\n * it is mid-change (being removed, undone, re-parented) costs one frame, not the loop.\n */\n private _tick = () => {\n this._frame = requestAnimationFrame(this._tick)\n\n try {\n this._place()\n } catch (e) {\n /* stale selection; the next frame sees the settled scene */\n }\n }\n\n private _place() {\n /* A popup or dialog owns the screen while it is open; the bar must not show through it. */\n const box = SelectionToolbar._overlayOpen() ? null : this._selectionBox()\n\n if (!box) {\n if (this._visible) {\n this._visible = false\n this._lastKey = ''\n }\n return\n }\n\n const host = this.anchor || (this.parentElement as HTMLElement)\n const hostRect = host.getBoundingClientRect()\n const BAR_HEIGHT = 36\n\n if (this.placement === 'docked') {\n const key = `docked:${Math.round(hostRect.width)}`\n if (key === this._lastKey && this._visible) return\n this._lastKey = key\n this._left = hostRect.width / 2\n this._top = 8\n this._visible = true\n this.toggleAttribute('below', false)\n return\n }\n /* Enough clearance for the top resize handle and the rotate handle that sits above it. */\n const GAP = 26\n\n let left = (box.left + box.right) / 2 - hostRect.left\n let top = box.top - hostRect.top - BAR_HEIGHT - GAP\n let below = false\n\n /* Not enough room above: sit below the selection instead of on top of it. */\n if (top < 8) {\n top = box.bottom - hostRect.top + GAP\n below = true\n }\n\n const barWidth = (this.renderRoot.querySelector('[bar]') as HTMLElement)?.offsetWidth || 240\n left = Math.max(barWidth / 2 + 4, Math.min(hostRect.width - barWidth / 2 - 4, left))\n top = Math.max(4, Math.min(hostRect.height - BAR_HEIGHT - 4, top))\n\n const key = `${Math.round(left)}:${Math.round(top)}:${below}`\n if (key === this._lastKey && this._visible) {\n return\n }\n\n this._lastKey = key\n this._left = left\n this._top = top\n this._visible = true\n this.toggleAttribute('below', below)\n }\n\n /* The union of the selected shapes' boxes, in viewport pixels; null when there is no bar to show. */\n /* The shell mounts popups inside its header bar's shadow tree, so a plain query never sees them. */\n private static _overlayOpen(): boolean {\n const q = 'ox-floating-overlay, ox-popup, md-dialog[open]'\n const app = document.querySelector('things-app')\n const bar = app?.shadowRoot?.querySelector('ox-header-bar')\n return !!(document.querySelector(q) || app?.shadowRoot?.querySelector(q) || bar?.shadowRoot?.querySelector(q))\n }\n\n private _selectionBox(): { left: number; top: number; right: number; bottom: number } | null {\n const scene: any = this.scene\n const root = scene?.root\n const selected = (this.selected || []) as Component[]\n\n if (!root?.element || !selected.length) {\n return null\n }\n\n /* Only 2D boards; and never the root or a layer. */\n if (scene.model_layer?.model?.threed) {\n return null\n }\n\n const scale = root.get('scale') || { x: 1, y: 1 }\n const translate = root.get('translate') || { x: 0, y: 0 }\n const canvas = root.element.getBoundingClientRect()\n\n let left = Infinity\n let top = Infinity\n let right = -Infinity\n let bottom = -Infinity\n\n for (const component of selected) {\n const c: any = component\n if (!c || (typeof c.isRootModel === 'function' && c.isRootModel()) || (typeof c.isLayer === 'function' && c.isLayer())) {\n return null\n }\n\n const b = c.bounds\n if (!b) continue\n\n const corners = [\n [b.left, b.top],\n [b.left + b.width, b.top],\n [b.left + b.width, b.top + b.height],\n [b.left, b.top + b.height]\n ]\n\n for (const [x, y] of corners) {\n const p = c.transcoordC2S(x, y)\n /* to root coordinates, then to canvas pixels */\n const rx = p.x * scale.x + translate.x\n const ry = p.y * scale.y + translate.y\n const sx = rx * scale.x + translate.x + canvas.left\n const sy = ry * scale.y + translate.y + canvas.top\n\n left = Math.min(left, sx)\n top = Math.min(top, sy)\n right = Math.max(right, sx)\n bottom = Math.max(bottom, sy)\n }\n }\n\n if (!Number.isFinite(left)) {\n return null\n }\n\n return { left, top, right, bottom }\n }\n}\n"]}
|
|
@@ -11,6 +11,7 @@ import { LitElement, PropertyValues } from 'lit';
|
|
|
11
11
|
import { LoadTracker, Scene, SceneMode } from '@hatiolab/things-scene';
|
|
12
12
|
import { ComponentToolbar } from './modeller/component-toolbar/component-toolbar.js';
|
|
13
13
|
import { EditToolbar } from './modeller/edit-toolbar.js';
|
|
14
|
+
import { SelectionToolbar } from './modeller/selection-toolbar.js';
|
|
14
15
|
import { PropertySidebar } from './modeller/property-sidebar.js';
|
|
15
16
|
import { ComponentGroup, ComponentTemplate } from './types.js';
|
|
16
17
|
declare const BoardModeller_base: typeof LitElement & import("@open-wc/dedupe-mixin").Constructor<import("@open-wc/scoped-elements/types.js").ScopedElementsHost>;
|
|
@@ -27,6 +28,8 @@ export declare class BoardModeller extends BoardModeller_base {
|
|
|
27
28
|
mode: SceneMode;
|
|
28
29
|
provider: any;
|
|
29
30
|
hideProperty: boolean;
|
|
31
|
+
contextualToolbar: boolean;
|
|
32
|
+
contextualToolbarPlacement: 'floating' | 'docked';
|
|
30
33
|
overlay: string;
|
|
31
34
|
scene?: Scene;
|
|
32
35
|
loadTracker?: LoadTracker;
|
|
@@ -41,6 +44,7 @@ export declare class BoardModeller extends BoardModeller_base {
|
|
|
41
44
|
constructor();
|
|
42
45
|
static get scopedElements(): {
|
|
43
46
|
'edit-toolbar': typeof EditToolbar;
|
|
47
|
+
'selection-toolbar': typeof SelectionToolbar;
|
|
44
48
|
'property-sidebar': typeof PropertySidebar;
|
|
45
49
|
'component-toolbar': typeof ComponentToolbar;
|
|
46
50
|
};
|
|
@@ -19,6 +19,7 @@ import { i18next } from '@operato/i18n';
|
|
|
19
19
|
import { isMacOS, togglefullscreen } from '@operato/utils';
|
|
20
20
|
import { ComponentToolbar } from './modeller/component-toolbar/component-toolbar.js';
|
|
21
21
|
import { EditToolbar } from './modeller/edit-toolbar.js';
|
|
22
|
+
import { SelectionToolbar } from './modeller/selection-toolbar.js';
|
|
22
23
|
import { PropertySidebar } from './modeller/property-sidebar.js';
|
|
23
24
|
const MACOS = isMacOS();
|
|
24
25
|
const ICON_HTOOLBAR = new URL('../../icons/icon-htoolbar.png', import.meta.url).href;
|
|
@@ -65,6 +66,12 @@ let BoardModeller = class BoardModeller extends ScopedElementsMixin(LitElement)
|
|
|
65
66
|
this.mode = SCENE_MODE.EDIT;
|
|
66
67
|
this.provider = null;
|
|
67
68
|
this.hideProperty = false;
|
|
69
|
+
/* Selection verbs float next to the selection (SelectionToolbar) and the top bar keeps only
|
|
70
|
+
* the board verbs. Set false to get the old one-row-of-everything toolbar back. */
|
|
71
|
+
this.contextualToolbar = true;
|
|
72
|
+
/* Where the contextual bar lives when it is on: floating by the selection, or docked at the
|
|
73
|
+
* top of the canvas. */
|
|
74
|
+
this.contextualToolbarPlacement = 'floating';
|
|
68
75
|
this.overlay = '';
|
|
69
76
|
this.componentGroupList = [];
|
|
70
77
|
this.fonts = [];
|
|
@@ -93,6 +100,7 @@ let BoardModeller = class BoardModeller extends ScopedElementsMixin(LitElement)
|
|
|
93
100
|
static get scopedElements() {
|
|
94
101
|
return {
|
|
95
102
|
'edit-toolbar': EditToolbar,
|
|
103
|
+
'selection-toolbar': SelectionToolbar,
|
|
96
104
|
'property-sidebar': PropertySidebar,
|
|
97
105
|
'component-toolbar': ComponentToolbar
|
|
98
106
|
};
|
|
@@ -102,6 +110,7 @@ let BoardModeller = class BoardModeller extends ScopedElementsMixin(LitElement)
|
|
|
102
110
|
<edit-toolbar
|
|
103
111
|
.scene=${this.scene}
|
|
104
112
|
.selected=${this.selected}
|
|
113
|
+
.compact=${this.contextualToolbar}
|
|
105
114
|
@hide-property-changed=${(e) => (this.hideProperty = e.detail.value)}
|
|
106
115
|
@open-preview=${() => this.preview()}
|
|
107
116
|
@open-data-binding=${() => this.openDataBinding()}
|
|
@@ -167,6 +176,14 @@ let BoardModeller = class BoardModeller extends ScopedElementsMixin(LitElement)
|
|
|
167
176
|
<ox-scene-handler type="paste-handler"></ox-scene-handler>
|
|
168
177
|
</ox-scene-viewer>
|
|
169
178
|
|
|
179
|
+
${this.contextualToolbar
|
|
180
|
+
? html `<selection-toolbar
|
|
181
|
+
.scene=${this.scene}
|
|
182
|
+
.selected=${this.selected}
|
|
183
|
+
.placement=${this.contextualToolbarPlacement}
|
|
184
|
+
></selection-toolbar>`
|
|
185
|
+
: ''}
|
|
186
|
+
|
|
170
187
|
<md-fab @click=${() => this.onTapSave()} title="save">
|
|
171
188
|
<md-icon slot="icon">save</md-icon>
|
|
172
189
|
</md-fab>
|
|
@@ -175,6 +192,7 @@ let BoardModeller = class BoardModeller extends ScopedElementsMixin(LitElement)
|
|
|
175
192
|
<property-sidebar
|
|
176
193
|
.scene=${this.scene}
|
|
177
194
|
.selected=${this.selected}
|
|
195
|
+
.heading=${this.boardName}
|
|
178
196
|
.collapsed=${this.hideProperty}
|
|
179
197
|
.fonts=${this.fonts}
|
|
180
198
|
.propertyEditor=${this.propertyEditor}
|
|
@@ -487,6 +505,12 @@ __decorate([
|
|
|
487
505
|
__decorate([
|
|
488
506
|
property({ type: Boolean })
|
|
489
507
|
], BoardModeller.prototype, "hideProperty", void 0);
|
|
508
|
+
__decorate([
|
|
509
|
+
property({ type: Boolean })
|
|
510
|
+
], BoardModeller.prototype, "contextualToolbar", void 0);
|
|
511
|
+
__decorate([
|
|
512
|
+
property({ type: String })
|
|
513
|
+
], BoardModeller.prototype, "contextualToolbarPlacement", void 0);
|
|
490
514
|
__decorate([
|
|
491
515
|
property({ type: String })
|
|
492
516
|
], BoardModeller.prototype, "overlay", void 0);
|