spriteStackist/frontend/src/App.svelte

172 lines
5.0 KiB
Svelte

<script lang="ts">
import type { data } from '../wailsjs/go/models.js'
import Editor2D from './sections/Editor2D.svelte'
import Importer from './sections/Importer.svelte';
import PaletteSection from './sections/Palette.svelte'
import FloatingPanel from './components/FloatingPanel.svelte'
import { Palette, PaletteEntry, defaultPalette } from './types/palette'
import { LoadedFile } from './types/file.ts'
import "carbon-components-svelte/css/all.css"
import { Tabs, Tab, TabContent, Theme, Button, Modal, Truncate } from "carbon-components-svelte"
import { ComposedModal } from "carbon-components-svelte"
import { OverflowMenu, OverflowMenuItem } from "carbon-components-svelte"
import { Close } from "carbon-icons-svelte"
import StackPreview from './sections/StackPreview.svelte'
import type { Canvas } from './types/canvas'
let theme: 'white'|'g10'|'g80'|'g90'|'g100' = 'g90'
let palette: Palette = defaultPalette()
let primaryColorIndex: number = 1
let secondaryColorIndex: number = 0
let showImport: boolean = false
let importValid: boolean = false
let importFile: data.StackistFileV1 = null
let importFilepath: string = ''
let importCanvas: Canvas = null
let showPreview: boolean = false
let refresh = {}
let files: LoadedFile[] = []
let focusedFileIndex: number = -1
let focusedFile: LoadedFile = null
$: focusedFile = files[focusedFileIndex] ?? null
$: console.log(focusedFile)
function selectFile(file: LoadedFile, index: number) {
focusedFileIndex = index
refresh = {}
}
function engageImport() {
if (importValid) {
files = [...files, new LoadedFile({filepath: importFilepath, title: importFilepath, canvas: importCanvas, data: importFile})]
console.log(files)
}
showImport = false
}
function closeFile(index: number) {
files = files.filter((_,i)=>i!==index)
}
</script>
<Theme bind:theme/>
<main>
<menu>
<OverflowMenu size="sm">
<div slot="menu">File</div>
<OverflowMenuItem text="New"/>
<OverflowMenuItem text="Open..."/>
<OverflowMenuItem text="Import from PNG..." on:click={() => showImport = true}/>
<OverflowMenuItem text="Save"/>
<OverflowMenuItem text="Save As..."/>
<OverflowMenuItem hasDivider danger text="Quit"/>
</OverflowMenu>
<OverflowMenu size="sm">
<div slot="menu">Edit</div>
<OverflowMenuItem text="Undo" on:click={() => focusedFile?.undo()} disabled={!focusedFile?.canUndo()}/>
<OverflowMenuItem text="Redo" on:click={() => focusedFile?.redo()} disabled={!focusedFile?.canRedo()}/>
</OverflowMenu>
<OverflowMenu size="sm">
<div slot="menu">Windows</div>
<OverflowMenuItem text="Preview" on:click={() => showPreview = true}/>
</OverflowMenu>
</menu>
<section class='content'>
<section class='left'>
<PaletteSection bind:palette bind:primaryColorIndex bind:secondaryColorIndex file={focusedFile} />
</section>
<section class='middle'>
<Tabs>
{#each files as file, index}
<Tab on:click={()=>selectFile(file, index)}>
<span class='tab'>
<span>{file.title}</span>
<Button size="small" kind="ghost" iconDescription="close" icon={Close} href="#" on:click={(e)=>{e.preventDefault();closeFile(index)}} />
</span>
</Tab>
{/each}
<svelte:fragment slot="content">
{#each files as file}
<TabContent>
<Editor2D bind:file={file} refresh={refresh} primaryColorIndex={primaryColorIndex} secondaryColorIndex={secondaryColorIndex} />
</TabContent>
{/each}
</svelte:fragment>
</Tabs>
</section>
{#if showPreview}
<FloatingPanel
label="Stack Preview"
noPadding
bind:open={showPreview}
>
<StackPreview files={files} />
</FloatingPanel>
{/if}
</section>
</main>
<ComposedModal bind:open={showImport} size="sm" preventCloseOnClickOutside on:click:button--primary={engageImport}>
<Importer
bind:open={showImport}
bind:valid={importValid}
bind:file={importFile}
bind:filepath={importFilepath}
bind:canvas={importCanvas}
/>
</ComposedModal>
<style>
main {
width: 100%;
height: 100%;
display: grid;
grid-template-rows: auto minmax(0, 1fr);
}
menu {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
:global(menu > button) {
width: 4rem !important;
color: var(--cds-text-02, #c6c6c6);
}
.content {
display: grid;
grid-template-columns: 1fr 4fr;
grid-template-rows: minmax(0, 1fr);
}
.left {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.middle {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
}
.tab {
display: inline-grid;
grid-template-columns: 9em minmax(0, 1fr);
grid-template-rows: minmax(0, 1fr);
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
}
.tab span {
overflow: hidden;
text-overflow: ellipsis;
}
</style>