@infinite-canvas-tutorial/webcomponents
Version:
WebComponents UI implementation
334 lines (330 loc) • 15.1 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { html, css, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { consume } from '@lit/context';
import { localized, msg, str } from '@lit/localize';
import { when } from 'lit/directives/when.js';
import { Pen } from '@infinite-canvas-tutorial/ecs';
import { apiContext, appStateContext } from '../context';
import { fileOpen } from '../utils';
let Penbar = class Penbar extends LitElement {
constructor() {
super(...arguments);
this.binded = false;
// keyboard shortcuts R L O
this.handleKeyDown = (event) => {
if (document.activeElement !== this.api.element) {
return;
}
this.setPenWithKeyboard(event, Pen.DRAW_RECT, 'R');
this.setPenWithKeyboard(event, Pen.DRAW_LINE, 'L');
this.setPenWithKeyboard(event, Pen.DRAW_ELLIPSE, 'O');
this.setPenWithKeyboard(event, Pen.DRAW_ARROW, 'L', true);
};
}
shouldUpdate(changedProperties) {
const newPen = this.appState.penbarSelected;
if (newPen !== this.previousPen) {
this.previousPen = newPen;
return true;
}
const newPenbarVisible = this.appState.penbarVisible;
if (newPenbarVisible !== this.previousPenbarVisible) {
this.previousPenbarVisible = newPenbarVisible;
return true;
}
return super.shouldUpdate(changedProperties);
}
handlePenChanged(e) {
return __awaiter(this, void 0, void 0, function* () {
const pen = e.target.selected[0];
if (!this.api.getAppState().penbarAll.includes(pen)) {
return;
}
this.api.setAppState({
penbarSelected: pen,
});
if (pen === Pen.DRAW_RECT ||
pen === Pen.DRAW_ELLIPSE ||
pen === Pen.DRAW_LINE ||
pen === Pen.DRAW_ARROW ||
pen === Pen.DRAW_ROUGH_RECT ||
pen === Pen.DRAW_ROUGH_ELLIPSE ||
pen === Pen.DRAW_ROUGH_LINE) {
this.lastDrawPen = pen;
}
else if (pen === Pen.IMAGE) {
try {
const file = yield fileOpen({
extensions: ['jpg', 'png', 'svg', 'webp'],
description: 'Image to upload',
});
if (file) {
const center = this.api.viewport2Canvas({
x: this.api.element.clientWidth / 2,
y: this.api.element.clientHeight / 2,
});
yield this.api.createImageFromFile(file, { position: center });
this.api.setAppState({
penbarSelected: Pen.SELECT,
});
this.api.record();
}
}
catch (e) {
this.api.setAppState({
penbarSelected: Pen.SELECT,
});
}
}
});
}
setPenWithKeyboard(event, pen, targetKey, shiftKey = false) {
if (event.key.toUpperCase() === targetKey.toUpperCase() &&
!event.ctrlKey &&
!event.metaKey &&
!event.altKey &&
(!shiftKey || (shiftKey && event.shiftKey))) {
event.preventDefault();
event.stopPropagation();
this.api.setAppState({
penbarSelected: pen,
});
this.lastDrawPen = pen;
}
}
disconnectedCallback() {
super.disconnectedCallback();
// this.api
// .getCanvasElement()
// .removeEventListener('keydown', this.handleKeyDown);
}
render() {
if (!this.api) {
return;
}
// FIXME: wait for the element to be ready.
if (this.api.element && !this.binded) {
this.api
.getCanvasElement()
.addEventListener('keydown', this.handleKeyDown);
this.binded = true;
const pen = this.api.getAppState().penbarSelected;
this.lastDrawPen =
pen === Pen.DRAW_RECT ||
pen === Pen.DRAW_ELLIPSE ||
pen === Pen.DRAW_LINE ||
pen === Pen.DRAW_ARROW ||
pen === Pen.DRAW_ROUGH_RECT ||
pen === Pen.DRAW_ROUGH_ELLIPSE ||
pen === Pen.DRAW_ROUGH_LINE
? pen
: Pen.DRAW_RECT;
}
const { penbarAll, penbarSelected, penbarVisible } = this.api.getAppState();
return when(penbarVisible, () => html `
<sp-action-group
class="penbar"
vertical
selects="single"
.selected=${[penbarSelected]}
=${this.handlePenChanged}
emphasized
quiet
>
${when(penbarAll.includes(Pen.HAND), () => html `
<sp-action-button value="${Pen.HAND}">
<sp-icon-hand slot="icon"></sp-icon-hand>
<sp-tooltip self-managed placement="right">
${msg(str `Hand (Panning tool)`)}
</sp-tooltip>
</sp-action-button>
`)}
${when(penbarAll.includes(Pen.SELECT), () => html `
<sp-action-button value="${Pen.SELECT}">
<sp-icon-select slot="icon"></sp-icon-select>
<sp-tooltip self-managed placement="right">
${msg(str `Select`)}
</sp-tooltip>
</sp-action-button>
`)}
${when(penbarAll.includes(Pen.DRAW_RECT) ||
penbarAll.includes(Pen.DRAW_ELLIPSE) ||
penbarAll.includes(Pen.DRAW_LINE) ||
penbarAll.includes(Pen.DRAW_ARROW) ||
penbarAll.includes(Pen.DRAW_ROUGH_RECT) ||
penbarAll.includes(Pen.DRAW_ROUGH_ELLIPSE) ||
penbarAll.includes(Pen.DRAW_ROUGH_LINE), () => html `
<overlay-trigger placement="right">
<sp-action-button
value=${this.lastDrawPen}
hold-affordance
slot="trigger"
>
${when(this.lastDrawPen === Pen.DRAW_RECT, () => html `<sp-icon-rectangle slot="icon"></sp-icon-rectangle>`)}
${when(this.lastDrawPen === Pen.DRAW_ELLIPSE, () => html `<sp-icon-ellipse slot="icon"></sp-icon-ellipse>`)}
${when(this.lastDrawPen === Pen.DRAW_LINE, () => html `<sp-icon-line slot="icon"></sp-icon-line>`)}
${when(this.lastDrawPen === Pen.DRAW_ARROW, () => html `<sp-icon-arrow-up-right
slot="icon"
></sp-icon-arrow-up-right>`)}
${when(this.lastDrawPen === Pen.DRAW_ROUGH_RECT, () => html `<sp-icon-rect-select
slot="icon"
></sp-icon-rect-select>`)}
${when(this.lastDrawPen === Pen.DRAW_ROUGH_ELLIPSE, () => html `<sp-icon-ellipse slot="icon"></sp-icon-ellipse>`)}
${when(this.lastDrawPen === Pen.DRAW_ROUGH_LINE, () => html `<sp-icon-line slot="icon"></sp-icon-line>`)}
</sp-action-button>
<sp-popover slot="hover-content" style="padding: 8px;">
<ic-spectrum-penbar-draw-settings
.pen=${this.lastDrawPen}
></ic-spectrum-penbar-draw-settings>
</sp-popover>
<sp-popover slot="click-content">
<sp-menu
=${this.handlePenChanged}
selects="single"
.selected=${[penbarSelected]}
>
${when(penbarAll.includes(Pen.DRAW_RECT), () => html ` <sp-menu-item value="${Pen.DRAW_RECT}">
<sp-icon-rectangle slot="icon"></sp-icon-rectangle>
${msg(str `Rectangle`)}
<kbd slot="value">R</kbd>
</sp-menu-item>`)}
${when(penbarAll.includes(Pen.DRAW_ELLIPSE), () => html ` <sp-menu-item value="${Pen.DRAW_ELLIPSE}">
<sp-icon-ellipse slot="icon"></sp-icon-ellipse>
${msg(str `Ellipse`)}
<kbd slot="value">O</kbd>
</sp-menu-item>`)}
${when(penbarAll.includes(Pen.DRAW_LINE), () => html ` <sp-menu-item value="${Pen.DRAW_LINE}">
<sp-icon-line slot="icon"></sp-icon-line>
${msg(str `Line`)}
<kbd slot="value">L</kbd>
</sp-menu-item>`)}
${when(penbarAll.includes(Pen.DRAW_ARROW), () => html ` <sp-menu-item value="${Pen.DRAW_ARROW}">
<sp-icon-arrow-up-right
slot="icon"
></sp-icon-arrow-up-right>
${msg(str `Arrow`)}
<kbd slot="value">⇧L</kbd>
</sp-menu-item>`)}
${when(penbarAll.includes(Pen.DRAW_ROUGH_RECT), () => html ` <sp-menu-item value="${Pen.DRAW_ROUGH_RECT}">
<sp-icon-rect-select slot="icon"></sp-icon-rect-select>
${msg(str `Rough Rectangle`)}
</sp-menu-item>`)}
${when(penbarAll.includes(Pen.DRAW_ROUGH_ELLIPSE), () => html ` <sp-menu-item
value="${Pen.DRAW_ROUGH_ELLIPSE}"
>
<sp-icon-ellipse slot="icon"></sp-icon-ellipse>
${msg(str `Rough Ellipse`)}
</sp-menu-item>`)}
${when(penbarAll.includes(Pen.DRAW_ROUGH_LINE), () => html ` <sp-menu-item value="${Pen.DRAW_ROUGH_LINE}">
<sp-icon-line slot="icon"></sp-icon-line>
${msg(str `Rough Line`)}
</sp-menu-item>`)}
</sp-menu>
</sp-popover>
</overlay-trigger>
`)}
${when(penbarAll.includes(Pen.IMAGE), () => html `
<sp-action-button value="${Pen.IMAGE}">
<sp-icon-image slot="icon"></sp-icon-image>
<sp-tooltip self-managed placement="right">
${msg(str `Image`)}
</sp-tooltip>
</sp-action-button>
`)}
${when(penbarAll.includes(Pen.TEXT), () => html `
<overlay-trigger placement="right">
<sp-action-button value="${Pen.TEXT}" slot="trigger">
<sp-icon-text slot="icon"></sp-icon-text>
<sp-tooltip self-managed placement="right">
${msg(str `Text`)}
</sp-tooltip>
</sp-action-button>
<sp-popover slot="hover-content" style="padding: 8px;">
<ic-spectrum-penbar-text-settings></ic-spectrum-penbar-text-settings>
</sp-popover>
</overlay-trigger>
`)}
${when(penbarAll.includes(Pen.PENCIL), () => html `
<overlay-trigger placement="right">
<sp-action-button value="${Pen.PENCIL}" slot="trigger">
<sp-icon-annotate-pen slot="icon"></sp-icon-annotate-pen>
<sp-tooltip self-managed placement="right">
${msg(str `Pencil`)}
</sp-tooltip>
</sp-action-button>
<sp-popover slot="hover-content" style="padding: 8px;">
<ic-spectrum-penbar-pencil-settings></ic-spectrum-penbar-pencil-settings>
</sp-popover>
</overlay-trigger>
`)}
${when(penbarAll.includes(Pen.BRUSH), () => html `
<overlay-trigger placement="right">
<sp-action-button value="${Pen.BRUSH}" slot="trigger">
<sp-icon-brush slot="icon"></sp-icon-brush>
<sp-tooltip self-managed placement="right">
${msg(str `Brush`)}
</sp-tooltip>
</sp-action-button>
<sp-popover slot="hover-content" style="padding: 8px;">
<ic-spectrum-penbar-brush-settings></ic-spectrum-penbar-brush-settings>
</sp-popover>
</overlay-trigger>
`)}
<slot name="penbar-item"></slot>
</sp-action-group>
`);
}
};
Penbar.styles = css `
.penbar {
display: flex;
justify-content: center;
background: var(--spectrum-gray-100);
border-radius: var(--spectrum-corner-radius-200);
padding: var(--spectrum-global-dimension-size-100);
margin: 4px;
filter: drop-shadow(
var(--spectrum-drop-shadow-color) 0px var(--spectrum-drop-shadow-y)
var(--spectrum-drop-shadow-blur)
);
}
kbd {
font-family: var(--spectrum-alias-body-text-font-family);
letter-spacing: 0.1em;
white-space: nowrap;
border: none;
padding: none;
padding: 0;
line-height: normal;
}
`;
__decorate([
consume({ context: appStateContext, subscribe: true })
], Penbar.prototype, "appState", void 0);
__decorate([
consume({ context: apiContext, subscribe: true })
], Penbar.prototype, "api", void 0);
__decorate([
state()
], Penbar.prototype, "lastDrawPen", void 0);
Penbar = __decorate([
customElement('ic-spectrum-penbar'),
localized()
], Penbar);
export { Penbar };
//# sourceMappingURL=penbar.js.map