diff --git a/components.js b/components.js index d09a7d7..2e1d14e 100644 --- a/components.js +++ b/components.js @@ -1 +1,3 @@ export {default as Block} from './components/block/element.js'; +export {default as Placeholder} from './components/placeholder/element.js'; +export {default as BlockPicker} from './components/block-picker/element.js'; diff --git a/components/block-picker/element.js b/components/block-picker/element.js new file mode 100644 index 0000000..1188b1b --- /dev/null +++ b/components/block-picker/element.js @@ -0,0 +1,226 @@ +import {LitElement, html} from 'lit'; +import {classMap} from 'lit/directives/class-map.js'; +import { CloseIcon } from '../icons.js'; +import style from './style.js'; + +export default class BlockPicker extends LitElement { + static styles = [style]; + + static properties = { + blockId: {type: String}, + isActive: {type: Boolean, state: true, default: false}, + isLoading: {type: Boolean, state: true}, + placeholderIdentifier: {type: String} + }; + + constructor() { + super(); + } + + connectedCallback() { + super.connectedCallback(); + } + + + get core() { + return window.parent.Core; + } + + get layout() { + return this.core.g.layout; + } + + get zone() { + return this.layout.zones.models.find(model => model.id === this.block.attributes.zone_identifier) + } + + get blockGroups() { + return this.core.g.block_types.groups.models + } + + get block() { + return this.layout.blocks._byId[this.blockId]; + } + + get iframe() { + const iframe = window.parent.document.querySelector('.preview-iframe-sizer iframe') + return iframe; + } + + handleClose() { + this.isActive = false + this.placeholderIdentifier = false + this.iframe.contentDocument.querySelector('body').style.overflowY = 'auto'; + } + + handleOpen() { + this.isActive = true + this.iframe.contentDocument.querySelector('body').style.overflowY = 'hidden'; + } + + renderCloseBtn() { + return html` + + ${CloseIcon()} + + ` + } + + renderBlockGroups() { + if(!this.isActive) return; + + return html` +
+
+ ${this.renderCloseBtn()} + ${this.blockGroups.map(group => this.renderBlockGroup(group))} +
+
+ ` + } + + renderBlockGroup(group) { + const blockTypes = group._block_types.filter(blockType => this.placeholderIdentifier || this.block.attributes.parent_placeholder ? !blockType.attributes.is_container : true) + + if(blockTypes.length <= 0 ) return; + + return html` +
+

${group.attributes.name}

+
+
+ ${blockTypes.map((blockType, index) => this.renderBlockType(blockType, index))} +
+ ` + } + + renderBlockType(blockType, index) { + const icon = blockType.attributes.icon ? html`` : html`` + + return html` +
+ ${icon} + ${blockType.attributes.name} +
+ ` + } + + renderLoader() { + if(!this.isLoading) return; + + return html` +
+
+ + Loading +
+
+ ` + } + + + handleCreateBlockFromType(blockType) { + const identifier = blockType.get('identifier'); + const isContainer = this.block.attributes.is_container && this.placeholderIdentifier; + const parentBlockId = isContainer ? this.blockId : this.block.attributes.parent_block_id + + const attributes = { + block_type: identifier, + zone_identifier: this.zone.id, + layout_id: this.layout.id, + parent_position: isContainer ? 0 : this.block.attributes.parent_position + 1, + parent_placeholder: isContainer ? this.placeholderIdentifier : this.block.attributes.parent_placeholder, + parent_block_id: parentBlockId + }; + + const newBlock = this.core.model_helper.init_block_from_type(blockType, attributes); + + let responseData = {}; + + const saveInContainer = isContainer || this.block.attributes.parent_block_id + this.isLoading = true; + + this.handleSaveNewBlock(newBlock, saveInContainer, parentBlockId) + .then((res) => { + responseData = res + this.layout.reset_blocks_loaded() + return this.layout.load_all_blocks() + }) + .then(() => { + this.isActive = false; + this.handleRefreshView(responseData.id) + }) + } + + handleSaveNewBlock(newBlock, saveInContainer, blockId) { + if(saveInContainer) { + console.warn('Save in container'); + return newBlock.save({}, { url: newBlock.url(blockId) } ) + } else { + console.warn('Save') + return newBlock.save() + } + } + + + async handleRefreshView(blockId) { + + return await fetch(window.location.href) + .then(resp => { + return resp.text() + }) + .then(html => { + const template = document.createElement('template'); + template.innerHTML = html; + + const futurePage = template.content.querySelector( + '#page' + ); + const iframe = window.parent.document.querySelector('.preview-iframe-sizer iframe') + const currentPage = iframe.contentDocument.querySelector( + '#page' + ); + + currentPage.innerHTML = futurePage.innerHTML + + this.dispatchEvent( + new Event('ngl:refresh', {bubbles: true, composed: true}) + ); + + const block = this.layout.blocks._byId[blockId] + const blockElement = iframe.contentDocument.querySelector( + `ngl-block[blockId="${blockId}"]` + ) + blockElement.isSelected = true; + block.trigger('edit'); + }) + .catch(err => console.error(err)) + .finally(() => { + this.isLoading = false + this.placeholderIdentifier = "" + }) + } + + updated(changedProperties) { + if(!this.isActive) return; + + this.handleOpen() + } + + render() { + const classes = { + is_active: this.isActive, + is_loading: this.isLoading, + }; + + return html` +
+ ${this.renderBlockGroups()} + +
+ ${this.renderLoader()} + `; + } +} + +customElements.get('ngl-block-picker') || customElements.define('ngl-block-picker', BlockPicker); \ No newline at end of file diff --git a/components/block-picker/spec.js b/components/block-picker/spec.js new file mode 100644 index 0000000..e69de29 diff --git a/components/block-picker/style.js b/components/block-picker/style.js new file mode 100644 index 0000000..0eeffa5 --- /dev/null +++ b/components/block-picker/style.js @@ -0,0 +1,283 @@ +import {css} from 'lit'; + +export default css` + :host, + :after, + :before { + --ngl-block-picker-width: 22.625rem; + --ngl-block-picker-gutter: 0.9375rem; + --ngl-block-picker-background-color: #383838; + --ngl-block-picker-border-color: #4f4f4f; + --ngl-block-picker-block-background-color: #4f4f4f; + --ngl-block-picker-text-color: #9c9c9c; + } + + main { + display: none; + position: fixed; + z-index: 80050; + inset: 0; + background-color: rgba(0, 0, 0, 0.7); + } + + main.is_active { + display: block; + } + + .panel { + position: absolute; + left: 50%; + top: 50%; + max-height: 90vh; + border-top: 1px solid var(--ngl-block-picker-border-color); + width: var(--ngl-block-picker-width); + background: var(--ngl-block-picker-background-color); + color: var(--ngl-block-picker-text-color); + overflow-y: scroll; + transform: translate(-50%, -200vh); + } + + .panel::-webkit-scrollbar { + width: .3125rem; + } + + .panel::-webkit-scrollbar-thumb { + background: #999; + } + + main.is_active .panel { + transform: translate(-50%, -50%); + transition: transform 350ms 150ms ease; + } + + .panel-content { + padding: var(--ngl-block-picker-gutter); + } + + .close-panel { + position: absolute; + right: .25em; + top: .25em; + width: 1.5em; + height: 1.5em; + cursor: pointer; + text-align: right; + color: var(--ngl-block-picker-text-color); + z-index: 2; + display: flex; + justify-content: center; + align-items: center; + } + + .close-panel svg { + fill: var(--ngl-block-picker-text-color) + } + + .close-panel:hover { + color: #fff; + } + + .header { + position: relative; + } + + .header h2 { + font-size: .75em; + font-weight: 500; + line-height: 1.25; + text-transform: uppercase; + margin: 0 0 .5em; + color: inherit; + } + + .block-items { + margin: 0 0 1.5em; + display: flex; + flex-wrap: wrap; + } + + .add-block-btn { + border: 0; + border-bottom: 1px solid var(--ngl-block-picker-background-color); + border-right: 1px solid var(--ngl-block-picker-background-color); + width: calc( ( var(--ngl-block-picker-width) - 2 * var(--ngl-block-picker-gutter) - 2rem)/ 4); + background: #4a4a4a; + border: 1px solid var(--ngl-block-picker-background-color); + aspect-ratio: 1/1; + color: var(--ngl-block-picker-text-color); + text-align: center; + padding: 0.25em 0.25em 0.625em; + transition: background .15s ease, color .15s ease; + cursor: pointer; + display: flex; + flex-direction: column; + font-size: .625rem; + line-height: 1.2; + align-itmes: center; + justify-content: center; + } + + .add-block-btn:hover { + background: #5c5c5c; + color: #fff; + } + + .add-block-btn .icon { + font-size: 2em; + height: 2.5rem; + line-height: 1.25; + margin-bottom: .125em; + padding: .125em; + display: flex; + align-items: center; + justify-content: center; + } + + .add-block-btn .icon { + max-width: 100%; + max-height: 100%; + display: block; + } + + .add-block-btn:hover .icon { + filter: brightness(0) saturate(100%) invert(99%) sepia(97%) saturate(0%) hue-rotate(74deg) brightness(104%) contrast(100%); + } + + .add-block-btn:nth-child(4n) { + border-right: 0; + } + + .loader-container { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, .75); + display: flex; + align-items: center; + justify-content: center; + z-index: 80100; + color: white; + } + + .loading-ng-icon { + display:inline-block; + position:relative; + font-size:1em; + width:1.375em; + height:2.375em; + margin:0em 1.5em -0.3em; + transform:rotate(-48deg); + animation:loadRotate 1.5s infinite cubic-bezier(0.45, 0.05, 0.55, 0.95); + } + + .loading-ng-icon::before, + .loading-ng-icon::after { + content:""; + display:block; + background:currentColor; + border-radius:50%; + position:absolute; + left:50%; + } + + .loading-ng-icon::before { + width:1em; + height:1em; + margin-left:-0.5em; + bottom:1.375em; + animation:loadBounceTopSquash 0.75s alternate infinite ease, loadBounceTopFlow 0.75s alternate infinite ease; + } + + .loading-ng-icon::after { + width:1.375em; + height:1.375em; + margin-left:-0.6875em; + bottom:0; + animation:loadBounceBottomSquash 0.75s alternate infinite ease, loadBounceBottomFlow 0.75s alternate infinite ease; + } + + @keyframes loadBounceTopSquash { + 0% { + height:0.375em; + border-radius:3.75em 3.75em 1.25em 1.25em; + transform:scaleX(2); + } + 15% { + height:1em; + border-radius:50%; + transform:scaleX(1); + } + 100% { + height:1em; + border-radius:50%; + transform:scaleX(1); + } + } + + @keyframes loadBounceBottomSquash { + 0% { + height:1em; + border-radius:1.25em 1.25em 3.75em 3.75em; + transform:scaleX(1.5); + } + 15% { + height:1.375em; + border-radius:50%; + transform:scaleX(1); + } + 100% { + height:1.375em; + border-radius:50%; + transform:scaleX(1); + } + } + + @keyframes loadBounceTopFlow { + 0% { + bottom:1.125em; + } + 50% { + bottom:2.25em; + animation-timing-function:cubic-bezier(0.55, 0.06, 0.68, 0.19); + } + 90% { + bottom:1.75em; + } + 100% { + bottom:1.75em; + } + } + + @keyframes loadBounceBottomFlow { + 0% { + bottom:0.1875em; + } + 50% { + bottom:-0.9375em; + animation-timing-function:cubic-bezier(0.55, 0.06, 0.68, 0.19); + } + 90% { + bottom:0em; + } + 100% { + bottom:0em; + } + } + + @keyframes loadRotate { + 0% { + transform:rotate(-228deg); + } + 49% { + transform:rotate(-48deg); + } + 51% { + transform:rotate(-48deg); + } + 92% { + transform:rotate(132deg); + } + 100% { + transform:rotate(132deg); + } + } +` \ No newline at end of file diff --git a/components/block/element.js b/components/block/element.js index 6b16865..9488828 100644 --- a/components/block/element.js +++ b/components/block/element.js @@ -2,184 +2,240 @@ import {LitElement, html} from 'lit'; import {classMap} from 'lit/directives/class-map.js'; import style from './style.js'; +import { ArrowDownIcon, ArrowUpIcon, BreadcrumbArrowIcon, PlusIcon, RefreshIcon } from '../icons.js'; + export default class Block extends LitElement { static styles = [style]; static properties = { loading: {type: Boolean, state: true}, blockId: {type: String}, - templateName: {type: String}, - isSelected: {type: Boolean, state: true}, + viewTypeName: {type: String}, + isSelected: {type: Boolean}, isHovered: {type: Boolean, state: true}, - isParent: {type: Boolean, state: true}, + isContainer: {type: Boolean, state: true}, + isEmpty: {type: Boolean}, + isContainerEmpty: {type: Boolean, default: false}, + isContainerSelected: {type: Boolean, default: false}, + isChildSelected: {type: Boolean, default: false}, + isFullViewBlock: {type: Boolean, default: false}, }; constructor() { super(); - this.loading = false; + this.loading = false; } - + connectedCallback() { + if (typeof window.parent.Core === 'undefined') { + return; + } + super.connectedCallback(); + + this.isContainer = this.model.attributes.is_container; + this.isFullViewBlock = this.model.attributes.definition_identifier === 'full_view' + this.model.on('change', this.refresh.bind(this)); + this.model.on('sidebar:destroyed', () => { + this.isSelected = false; + this.unmarkPlaceholders(); + this.setIsContainerSelected(false) + this.setIsChildSelected(false) + }); + + const bc = new BroadcastChannel('publish_content'); + bc.onmessage = (event) => { + this.handleMessageRecieved(event.data) + }; + } - this.isParent = this.model.attributes.is_container; + handleMessageRecieved(data) { + const { contentId, blockId, locale } = data; - this.model.on('all', console.debug) + if(blockId !== this.blockId) return; - this.model.on('change', this.refresh.bind(this)); - this.model.on('sidebar:destroyed', () => this.isSelected = false) + this.model.trigger('edit'); } - get layout() { - return this.core.g.layout; - } - get core(){ + // GETTERS - start + get core() { return window.parent.Core; } + get layout() { + return this.core.g.layout; + } + get model() { return (this.cached_model ||= this.layout.blocks.findWhere({ id: this.blockId, })); } - get parent() { + get parentModel() { + const parentId = this.model.attributes.parent_block_id; + + return this.layout.blocks.models.find(model => model.id === parentId) + } + + get parentElement() { const parentId = this.model.attributes.parent_block_id; + this.cached_parent ||= parentId && document.querySelector(`ngl-block[blockId="${parentId}"]`); return this.cached_parent; } - get isInLinkedZone() { - return this.model.zone().is_linked(); + get parentName() { + if (!this.parentElement) return; + + return this.parentElement.getAttribute('viewTypeName') } - deselectIcon() { - return html` - - - - - - ` + get isInLinkedZone() { + return this.model.zone()?.is_linked(); } - refreshIcon() { - return html` - - - - + get slot() { + return this.shadowRoot.querySelector('slot'); + } - ` + get slottedChildren() { + return this.slot.assignedElements({flatten: true}); } - renderMenu() { - if (this.isInLinkedZone) return this.renderLinkedBlockMenu(); + get placeholders() { + return this.slottedChildren[0]?.querySelectorAll('ngl-placeholder') + } - return this.renderOuterBlockMenu(); + get childBlocks() { + return this.slottedChildren[0]?.querySelectorAll('ngl-block') } + // GETTERS - end - renderLinkedBlockMenu() { - return html` - `; + + async fetch() { + this.loading = true; + const resp = await fetch(window.location.href); + this.loading = false; + return resp.text(); } - renderOuterBlockMenu() { - const label = html` - ${this.isSelected ? 'Deselect' : 'Select'} - ` + async refresh() { + let html = await this.fetch(); - return html` - - - `; + const template = document.createElement('template'); + template.innerHTML = html; + + const currentBlockHtml = template.content.querySelector( + `ngl-block[blockId="${this.blockId}"]` + ); + this.innerHTML = currentBlockHtml.innerHTML; + + + this.setNewAttributes(currentBlockHtml); + this.isSelected = true; + + this.dispatchEvent( + new Event('ngl:preview:block:refresh', {bubbles: true, composed: true}) + ); + this.markPlaceholders(); + this.setIsContainerSelected(true) + this.setIsChildSelected(true) + + if(this.parentElement) [ + this.parentElement.setIsEmptyState() + ] } - renderBreadcrumbs() { - if(this.isInLinkedZone) return; + setNewAttributes(newElement) { + const oldAttributess = this.getAttributesObject(this); + const newAttributess = this.getAttributesObject(newElement); - return html` - - ` + Object.entries(oldAttributess).map(attribute => !newAttributess[attribute[0]] && this.removeAttribute(attribute[0])) + Object.entries(newAttributess).map(attribute => this[attribute[1]] = attribute[1]) } - renderInnerBlokcBreadcrumbs() { - return html` - - ${this.renderOuterBlokcBreadcrumbs()} - - ` + getAttributesObject(el) { + const attrs = el.getAttributeNames().reduce((acc, name) => { + return {...acc, [name]: el.getAttribute(name)}; + }, {}); + + return attrs } - renderOuterBlokcBreadcrumbs() { - return html` - - ` + setIsEmptyState() { + if(!this.isContainer) return; + + const areAllPlaceholdersEmpty = [...this.placeholders].every(el => el.isEmpty) + const areAllChildBlocksEmpty = [...this.childBlocks].every(el => el.isEmpty) + + this.isEmpty = areAllPlaceholdersEmpty || areAllChildBlocksEmpty; + this.isChildSelected = [...this.childBlocks].some(el => el.isSelected) + + this.setChildBlocksIsEmptyState(); + + if(this.isSelected) this.markPlaceholders() } - breadcrumbArrowIcon() { - return html` - - - - - ` + setChildBlocksIsEmptyState() { + if(!this.isEmpty) return; + + [...this.placeholders, ...this.childBlocks].map(el => el.isContainerEmpty = true) } - renderAddButton() { - if(this.isInLinkedZone) return; + handleAddButtonClick() { + const blockPicker = document.querySelector('ngl-block-picker'); - return html` - - ` + blockPicker.blockId = this.blockId; + blockPicker.isActive = true; } toggleSelect() { - if(this.isSelected) { + if (this.isSelected) { this.isSelected = false; - this.core.trigger('editing:unmark', { block: this.model }) - + this.core.trigger('editing:unmark', {block: this.model}); + this.unmarkPlaceholders(); + this.setIsContainerSelected(false) + this.setIsChildSelected(false) } else { this.select(); + this.markPlaceholders(); + this.setIsContainerSelected(true) + this.setIsChildSelected(true) } } select() { - if(this.isInLinkedZone) return; + if (this.isInLinkedZone) return; + + console.debug(this.model) this.model.trigger('edit'); this.isSelected = true; } parentSelect() { - this.parent.select(); + this.parentElement.toggleSelect(); + } + + setIsChildSelected(selected) { + if(this.isContainer) return; + + const parentBlock = document.querySelector(`ngl-block[blockId="${this.blockId}"]`)?.parentElement?.closest('ngl-block') + if(!parentBlock) return; + + parentBlock.isChildSelected = selected; + } + + setIsContainerSelected(selected) { + if(!this.isContainer || !this.childBlocks) return; + + this.childBlocks.forEach(el => el.isContainerSelected = selected) } getClosestBlockId(el) { @@ -190,56 +246,225 @@ export default class Block extends LitElement { } selectOnBlockClick(e) { - if( this.blockId !== this.getClosestBlockId(e.target) ) return; + if (this.blockId !== this.getClosestBlockId(e.target)) return; this.toggleSelect(); } + markPlaceholders() { + this.toggleMarkPlaceholders(true) + } + + unmarkPlaceholders() { + this.toggleMarkPlaceholders(false) + } + + toggleMarkPlaceholders(mark) { + if(!this.placeholders) return; + + this.placeholders.forEach(el => el.isMarked = mark) + } + + // EVENTS - start handleMouseover(e) { - if(this.isInLinkedZone) return; + if (this.isInLinkedZone) return; this.isHovered = this.blockId === this.getClosestBlockId(e.target); } - handleMouseout(e) { + handleMouseout() { this.isHovered = false; } - async fetch() { - this.loading = true; - const resp = await fetch(window.location.href); - this.loading = false; - return resp.text(); + handleMoveBlock(direction) { + const directionNumber = direction === 'up' ? -1 : 1; + + + let blockIds = [...this.model.zone().attributes.block_ids]; + const fromIndex = blockIds.findIndex(id => id === this.blockId) + const toIndex = fromIndex - 1; + + blockIds.splice(fromIndex, 1) + blockIds.splice(toIndex, 0, this.blockId) + + if(this.parentElement) { + this.model.set({ + parent_position: this.model.attributes.parent_position + directionNumber, + zone_identifier: this.model.attributes.zone_identifier, + parent_placeholder: this.model.attributes.placeholder_id, + parent_block_id: this.model.attributes.parent_block_id + }); + this.model.move_to_container(blockIds) + .then(() => { + const iframe = window.parent.document.querySelector('.preview-iframe-sizer iframe') + iframe?.contentWindow.location.reload() + }) + } else { + this.model.set({ + parent_position: this.model.attributes.parent_position + directionNumber, + zone_identifier: this.model.attributes.zone_identifier + }); + this.model.move(blockIds) + .then(() => { + this.handleRefreshView() + }) + } + } - async refresh() { - let html = await this.fetch(); + async handleRefreshView() { + + return await fetch(window.location.href) + .then(resp => { + return resp.text() + }) + .then(html => { + const template = document.createElement('template'); + template.innerHTML = html; + + const futurePage = template.content.querySelector( + '#page' + ); + const iframe = window.parent.document.querySelector('.preview-iframe-sizer iframe') + const currentPage = iframe.contentDocument.querySelector( + '#page' + ); + currentPage.innerHTML = futurePage.innerHTML + + const blockElement = iframe.contentDocument.querySelector( + `ngl-block[blockId="${this.blockId}"]` + ) + blockElement.isSelected = true; + this.model.trigger('edit'); + }) + .catch(err => console.error(err)) + .finally(() => { + this.isLoading = false + this.placeholderIdentifier = "" + }) + } - const template = document.createElement('template'); - template.innerHTML = html; - const currentBlockHtml = template.content.querySelector( - `ngl-block[blockId="${this.blockId}"]` - ); + handleMoveBlockUp() { + const parentPosition = this.model.attributes.parent_position + if(parentPosition === 0) this.handleMoveBlockToZoneAbove() + + this.handleMoveBlock('up'); + } - this.innerHTML = currentBlockHtml.innerHTML; + handleMoveBlockDown() { + const parentPosition = this.model.attributes.parent_position + const numberOfBlocks = this.model.zone().attributes.block_ids.length - 1 + if(parentPosition === numberOfBlocks) this.handleMoveBlockToZoneBelow() + + this.handleMoveBlock('down'); + } - this.dispatchEvent( - new Event('ngl:refresh', {bubbles: true, composed: true}) - ); + handleMoveBlockToZoneAbove() { + // @todo: implement move block to zone above + } + + handleMoveBlockToZoneBelow() { + // @todo: implement move block to zone below } + // EVENTS - end - parentRefresh() { - this.parent.refresh(); + // RENDERS - start + renderAddButton() { + if (this.isInLinkedZone) return; + + return html` + + `; + } + + renderMoveButtons() { + return html` +
+ + +
+ ` + } + + renderMenu() { + if (this.isInLinkedZone) return; + + return html` +
+ ${this.renderOuterBlockMenu()} +
` + } + + renderOuterBlockMenu() { + return html` + + `; + } + + renderBreadcrumbs() { + if (this.isInLinkedZone) return; + + return html` + + `; + } + + renderInnerBlockBreadcrumbs() { + return html` + + ${this.renderOuterBlockBreadcrumbs()} + + `; + } + + renderOuterBlockBreadcrumbs() { + return html` + + `; } + // RENDERS - end render() { - const classes = { loading: this.loading, is_selected: this.isSelected, is_child: Boolean(this.parent), is_hovered: this.isHovered, is_parent: this.isParent }; + const classes = { + loading: this.loading, + is_selected: this.isSelected, + is_hovered: this.isHovered, + is_container: this.isContainer, + is_empty: this.isEmpty, + is_full_view_block: this.isFullViewBlock, + is_container_empty: this.isContainerEmpty, + is_container_selected: this.isContainerSelected, + is_child_selected: this.isChildSelected, + is_child_block: this.parentElement, + }; return html` -
-
${this.renderMenu()}
+
${this.renderBreadcrumbs()} - + ${this.renderMenu()} + ${this.renderAddButton()}
`; diff --git a/components/block/spec.js b/components/block/spec.js index 84d0131..535350f 100644 --- a/components/block/spec.js +++ b/components/block/spec.js @@ -47,17 +47,33 @@ describe('ngl-block', () => { }, }); - const element = await fixture(html``); + const element = await fixture( + html`` + ); assert.shadowDom.equal( element, `
+
- - +
+
` ); @@ -75,15 +91,16 @@ describe('ngl-block', () => { }, }); - const element = await fixture(html``); + const element = await fixture( + html`` + ); assert.shadowDom.equal( element, `
-
- -
` @@ -102,19 +119,37 @@ describe('ngl-block', () => { }, }); - const element = await fixture(html``); + const element = await fixture( + html` + + + ` + ); assert.shadowDom.equal( - element, + element.querySelector('ngl-block'), ` -
+
+
- - - - +
+
` ); @@ -132,12 +167,18 @@ describe('ngl-block', () => { }, }); - const element = await fixture(html``); + const element = await fixture( + html`` + ); // Here we stub method fetch to return our test HTML sinon .stub(element, 'fetch') - .resolves('Hello world'); + .resolves( + 'Hello world' + ); await element.refresh(); diff --git a/components/block/style.js b/components/block/style.js index 3057312..c191b3e 100644 --- a/components/block/style.js +++ b/components/block/style.js @@ -4,90 +4,107 @@ export default css` :host, :after, :before { - --ngl-block-base-z-index: 80000; // was this randomly chosen? - --ngl-block-priamry-color: #9747FF; + --ngl-block-priamry-color: #9747ff; --ngl-block-outline-color: #333; --ngl-block-outline-color-hover: #990099; - --ngl-block-outline-color-selected: #9747FF; - --ngl-block-outline-width: .125rem; + --ngl-block-outline-color-selected: #9747ff; + --ngl-block-outline-width: 0.125rem; --ngl-block-background-color-selected: rgba(151, 71, 255, 0.1); - --ngl-block-button-background-color: #9747FF; - --ngl-block-button-background-color-hover: #7625DF; + --ngl-block-button-background-color: #9747ff; + --ngl-block-button-background-color-hover: #7625df; } :host { - display: contents + display: contents; } main { position: relative; - /* z-index: 1; */ } - /* main main { - z-index: 3; - } */ - main.loading { opacity: 0.5; } - main ::slotted(.ngl-block):before { + main ::slotted(.ngl-slotted-block):before, + main ::slotted(.ngl-slotted-block):after { content: ''; position: absolute; inset: 0; - z-index: 0; + z-index: calc(var(--ngl-block-base-z-index, 80000)); + cursor: pointer; } - main ::slotted(.ngl-block):after { - content: ''; - inset: 0; - position: absolute; - pointer-events: none; - z-index: calc(var(--ngl-block-base-z-index, 80000) + 1); + main.is_child_block ::slotted(.ngl-slotted-block):after { + z-index: calc(var(--ngl-block-base-z-index, 80000) + 5); } - main.is_selected ::slotted(.ngl-block):before { + main ::slotted(.ngl-slotted-block):before { pointer-events: none; - z-index: 2; } + main.is_selected ::slotted(.ngl-slotted-block):before, + main.is_selected ::slotted(.ngl-slotted-block):after { + pointer-events: none; + } - main:not(.is_selected).is_hovered ::slotted(.ngl-block):before { + main:not(.is_selected).is_hovered ::slotted(.ngl-slotted-block):before { background-color: var(--ngl-block-background-color-selected); - z-index: 80000; + z-index: calc(var(--ngl-block-base-z-index, 80000)); + } + + + main:not(.is_selected):not(.is_child_selected).is_hovered ::slotted(.ngl-slotted-block):before { + pointer-events: auto; } - main:not(.is_selected).is_parent.is_hovered ::slotted(.ngl-block):before { - z-index: 0; + main.is_child_selected ::slotted(.ngl-slotted-block):after { + pointer-events: none; } - main.is_selected ::slotted(.ngl-block):after { + main.is_selected ::slotted(.ngl-slotted-block):after { border: solid var(--ngl-block-outline-width) var(--ngl-block-outline-color-selected); } + main:not(.is_container).is_selected.is_empty ::slotted(.ngl-slotted-block):after { + z-index: calc(var(--ngl-block-base-z-index, 80000) + 10); + pointer-events: auto; + } - main:not(.is_selected).is_hovered ::slotted(.ngl-block):after { + main:not(.is_selected).is_hovered ::slotted(.ngl-slotted-block):after { border: solid 1px var(--ngl-block-outline-color-hover); + } + main:not(.is_selected):not(.is_container_empty):not(.is_child_selected):not(.is_container_selected).is_empty ::slotted(.ngl-slotted-block):before { + background-image: linear-gradient(135deg, #cfcfcf 2.94%, rgba(151, 71, 255, 0) 2.94%, rgba(151, 71, 255, 0) 50%, #cfcfcf 50%, #cfcfcf 52.94%, rgba(151, 71, 255, 0) 52.94%, rgba(151, 71, 255, 0) 100%); + background-size: 24.04px 24.04px; + z-index: calc(var(--ngl-block-base-z-index, 80000) + 4); + } + + main.is_empty, + main.is_empty ::slotted(.ngl-slotted-block), + main.is_full_view_block, + main.is_full_view_block ::slotted(.ngl-slotted-block) { + min-height: 100px; } .edit-menu { - z-index: calc(var(--ngl-block-base-z-index) + 2); + z-index: 80010; display: none; visibility: hidden; opacity: 0; position: absolute; right: 0; bottom: 100%; - gap: .25rem; + gap: 0.25rem; + z-index: calc(var(--ngl-block-base-z-index, 80000) + 7); } - main.is_selected .edit-menu, - main.is_hovered .edit-menu { + + main.is_selected .edit-menu { display: inline-flex; opacity: 1; visibility: visible; @@ -98,23 +115,23 @@ export default css` background-color: var(--_btn-background-color); border: none; margin: 0; - padding: .125rem .5rem; - font-size: .75rem; + padding: 0.125rem 0.5rem; + font-size: 0.75rem; font-weight: 500; color: #ffffff; - gap: .25rem; + gap: 0.25rem; display: flex; align-items: center; justify-content: center; text-align: center; - border-radius: .125rem .125rem 0 0; + border-radius: 0.125rem 0.125rem 0 0; cursor: pointer; position: relative; } button.refresh-btn { - padding-left: .125rem; - padding-right: .125rem; + padding-left: 0.125rem; + padding-right: 0.125rem; } button:hover { @@ -127,7 +144,7 @@ export default css` display: none; visibility: hidden; opacity: 0; - z-index: calc(var(--ngl-block-base-z-index) + 2); + z-index: calc(var(--ngl-block-base-z-index, 80000) + 10); } main.is_selected .breadcrumbs { @@ -137,38 +154,42 @@ export default css` } main button.breadcrumb-btn { - --_btn-background-color: var(--ngl-block-button-background-color); - padding: .25rem .5rem; - gap: .25rem; + --_btn-background-color: var(--ngl-block-button-background-color); + padding: 0.25rem 0.5rem; + gap: 0.25rem; color: #fff; - border-radius: .125rem .125rem 0 0; + border-radius: 0.125rem 0.125rem 0 0; + text-transform: capitalize; } + main button.breadcrumb-btn:not(:last-child):hover { --_btn-background-color: var(--ngl-block-button-background-color-hover); } main button.breadcrumb-btn:not(:first-child) { - padding-right: .75rem; + padding-right: 0.75rem; padding-left: 1.5rem; } .breadcrumb-btn > svg { position: absolute; left: calc(100% - 5px); - z-index: calc(var(--ngl-block-base-z-index) + 3); + z-index: calc(var(--ngl-block-base-z-index, 80000) + 3); + height: 21px; + width: 18px; } .add-btn { position: absolute; bottom: 0; left: 50%; - transform: translate(-50%, calc(50% - 2px)); - padding: .125rem .5rem .125rem .25rem; + transform: translate(-50%, 100%); + padding: 0.125rem 0.5rem 0.125rem 0.25rem; display: none; opacity: 0; - z-index: calc(var(--ngl-block-base-z-index) + 3); visibility: hidden; - border-radius: .125rem; + border-radius: 0 0 .125rem .125rem; + z-index: calc(var(--ngl-block-base-z-index, 80000) + 10); } main.is_selected .add-btn { @@ -176,4 +197,21 @@ export default css` opacity: 1; visibility: visible; } + + .move-btns { + display: none; + } + + main.is_selected .move-btns { + display: flex; + gap: .125rem; + position: absolute; + top: .5rem; + right: .5rem; + z-index: calc(var(--ngl-block-base-z-index, 80000) + 11); + } + + .move-btn { + padding: .25rem; + } `; diff --git a/components/icons.js b/components/icons.js new file mode 100644 index 0000000..9ff92ae --- /dev/null +++ b/components/icons.js @@ -0,0 +1,99 @@ +import {html} from 'lit'; + +export const ArrowUpIcon = () => { + return html` + + + + + + ` +} + +export const ArrowDownIcon = () => { + return html` + + + + + + ` +} + +export const RefreshIcon = () => { + return html` + + + + + `; +} + +export const BreadcrumbArrowIcon = () => { + return html` + + + + + `; +} + +export const PlusIcon = () => { + return html` + + + + + ` +} + +export const CloseIcon = () => { + return html` + + + + ` +} \ No newline at end of file diff --git a/components/placeholder/element.js b/components/placeholder/element.js new file mode 100644 index 0000000..c934185 --- /dev/null +++ b/components/placeholder/element.js @@ -0,0 +1,80 @@ +import {LitElement, html} from 'lit'; +import {classMap} from 'lit/directives/class-map.js'; +import style from './style.js'; + +export default class Placeholder extends LitElement { + static styles = [style]; + + static properties = { + isEmpty: {type: Boolean}, + isMarked: {type: Boolean, state: true}, + identifier: {type: String}, + isContainerEmpty: {type: Boolean, default: false}, + }; + + constructor() { + super(); + } + + get slottedChildren() { + const slot = this.shadowRoot.querySelector('slot'); + return slot.assignedElements({flatten: true}); + } + + connectedCallback() { + super.connectedCallback(); + } + + renderAddButton() { + + return html` + + `; + } + + handleAddButtonClick(e) { + const blockPicker = document.querySelector('ngl-block-picker'); + const parentBlock = this.slottedChildren[0].closest('ngl-block'); + + blockPicker.blockId = parentBlock.getAttribute('blockid') + blockPicker.isActive = true + blockPicker.placeholderIdentifier = this.identifier; + } + + render() { + const classes = { + is_empty: this.isEmpty, + is_marked: this.isMarked, + is_container_empty: this.isContainerEmpty, + }; + + return html` +
+ ${this.renderAddButton()} + +
+ + `; + } +} + +customElements.get('ngl-placeholder') || customElements.define('ngl-placeholder', Placeholder); \ No newline at end of file diff --git a/components/placeholder/spec.js b/components/placeholder/spec.js new file mode 100644 index 0000000..e69de29 diff --git a/components/placeholder/style.js b/components/placeholder/style.js new file mode 100644 index 0000000..f3fe3fa --- /dev/null +++ b/components/placeholder/style.js @@ -0,0 +1,81 @@ +import {css} from 'lit'; + +export default css` + :host, + :after, + :before { + } + + :host { + display: contents; + } + + main { + min-height: 102px; + position: relative; + } + + main:after { + position: absolute; + inset: 0; + pointer-events: none; + } + + main.is_marked:after { + content: ""; + border: dashed 1px var(--ngl-block-outline-color-hover); + } + + main.is_empty.is_marked:after { + content: ""; + border: dashed 1px var(--ngl-block-outline-color-hover); + min-height: 100px; + } + + main:not(.is_marked):not(.is_container_empty).is_empty { + background-image: linear-gradient(135deg, #cfcfcf 2.94%, rgba(151, 71, 255, 0) 2.94%, rgba(151, 71, 255, 0) 50%, #cfcfcf 50%, #cfcfcf 52.94%, rgba(151, 71, 255, 0) 52.94%, rgba(151, 71, 255, 0) 100%); + background-size: 24.04px 24.04px; + } + + button { + --_btn-background-color: var(--ngl-block-button-background-color); + background-color: var(--_btn-background-color); + border: none; + margin: 0; + padding: 0.125rem 0.5rem; + font-size: 0.75rem; + font-weight: 500; + color: #ffffff; + gap: 0.25rem; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + border-radius: 0.125rem 0.125rem 0 0; + cursor: pointer; + position: relative; + } + + button:hover { + --_btn-background-color: var(--ngl-block-button-background-color-hover); + } + + .add-btn { + position: absolute; + top: 0; + left: 50%; + transform: translate(-50%, 0); + padding: 0.125rem 0.5rem 0.125rem 0.25rem; + display: none; + opacity: 0; + z-index: calc(var(--ngl-block-base-z-index) + 3); + visibility: hidden; + border-radius: 0 0 0.125rem 0.125rem; + } + + main.is_marked.is_empty .add-btn { + display: inline-flex; + opacity: 1; + visibility: visible; + } +`; diff --git a/custom-elements.json b/custom-elements.json new file mode 100644 index 0000000..89b1301 --- /dev/null +++ b/custom-elements.json @@ -0,0 +1,835 @@ +{ + "schemaVersion": "1.0.0", + "readme": "", + "modules": [ + { + "kind": "javascript-module", + "path": "components.js", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "Block", + "declaration": { + "name": "default", + "module": "./components/block/element.js" + } + }, + { + "kind": "js", + "name": "Placeholder", + "declaration": { + "name": "default", + "module": "./components/placeholder/element.js" + } + }, + { + "kind": "js", + "name": "BlockPicker", + "declaration": { + "name": "default", + "module": "./components/block-picker/element.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "dist/dist.js", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "ot", + "members": [ + { + "kind": "field", + "name": "layout" + }, + { + "kind": "field", + "name": "core" + }, + { + "kind": "field", + "name": "model" + }, + { + "kind": "field", + "name": "parent" + }, + { + "kind": "field", + "name": "isInLinkedZone" + }, + { + "kind": "method", + "name": "deselectIcon" + }, + { + "kind": "method", + "name": "refreshIcon" + }, + { + "kind": "method", + "name": "renderMenu" + }, + { + "kind": "method", + "name": "renderLinkedBlockMenu" + }, + { + "kind": "method", + "name": "renderOuterBlockMenu" + }, + { + "kind": "method", + "name": "renderBreadcrumbs" + }, + { + "kind": "method", + "name": "renderInnerBlokcBreadcrumbs" + }, + { + "kind": "method", + "name": "renderOuterBlokcBreadcrumbs" + }, + { + "kind": "method", + "name": "breadcrumbArrowIcon" + }, + { + "kind": "method", + "name": "renderAddButton" + }, + { + "kind": "method", + "name": "toggleSelect" + }, + { + "kind": "method", + "name": "select" + }, + { + "kind": "method", + "name": "parentSelect" + }, + { + "kind": "method", + "name": "getClosestBlockId", + "parameters": [ + { + "name": "t" + } + ] + }, + { + "kind": "method", + "name": "selectOnBlockClick", + "parameters": [ + { + "name": "t" + } + ] + }, + { + "kind": "method", + "name": "handleMouseover", + "parameters": [ + { + "name": "t" + } + ] + }, + { + "kind": "method", + "name": "handleMouseout", + "parameters": [ + { + "name": "t" + } + ] + }, + { + "kind": "method", + "name": "fetch" + }, + { + "kind": "method", + "name": "refresh" + }, + { + "kind": "method", + "name": "parentRefresh" + }, + { + "kind": "field", + "name": "loading", + "type": { + "text": "boolean" + }, + "default": "!1", + "privacy": "public", + "attribute": "loading" + }, + { + "kind": "field", + "name": "blockId", + "privacy": "public", + "attribute": "blockId" + }, + { + "kind": "field", + "name": "templateName", + "privacy": "public", + "attribute": "templateName" + }, + { + "kind": "field", + "name": "isSelected", + "privacy": "public", + "attribute": "isSelected" + }, + { + "kind": "field", + "name": "isHovered", + "privacy": "public", + "attribute": "isHovered" + }, + { + "kind": "field", + "name": "isParent", + "privacy": "public", + "attribute": "isParent" + }, + { + "kind": "method", + "name": "createRenderRoot", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "renderOptions", + "type": { + "text": "object" + }, + "default": "{host:this}", + "inheritedFrom": { + "name": "Y", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "_$Do", + "default": "void 0", + "inheritedFrom": { + "name": "Y", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "addInitializer", + "static": true, + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "createProperty", + "static": true, + "parameters": [ + { + "name": "t" + }, + { + "name": "e", + "default": "v" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "getPropertyDescriptor", + "static": true, + "parameters": [ + { + "name": "t" + }, + { + "name": "e" + }, + { + "name": "i" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "getPropertyOptions", + "static": true, + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "finalize", + "static": true, + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "finalizeStyles", + "static": true, + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$Ep", + "static": true, + "parameters": [ + { + "name": "t" + }, + { + "name": "e" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "u", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "addController", + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "removeController", + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$Eg", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "enableUpdating", + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$EO", + "parameters": [ + { + "name": "t" + }, + { + "name": "e" + }, + { + "name": "i", + "default": "v" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$AK", + "parameters": [ + { + "name": "t" + }, + { + "name": "e" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$Ej", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "scheduleUpdate", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$AE", + "parameters": [ + { + "name": "t" + } + ], + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "_$Ek", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "updateComplete", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "method", + "name": "getUpdateComplete", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "_$Ei", + "default": "new Map", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "isUpdatePending", + "type": { + "text": "boolean" + }, + "default": "!1", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "hasUpdated", + "type": { + "text": "boolean" + }, + "default": "!1", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + }, + { + "kind": "field", + "name": "_$El", + "type": { + "text": "null" + }, + "default": "null", + "inheritedFrom": { + "name": "b", + "module": "dist/dist.js" + } + } + ], + "events": [ + { + "name": "ngl:refresh", + "type": { + "text": "Event" + } + } + ], + "attributes": [ + { + "name": "loading", + "fieldName": "loading" + }, + { + "name": "blockId", + "fieldName": "blockId" + }, + { + "name": "templateName", + "fieldName": "templateName" + }, + { + "name": "isSelected", + "fieldName": "isSelected" + }, + { + "name": "isHovered", + "fieldName": "isHovered" + }, + { + "name": "isParent", + "fieldName": "isParent" + } + ], + "superclass": { + "name": "Y", + "module": "dist/dist.js" + }, + "tagName": "ngl-block", + "customElement": true + } + ], + "exports": [ + { + "kind": "custom-element-definition", + "name": "ngl-block", + "declaration": { + "name": "ot", + "module": "dist/dist.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "components/block/element.js", + "declarations": [ + { + "kind": "class", + "description": "", + "name": "Block", + "members": [ + { + "kind": "field", + "name": "layout" + }, + { + "kind": "field", + "name": "core" + }, + { + "kind": "field", + "name": "model" + }, + { + "kind": "field", + "name": "parent" + }, + { + "kind": "field", + "name": "isInLinkedZone" + }, + { + "kind": "method", + "name": "deselectIcon" + }, + { + "kind": "method", + "name": "refreshIcon" + }, + { + "kind": "method", + "name": "renderMenu" + }, + { + "kind": "method", + "name": "renderLinkedBlockMenu" + }, + { + "kind": "method", + "name": "renderOuterBlockMenu" + }, + { + "kind": "method", + "name": "renderBreadcrumbs" + }, + { + "kind": "method", + "name": "renderInnerBlokcBreadcrumbs" + }, + { + "kind": "method", + "name": "renderOuterBlokcBreadcrumbs" + }, + { + "kind": "method", + "name": "breadcrumbArrowIcon" + }, + { + "kind": "method", + "name": "renderAddButton" + }, + { + "kind": "method", + "name": "toggleSelect" + }, + { + "kind": "method", + "name": "select" + }, + { + "kind": "method", + "name": "parentSelect" + }, + { + "kind": "method", + "name": "getClosestBlockId", + "parameters": [ + { + "name": "el" + } + ] + }, + { + "kind": "method", + "name": "selectOnBlockClick", + "parameters": [ + { + "name": "e" + } + ] + }, + { + "kind": "method", + "name": "handleMouseover", + "parameters": [ + { + "name": "e" + } + ] + }, + { + "kind": "method", + "name": "handleMouseout", + "parameters": [ + { + "name": "e" + } + ] + }, + { + "kind": "method", + "name": "fetch" + }, + { + "kind": "method", + "name": "refresh" + }, + { + "kind": "method", + "name": "parentRefresh" + }, + { + "kind": "field", + "name": "loading", + "type": { + "text": "boolean" + }, + "default": "false", + "privacy": "public", + "attribute": "loading" + }, + { + "kind": "field", + "name": "blockId", + "privacy": "public", + "attribute": "blockId" + }, + { + "kind": "field", + "name": "templateName", + "privacy": "public", + "attribute": "templateName" + }, + { + "kind": "field", + "name": "isSelected", + "privacy": "public", + "attribute": "isSelected" + }, + { + "kind": "field", + "name": "isHovered", + "privacy": "public", + "attribute": "isHovered" + }, + { + "kind": "field", + "name": "isParent", + "privacy": "public", + "attribute": "isParent" + } + ], + "events": [ + { + "name": "ngl:refresh", + "type": { + "text": "Event" + } + } + ], + "attributes": [ + { + "name": "loading", + "fieldName": "loading" + }, + { + "name": "blockId", + "fieldName": "blockId" + }, + { + "name": "templateName", + "fieldName": "templateName" + }, + { + "name": "isSelected", + "fieldName": "isSelected" + }, + { + "name": "isHovered", + "fieldName": "isHovered" + }, + { + "name": "isParent", + "fieldName": "isParent" + } + ], + "superclass": { + "name": "LitElement", + "package": "lit" + }, + "tagName": "ngl-block", + "customElement": true + } + ], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "name": "Block", + "module": "components/block/element.js" + } + }, + { + "kind": "custom-element-definition", + "name": "ngl-block", + "declaration": { + "name": "Block", + "module": "components/block/element.js" + } + } + ] + }, + { + "kind": "javascript-module", + "path": "components/block/spec.js", + "declarations": [], + "exports": [] + }, + { + "kind": "javascript-module", + "path": "components/block/style.js", + "declarations": [], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "module": "components/block/style.js" + } + } + ] + } + ] +} diff --git a/package.json b/package.json index f32eb85..8da5e48 100644 --- a/package.json +++ b/package.json @@ -74,5 +74,6 @@ "test:prod": "MODE=prod wtr", "test:prod:watch": "MODE=prod wtr --watch", "checksize": "rollup -c ; cat components.bundled.js | gzip -9 | wc -c ; rm components.bundled.js" - } + }, + "customElements": "custom-elements.json" }