You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.2 KiB
HTML

<style>
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
display: flex;
flex-direction: column;
align-items: stretch;
}
</style>
<script type="module">
class FileGroup extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
this.headerEl = document.createElement('div')
this.headerEl.classList.add('header')
this.contentEl = document.createElement('div')
this.contentEl.classList.add('content')
this.shadowRoot.appendChild(this.headerEl)
this.shadowRoot.appendChild(this.contentEl)
}
connectedCallback() {
const style = document.createElement('style')
style.textContent = `
:host {
display: flex;
flex-direction: column;
align-items: stretch;
}
div.header {
display: flex;
flex-direction: row;
}
div.files {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow-y: auto;
}
`
this.shadowRoot.appendChild(style)
this.addNewFile()
this.addNewFile()
this.addNewFile()
}
addNewFile() {
const el = document.createElement('m-file-view')
this.contentEl.appendChild(el)
}
}
class FileView extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
this.headerEl = document.createElement('div')
this.headerEl.classList.add('header')
this.contentEl = document.createElement('div')
this.contentEl.classList.add('content')
this.shadowRoot.appendChild(this.headerEl)
this.shadowRoot.appendChild(this.contentEl)
}
connectedCallback() {
const style = document.createElement('style')
style.textContent = `
:host {
display: flex;
flex-direction: column;
align-items: stretch;
}
div.header {
display: flex;
flex-direction: row;
}
.name {
flex-grow: 1;
}
div.content {
display: flex;
flex-direction: column;
align-items: stretch;
}
`
this.shadowRoot.appendChild(style)
this.nameEl = document.createElement('input')
this.nameEl.classList.add('name')
this.headerEl.appendChild(this.nameEl)
this.editEl = document.createElement('m-text-edit')
this.contentEl.appendChild(this.editEl)
}
}
class TextEdit extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
}
connectedCallback() {
// https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/
const style = document.createElement('style')
style.textContent = `
:host {
display: flex;
flex-direction: column;
align-items: stretch;
margin: 5px 0;
}
div.stack {
display: grid;
}
div.stack::after {
content: attr(data-copy) " ";
visibility: hidden;
resize: none;
overflow: hidden;
}
div.stack::after, div.stack > textarea {
white-space: pre-wrap;
border: 1px solid #444;
padding: 5px;
font: inherit;
font-family: monospace;
grid-area: 1 / 1 / 2 / 2;
}
`
this.shadowRoot.appendChild(style)
const stackEl = document.createElement('div')
stackEl.classList.add('stack')
this.textEl = document.createElement('textarea')
this.textEl.classList.add('text')
stackEl.appendChild(this.textEl)
this.shadowRoot.appendChild(stackEl)
this.textEl.addEventListener('input', () => {
stackEl.dataset.copy = this.textEl.value
})
}
}
customElements.define('m-file-group', FileGroup)
customElements.define('m-file-view', FileView)
customElements.define('m-text-edit', TextEdit)
const fileGroup = document.createElement('m-file-group')
document.body.appendChild(fileGroup)
</script>
<!--
Each file has a header with the filename, an edit icon, and a menu icon. When editing or creating a new one, the filename is a text field. When not editing, tapping on the filename expands and collapses it.
Tapping on a line selects it and shows icons, tapping on another line selects down to that line.
At the top is a dropdown for selecting the file and a button for.
After all the files is a plus skeleton icon bar.
-->