@silexlabs/silex
Version:
Free and easy website builder for everyone.
115 lines (108 loc) • 3.5 kB
text/typescript
/*
* Silex website builder, free/libre no-code tool for makers.
* Copyright (c) 2023 lexoyo and Silex Labs foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {html, render} from 'lit-html'
import {map} from 'lit-html/directives/map.js'
// constants
const pluginName = 'semantic'
const tags = [
'DIV',
'P',
'H1',
'H2',
'H3',
'H4',
'H5',
'H6',
'SPAN',
'MAIN',
'ASIDE',
'SECTION',
'ADDRESS',
'ARTICLE',
'BUTTON',
'NAV',
'HEADER',
'FOOTER',
'DETAILS',
'SUMMARY',
'PRE',
'BLOCKQUOTE',
]
// plugin code
export const semanticPlugin = (editor, opts) => {
// Add the new trait to all component types
editor.DomComponents.getTypes().map(type => {
editor.DomComponents.addType(type.id, {
model: {
defaults: {
traits: [
// Keep the type original traits
...editor.DomComponents.getType(type.id).model.prototype.defaults.traits,
// Add the new trait
{
label: 'Tag name',
type: 'tag-name',
name: 'tag-name',
},
]
}
}
})
})
function doRender(el: HTMLElement, tagName: string) {
const tagsWithCurrent = tags.includes(tagName.toUpperCase()) ? tags : tags.concat(tagName.toUpperCase())
render(html`
<label for="semantic__select" class="gjs-one-bg silex-label">Type</label>
<select id="semantic__select" @change=${event => doRender(el, event.target.value)}>
${map<string>(tagsWithCurrent, tag => html`
<option value="${tag}" ?selected=${tagName.toUpperCase() === tag}>${tag}</option>
`)}
</select>
`, el)
}
function doRenderCurrent(el: HTMLElement) {
doRender(el, editor.getSelected()?.get('tagName') || '')
}
// Add semantic traits
// inspired by https://github.com/olivmonnier/grapesjs-plugin-header/blob/master/src/components.js
editor.TraitManager.addType('tag-name', {
createInput({ trait }) {
// Create a new element container and add some content
const el = document.createElement('div')
// update the UI when a page is added/renamed/removed
editor.on('page', () => doRenderCurrent(el))
doRenderCurrent(el)
// this will be the element passed to onEvent and onUpdate
return el
},
// Update the component based on UI changes
// `elInput` is the result HTMLElement you get from `createInput`
onEvent({ elInput, component, event }) {
const value = elInput.querySelector('#semantic__select').value
if(component.get('tagName').toUpperCase() === value.toUpperCase()){
// Already done
} else {
component.set('tagName', value)
}
},
// Update UI on the component change
onUpdate({ elInput, component }) {
const tagName = component.get('tagName')
doRender(elInput, tagName)
},
})
}