Merge pull request 'Add components' (#1) from components into pages

Reviewed-on: https://codeberg.org/macchiato/editor/pulls/1
pages
bat 3 years ago
commit ce0544dfad

@ -0,0 +1,88 @@
export class FileGroup extends HTMLElement {
textEn = {
addFile: 'Add File',
}
textEs = {
addFile: 'Añadir archivo',
}
constructor() {
super()
this.language = navigator.language
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)
const bGroup = document.createElement(
'm-forms-button-group'
)
bGroup.addPrimary(this.text.addFile, () => {
this.addFile()
const btn = bGroup.primary
if (btn.scrollIntoViewIfNeeded) {
btn.scrollIntoViewIfNeeded()
} else {
btn.scrollIntoView()
}
})
this.shadowRoot.appendChild(bGroup)
}
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)
if (this.contentEl.childNodes.length === 0) {
this.addFile()
}
}
addFile({name, data} = {}) {
const el = document.createElement('m-editor-file-view')
if (name !== undefined) {
el.name = name
}
if (data !== undefined) {
el.data = data
}
this.contentEl.appendChild(el)
return el
}
get language() {
return this._language
}
set language(language) {
this._language = language
this.text = this.langEs ? this.textEs : this.textEn
}
get langEs() {
return /^es\b/.test(this.language)
}
get files() {
return [...this.contentEl.children]
}
}

@ -0,0 +1,120 @@
export class FileView extends HTMLElement {
icons = {
menu: `
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-three-dots" viewBox="0 0 16 16">
<path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
</svg>
`,
}
textEn = {
delete: 'Delete',
}
textEs = {
delete: 'Borrar',
}
constructor() {
super()
this.language = navigator.language
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)
this.nameEl = document.createElement('input')
this.nameEl.classList.add('name')
this.headerEl.appendChild(this.nameEl)
this.editEl = document.createElement('m-editor-text-edit')
this.contentEl.appendChild(this.editEl)
this.menuBtn = document.createElement('button')
this.menuBtn.innerHTML = this.icons.menu
this.menuBtn.addEventListener('click', () => {
this.menu.open(this.menuBtn)
})
this.headerEl.appendChild(this.menuBtn)
this.menu = document.createElement(
'm-menu-dropdown'
)
this.menu.add('Borrar', () => {
this.remove()
})
this.shadowRoot.appendChild(this.menu)
}
connectedCallback() {
const style = document.createElement('style')
style.textContent = `
:host {
display: flex;
flex-direction: column;
align-items: stretch;
}
div.header {
display: flex;
flex-direction: row;
align-items: stretch;
background-color: #111;
color: #ddd;
padding: 3px 0;
}
div.header > * {
background: inherit;
color: inherit;
border: none;
}
.name {
flex-grow: 1;
padding: 0 5px;
font: inherit;
font-family: monospace;
outline: none;
}
div.header button svg {
margin-bottom: -3px;
}
div.content {
display: flex;
flex-direction: column;
align-items: stretch;
}
svg {
height: 20px;
width: 20px;
}
`
this.shadowRoot.appendChild(style)
}
set name(name) {
this.nameEl.value = name
}
get name() {
return this.nameEl.value
}
set data(data) {
this.editEl.value = data
}
get data() {
return this.editEl.value
}
get language() {
return this._language
}
set language(language) {
this._language = language
this.text = this.langEs ? this.textEs : this.textEn
}
get langEs() {
return /^es\b/.test(this.language)
}
}

@ -1,244 +0,0 @@
<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)
if (this.contentEl.childNodes.length === 0) {
this.addFile()
}
}
addFile({name, data} = {}) {
const el = document.createElement('m-file-view')
if (name !== undefined) {
el.name = name
}
if (data !== undefined) {
el.data = data
}
this.contentEl.appendChild(el)
return el
}
}
class FileView extends HTMLElement {
icons = {
menu: `
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-three-dots" viewBox="0 0 16 16">
<path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
</svg>
`,
}
text = {
delete: {en: 'Delete', es: 'Borrar'},
}
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)
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)
this.menuEl = document.createElement('button')
this.menuEl.innerHTML = this.icons.menu
this.headerEl.appendChild(this.menuEl)
}
connectedCallback() {
const style = document.createElement('style')
style.textContent = `
:host {
display: flex;
flex-direction: column;
align-items: stretch;
}
div.header {
display: flex;
flex-direction: row;
align-items: stretch;
background-color: #111;
color: #ddd;
padding: 3px 0;
}
div.header > * {
background: inherit;
color: inherit;
border: none;
}
.name {
flex-grow: 1;
padding: 0 5px;
font: inherit;
font-family: monospace;
outline: none;
}
div.header button svg {
margin-bottom: -3px;
}
div.content {
display: flex;
flex-direction: column;
align-items: stretch;
}
svg {
height: 20px;
width: 20px;
}
`
this.shadowRoot.appendChild(style)
}
set name(name) {
this.nameEl.value = name
}
get name() {
return this.nameEl.value
}
set data(data) {
this.editEl.value = data
}
get data() {
return this.editEl.value
}
}
class TextEdit extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
const stackEl = document.createElement('div')
stackEl.classList.add('stack')
this.textEl = document.createElement('textarea')
this.textEl.classList.add('text')
this.textEl.rows = 1
stackEl.appendChild(this.textEl)
this.shadowRoot.appendChild(stackEl)
this.textEl.addEventListener('input', () => {
stackEl.dataset.copy = this.textEl.value
})
}
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;
overflow: hidden;
}
div.stack::after, div.stack > textarea {
white-space: pre-wrap;
border: 1px solid #888;
padding: 3px;
font: inherit;
font-family: monospace;
grid-area: 1 / 1 / 2 / 2;
min-height: 1em;
border-radius: 2px;
resize: none;
}
`
this.shadowRoot.appendChild(style)
}
set value(value) {
this.textEl.value = value
}
get value() {
return 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')
fileGroup.addFile({
name: 'file-group.js',
data: 'code here'
})
fileGroup.addFile({
name: 'file-view.js',
data: 'code here'
})
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.
-->

@ -0,0 +1,58 @@
export class TextEdit extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
this.stackEl = document.createElement('div')
this.stackEl.classList.add('stack')
this.textEl = document.createElement('textarea')
this.textEl.classList.add('text')
this.textEl.rows = 1
this.stackEl.appendChild(this.textEl)
this.shadowRoot.appendChild(this.stackEl)
this.textEl.addEventListener('input', () => {
this.stackEl.dataset.copy = this.textEl.value
})
}
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;
overflow: hidden;
}
div.stack::after, div.stack > textarea {
white-space: pre-wrap;
border: 1px solid #888;
padding: 3px;
font: inherit;
font-family: monospace;
grid-area: 1 / 1 / 2 / 2;
min-height: 1em;
border-radius: 2px;
resize: none;
}
`
this.shadowRoot.appendChild(style)
}
set value(value) {
this.textEl.value = value
this.stackEl.dataset.copy = this.textEl.value
}
get value() {
return this.textEl.value
}
}
Loading…
Cancel
Save