UNPKG

@infinite-canvas-tutorial/webcomponents

Version:
333 lines (330 loc) 12.4 kB
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; }; import { localized, msg, str } from '@lit/localize'; import { html, css, LitElement } from 'lit'; import { customElement, query, state } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; import { consume } from '@lit/context'; import { CheckboardStyle, readSystemClipboard, ThemeMode, } from '@infinite-canvas-tutorial/ecs'; import { apiContext, appStateContext } from '../context'; import { executeCopy, executeCut, executePaste } from './context-menu'; export var ExportFormat; (function (ExportFormat) { ExportFormat["SVG"] = "svg"; ExportFormat["PNG"] = "png"; ExportFormat["JPEG"] = "jpeg"; })(ExportFormat || (ExportFormat = {})); let TopNavbar = class TopNavbar extends LitElement { constructor() { super(...arguments); this.isClipboardEmpty = true; this.binded = false; this.handleKeyDown = (e) => { // Canvas is focused if (!this.api || document.activeElement !== this.api.element) { return; } if (e.key === 'z' && e.metaKey) { e.preventDefault(); if (e.shiftKey) { this.handleRedo(); } else { this.handleUndo(); } } }; } firstUpdated(_changedProperties) { var _a; (_a = this.actionMenu) === null || _a === void 0 ? void 0 : _a.addEventListener('sp-opened', this.handleOpen); } disconnectedCallback() { super.disconnectedCallback(); document.removeEventListener('keydown', this.handleKeyDown); } handleExport(event) { const format = event.target.value; this.api.export(format); } handleEdit(event) { const value = event.target.value; if (value === 'undo') { this.handleUndo(); } else if (value === 'redo') { this.handleRedo(); } else if (value === 'cut') { this.handleCut(); } else if (value === 'copy') { this.handleCopy(); } else if (value === 'paste') { this.handlePaste(); } } handleConfigView(event) { const value = event.target.value; if (value === 'grid') { this.api.setAppState({ checkboardStyle: CheckboardStyle.GRID, }); } else { this.api.setAppState({ checkboardStyle: CheckboardStyle.NONE, }); } } handleConfigPreferences(event) { const selected = event.target.selected; this.api.setAppState({ snapToPixelGridEnabled: selected.includes('snapToPixelGrid'), snapToObjectsEnabled: selected.includes('snapToObjects'), }); } handleConfigTheme(event) { const selected = event.target.selected[0]; let themeMode = selected === 'dark' ? ThemeMode.DARK : ThemeMode.LIGHT; if (selected === 'system') { themeMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? ThemeMode.DARK : ThemeMode.LIGHT; } this.api.setThemeMode(themeMode); } handleUndo() { this.api.undo(); } handleRedo() { this.api.redo(); } handleCut() { executeCut(this.api, this.appState); } handleCopy() { executeCopy(this.api, this.appState); } handlePaste() { executePaste(this.api, this.appState); } handleOpen() { readSystemClipboard().then((clipboard) => { this.isClipboardEmpty = Object.keys(clipboard).length === 0; }); } handleConfigLanguage(event) { const selected = event.target.selected[0]; this.api.setAppState({ language: selected, }); this.api.setLocale(selected); } render() { var _a; // FIXME: wait for the element to be ready. if (((_a = this.api) === null || _a === void 0 ? void 0 : _a.element) && !this.binded) { this.api.element.addEventListener('keydown', this.handleKeyDown); this.binded = true; } const isSelectedEmpty = this.appState.layersSelected.length === 0; return when(this.appState.topbarVisible, () => { var _a, _b, _c, _d; return html ` <div class="top-navbar"> <sp-action-menu size="m" label="Main menu" quiet> <sp-tooltip slot="tooltip" self-managed placement="bottom"> ${msg(str `Main menu`)} </sp-tooltip> <sp-icon-show-menu slot="icon" size="l"></sp-icon-show-menu> <sp-menu-item> ${msg(str `Edit`)} <sp-menu slot="submenu" @change=${this.handleEdit}> <sp-menu-item value="undo" ?disabled=${(_a = this.api) === null || _a === void 0 ? void 0 : _a.isUndoStackEmpty()} > ${msg(str `Undo`)} <kbd slot="value">⌘Z</kbd> </sp-menu-item> <sp-menu-item value="redo" ?disabled=${(_b = this.api) === null || _b === void 0 ? void 0 : _b.isRedoStackEmpty()} > ${msg(str `Redo`)} <kbd slot="value">⇧⌘Z</kbd> </sp-menu-item> <sp-menu-divider></sp-menu-divider> <sp-menu-item value="cut" ?disabled=${isSelectedEmpty}> ${msg(str `Cut`)} <kbd slot="value">⌘X</kbd> </sp-menu-item> <sp-menu-item value="copy" ?disabled=${isSelectedEmpty}> ${msg(str `Copy`)} <kbd slot="value">⌘C</kbd> </sp-menu-item> <sp-menu-item value="paste" ?disabled=${this.isClipboardEmpty} > ${msg(str `Paste`)} <kbd slot="value">⌘V</kbd> </sp-menu-item> </sp-menu> </sp-menu-item> <sp-menu-item> ${msg(str `View`)} <sp-menu slot="submenu" selects="multiple" .selected=${this.appState.checkboardStyle === CheckboardStyle.GRID ? ['grid'] : []} @change=${this.handleConfigView} > <sp-menu-item value="grid"> ${msg(str `Grid`)} </sp-menu-item> </sp-menu> </sp-menu-item> <sp-menu-item> ${msg(str `Preferences`)} <sp-menu slot="submenu" selects="multiple" .selected=${[ this.appState.snapToPixelGridEnabled ? 'snapToPixelGrid' : undefined, this.appState.snapToObjectsEnabled ? 'snapToObjects' : undefined, ].filter(Boolean)} @change=${this.handleConfigPreferences} > <sp-menu-item value="snapToPixelGrid"> ${msg(str `Snap to pixel grid`)} </sp-menu-item> <sp-menu-item value="snapToObjects"> ${msg(str `Snap to objects`)} </sp-menu-item> <sp-menu-divider></sp-menu-divider> <sp-menu-item> ${msg(str `Theme`)} <sp-menu slot="submenu" selects="single" .selected=${[this.appState.themeMode]} @change=${this.handleConfigTheme} > <sp-menu-item value="light"> ${msg(str `Light`)} </sp-menu-item> <sp-menu-item value="dark"> ${msg(str `Dark`)} </sp-menu-item> <sp-menu-item value="system"> ${msg(str `System`)} </sp-menu-item> </sp-menu> </sp-menu-item> <sp-menu-item> ${msg(str `Language`)} <sp-menu slot="submenu" selects="single" .selected=${[this.appState.language]} @change=${this.handleConfigLanguage} > <sp-menu-item value="en"> English </sp-menu-item> <sp-menu-item value="es-419"> Español </sp-menu-item> <sp-menu-item value="zh-Hans"> 中文 (简体) </sp-menu-item> </sp-menu> </sp-menu-item> </sp-menu> </sp-menu-item> <sp-menu-divider></sp-menu-divider> <sp-menu-item> ${msg(str `Export as...`)} <sp-menu slot="submenu" @change=${this.handleExport}> <sp-menu-item value=${ExportFormat.SVG}>SVG</sp-menu-item> <sp-menu-item value=${ExportFormat.PNG}>PNG</sp-menu-item> <sp-menu-item value=${ExportFormat.JPEG}>JPEG</sp-menu-item> </sp-menu> </sp-menu-item> </sp-action-menu> <div class="actions"> <sp-action-button quiet @click=${this.handleUndo} ?disabled=${(_c = this.api) === null || _c === void 0 ? void 0 : _c.isUndoStackEmpty()} > <sp-icon-undo slot="icon"></sp-icon-undo> <sp-tooltip self-managed placement="bottom"> ${msg(str `Undo`)} </sp-tooltip> </sp-action-button> <sp-action-button quiet @click=${this.handleRedo} ?disabled=${(_d = this.api) === null || _d === void 0 ? void 0 : _d.isRedoStackEmpty()} > <sp-icon-redo slot="icon"></sp-icon-redo> <sp-tooltip self-managed placement="bottom"> ${msg(str `Redo`)} </sp-tooltip> </sp-action-button> <ic-spectrum-zoom-toolbar /> </div> </div> `; }); } }; TopNavbar.styles = css ` .top-navbar { position: relative; display: flex; justify-content: space-between; padding: var(--spectrum-global-dimension-size-100); background: var(--spectrum-gray-100); } sp-menu-item { width: 200px; } 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; } .actions { display: flex; align-items: center; gap: var(--spectrum-global-dimension-size-100); } `; __decorate([ consume({ context: appStateContext, subscribe: true }) ], TopNavbar.prototype, "appState", void 0); __decorate([ consume({ context: apiContext, subscribe: true }) ], TopNavbar.prototype, "api", void 0); __decorate([ state() ], TopNavbar.prototype, "isClipboardEmpty", void 0); __decorate([ query('sp-action-menu', true) ], TopNavbar.prototype, "actionMenu", void 0); TopNavbar = __decorate([ customElement('ic-spectrum-top-navbar'), localized() ], TopNavbar); export { TopNavbar }; //# sourceMappingURL=top-navbar.js.map