diff --git a/infra/nix/sources.json b/infra/nix/sources.json index 785afb511..4ca210e80 100644 --- a/infra/nix/sources.json +++ b/infra/nix/sources.json @@ -1,97 +1,97 @@ { - "deckdeckgo-starter": { - "branch": "studio", - "description": "The Progressive Web App alternative for simple presentations", - "homepage": "https://deckdeckgo.com", - "owner": "deckgo", - "repo": "deckdeckgo-starter", - "rev": "c49bb065eb3896efc3fb57d3a032aa70c8d99d0d", - "sha256": "0nxwvpy8szdkia3c5jxscq02l5iybpsldly23n7h58xffj912xcg", - "type": "tarball", - "url": "https://github.com/deckgo/deckdeckgo-starter/archive/c49bb065eb3896efc3fb57d3a032aa70c8d99d0d.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "elasticmq": { - "sha256": "1cp2pmkc6gx7gr6109jlcphlky5rr6s1wj528r6hyhzdc01sjhhz", - "type": "file", - "url": "https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.14.6.jar", - "url_template": "https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.14.6.jar" - }, - "hs-jose": { - "branch": "master", - "description": "Haskell JOSE and JWT library", - "homepage": "http://hackage.haskell.org/package/jose", - "owner": "frasertweedale", - "repo": "hs-jose", - "rev": "71274bf64c0600c1d877152173a08a5bff7adf4d", - "sha256": "0ah189vika1s0jk8f17mn77gilkw24vbs6xlggxw1qj926i6c4pk", - "type": "tarball", - "url": "https://github.com/frasertweedale/hs-jose/archive/71274bf64c0600c1d877152173a08a5bff7adf4d.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "napalm": { - "branch": "master", - "description": "Support for building npm packages in Nix and lightweight npm registry", - "homepage": "", - "owner": "nmattia", - "repo": "napalm", - "rev": "0331a5b586a186c966f816d434bd5c1ecfa16089", - "sha256": "14nlqmmv3xx4cf3r9kcw2xbfgpddppw27ygp8s3r0bbccgwcp9gi", - "type": "tarball", - "url": "https://github.com/nmattia/napalm/archive/0331a5b586a186c966f816d434bd5c1ecfa16089.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "niv": { - "branch": "master", - "description": "Easy dependency management for Nix projects", - "homepage": "https://github.com/nmattia/niv", - "owner": "nmattia", - "repo": "niv", - "rev": "c2698b0780b783880e0b1a520723948fe3b5c26a", - "sha256": "0v68x0h9si6kjqg5fcjrgsbsf4x18m32a786yvjmrdkrki9qwmcq", - "type": "tarball", - "url": "https://github.com/nmattia/niv/archive/c2698b0780b783880e0b1a520723948fe3b5c26a.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "nixpkgs": { - "branch": "master", - "description": "Nixpkgs/NixOS branches that track the Nixpkgs/NixOS channels", - "homepage": null, - "owner": "nh2", - "repo": "nixpkgs", - "rev": "a2d7e9b875e8ba7fd15b989cf2d80be4e183dc72", - "sha256": "1hnmp637r99qd6g0sbx4w3za564gbzwl5c4z0x7fvn7kfi2jp1hx", - "type": "tarball", - "url": "https://github.com/nh2/nixpkgs/archive/a2d7e9b875e8ba7fd15b989cf2d80be4e183dc72.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "port-utils": { - "sha256": "1vfmm8mmkmfffgza64h6qz4ibniibqdr8mj452ikp1xmvv6m8qm9", - "type": "tarball", - "url": "http://hackage.haskell.org/package/port-utils-0.2.1.0/port-utils-0.2.1.0.tar.gz", - "url_template": "http://hackage.haskell.org/package/port-utils-0.2.1.0/port-utils-0.2.1.0.tar.gz" - }, - "static-haskell-nix": { - "branch": "master", - "description": "easily build most Haskell programs into fully static Linux executables", - "homepage": "", - "owner": "nh2", - "repo": "static-haskell-nix", - "rev": "8d004d7ced9da947c785b93b4011f39367442339", - "sha256": "0nw4g23c5rs0cvaar2phpr60zim9r0qycznpifi8d8k85y4r3bdd", - "type": "tarball", - "url": "https://github.com/nh2/static-haskell-nix/archive/8d004d7ced9da947c785b93b4011f39367442339.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "wai-lambda": { - "branch": "master", - "description": "Haskell Webapps on AWS Lambda", - "owner": "deckgo", - "repo": "wai-lambda", - "rev": "7f139047addff89e9d30e55b7eebb07c0e846456", - "sha256": "0qqi6wlg8v35dkh6gh9mrj0kb9kpzrz2pc7k0dykk2ahcj6m22k6", - "type": "tarball", - "url": "https://github.com/deckgo/wai-lambda/archive/7f139047addff89e9d30e55b7eebb07c0e846456.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - } + "deckdeckgo-starter": { + "branch": "studio", + "description": "The Progressive Web App alternative for simple presentations", + "homepage": "https://deckdeckgo.com", + "owner": "deckgo", + "repo": "deckdeckgo-starter", + "rev": "c49bb065eb3896efc3fb57d3a032aa70c8d99d0d", + "sha256": "0nxwvpy8szdkia3c5jxscq02l5iybpsldly23n7h58xffj912xcg", + "type": "tarball", + "url": "https://github.com/deckgo/deckdeckgo-starter/archive/c49bb065eb3896efc3fb57d3a032aa70c8d99d0d.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "elasticmq": { + "sha256": "1cp2pmkc6gx7gr6109jlcphlky5rr6s1wj528r6hyhzdc01sjhhz", + "type": "file", + "url": "https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.14.6.jar", + "url_template": "https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-0.14.6.jar" + }, + "hs-jose": { + "branch": "master", + "description": "Haskell JOSE and JWT library", + "homepage": "http://hackage.haskell.org/package/jose", + "owner": "frasertweedale", + "repo": "hs-jose", + "rev": "71274bf64c0600c1d877152173a08a5bff7adf4d", + "sha256": "0ah189vika1s0jk8f17mn77gilkw24vbs6xlggxw1qj926i6c4pk", + "type": "tarball", + "url": "https://github.com/frasertweedale/hs-jose/archive/71274bf64c0600c1d877152173a08a5bff7adf4d.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "napalm": { + "branch": "master", + "description": "Support for building npm packages in Nix and lightweight npm registry", + "homepage": "", + "owner": "nmattia", + "repo": "napalm", + "rev": "0331a5b586a186c966f816d434bd5c1ecfa16089", + "sha256": "14nlqmmv3xx4cf3r9kcw2xbfgpddppw27ygp8s3r0bbccgwcp9gi", + "type": "tarball", + "url": "https://github.com/nmattia/napalm/archive/0331a5b586a186c966f816d434bd5c1ecfa16089.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "niv": { + "branch": "master", + "description": "Easy dependency management for Nix projects", + "homepage": "https://github.com/nmattia/niv", + "owner": "nmattia", + "repo": "niv", + "rev": "c2698b0780b783880e0b1a520723948fe3b5c26a", + "sha256": "0v68x0h9si6kjqg5fcjrgsbsf4x18m32a786yvjmrdkrki9qwmcq", + "type": "tarball", + "url": "https://github.com/nmattia/niv/archive/c2698b0780b783880e0b1a520723948fe3b5c26a.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs": { + "branch": "master", + "description": "Nixpkgs/NixOS branches that track the Nixpkgs/NixOS channels", + "homepage": null, + "owner": "nh2", + "repo": "nixpkgs", + "rev": "a2d7e9b875e8ba7fd15b989cf2d80be4e183dc72", + "sha256": "1hnmp637r99qd6g0sbx4w3za564gbzwl5c4z0x7fvn7kfi2jp1hx", + "type": "tarball", + "url": "https://github.com/nh2/nixpkgs/archive/a2d7e9b875e8ba7fd15b989cf2d80be4e183dc72.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "port-utils": { + "sha256": "1vfmm8mmkmfffgza64h6qz4ibniibqdr8mj452ikp1xmvv6m8qm9", + "type": "tarball", + "url": "http://hackage.haskell.org/package/port-utils-0.2.1.0/port-utils-0.2.1.0.tar.gz", + "url_template": "http://hackage.haskell.org/package/port-utils-0.2.1.0/port-utils-0.2.1.0.tar.gz" + }, + "static-haskell-nix": { + "branch": "master", + "description": "easily build most Haskell programs into fully static Linux executables", + "homepage": "", + "owner": "nh2", + "repo": "static-haskell-nix", + "rev": "8d004d7ced9da947c785b93b4011f39367442339", + "sha256": "0nw4g23c5rs0cvaar2phpr60zim9r0qycznpifi8d8k85y4r3bdd", + "type": "tarball", + "url": "https://github.com/nh2/static-haskell-nix/archive/8d004d7ced9da947c785b93b4011f39367442339.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "wai-lambda": { + "branch": "master", + "description": "Haskell Webapps on AWS Lambda", + "owner": "deckgo", + "repo": "wai-lambda", + "rev": "7f139047addff89e9d30e55b7eebb07c0e846456", + "sha256": "0qqi6wlg8v35dkh6gh9mrj0kb9kpzrz2pc7k0dykk2ahcj6m22k6", + "type": "tarball", + "url": "https://github.com/deckgo/wai-lambda/archive/7f139047addff89e9d30e55b7eebb07c0e846456.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } } diff --git a/studio/src/app/components/editor/actions/element/app-actions-element/app-actions-element.tsx b/studio/src/app/components/editor/actions/element/app-actions-element/app-actions-element.tsx index a08f06977..3c43b7a22 100644 --- a/studio/src/app/components/editor/actions/element/app-actions-element/app-actions-element.tsx +++ b/studio/src/app/components/editor/actions/element/app-actions-element/app-actions-element.tsx @@ -15,8 +15,6 @@ import {ToggleSlotUtils} from '../../../../../utils/editor/toggle-slot.utils'; import {RevealSlotUtils} from '../../../../../utils/editor/reveal-slot.utils'; import {SlotType} from '../../../../../utils/editor/slot-type'; import {SlotUtils} from '../../../../../utils/editor/slot.utils'; -import {AlignUtils, TextAlign} from '../../../../../utils/editor/align.utils'; -import {ListUtils} from '../../../../../utils/editor/list.utils'; import {EditAction} from '../../../../../utils/editor/edit-action'; import {MoreAction} from '../../../../../utils/editor/more-action'; @@ -61,12 +59,6 @@ export class AppActionsElement { @State() private shape: boolean = false; - @State() - private align: TextAlign | undefined; - - @State() - private list: SlotType.OL | SlotType.UL | undefined; - @Event() private blockSlide: EventEmitter; @Event() private slideDelete: EventEmitter; @@ -149,6 +141,36 @@ export class AppActionsElement { await this.blurSelectedElement(); } + @Listen('pagerClick', {target: 'document'}) + async onPagerClick() { + await this.reset(); + } + + @Listen('styleDidChange', {target: 'document'}) + async onStyleDidChange() { + await this.emitChange(); + } + + @Listen('toggleReveal', {target: 'document'}) + async onToggleReveal($event: CustomEvent) { + if (!this.selectedElement || !this.selectedElement.parentElement || !$event) { + return; + } + + const element: HTMLElement = await RevealSlotUtils.toggleReveal(this.selectedElement, $event.detail); + + await this.replaceSlot(element); + } + + @Listen('toggleList', {target: 'document'}) + async onToggleList($event: CustomEvent) { + if (!$event) { + return; + } + + await this.toggleList($event.detail); + } + @Method() touch(element: HTMLElement, autoOpen: boolean = true): Promise { return new Promise(async (resolve) => { @@ -348,11 +370,6 @@ export class AppActionsElement { }); } - @Listen('pagerClick', {target: 'document'}) - async onPagerClick() { - await this.reset(); - } - @Method() async reset() { await this.initSelectedElement(null); @@ -545,7 +562,6 @@ export class AppActionsElement { componentProps: { selectedElement: this.selectedElement, slide: this.slide, - imgDidChange: this.imgDidChange, }, mode: 'md', showBackdrop: false, @@ -577,34 +593,6 @@ export class AppActionsElement { await modal.present(); } - private async openSingleAction($event: UIEvent, component: 'app-reveal' | 'app-align' | 'app-list') { - if (this.slide) { - return; - } - - const popover: HTMLIonPopoverElement = await popoverController.create({ - component: component, - componentProps: { - selectedElement: this.selectedElement, - }, - mode: 'ios', - event: $event, - cssClass: 'info', - }); - - popover.onDidDismiss().then(async (detail: OverlayEventDetail) => { - if (detail.data && component === 'app-reveal') { - await this.toggleReveal(detail.data.reveal); - } else if (detail.data && component === 'app-align') { - await this.updateAlignAttribute(detail.data.align); - } else if (detail.data && component === 'app-list') { - await this.toggleList(detail.data.list); - } - }); - - await popover.present(); - } - private async openCode() { if (!this.code) { return; @@ -728,21 +716,6 @@ export class AppActionsElement { }); } - private toggleReveal(reveal: boolean): Promise { - return new Promise(async (resolve) => { - if (!this.selectedElement || !this.selectedElement.parentElement) { - resolve(); - return; - } - - const element: HTMLElement = await RevealSlotUtils.toggleReveal(this.selectedElement, reveal); - - await this.replaceSlot(element); - - resolve(); - }); - } - private replaceSlot(element: HTMLElement): Promise { return new Promise(async (resolve) => { if (!this.selectedElement || !this.selectedElement.parentElement || !element) { @@ -764,11 +737,6 @@ export class AppActionsElement { }); } - @Listen('colorDidChange', {target: 'document'}) - async onColorDidChange(_$event: CustomEvent) { - await this.emitChange(); - } - private emitChange(): Promise { return new Promise((resolve) => { if (!this.selectedElement || !this.selectedElement.parentElement) { @@ -776,7 +744,7 @@ export class AppActionsElement { return; } - // If not deck or slide, then parent is the container slide + // If not slide, then parent is the container slide this.slideDidChange.emit(this.slide ? this.selectedElement : this.selectedElement.parentElement); resolve(); @@ -801,10 +769,6 @@ export class AppActionsElement { this.image = this.isElementImage(SlotUtils.isNodeReveal(element) ? (element.firstElementChild as HTMLElement) : element); this.shape = this.isElementShape(element); - this.align = await AlignUtils.getAlignment(element); - - this.list = await ListUtils.isElementList(element); - if (element) { element.addEventListener('paste', this.cleanOnPaste, false); @@ -883,12 +847,18 @@ export class AppActionsElement { }); } - private async openColor() { + private async openStyle() { const popover: HTMLIonPopoverElement = await popoverController.create({ - component: 'app-color', + component: 'app-element-style', componentProps: { slide: this.slide, selectedElement: this.selectedElement, + imgDidChange: this.imgDidChange, + imageHelper: this.imageHelper, + code: this.code, + math: this.math, + shape: this.shape, + image: this.image, }, mode: 'md', showBackdrop: false, @@ -956,7 +926,7 @@ export class AppActionsElement { private toggleList(destinationListType: SlotType.OL | SlotType.UL): Promise { return new Promise(async (resolve) => { - if (!this.selectedElement || !this.list) { + if (!this.selectedElement) { resolve(); return; } @@ -988,18 +958,6 @@ export class AppActionsElement { }); } - private async updateAlignAttribute(align: TextAlign): Promise { - if (!this.selectedElement) { - return; - } - - this.selectedElement.style.textAlign = align; - - await this.emitChange(); - - await this.reset(); - } - private resizeSlideContent(slideElement?: HTMLElement): Promise { return new Promise(async (resolve) => { if (!this.selectedElement) { @@ -1043,8 +1001,6 @@ export class AppActionsElement { componentProps: { notes: this.slide, copy: this.slide || this.shape, - reveal: !this.hideReveal(), - list: this.list !== undefined, }, event: $event, mode: 'ios', @@ -1058,10 +1014,6 @@ export class AppActionsElement { await this.clone(); } else if (detail.data.action === MoreAction.DELETE) { await this.confirmDeleteElement($event); - } else if (detail.data.action === MoreAction.REVEAL) { - await this.openSingleAction($event, 'app-reveal'); - } else if (detail.data.action === MoreAction.LIST) { - await this.openSingleAction($event, 'app-list'); } } }); @@ -1069,23 +1021,17 @@ export class AppActionsElement { await popover.present(); } - private hideReveal(): boolean { - return this.slide || this.code || this.math || this.shape || this.slideNodeName === 'deckgo-slide-youtube'; - } - render() { return ( + {this.renderStyle()} {this.renderEdit()} {this.renderShapes()} - {this.renderColor()} - {this.renderReveal()} - {this.renderAlign()} - {this.renderList()} {this.renderImages()} {this.renderCodeOptions()} {this.renderMathOptions()} + {this.renderTransform()} @@ -1135,20 +1081,19 @@ export class AppActionsElement { ); } - private renderColor() { + private renderStyle() { return ( - this.openColor()} aria-label="Color" color="primary" mode="md"> - - Color + this.openStyle()} aria-label="Style" color="primary" mode="md"> + + Style ); } private renderEdit() { const classSlide: string | undefined = this.slide && this.isSlideEditable() ? undefined : 'hidden'; - const classToggle: string | undefined = !this.slide && !this.shape ? undefined : 'hidden'; - return [ + return ( this.slideNodeName === 'deckgo-slide-poll' @@ -1163,14 +1108,21 @@ export class AppActionsElement { aria-label="Edit slide options" mode="md" class={classSlide}> - + Options - , + + ); + } + + private renderTransform() { + const classToggle: string | undefined = !this.slide && !this.shape ? undefined : 'hidden'; + + return ( this.openTransform()} aria-label="Toggle element type" color="primary" mode="md" class={classToggle}> Transform - , - ]; + + ); } private renderShapes() { @@ -1189,8 +1141,8 @@ export class AppActionsElement { return ( this.openCode()} aria-label="Code attributes" color="primary" mode="md" class={classSlideCode}> - - Attributes + + Options ); } @@ -1199,71 +1151,19 @@ export class AppActionsElement { return ( this.openMath()} aria-label="Math options" color="primary" mode="md" class={classSlideMath}> - - Attributes + + Options ); } private renderImages() { - const classImage: string | undefined = this.image || this.slide ? undefined : 'hidden'; + const classImage: string | undefined = this.image ? undefined : 'hidden'; return ( - this.openImage()} aria-label={this.slide ? 'Background' : 'Image'} color="primary" mode="md" class={classImage}> + this.openImage()} aria-label="Image" color="primary" mode="md" class={classImage}> - {this.slide ? 'Background' : 'Image'} - - ); - } - - private renderReveal() { - const classReveal: string | undefined = this.hideReveal() ? 'hidden wider-devices' : 'wider-devices'; - - return ( - this.openSingleAction($event, 'app-reveal')} - aria-label="Edit element animation" - color="primary" - mode="md" - class={classReveal}> - - Animation - - ); - } - - private renderAlign() { - const classAlign: string | undefined = this.align === undefined ? 'hidden' : undefined; - - return ( - this.openSingleAction($event, 'app-align')} - aria-label="Edit element alignment" - color="primary" - mode="md" - class={classAlign}> - {this.align !== undefined ? ( - - ) : ( - - )} - Alignment - - ); - } - - private renderList() { - const classList: string | undefined = this.list === undefined ? 'hidden wider-devices' : 'wider-devices'; - - return ( - this.openSingleAction($event, 'app-list')} - aria-label="Edit ordered or unordered list" - color="primary" - mode="md" - class={classList}> - - List + Image ); } diff --git a/studio/src/app/components/editor/app-image/app-image.tsx b/studio/src/app/components/editor/app-image/app-image.tsx deleted file mode 100644 index 3702f666d..000000000 --- a/studio/src/app/components/editor/app-image/app-image.tsx +++ /dev/null @@ -1,386 +0,0 @@ -import {Component, Element, Prop, State, h, EventEmitter, Event} from '@stencil/core'; - -import {alertController} from '@ionic/core'; - -import {EditAction} from '../../../utils/editor/edit-action'; -import {ImageAction} from '../../../utils/editor/image-action'; - -import {ImageHistoryService} from '../../../services/editor/image-history/image-history.service'; - -enum ImageSize { - SMALL = '25%', - MEDIUM = '50%', - LARGE = '75%', - ORIGINAL = '100%', -} - -enum ImageAlignment { - START = 'flex-start', - CENTER = 'center', - END = 'flex-end', -} - -@Component({ - tag: 'app-image', - styleUrl: 'app-image.scss', -}) -export class AppImage { - @Element() el: HTMLElement; - - @Event() private action: EventEmitter; - - @Event() private imgDidChange: EventEmitter; - - @Prop() - selectedElement: HTMLElement; - - @Prop() - slide: boolean = false; - - @Prop() - deleteBackground: boolean = true; - - @Prop() - deck: boolean = false; - - private imageHistoryService: ImageHistoryService; - - @State() - private imagesHistoryOdd: (UnsplashPhoto | TenorGif | StorageFile)[]; - - @State() - private imagesHistoryEven: (UnsplashPhoto | TenorGif | StorageFile)[]; - - @State() - private currentImageSize: ImageSize; - - @State() - private currentImageAlignment: ImageAlignment; - - @State() - private navigatorOnline: boolean = navigator.onLine; - - constructor() { - this.imageHistoryService = ImageHistoryService.getInstance(); - } - - async componentWillLoad() { - await this.initImagesHistory(); - - this.currentImageSize = await this.initImageSize(); - this.currentImageAlignment = await this.initImageAlignment(); - } - - private initImagesHistory(): Promise { - return new Promise(async (resolve) => { - const imagesHistory: (UnsplashPhoto | TenorGif | StorageFile)[] = await this.imageHistoryService.get(); - - if (!imagesHistory || imagesHistory.length <= 0) { - resolve(); - return; - } - - this.imagesHistoryEven = [...imagesHistory.filter((_a, i) => i % 2)]; - this.imagesHistoryOdd = [...imagesHistory.filter((_a, i) => !(i % 2))]; - - resolve(); - }); - } - - private initImageSize(): Promise { - return new Promise((resolve) => { - if (!this.selectedElement || !this.selectedElement.style) { - resolve(null); - return; - } - - if (this.selectedElement.style.getPropertyValue('--deckgo-lazy-img-height') === '25%') { - resolve(ImageSize.SMALL); - } else if (this.selectedElement.style.getPropertyValue('--deckgo-lazy-img-height') === '50%') { - resolve(ImageSize.MEDIUM); - } else if (this.selectedElement.style.getPropertyValue('--deckgo-lazy-img-height') === '75%') { - resolve(ImageSize.LARGE); - } else { - resolve(ImageSize.ORIGINAL); - } - }); - } - - private initImageAlignment(): Promise { - return new Promise(async (resolve) => { - if (!this.selectedElement || !this.selectedElement.style) { - resolve(null); - return; - } - - if (this.selectedElement.style.getPropertyValue('justify-content') === 'center') { - resolve(ImageAlignment.CENTER); - } else if (this.selectedElement.style.getPropertyValue('justify-content') === 'flex-end') { - resolve(ImageAlignment.END); - } else if (this.selectedElement.style.getPropertyValue('justify-content') === 'flex-start') { - resolve(ImageAlignment.START); - } else { - const result: ImageAlignment = await this.findSlideDefaultAlignment(); - resolve(result); - } - }); - } - - private findSlideDefaultAlignment(): Promise { - return new Promise((resolve) => { - const parent: HTMLElement = this.selectedElement.parentElement; - - if (parent && parent.nodeName && parent.nodeName.toLowerCase().indexOf('deckgo-slide') > -1) { - const container: HTMLElement = parent.shadowRoot.querySelector('.deckgo-slide'); - if (container) { - const style: CSSStyleDeclaration = window.getComputedStyle(container); - - if (style && style.alignItems === 'center') { - resolve(ImageAlignment.CENTER); - return; - } - } - } - - resolve(ImageAlignment.START); - }); - } - - private async selectAction(action: EditAction, image?: UnsplashPhoto | TenorGif | StorageFile) { - const data: ImageAction = { - action: action, - }; - - if (image) { - data['image'] = image; - } - - this.action.emit(data); - } - - private selectImageFromHistory($event: CustomEvent): Promise { - return new Promise(async (resolve) => { - if (!$event || !$event.detail) { - resolve(); - return; - } - - await this.selectAction(EditAction.ADD_IMAGE, $event.detail); - - resolve(); - }); - } - - private async presentHistoryInfo() { - const alert: HTMLIonAlertElement = await alertController.create({ - message: 'The editor keeps track of the last 10 images you would have use in any of your presentations.

Select one to add it again quickly.', - buttons: ['Ok'], - }); - - return await alert.present(); - } - - private toggleImageSize($event: CustomEvent): Promise { - return new Promise(async (resolve) => { - if (!$event || !$event.detail) { - resolve(); - return; - } - - this.currentImageSize = $event.detail.value; - - if (!this.selectedElement) { - resolve(); - return; - } - - if (this.currentImageSize === ImageSize.ORIGINAL) { - this.selectedElement.style.removeProperty('--deckgo-lazy-img-height'); - } else { - this.selectedElement.style.setProperty('--deckgo-lazy-img-height', this.currentImageSize); - } - - this.imgDidChange.emit(this.selectedElement); - - resolve(); - }); - } - - private toggleImageAlignment($event: CustomEvent): Promise { - return new Promise(async (resolve) => { - if (!$event || !$event.detail) { - resolve(); - return; - } - - this.currentImageAlignment = $event.detail.value; - - if (!this.selectedElement) { - resolve(); - return; - } - - this.selectedElement.style.setProperty('display', 'inline-flex'); - this.selectedElement.style.setProperty('justify-content', this.currentImageAlignment); - - this.imgDidChange.emit(this.selectedElement); - - resolve(); - }); - } - - render() { - return ( - - {this.renderImageSize()} - {this.renderImageAlignment()} - - {this.renderStockPhotos()} - {this.renderGif()} - - {this.renderCustom()} - - {this.renderDeleteAction()} - - - History - - - - {this.renderImagesHistory()} - - ); - } - - private renderStockPhotos() { - if (!this.navigatorOnline) { - // Unsplash not available offline - return undefined; - } - - return ( - - this.selectAction(EditAction.OPEN_PHOTOS)} color="primary"> - Stock photo - - - ); - } - - private renderGif() { - if (!this.navigatorOnline) { - // Tenor not available offline - return undefined; - } - - return ( - - this.selectAction(EditAction.OPEN_GIFS)} color="secondary"> - Gif - - - ); - } - - private renderCustom() { - return ( - - this.selectAction(EditAction.OPEN_CUSTOM)} color="tertiary"> - Your images - - - ); - } - - private renderDeleteAction() { - if ((!this.deck && !this.slide) || !this.deleteBackground) { - return undefined; - } else { - return ( - - this.selectAction(EditAction.DELETE_BACKGROUND)} fill="outline" class="delete"> - Delete background - - - ); - } - } - - private renderImagesHistory() { - if (!this.imagesHistoryOdd && !this.imagesHistoryEven) { - return ( - - - You have not used any images so far. - - - ); - } else { - return ( -
- this.selectImageFromHistory($event)}> -
- ); - } - } - - private renderImageSize() { - if (this.deck || this.slide) { - return undefined; - } else { - return [ - - Size - , - - - Size - - this.toggleImageSize(e)} - class="ion-padding-start ion-padding-end"> - Small - Medium - Large - Original - - , - ]; - } - } - - private renderImageAlignment() { - if (this.deck || this.slide) { - return undefined; - } else { - return [ - - Alignment - , - - - Alignment - - this.toggleImageAlignment(e)} - interface="popover" - mode="md" - class="ion-padding-start ion-padding-end"> - Start - Center - End - - , - ]; - } - } -} diff --git a/studio/src/app/components/editor/app-select-target-element/app-select-target-element.tsx b/studio/src/app/components/editor/app-select-target-element/app-select-target-element.tsx index 06f55d3ae..baded3f67 100644 --- a/studio/src/app/components/editor/app-select-target-element/app-select-target-element.tsx +++ b/studio/src/app/components/editor/app-select-target-element/app-select-target-element.tsx @@ -4,7 +4,7 @@ import {TargetElement} from '../../../utils/editor/target-element'; @Component({ tag: 'app-select-target-element', - styleUrl: 'app-select-target-element.scss' + styleUrl: 'app-select-target-element.scss', }) export class AppSelectTargetElement { @Prop() @@ -24,7 +24,7 @@ export class AppSelectTargetElement { // color is a reserved prop word @Prop() - colorTarget: boolean = false; + textTarget: boolean = false; @Prop() background: boolean = false; @@ -41,6 +41,9 @@ export class AppSelectTargetElement { @Prop() images: boolean = false; + @Prop() + image: boolean = false; + @Event() applyTo: EventEmitter; @@ -51,51 +54,40 @@ export class AppSelectTargetElement { } render() { - if (!this.colorTarget && !this.slide && !this.shapes) { - if (!this.code) { - return undefined; - } - - return ( - this.selectApplyToAll($event)}> - - Code - - - Section - - - ); - } else { - const selectedValue: TargetElement = this.colorTarget - ? TargetElement.COLOR - : this.sides - ? TargetElement.SIDES - : this.qrCode - ? TargetElement.QR_CODE - : this.chart - ? TargetElement.CHART - : this.shapes - ? TargetElement.SHAPES - : this.images - ? TargetElement.IMAGES - : TargetElement.SLIDE; - - return ( - this.selectApplyToAll($event)}> - {this.renderQRCode()} - {this.renderChart()} - {this.renderSides()} - {this.renderSlide()} - {this.renderColor()} - {this.renderBackground()} - {this.renderFonts()} - {this.renderTransition()} - {this.renderShapes()} - {this.renderImages()} - - ); - } + const selectedValue: TargetElement = this.code + ? TargetElement.CODE + : this.image + ? TargetElement.IMAGE + : this.textTarget + ? TargetElement.TEXT + : this.sides + ? TargetElement.SIDES + : this.qrCode + ? TargetElement.QR_CODE + : this.chart + ? TargetElement.CHART + : this.shapes + ? TargetElement.SHAPES + : this.images + ? TargetElement.IMAGES + : TargetElement.SLIDE; + + return ( + this.selectApplyToAll($event)}> + {this.renderQRCode()} + {this.renderChart()} + {this.renderSides()} + {this.renderSlide()} + {this.renderCode()} + {this.renderImage()} + {this.renderText()} + {this.renderBackground()} + {this.renderFonts()} + {this.renderTransition()} + {this.renderShapes()} + {this.renderImages()} + + ); } private renderQRCode() { @@ -126,7 +118,7 @@ export class AppSelectTargetElement { if (this.slide) { return ( - Slide + Text ); } else { @@ -134,11 +126,11 @@ export class AppSelectTargetElement { } } - private renderColor() { - if (this.colorTarget) { + private renderText() { + if (this.textTarget) { return ( - - Colors + + Text ); } else { @@ -158,6 +150,30 @@ export class AppSelectTargetElement { } } + private renderCode() { + if (this.code) { + return ( + + Code + + ); + } else { + return undefined; + } + } + + private renderImage() { + if (this.image) { + return ( + + Image + + ); + } else { + return undefined; + } + } + private renderTransition() { if (this.transition) { return ( diff --git a/studio/src/app/components/editor/color/app-color-chart/app-color-chart.tsx b/studio/src/app/components/editor/color/app-color-chart/app-color-chart.tsx index 9a2675a21..9c575f37a 100644 --- a/studio/src/app/components/editor/color/app-color-chart/app-color-chart.tsx +++ b/studio/src/app/components/editor/color/app-color-chart/app-color-chart.tsx @@ -43,7 +43,7 @@ export class AppColorDeckSlide { private indexes: number[] = [...Array(99).keys()]; - @Event() colorChange: EventEmitter; + @Event() colorChange: EventEmitter; async componentWillLoad() { this.chartType = await ChartUtils.initSlideChartType(this.selectedElement); @@ -129,7 +129,7 @@ export class AppColorDeckSlide { this.selectedElement.style.setProperty('--deckgo-chart-text-color', selectedColor); } - this.colorChange.emit(false); + this.colorChange.emit(); resolve(); }); @@ -174,15 +174,15 @@ export class AppColorDeckSlide { render() { return [ - Apply color to + Apply a color to , - Apply color to + Apply a color to this.toggleColorType(e)} interface="popover" mode="md" diff --git a/studio/src/app/components/editor/color/app-color-code/app-color-code.tsx b/studio/src/app/components/editor/color/app-color-code/app-color-code.tsx index 8c7b88b35..fc82794f3 100644 --- a/studio/src/app/components/editor/color/app-color-code/app-color-code.tsx +++ b/studio/src/app/components/editor/color/app-color-code/app-color-code.tsx @@ -45,7 +45,7 @@ export class AppColorCode { @State() private highlightColorOpacity: number = 100; - @Event() colorChange: EventEmitter; + @Event() colorChange: EventEmitter; async componentWillLoad() { await this.initColor(); @@ -236,7 +236,9 @@ export class AppColorCode { } // prettier-ignore - private async presentHighlightInfo() { + private async presentHighlightInfo($event: UIEvent) { + $event.stopPropagation(); + const alert: HTMLIonAlertElement = await alertController.create({ message: 'If you wish to highlight some specific lines of your code, list their line numbers separately using comma.

For example: 1,2 7,7 13,15

Which would highlight lines 1 to 2, line 7 and lines 13 to 15.', buttons: ['Ok'] @@ -246,7 +248,7 @@ export class AppColorCode { } private emitColorChange() { - this.colorChange.emit(false); + this.colorChange.emit(); } private updateOpacity($event: CustomEvent, opacityFunction: Function): Promise { @@ -296,110 +298,118 @@ export class AppColorCode { } render() { - return [ - - - Apply color to - - - - Apply color to - - this.toggleColorType(e)} - interface="popover" - mode="md" - class="ion-padding-start ion-padding-end"> - Comments - Functions - Keywords - Operators - Punctuation - Properties - Regex - Selector - Line numbers - - - - - - Opacity {this.codeColorOpacity}% - - - - - ) => this.updateOpacity($event, this.setCodeOpacity)}> - - -
- this.selectColor($event, this.setCodeColor)} - color-rgb={this.codeColor} - more={this.moreColors}> - - -
- - - this.resetCodeColor()} fill="outline" class="delete"> - Reset color - - - - - Highlight lines - - - - - ) => this.handleInput(e)} - onIonChange={() => this.highlightSelectedLines()}> - - - - - Opacity {this.highlightColorOpacity}% - - - - - ) => this.updateOpacity($event, this.setHighlightOpacity)}> - - -
- this.selectColor($event, this.setHighlightColor)} - color-rgb={this.highlightColor} - more={this.moreColors}> - - -
-
, - ]; + return [this.renderCategoryColor(), this.renderHighlightLinesColor()]; + } + + private renderCategoryColor() { + return ( + + Colors + + + Apply a color to + + this.toggleColorType(e)} + interface="popover" + mode="md" + class="ion-padding-start ion-padding-end"> + Comments + Functions + Keywords + Operators + Punctuation + Properties + Regex + Selector + Line numbers + + + + + + Opacity {this.codeColorOpacity}% + + + + + ) => this.updateOpacity($event, this.setCodeOpacity)}> + + +
+ this.selectColor($event, this.setCodeColor)} + color-rgb={this.codeColor} + more={this.moreColors}> + + +
+ + + this.resetCodeColor()} fill="outline" class="delete"> + Reset color + + +
+
+ ); + } + + private renderHighlightLinesColor() { + return ( + + Highlight lines + + + + ) => this.handleInput(e)} + onIonChange={() => this.highlightSelectedLines()}> + + + + + Opacity {this.highlightColorOpacity}% + + + + + ) => this.updateOpacity($event, this.setHighlightOpacity)}> + + +
+ this.selectColor($event, this.setHighlightColor)} + color-rgb={this.highlightColor} + more={this.moreColors}> + + +
+
+
+ ); } } diff --git a/studio/src/app/components/editor/color/app-color-qrcode/app-color-qrcode.tsx b/studio/src/app/components/editor/color/app-color-qrcode/app-color-qrcode.tsx index 41a6119bc..fe0044628 100644 --- a/studio/src/app/components/editor/color/app-color-qrcode/app-color-qrcode.tsx +++ b/studio/src/app/components/editor/color/app-color-qrcode/app-color-qrcode.tsx @@ -5,7 +5,7 @@ import {ColorUtils, InitStyleColor} from '../../../../utils/editor/color.utils'; enum ApplyColorType { QR_CODE, - BACKGROUND, + BACKDROP, } @Component({ @@ -29,7 +29,7 @@ export class AppColorQRCode { @State() private applyColorType: ApplyColorType = ApplyColorType.QR_CODE; - @Event() colorChange: EventEmitter; + @Event() colorChange: EventEmitter; async componentWillLoad() { await this.initCurrentColors(); @@ -49,7 +49,7 @@ export class AppColorQRCode { let styleColor: InitStyleColor; - if (this.applyColorType === ApplyColorType.BACKGROUND) { + if (this.applyColorType === ApplyColorType.BACKDROP) { styleColor = await ColorUtils.splitColor(element.style.getPropertyValue('--deckgo-qrcode-background-fill')); } else { styleColor = await ColorUtils.splitColor(element.style.getPropertyValue('--deckgo-qrcode-color-fill')); @@ -84,7 +84,7 @@ export class AppColorQRCode { return; } - if (this.applyColorType === ApplyColorType.BACKGROUND) { + if (this.applyColorType === ApplyColorType.BACKDROP) { this.selectedElement.style.removeProperty('--deckgo-qrcode-background-fill'); } else { this.selectedElement.style.removeProperty('--deckgo-qrcode-color-fill'); @@ -93,7 +93,7 @@ export class AppColorQRCode { this.color = null; this.colorOpacity = 100; - this.colorChange.emit(false); + this.colorChange.emit(); resolve(); }); @@ -108,13 +108,13 @@ export class AppColorQRCode { const selectedColor: string = `rgba(${this.color},${ColorUtils.transformOpacity(this.colorOpacity)})`; - if (this.applyColorType === ApplyColorType.BACKGROUND) { + if (this.applyColorType === ApplyColorType.BACKDROP) { this.selectedElement.style.setProperty('--deckgo-qrcode-background-fill', selectedColor); } else { this.selectedElement.style.setProperty('--deckgo-qrcode-color-fill', selectedColor); } - this.colorChange.emit(false); + this.colorChange.emit(); resolve(); }); @@ -141,22 +141,26 @@ export class AppColorQRCode { render() { return [ + + Apply a color to + , + - this.selectApplyType($event)} value={ApplyColorType.QR_CODE}> - - Apply color to - - - - Fill - - - - - Background - - - + + Apply a color to + + this.selectApplyType($event)} + interface="popover" + mode="md" + class="ion-padding-start ion-padding-end"> + Fill, + Backdrop, + + + Opacity {this.colorOpacity}% diff --git a/studio/src/app/components/editor/color/app-color-sides/app-color-sides.tsx b/studio/src/app/components/editor/color/app-color-sides/app-color-sides.tsx index bc0a52349..c96907249 100644 --- a/studio/src/app/components/editor/color/app-color-sides/app-color-sides.tsx +++ b/studio/src/app/components/editor/color/app-color-sides/app-color-sides.tsx @@ -32,7 +32,7 @@ export class AppColorSides { @State() private applyColorType: ApplyColorType = ApplyColorType.TEXT; - @Event() colorChange: EventEmitter; + @Event() colorChange: EventEmitter; @State() private endSide: boolean = false; @@ -99,7 +99,7 @@ export class AppColorSides { this.color = null; this.colorOpacity = 100; - this.colorChange.emit(false); + this.colorChange.emit(); resolve(); }); @@ -120,7 +120,7 @@ export class AppColorSides { this.selectedElement.style.setProperty(`--slide-${this.template}-color-${this.endSide ? 'end' : 'start'}`, selectedColor); } - this.colorChange.emit(false); + this.colorChange.emit(); resolve(); }); @@ -155,27 +155,33 @@ export class AppColorSides { return [ - Selected side + Style which side of the slide? + {this.endSide ? 'End' : 'Start'} this.toggleSide()}> - this.selectApplyType($event)} class="ion-padding-top" value={ApplyColorType.TEXT}> - - Apply color to - - - - Text - - - - - Background - - - + + + Apply which color to this side? + + + + Apply a color to + + this.selectApplyType($event)} + interface="popover" + mode="md" + class="ion-padding-start ion-padding-end"> + Text, + Background, + + + Opacity {this.colorOpacity}% diff --git a/studio/src/app/components/editor/color/app-color-text-background/app-color-text-background.tsx b/studio/src/app/components/editor/color/app-color-text-background/app-color-text-background.tsx index dd5f5a0ba..ced08687e 100644 --- a/studio/src/app/components/editor/color/app-color-text-background/app-color-text-background.tsx +++ b/studio/src/app/components/editor/color/app-color-text-background/app-color-text-background.tsx @@ -1,13 +1,8 @@ -import {Component, Element, Event, EventEmitter, h, Method, Prop, State} from '@stencil/core'; +import {Component, Element, Event, EventEmitter, h, Method, Prop, State, Watch} from '@stencil/core'; import {RangeChangeEventDetail} from '@ionic/core'; import {ColorUtils, InitStyleColor} from '../../../../utils/editor/color.utils'; -enum ApplyColorType { - TEXT, - BACKGROUND, -} - @Component({ tag: 'app-color-text-background', }) @@ -29,21 +24,29 @@ export class AppColorTextBackground { @Prop() shape: boolean = false; + @Prop() + colorType: 'text' | 'background' = 'text'; + + @Prop() + expander: boolean = true; + @State() private color: string; @State() private colorOpacity: number = 100; - @State() - private applyColorType: ApplyColorType = ApplyColorType.TEXT; - - @Event() colorChange: EventEmitter; + @Event() colorChange: EventEmitter; async componentWillLoad() { await this.initCurrentColors(); } + @Watch('colorType') + async onColorTypeChange() { + await this.initCurrentColors(); + } + @Method() async initCurrentColors() { if (!this.selectedElement) { @@ -53,7 +56,7 @@ export class AppColorTextBackground { let styleColor: InitStyleColor; // prettier-ignore - if (this.applyColorType === ApplyColorType.BACKGROUND) { + if (this.colorType === 'background') { styleColor = await ColorUtils.splitColor(this.selectedElement.style.getPropertyValue('--background') ? this.selectedElement.style.getPropertyValue('--background') : this.selectedElement.style.background); } else { styleColor = await ColorUtils.splitColor(this.selectedElement.style.getPropertyValue('--color') ? this.selectedElement.style.getPropertyValue('--color') : this.selectedElement.style.color); @@ -63,14 +66,6 @@ export class AppColorTextBackground { this.colorOpacity = styleColor.opacity; } - private async selectApplyType($event: CustomEvent) { - if ($event && $event.detail) { - this.applyColorType = $event.detail.value; - - await this.initCurrentColors(); - } - } - private async selectColor($event: CustomEvent) { if (!this.selectedElement || !$event || !$event.detail) { return; @@ -82,7 +77,7 @@ export class AppColorTextBackground { } private async applyColor() { - if (this.applyColorType === ApplyColorType.BACKGROUND) { + if (this.colorType === 'background') { await this.applyBackground(); } else { await this.applyTextColor(); @@ -96,7 +91,7 @@ export class AppColorTextBackground { return; } - if (this.applyColorType === ApplyColorType.BACKGROUND) { + if (this.colorType === 'background') { this.selectedElement.style.removeProperty('--background'); this.selectedElement.style.removeProperty('background'); } else { @@ -107,7 +102,7 @@ export class AppColorTextBackground { this.color = null; this.colorOpacity = 100; - this.colorChange.emit(this.deck); + this.colorChange.emit(); resolve(); }); @@ -128,7 +123,7 @@ export class AppColorTextBackground { this.selectedElement.style.color = selectedColor; } - this.colorChange.emit(this.deck); + this.colorChange.emit(); resolve(); }); @@ -149,7 +144,7 @@ export class AppColorTextBackground { this.selectedElement.style.background = selectedColor; } - this.colorChange.emit(this.deck); + this.colorChange.emit(); resolve(); }); @@ -175,59 +170,39 @@ export class AppColorTextBackground { } render() { - return [ - - this.selectApplyType($event)} value={ApplyColorType.TEXT}> + return ( + + Color + - Apply color to + + Opacity {this.colorOpacity}% + - - - {this.shape ? 'Shape' : 'Text'} - + + ) => this.updateOpacity(e)}> - - - Background - - - - - - Opacity {this.colorOpacity}% - - - - ) => this.updateOpacity(e)}> + + this.selectColor($event)} + color-rgb={this.color}> + + + + this.resetColor()} fill="outline" class="delete"> + Reset color + - , - this.selectColor($event)} - color-rgb={this.color}> - - , - - this.resetColor()} fill="outline" class="delete"> - {this.resetLabelContent()} - - , - ]; - } - - private resetLabelContent() { - if (this.applyColorType === ApplyColorType.BACKGROUND) { - return 'Reset background'; - } else { - return 'Reset color'; - } + + ); } } diff --git a/studio/src/app/components/editor/styles/app-expansion-panel/app-expansion-panel.scss b/studio/src/app/components/editor/styles/app-expansion-panel/app-expansion-panel.scss new file mode 100644 index 000000000..1457b992a --- /dev/null +++ b/studio/src/app/components/editor/styles/app-expansion-panel/app-expansion-panel.scss @@ -0,0 +1,44 @@ +app-expansion-panel { + display: block; + + article { + > div { + overflow: hidden; + transition: height 0.25s ease-in; + } + + > ion-item { + font-size: var(--font-size-normal); + + &.hidden { + display: none; + } + + > ion-icon { + margin: 12px 8px 12px 0; + color: black; + font-size: var(--font-size-small); + + transition: transform 0.25s ease-in; + } + + div[slot="end"] { + opacity: 1; + + transition: opacity 0.25s ease-in; + } + } + + &.close { + > ion-item { + > ion-icon { + transform: rotate(-90deg); + } + + div[slot="end"] { + opacity: 0; + } + } + } + } +} diff --git a/studio/src/app/components/editor/styles/app-expansion-panel/app-expansion-panel.tsx b/studio/src/app/components/editor/styles/app-expansion-panel/app-expansion-panel.tsx new file mode 100644 index 000000000..50161d8de --- /dev/null +++ b/studio/src/app/components/editor/styles/app-expansion-panel/app-expansion-panel.tsx @@ -0,0 +1,85 @@ +import {Component, h, State, Prop} from '@stencil/core'; + +@Component({ + tag: 'app-expansion-panel', + styleUrl: 'app-expansion-panel.scss', +}) +export class AppExpansionPanel { + container!: HTMLDivElement; + + @Prop() + expander: boolean = true; + + @State() + private expanded: 'open' | 'close' = 'open'; + + // Source animation: https://css-tricks.com/using-css-transitions-auto-dimensions/ + + private toggle() { + if (this.expanded === 'close') { + this.expand(); + } else { + this.collapse(); + } + } + + private collapse() { + if (!this.container) { + return; + } + + const sectionHeight: number = this.container.scrollHeight; + const elementTransition = this.container.style.transition; + this.container.style.transition = ''; + + requestAnimationFrame(() => { + this.container.style.height = sectionHeight + 'px'; + this.container.style.transition = elementTransition; + + requestAnimationFrame(() => { + this.container.style.height = 0 + 'px'; + }); + }); + + this.expanded = 'close'; + } + + private expand() { + if (!this.container) { + return; + } + + const sectionHeight: number = this.container.scrollHeight; + this.container.style.height = sectionHeight + 'px'; + + this.container.addEventListener( + 'transitionend', + () => { + this.container.style.height = ''; + }, + {once: true} + ); + + this.expanded = 'open'; + } + + render() { + return ( +
+ this.toggle()} class={this.expander ? undefined : 'hidden'}> +
+ +
+ +
+ +
+
+ +
(this.container = el as HTMLDivElement)}> + +
+
+ ); + } +} diff --git a/studio/src/app/components/editor/app-image/app-image.scss b/studio/src/app/components/editor/styles/app-image/app-image.scss similarity index 100% rename from studio/src/app/components/editor/app-image/app-image.scss rename to studio/src/app/components/editor/styles/app-image/app-image.scss diff --git a/studio/src/app/components/editor/styles/app-image/app-image.tsx b/studio/src/app/components/editor/styles/app-image/app-image.tsx new file mode 100644 index 000000000..c4375f939 --- /dev/null +++ b/studio/src/app/components/editor/styles/app-image/app-image.tsx @@ -0,0 +1,202 @@ +import {Component, Element, Prop, State, h, EventEmitter, Event} from '@stencil/core'; + +import {alertController} from '@ionic/core'; + +import {EditAction} from '../../../../utils/editor/edit-action'; +import {ImageAction} from '../../../../utils/editor/image-action'; + +import {ImageHistoryService} from '../../../../services/editor/image-history/image-history.service'; + +@Component({ + tag: 'app-image', + styleUrl: 'app-image.scss', +}) +export class AppImage { + @Element() el: HTMLElement; + + @Event() private action: EventEmitter; + + @Prop() + selectedElement: HTMLElement; + + @Prop() + slide: boolean = false; + + @Prop() + deleteBackground: boolean = true; + + @Prop() + deck: boolean = false; + + @Prop() + expander: boolean = true; + + private imageHistoryService: ImageHistoryService; + + @State() + private imagesHistoryOdd: (UnsplashPhoto | TenorGif | StorageFile)[]; + + @State() + private imagesHistoryEven: (UnsplashPhoto | TenorGif | StorageFile)[]; + + @State() + private navigatorOnline: boolean = navigator.onLine; + + constructor() { + this.imageHistoryService = ImageHistoryService.getInstance(); + } + + async componentWillLoad() { + await this.initImagesHistory(); + } + + private initImagesHistory(): Promise { + return new Promise(async (resolve) => { + const imagesHistory: (UnsplashPhoto | TenorGif | StorageFile)[] = await this.imageHistoryService.get(); + + if (!imagesHistory || imagesHistory.length <= 0) { + resolve(); + return; + } + + this.imagesHistoryEven = [...imagesHistory.filter((_a, i) => i % 2)]; + this.imagesHistoryOdd = [...imagesHistory.filter((_a, i) => !(i % 2))]; + + resolve(); + }); + } + + private async selectAction(action: EditAction, image?: UnsplashPhoto | TenorGif | StorageFile) { + const data: ImageAction = { + action: action, + }; + + if (image) { + data['image'] = image; + } + + this.action.emit(data); + } + + private selectImageFromHistory($event: CustomEvent): Promise { + return new Promise(async (resolve) => { + if (!$event || !$event.detail) { + resolve(); + return; + } + + await this.selectAction(EditAction.ADD_IMAGE, $event.detail); + + resolve(); + }); + } + + private async presentHistoryInfo() { + const alert: HTMLIonAlertElement = await alertController.create({ + message: 'The editor keeps track of the last 10 images you would have use in any of your presentations.

Select one to add it again quickly.', + buttons: ['Ok'], + }); + + return await alert.present(); + } + + render() { + return ( + + Image + + {this.renderStockPhotos()} + {this.renderGif()} + + {this.renderCustom()} + + {this.renderDeleteAction()} + + + History + + + + {this.renderImagesHistory()} + + + ); + } + + private renderStockPhotos() { + if (!this.navigatorOnline) { + // Unsplash not available offline + return undefined; + } + + return ( + + this.selectAction(EditAction.OPEN_PHOTOS)} color="primary"> + Stock photo + + + ); + } + + private renderGif() { + if (!this.navigatorOnline) { + // Tenor not available offline + return undefined; + } + + return ( + + this.selectAction(EditAction.OPEN_GIFS)} color="secondary"> + Gif + + + ); + } + + private renderCustom() { + return ( + + this.selectAction(EditAction.OPEN_CUSTOM)} color="tertiary"> + Your images + + + ); + } + + private renderDeleteAction() { + if ((!this.deck && !this.slide) || !this.deleteBackground) { + return undefined; + } else { + return ( + + this.selectAction(EditAction.DELETE_BACKGROUND)} fill="outline" class="delete"> + Reset image + + + ); + } + } + + private renderImagesHistory() { + if (!this.imagesHistoryOdd && !this.imagesHistoryEven) { + return ( + + + You have not used any images so far. + + + ); + } else { + return ( +
+ this.selectImageFromHistory($event)}> +
+ ); + } + } +} diff --git a/studio/src/app/components/editor/app-deck-fonts/app-deck-fonts.scss b/studio/src/app/components/editor/styles/deck/app-deck-fonts/app-deck-fonts.scss similarity index 100% rename from studio/src/app/components/editor/app-deck-fonts/app-deck-fonts.scss rename to studio/src/app/components/editor/styles/deck/app-deck-fonts/app-deck-fonts.scss diff --git a/studio/src/app/components/editor/app-deck-fonts/app-deck-fonts.tsx b/studio/src/app/components/editor/styles/deck/app-deck-fonts/app-deck-fonts.tsx similarity index 90% rename from studio/src/app/components/editor/app-deck-fonts/app-deck-fonts.tsx rename to studio/src/app/components/editor/styles/deck/app-deck-fonts/app-deck-fonts.tsx index 39489c5d3..d0115b50f 100644 --- a/studio/src/app/components/editor/app-deck-fonts/app-deck-fonts.tsx +++ b/studio/src/app/components/editor/styles/deck/app-deck-fonts/app-deck-fonts.tsx @@ -1,10 +1,10 @@ import {Component, Event, EventEmitter, h, Prop, State} from '@stencil/core'; -import {FontsService} from '../../../services/editor/fonts/fonts.service'; +import {FontsService} from '../../../../../services/editor/fonts/fonts.service'; @Component({ tag: 'app-deck-fonts', - styleUrl: 'app-deck-fonts.scss' + styleUrl: 'app-deck-fonts.scss', }) export class AppDeckFonts { @Prop() @@ -38,10 +38,7 @@ export class AppDeckFonts { return; } - this.selectedFont = this.deckElement.style - .getPropertyValue('font-family') - .replace(/\'/g, '') - .replace(/"/g, ''); + this.selectedFont = this.deckElement.style.getPropertyValue('font-family').replace(/\'/g, '').replace(/"/g, ''); resolve(); }); diff --git a/studio/src/app/components/editor/app-deck-transition/app-deck-transition.scss b/studio/src/app/components/editor/styles/deck/app-deck-transition/app-deck-transition.scss similarity index 100% rename from studio/src/app/components/editor/app-deck-transition/app-deck-transition.scss rename to studio/src/app/components/editor/styles/deck/app-deck-transition/app-deck-transition.scss diff --git a/studio/src/app/components/editor/app-deck-transition/app-deck-transition.tsx b/studio/src/app/components/editor/styles/deck/app-deck-transition/app-deck-transition.tsx similarity index 98% rename from studio/src/app/components/editor/app-deck-transition/app-deck-transition.tsx rename to studio/src/app/components/editor/styles/deck/app-deck-transition/app-deck-transition.tsx index 6a02266cf..fea1a0f48 100644 --- a/studio/src/app/components/editor/app-deck-transition/app-deck-transition.tsx +++ b/studio/src/app/components/editor/styles/deck/app-deck-transition/app-deck-transition.tsx @@ -4,7 +4,7 @@ import {interval, Subscription} from 'rxjs'; @Component({ tag: 'app-deck-transition', - styleUrl: 'app-deck-transition.scss' + styleUrl: 'app-deck-transition.scss', }) export class AppDeckTransition { @Element() el: HTMLElement; diff --git a/studio/src/app/popovers/editor/app-align/app-align.scss b/studio/src/app/components/editor/styles/element/app-align/app-align.scss similarity index 73% rename from studio/src/app/popovers/editor/app-align/app-align.scss rename to studio/src/app/components/editor/styles/element/app-align/app-align.scss index 72365280a..6d78ca1f6 100644 --- a/studio/src/app/popovers/editor/app-align/app-align.scss +++ b/studio/src/app/components/editor/styles/element/app-align/app-align.scss @@ -1,7 +1,5 @@ app-align { - @import "../../../../global/theme/editor/editor-popover"; - - ion-item { + ion-item.align { --background-activated: transparent; --background-focused: transparent; --background-hover: transparent; @@ -11,6 +9,10 @@ app-align { &:hover, &.active { --color: var(--ion-color-primary); + + ion-icon { + color: var(--ion-color-primary); + } } } } diff --git a/studio/src/app/components/editor/styles/element/app-align/app-align.tsx b/studio/src/app/components/editor/styles/element/app-align/app-align.tsx new file mode 100644 index 000000000..641b9c823 --- /dev/null +++ b/studio/src/app/components/editor/styles/element/app-align/app-align.tsx @@ -0,0 +1,58 @@ +import {Component, Event, EventEmitter, h, Prop, State} from '@stencil/core'; + +import {AlignUtils, TextAlign} from '../../../../../utils/editor/align.utils'; + +@Component({ + tag: 'app-align', + styleUrl: 'app-align.scss', +}) +export class AppAlign { + @Prop() + selectedElement: HTMLElement; + + @State() + private align: TextAlign | undefined; + + @Event() alignChange: EventEmitter; + + async componentWillLoad() { + this.align = await AlignUtils.getAlignment(this.selectedElement); + } + + private async updateAlign(align: TextAlign): Promise { + if (!this.selectedElement) { + return; + } + + this.selectedElement.style.textAlign = align; + this.align = align; + + this.alignChange.emit(); + } + + render() { + if (this.align === undefined) { + return undefined; + } + + return ( + + Alignment + + {this.renderAlign(TextAlign.LEFT, 'Align left')} + {this.renderAlign(TextAlign.CENTER, 'Align center')} + {this.renderAlign(TextAlign.RIGHT, 'Align right')} + + + ); + } + + private renderAlign(align: TextAlign, text: string) { + return ( + this.updateAlign(align)} class={`align ${this.align == align ? 'active' : undefined}`}> + + {text} + + ); + } +} diff --git a/studio/src/app/components/editor/styles/element/app-image-style/app-image-style.tsx b/studio/src/app/components/editor/styles/element/app-image-style/app-image-style.tsx new file mode 100644 index 000000000..00459421d --- /dev/null +++ b/studio/src/app/components/editor/styles/element/app-image-style/app-image-style.tsx @@ -0,0 +1,203 @@ +import {Component, Element, Prop, State, h, EventEmitter, Event} from '@stencil/core'; + +enum ImageSize { + SMALL = '25%', + MEDIUM = '50%', + LARGE = '75%', + ORIGINAL = '100%', +} + +enum ImageAlignment { + START = 'flex-start', + CENTER = 'center', + END = 'flex-end', +} + +@Component({ + tag: 'app-image-style', +}) +export class AppImageStyle { + @Element() el: HTMLElement; + + @Event() private imgDidChange: EventEmitter; + + @Prop() + selectedElement: HTMLElement; + + @State() + private currentImageSize: ImageSize; + + @State() + private currentImageAlignment: ImageAlignment; + + async componentWillLoad() { + this.currentImageSize = await this.initImageSize(); + this.currentImageAlignment = await this.initImageAlignment(); + } + + private initImageSize(): Promise { + return new Promise((resolve) => { + if (!this.selectedElement || !this.selectedElement.style) { + resolve(null); + return; + } + + if (this.selectedElement.style.getPropertyValue('--deckgo-lazy-img-height') === '25%') { + resolve(ImageSize.SMALL); + } else if (this.selectedElement.style.getPropertyValue('--deckgo-lazy-img-height') === '50%') { + resolve(ImageSize.MEDIUM); + } else if (this.selectedElement.style.getPropertyValue('--deckgo-lazy-img-height') === '75%') { + resolve(ImageSize.LARGE); + } else { + resolve(ImageSize.ORIGINAL); + } + }); + } + + private initImageAlignment(): Promise { + return new Promise(async (resolve) => { + if (!this.selectedElement || !this.selectedElement.style) { + resolve(null); + return; + } + + if (this.selectedElement.style.getPropertyValue('justify-content') === 'center') { + resolve(ImageAlignment.CENTER); + } else if (this.selectedElement.style.getPropertyValue('justify-content') === 'flex-end') { + resolve(ImageAlignment.END); + } else if (this.selectedElement.style.getPropertyValue('justify-content') === 'flex-start') { + resolve(ImageAlignment.START); + } else { + const result: ImageAlignment = await this.findSlideDefaultAlignment(); + resolve(result); + } + }); + } + + private findSlideDefaultAlignment(): Promise { + return new Promise((resolve) => { + const parent: HTMLElement = this.selectedElement.parentElement; + + if (parent && parent.nodeName && parent.nodeName.toLowerCase().indexOf('deckgo-slide') > -1) { + const container: HTMLElement = parent.shadowRoot.querySelector('.deckgo-slide'); + if (container) { + const style: CSSStyleDeclaration = window.getComputedStyle(container); + + if (style && style.alignItems === 'center') { + resolve(ImageAlignment.CENTER); + return; + } + } + } + + resolve(ImageAlignment.START); + }); + } + + private toggleImageSize($event: CustomEvent): Promise { + return new Promise(async (resolve) => { + if (!$event || !$event.detail) { + resolve(); + return; + } + + this.currentImageSize = $event.detail.value; + + if (!this.selectedElement) { + resolve(); + return; + } + + if (this.currentImageSize === ImageSize.ORIGINAL) { + this.selectedElement.style.removeProperty('--deckgo-lazy-img-height'); + } else { + this.selectedElement.style.setProperty('--deckgo-lazy-img-height', this.currentImageSize); + } + + this.imgDidChange.emit(this.selectedElement); + + resolve(); + }); + } + + private toggleImageAlignment($event: CustomEvent): Promise { + return new Promise(async (resolve) => { + if (!$event || !$event.detail) { + resolve(); + return; + } + + this.currentImageAlignment = $event.detail.value; + + if (!this.selectedElement) { + resolve(); + return; + } + + this.selectedElement.style.setProperty('display', 'inline-flex'); + this.selectedElement.style.setProperty('justify-content', this.currentImageAlignment); + + this.imgDidChange.emit(this.selectedElement); + + resolve(); + }); + } + + render() { + return ( + + {this.renderImageSize()} + {this.renderImageAlignment()} + + ); + } + + private renderImageSize() { + return [ + + Size + , + + + Size + + this.toggleImageSize(e)} + interface="popover" + mode="md" + class="ion-padding-start ion-padding-end"> + Small + Medium + Large + Original + + , + ]; + } + + private renderImageAlignment() { + return [ + + Alignment + , + + + Alignment + + this.toggleImageAlignment(e)} + interface="popover" + mode="md" + class="ion-padding-start ion-padding-end"> + Start + Center + End + + , + ]; + } +} diff --git a/studio/src/app/popovers/editor/app-list/app-list.scss b/studio/src/app/components/editor/styles/element/app-list/app-list.scss similarity index 73% rename from studio/src/app/popovers/editor/app-list/app-list.scss rename to studio/src/app/components/editor/styles/element/app-list/app-list.scss index 1e718308d..143985fdf 100644 --- a/studio/src/app/popovers/editor/app-list/app-list.scss +++ b/studio/src/app/components/editor/styles/element/app-list/app-list.scss @@ -1,7 +1,5 @@ app-list { - @import "../../../../global/theme/editor/editor-popover"; - - ion-item { + ion-item.list { --background-activated: transparent; --background-focused: transparent; --background-hover: transparent; @@ -11,6 +9,10 @@ app-list { &:hover, &.active { --color: var(--ion-color-primary); + + ion-icon { + color: var(--ion-color-primary); + } } } } diff --git a/studio/src/app/components/editor/styles/element/app-list/app-list.tsx b/studio/src/app/components/editor/styles/element/app-list/app-list.tsx new file mode 100644 index 000000000..15adc5940 --- /dev/null +++ b/studio/src/app/components/editor/styles/element/app-list/app-list.tsx @@ -0,0 +1,46 @@ +import {Component, Event, EventEmitter, h, Prop, State} from '@stencil/core'; + +import {SlotType} from '../../../../../utils/editor/slot-type'; +import {ListUtils} from '../../../../../utils/editor/list.utils'; + +@Component({ + tag: 'app-list', + styleUrl: 'app-list.scss', +}) +export class AppList { + @Prop() + selectedElement: HTMLElement; + + @State() + private list: SlotType.OL | SlotType.UL | undefined; + + @Event() toggleList: EventEmitter; + + async componentWillLoad() { + this.list = await ListUtils.isElementList(this.selectedElement); + } + + private async selectList(list: SlotType.OL | SlotType.UL) { + this.list = list; + this.toggleList.emit(list); + } + + render() { + return ( + + List + + this.selectList(SlotType.UL)} class={`list ${this.list == SlotType.UL ? 'active' : undefined}`}> + + Unordered list + + + this.selectList(SlotType.OL)} class={`list ${this.list == SlotType.OL ? 'active' : undefined}`}> + + Ordered list + + + + ); + } +} diff --git a/studio/src/app/components/editor/styles/element/app-reveal/app-reveal.scss b/studio/src/app/components/editor/styles/element/app-reveal/app-reveal.scss new file mode 100644 index 000000000..e69de29bb diff --git a/studio/src/app/components/editor/styles/element/app-reveal/app-reveal.tsx b/studio/src/app/components/editor/styles/element/app-reveal/app-reveal.tsx new file mode 100644 index 000000000..fd8f91051 --- /dev/null +++ b/studio/src/app/components/editor/styles/element/app-reveal/app-reveal.tsx @@ -0,0 +1,37 @@ +import {Component, Event, EventEmitter, h, Prop, State} from '@stencil/core'; + +import {SlotUtils} from '../../../../../utils/editor/slot.utils'; + +@Component({ + tag: 'app-reveal', + styleUrl: 'app-reveal.scss', +}) +export class AppReveal { + @Prop() + selectedElement: HTMLElement; + + @State() + private reveal: boolean = false; + + @Event() toggleReveal: EventEmitter; + + componentWillLoad() { + this.reveal = SlotUtils.isNodeReveal(this.selectedElement) || SlotUtils.isNodeRevealList(this.selectedElement); + } + + private toggle() { + this.reveal = !this.reveal; + this.toggleReveal.emit(this.reveal); + } + + render() { + return ( + + + Animate transition + this.toggle()}> + + + ); + } +} diff --git a/studio/src/app/popovers/editor/actions/app-more-element-actions/app-more-element-actions.tsx b/studio/src/app/popovers/editor/actions/app-more-element-actions/app-more-element-actions.tsx index c22e0611f..0bebbea0e 100644 --- a/studio/src/app/popovers/editor/actions/app-more-element-actions/app-more-element-actions.tsx +++ b/studio/src/app/popovers/editor/actions/app-more-element-actions/app-more-element-actions.tsx @@ -14,12 +14,6 @@ export class AppMoreElementActions { @Prop() copy: boolean = false; - @Prop() - reveal: boolean = false; - - @Prop() - list: boolean = false; - private async closePopover(action: MoreAction) { await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss({ action: action, @@ -31,8 +25,6 @@ export class AppMoreElementActions {
{this.renderNotes()} {this.renderCopy()} - {this.renderReveal()} - {this.renderList()} {this.renderDelete()}
); @@ -62,30 +54,6 @@ export class AppMoreElementActions { ); } - private renderList() { - if (!this.list) { - return undefined; - } - - return ( - this.closePopover(MoreAction.LIST)} aria-label="List"> -

List

-
- ); - } - - private renderReveal() { - if (!this.reveal) { - return undefined; - } - - return ( - this.closePopover(MoreAction.REVEAL)} aria-label="Animation"> -

Animation

-
- ); - } - private renderDelete() { return ( this.closePopover(MoreAction.DELETE)} aria-label="Delete"> diff --git a/studio/src/app/popovers/editor/app-align/app-align.tsx b/studio/src/app/popovers/editor/app-align/app-align.tsx deleted file mode 100644 index e89064e7b..000000000 --- a/studio/src/app/popovers/editor/app-align/app-align.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import {Component, Element, h, Prop, State} from '@stencil/core'; - -import {AlignUtils, TextAlign} from '../../../utils/editor/align.utils'; - -@Component({ - tag: 'app-align', - styleUrl: 'app-align.scss', -}) -export class AppAlign { - @Element() el: HTMLElement; - - @Prop() - selectedElement: HTMLElement; - - @State() - private currentAlign: TextAlign | undefined; - - async componentWillLoad() { - this.currentAlign = await AlignUtils.getAlignment(this.selectedElement); - } - - private async closePopover(align: TextAlign) { - await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss({ - align: align, - }); - } - - private async align(align: TextAlign) { - await this.closePopover(align); - } - - render() { - return ( - - {this.renderAlign(TextAlign.LEFT, 'Align left')} - {this.renderAlign(TextAlign.CENTER, 'Align center')} - {this.renderAlign(TextAlign.RIGHT, 'Align right')} - - ); - } - - private renderAlign(align: TextAlign, text: string) { - return ( - this.align(align)} class={this.currentAlign == align ? 'active' : undefined}> - - {text} - - ); - } -} diff --git a/studio/src/app/popovers/editor/app-code/app-code.tsx b/studio/src/app/popovers/editor/app-code/app-code.tsx index 64b8a13f1..f1c9d28f8 100644 --- a/studio/src/app/popovers/editor/app-code/app-code.tsx +++ b/studio/src/app/popovers/editor/app-code/app-code.tsx @@ -209,7 +209,7 @@ export class AppCode { render() { return [ -

Code attributes

+

Code options

this.closePopover()}> diff --git a/studio/src/app/popovers/editor/app-color/app-color.tsx b/studio/src/app/popovers/editor/app-color/app-color.tsx deleted file mode 100644 index f4a7d08c5..000000000 --- a/studio/src/app/popovers/editor/app-color/app-color.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import {Component, Element, Event, EventEmitter, h, Prop, State} from '@stencil/core'; - -import {isIPad} from '@deckdeckgo/utils'; - -import {TargetElement} from '../../../utils/editor/target-element'; -import {SlotType} from '../../../utils/editor/slot-type'; - -@Component({ - tag: 'app-color', - styleUrl: 'app-color.scss' -}) -export class AppColor { - @Element() el: HTMLElement; - - @Prop() - slide: boolean = false; - - @Prop() - selectedElement: HTMLElement; - - @Event() colorDidChange: EventEmitter; - - @State() - private applyToTargetElement: TargetElement = TargetElement.SLIDE; - - @State() - private moreColors: boolean = true; - - @State() - private qrCode: boolean = false; - - @State() - private chart: boolean = false; - - @State() - private poll: boolean = false; - - @State() - private code: boolean = false; - - @State() - private shape: boolean = false; - - @State() - private author: boolean = false; - - @State() - private split: boolean = false; - - async componentWillLoad() { - if (this.slide) { - this.qrCode = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-qrcode'.toUpperCase(); - this.chart = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-chart'.toUpperCase(); - this.poll = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-poll'.toUpperCase(); - this.author = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-author'.toUpperCase(); - this.split = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-split'.toUpperCase(); - } - - this.code = this.selectedElement && this.selectedElement.nodeName && this.selectedElement.nodeName.toLocaleLowerCase() === SlotType.CODE; - this.shape = this.selectedElement && this.selectedElement.nodeName && this.selectedElement.nodeName.toLocaleLowerCase() === SlotType.DRAG_RESIZE_ROTATE; - - // prettier-ignore - this.applyToTargetElement = this.code ? TargetElement.CODE : (this.qrCode || this.poll ? TargetElement.QR_CODE : (this.chart ? TargetElement.CHART : (this.author || this.split ? TargetElement.SIDES : TargetElement.SLIDE))); - - this.moreColors = !isIPad(); - } - - private async closePopover() { - await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss(); - } - - private async selectApplyToTargetElement($event: CustomEvent) { - if ($event && $event.detail) { - this.applyToTargetElement = $event.detail; - - await this.initCurrentColors(); - } - } - - private async initCurrentColors() { - let element: HTMLElement; - - if (this.applyToTargetElement === TargetElement.QR_CODE) { - element = this.el.querySelector('app-color-qrcode'); - } else { - element = this.el.querySelector('app-color-text-background'); - } - - if (element) { - await (element as any).initCurrentColors(); - } - } - - private colorChange($event: CustomEvent) { - if ($event) { - this.colorDidChange.emit($event.detail); - } - } - - render() { - return [ - -

{this.slide ? 'Slide colors' : 'Colors'}

- this.closePopover()}> - - -
, - this.renderSelectTarget(), - - this.renderColorOptions() - ]; - } - - private renderSelectTarget() { - if (this.slide && !this.qrCode && !this.poll && !this.chart && !this.author && !this.split) { - return undefined; - } - - return ( - ) => this.selectApplyToTargetElement($event)}> - ); - } - - private renderColorOptions() { - if (this.applyToTargetElement === TargetElement.QR_CODE) { - return ( - ) => this.colorChange($event)} - moreColors={this.moreColors}> - ); - } else if (this.applyToTargetElement === TargetElement.CHART) { - return ( - ) => this.colorChange($event)} - moreColors={this.moreColors}> - ); - } else if (this.applyToTargetElement === TargetElement.CODE) { - return ( - ) => this.colorChange($event)} - moreColors={this.moreColors}> - ); - } else if (this.applyToTargetElement === TargetElement.SIDES) { - return ( - ) => this.colorChange($event)} - moreColors={this.moreColors}> - ); - } else { - return ( - ) => this.colorChange($event)}> - ); - } - } -} diff --git a/studio/src/app/popovers/editor/app-deck-style/app-deck-style.scss b/studio/src/app/popovers/editor/app-deck-style/app-deck-style.scss deleted file mode 100644 index 32bde4240..000000000 --- a/studio/src/app/popovers/editor/app-deck-style/app-deck-style.scss +++ /dev/null @@ -1,4 +0,0 @@ -app-deck-style { - @import "../../../../global/theme/editor/editor-info"; - @import "../../../../global/theme/editor/editor-popover"; -} diff --git a/studio/src/app/popovers/editor/app-image-element/app-image-element.tsx b/studio/src/app/popovers/editor/app-image-element/app-image-element.tsx index 65f167e91..11ea74ee7 100644 --- a/studio/src/app/popovers/editor/app-image-element/app-image-element.tsx +++ b/studio/src/app/popovers/editor/app-image-element/app-image-element.tsx @@ -1,10 +1,10 @@ -import {Component, Element, Prop, h, EventEmitter} from '@stencil/core'; +import {Component, Element, Prop, h} from '@stencil/core'; import {ImageAction} from '../../../utils/editor/image-action'; @Component({ tag: 'app-image-element', - styleUrl: 'app-image-element.scss' + styleUrl: 'app-image-element.scss', }) export class AppImageElement { @Element() el: HTMLElement; @@ -15,19 +15,10 @@ export class AppImageElement { @Prop() slide: boolean = false; - @Prop() - imgDidChange: EventEmitter; - private async closePopoverWithoutResults() { await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss(); } - private onImgDidChange($event: CustomEvent) { - if ($event && $event.detail) { - this.imgDidChange.emit($event.detail); - } - } - private async onAction($event: CustomEvent) { if ($event && $event.detail) { await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss($event.detail); @@ -43,10 +34,10 @@ export class AppImageElement {
, ) => this.onAction($event)} - onImgDidChange={($event: CustomEvent) => this.onImgDidChange($event)}> + onAction={($event: CustomEvent) => this.onAction($event)}>, ]; } } diff --git a/studio/src/app/popovers/editor/app-list/app-list.tsx b/studio/src/app/popovers/editor/app-list/app-list.tsx deleted file mode 100644 index 3e19bed43..000000000 --- a/studio/src/app/popovers/editor/app-list/app-list.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import {Component, Element, h, Prop, State} from '@stencil/core'; - -import {SlotType} from '../../../utils/editor/slot-type'; -import {ListUtils} from '../../../utils/editor/list.utils'; - -@Component({ - tag: 'app-list', - styleUrl: 'app-list.scss', -}) -export class AppList { - @Element() el: HTMLElement; - - @Prop() - selectedElement: HTMLElement; - - @State() - private currentList: SlotType.OL | SlotType.UL | undefined; - - async componentWillLoad() { - this.currentList = await ListUtils.isElementList(this.selectedElement); - } - - private async closePopover(list: SlotType.OL | SlotType.UL) { - await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss({ - list: list, - }); - } - - private async selectList(list: SlotType.OL | SlotType.UL) { - await this.closePopover(list); - } - - render() { - return ( - - this.selectList(SlotType.UL)} class={this.currentList == SlotType.UL ? 'active' : undefined}> - - Unordered list - - - this.selectList(SlotType.OL)} class={this.currentList == SlotType.OL ? 'active' : undefined}> - - Ordered list - - - ); - } -} diff --git a/studio/src/app/popovers/editor/app-math/app-math.tsx b/studio/src/app/popovers/editor/app-math/app-math.tsx index 10ea5fa5a..d0c8d1ce6 100644 --- a/studio/src/app/popovers/editor/app-math/app-math.tsx +++ b/studio/src/app/popovers/editor/app-math/app-math.tsx @@ -122,7 +122,7 @@ export class AppMath { render() { return [ -

Math attributes

+

Math options

this.closePopover()}> diff --git a/studio/src/app/popovers/editor/app-reveal/app-reveal.scss b/studio/src/app/popovers/editor/app-reveal/app-reveal.scss deleted file mode 100644 index 3fab8a2a1..000000000 --- a/studio/src/app/popovers/editor/app-reveal/app-reveal.scss +++ /dev/null @@ -1,9 +0,0 @@ -app-reveal { - @import "../../../../global/theme/editor/editor-popover"; - - ion-item { - --background-activated: transparent; - --background-focused: transparent; - --background-hover: transparent; - } -} diff --git a/studio/src/app/popovers/editor/app-reveal/app-reveal.tsx b/studio/src/app/popovers/editor/app-reveal/app-reveal.tsx deleted file mode 100644 index 6ca63de74..000000000 --- a/studio/src/app/popovers/editor/app-reveal/app-reveal.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import {Component, Element, h, Prop, State} from '@stencil/core'; - -import {SlotUtils} from '../../../utils/editor/slot.utils'; - -@Component({ - tag: 'app-reveal', - styleUrl: 'app-reveal.scss', -}) -export class AppReveal { - @Element() el: HTMLElement; - - @Prop() - selectedElement: HTMLElement; - - @State() - private currentReveal: boolean = false; - - componentWillLoad() { - this.currentReveal = SlotUtils.isNodeReveal(this.selectedElement) || SlotUtils.isNodeRevealList(this.selectedElement); - } - - private async closePopover(reveal: boolean) { - await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss({ - reveal: reveal, - }); - } - - render() { - return ( - - - Animate transition - this.closePopover(!this.currentReveal)}> - - - ); - } -} diff --git a/studio/src/app/popovers/editor/style/app-deck-style/app-deck-style.scss b/studio/src/app/popovers/editor/style/app-deck-style/app-deck-style.scss new file mode 100644 index 000000000..36cfc372a --- /dev/null +++ b/studio/src/app/popovers/editor/style/app-deck-style/app-deck-style.scss @@ -0,0 +1,4 @@ +app-deck-style { + @import "../../../../../global/theme/editor/editor-info"; + @import "../../../../../global/theme/editor/editor-popover"; +} diff --git a/studio/src/app/popovers/editor/app-deck-style/app-deck-style.tsx b/studio/src/app/popovers/editor/style/app-deck-style/app-deck-style.tsx similarity index 76% rename from studio/src/app/popovers/editor/app-deck-style/app-deck-style.tsx rename to studio/src/app/popovers/editor/style/app-deck-style/app-deck-style.tsx index 72a37b233..3c835f325 100644 --- a/studio/src/app/popovers/editor/app-deck-style/app-deck-style.tsx +++ b/studio/src/app/popovers/editor/style/app-deck-style/app-deck-style.tsx @@ -1,14 +1,14 @@ -import {Component, Element, Event, EventEmitter, h, Prop, State} from '@stencil/core'; +import {Component, Element, EventEmitter, h, Prop, State} from '@stencil/core'; import {isIPad} from '@deckdeckgo/utils'; -import {TargetElement} from '../../../utils/editor/target-element'; -import {ImageAction} from '../../../utils/editor/image-action'; -import {ImageHelper} from '../../../helpers/editor/image.helper'; +import {TargetElement} from '../../../../utils/editor/target-element'; +import {ImageAction} from '../../../../utils/editor/image-action'; +import {ImageHelper} from '../../../../helpers/editor/image.helper'; @Component({ tag: 'app-deck-style', - styleUrl: 'app-deck-style.scss' + styleUrl: 'app-deck-style.scss', }) export class AppDeck { @Element() el: HTMLElement; @@ -23,7 +23,7 @@ export class AppDeck { deckDidChange: EventEmitter; @State() - private applyToTargetElement: TargetElement = TargetElement.COLOR; + private applyToTargetElement: TargetElement = TargetElement.TEXT; @State() private moreColors: boolean = true; @@ -33,8 +33,6 @@ export class AppDeck { private imageHelper: ImageHelper; - @Event() private imgDidChange: EventEmitter; - async componentWillLoad() { this.moreColors = !isIPad(); @@ -77,12 +75,6 @@ export class AppDeck { } } - private onImgDidChange($event: CustomEvent) { - if ($event && $event.detail) { - this.imgDidChange.emit($event.detail); - } - } - render() { return [ @@ -92,33 +84,37 @@ export class AppDeck { , ) => this.selectApplyToTargetElement($event)}>, - this.renderOptions() + this.renderOptions(), ]; } private renderOptions() { - if (this.applyToTargetElement === TargetElement.COLOR) { + if (this.applyToTargetElement === TargetElement.TEXT) { return ( this.onColorChange()}> ); } else if (this.applyToTargetElement === TargetElement.BACKGROUND) { - return ( - ) => this.onImageAction($event)} - onImgDidChange={($event: CustomEvent) => this.onImgDidChange($event)}> - ); + onColorChange={() => this.onColorChange()}>, + ) => this.onImageAction($event)}>, + ]; } else if (this.applyToTargetElement === TargetElement.TRANSITION) { return this.onTransitionChange()}>; } else if (this.applyToTargetElement === TargetElement.FONTS) { diff --git a/studio/src/app/popovers/editor/app-color/app-color.scss b/studio/src/app/popovers/editor/style/app-element-style/app-element-style.scss similarity index 61% rename from studio/src/app/popovers/editor/app-color/app-color.scss rename to studio/src/app/popovers/editor/style/app-element-style/app-element-style.scss index 3bac06535..d8b9ebb85 100644 --- a/studio/src/app/popovers/editor/app-color/app-color.scss +++ b/studio/src/app/popovers/editor/style/app-element-style/app-element-style.scss @@ -1,6 +1,6 @@ -app-color { - @import "../../../../global/theme/editor/editor-info"; - @import "../../../../global/theme/editor/editor-popover"; +app-element-style { + @import "../../../../../global/theme/editor/editor-info"; + @import "../../../../../global/theme/editor/editor-popover"; ion-icon.more { font-size: 1rem; diff --git a/studio/src/app/popovers/editor/style/app-element-style/app-element-style.tsx b/studio/src/app/popovers/editor/style/app-element-style/app-element-style.tsx new file mode 100644 index 000000000..bfb2aa61b --- /dev/null +++ b/studio/src/app/popovers/editor/style/app-element-style/app-element-style.tsx @@ -0,0 +1,254 @@ +import {Component, Element, Event, EventEmitter, h, Prop, State} from '@stencil/core'; + +import {isIPad} from '@deckdeckgo/utils'; + +import {TargetElement} from '../../../../utils/editor/target-element'; +import {SlotType} from '../../../../utils/editor/slot-type'; +import {ImageAction} from '../../../../utils/editor/image-action'; +import {ListUtils} from '../../../../utils/editor/list.utils'; + +import {ImageHelper} from '../../../../helpers/editor/image.helper'; + +@Component({ + tag: 'app-element-style', + styleUrl: 'app-element-style.scss', +}) +export class AppElementStyle { + @Element() el: HTMLElement; + + @Prop() + slide: boolean = false; + + @Prop() + selectedElement: HTMLElement; + + @Prop() + imgDidChange: EventEmitter; + + @Prop() + imageHelper: ImageHelper; + + @Prop() + code: boolean = false; + + @Prop() + math: boolean = false; + + @Prop() + shape: boolean = false; + + @Prop() + image: boolean = false; + + @Event() styleDidChange: EventEmitter; + + @State() + private applyToTargetElement: TargetElement = TargetElement.SLIDE; + + @State() + private moreColors: boolean = true; + + @State() + private qrCode: boolean = false; + + @State() + private chart: boolean = false; + + @State() + private poll: boolean = false; + + @State() + private author: boolean = false; + + @State() + private split: boolean = false; + + @State() + private demo: boolean = false; + + @State() + private list: SlotType.OL | SlotType.UL | undefined; + + async componentWillLoad() { + if (this.slide) { + this.qrCode = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-qrcode'.toUpperCase(); + this.chart = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-chart'.toUpperCase(); + this.poll = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-poll'.toUpperCase(); + this.author = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-author'.toUpperCase(); + this.split = this.selectedElement && this.selectedElement.tagName && this.selectedElement.tagName.toUpperCase() === 'deckgo-slide-split'.toUpperCase(); + } + + this.demo = this.selectedElement && this.selectedElement.nodeName && this.selectedElement.nodeName.toLocaleLowerCase() === SlotType.DEMO; + + this.list = await ListUtils.isElementList(this.selectedElement); + + this.applyToTargetElement = this.image + ? TargetElement.IMAGE + : this.code + ? TargetElement.CODE + : this.qrCode || this.poll + ? TargetElement.QR_CODE + : this.chart + ? TargetElement.CHART + : this.author || this.split + ? TargetElement.SIDES + : TargetElement.SLIDE; + + this.moreColors = !isIPad(); + } + + private async closePopover() { + await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss(); + } + + private async selectApplyToTargetElement($event: CustomEvent) { + if ($event && $event.detail) { + this.applyToTargetElement = $event.detail; + + await this.initCurrentColors(); + } + } + + private async initCurrentColors() { + let element: HTMLElement; + + if (this.applyToTargetElement === TargetElement.QR_CODE) { + element = this.el.querySelector('app-color-qrcode'); + } else { + element = this.el.querySelector('app-color-text-background'); + } + + if (element) { + await (element as any).initCurrentColors(); + } + } + + private emitStyleChange() { + this.styleDidChange.emit(); + } + + private async onImageAction($event: CustomEvent) { + if (!this.slide) { + return; + } + + if ($event && $event.detail) { + const popover = this.el.closest('ion-popover') as HTMLIonPopoverElement; + + popover.onWillDismiss().then(async () => { + await this.imageHelper.imageAction(this.selectedElement, true, false, $event.detail); + }); + + await popover.dismiss(); + } + } + + private onImgDidChange($event: CustomEvent) { + if ($event && $event.detail) { + this.imgDidChange.emit($event.detail); + } + } + + render() { + return [ + +

{this.slide ? 'Slide style' : 'Style'}

+ this.closePopover()}> + + +
, + this.renderSelectTarget(), + + this.renderStyleOptions(), + ]; + } + + private renderSelectTarget() { + const elementTarget: boolean = !this.slide && !this.shape && !this.image; + const transition: boolean = !this.slide && !this.code && !this.math && !this.shape && !this.demo; + + return ( + ) => this.selectApplyToTargetElement($event)}> + ); + } + + private renderStyleOptions() { + if (this.applyToTargetElement === TargetElement.QR_CODE) { + return ( + this.emitStyleChange()} moreColors={this.moreColors}> + ); + } else if (this.applyToTargetElement === TargetElement.CHART) { + return ( + this.emitStyleChange()} moreColors={this.moreColors}> + ); + } else if (this.applyToTargetElement === TargetElement.CODE) { + return this.emitStyleChange()} moreColors={this.moreColors}>; + } else if (this.applyToTargetElement === TargetElement.SIDES) { + return ( + this.emitStyleChange()} + moreColors={this.moreColors}> + ); + } else if (this.applyToTargetElement === TargetElement.BACKGROUND) { + return [ + this.emitStyleChange()}>, + this.renderImage(), + ]; + } else if (this.applyToTargetElement === TargetElement.TRANSITION) { + return this.closePopover()}>; + } else if (this.applyToTargetElement === TargetElement.IMAGE) { + return ( + ) => this.onImgDidChange($event)}> + ); + } else { + return [ + this.emitStyleChange()}>, + this.emitStyleChange()}>, + this.renderList(), + ]; + } + } + + private renderImage() { + if (!this.slide) { + return undefined; + } + + return ( + ) => this.onImageAction($event)}> + ); + } + + private renderList() { + if (!this.list) { + return undefined; + } + + return this.closePopover()}>; + } +} diff --git a/studio/src/app/utils/editor/target-element.tsx b/studio/src/app/utils/editor/target-element.tsx index 13b7fa180..2de21da57 100644 --- a/studio/src/app/utils/editor/target-element.tsx +++ b/studio/src/app/utils/editor/target-element.tsx @@ -4,11 +4,12 @@ export enum TargetElement { SLIDE = 'slide', SECTION = 'section', CODE = 'code', - COLOR = 'color', + TEXT = 'text', BACKGROUND = 'background', TRANSITION = 'transition', SIDES = 'sides', FONTS = 'fonts', SHAPES = 'shapes', - IMAGES = 'shape' + IMAGES = 'images', + IMAGE = 'image', } diff --git a/studio/src/assets/assets.json b/studio/src/assets/assets.json index 7ebf49279..3deb9ee5d 100644 --- a/studio/src/assets/assets.json +++ b/studio/src/assets/assets.json @@ -229,17 +229,17 @@ {"src": "/icons/ionicons/create.svg", "ariaLabel": "Notes"}, {"src": "/icons/ionicons/copy.svg", "ariaLabel": "Copy"}, {"src": "/icons/ionicons/color-palette.svg", "ariaLabel": "Color"}, - {"src": "/icons/ionicons/pencil.svg", "ariaLabel": "Edit"}, {"src": "/icons/ionicons/add.svg", "ariaLabel": "Add"}, {"src": "/icons/ionicons/shapes.svg", "ariaLabel": "Shapes"}, {"src": "/icons/ionicons/code.svg", "ariaLabel": "Code"}, {"src": "/icons/ionicons/images.svg", "ariaLabel": "Images"}, - {"src": "/icons/album.svg", "ariaLabel": "Animation"}, {"src": "/icons/ionicons/checkmark.svg", "ariaLabel": "Check"}, {"src": "/icons/align-center.svg", "ariaLabel": "Align center"}, {"src": "/icons/align-left.svg", "ariaLabel": "Align left"}, {"src": "/icons/align-right.svg", "ariaLabel": "Align right"}, {"src": "/icons/math.svg", "ariaLabel": "Math"}, - {"src": "/icons/ionicons/color-wand.svg", "ariaLabel": "Transform element"} + {"src": "/icons/ionicons/color-wand.svg", "ariaLabel": "Transform element"}, + {"src": "/icons/ionicons/chevron-down.svg", "ariaLabel": "Chevron down"}, + {"src": "/icons/ionicons/settings.svg", "ariaLabel": "Settings"} ] } diff --git a/studio/src/assets/icons/album.svg b/studio/src/assets/icons/album.svg deleted file mode 100644 index 9d82fe50e..000000000 --- a/studio/src/assets/icons/album.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/studio/src/assets/icons/ionicons/chevron-down.svg b/studio/src/assets/icons/ionicons/chevron-down.svg new file mode 100644 index 000000000..0ddceaab6 --- /dev/null +++ b/studio/src/assets/icons/ionicons/chevron-down.svg @@ -0,0 +1 @@ +ionicons-v5-a diff --git a/studio/src/assets/icons/ionicons/settings.svg b/studio/src/assets/icons/ionicons/settings.svg new file mode 100644 index 000000000..204a1e405 --- /dev/null +++ b/studio/src/assets/icons/ionicons/settings.svg @@ -0,0 +1 @@ +ionicons-v5-q diff --git a/studio/src/components.d.ts b/studio/src/components.d.ts index c1c63a5c6..cdfd3e787 100644 --- a/studio/src/components.d.ts +++ b/studio/src/components.d.ts @@ -29,9 +29,15 @@ import { import { EditAction, } from './app/utils/editor/edit-action'; +import { + ImageHelper, +} from './app/helpers/editor/image.helper'; import { ImageAction, } from './app/utils/editor/image-action'; +import { + SlotType, +} from './app/utils/editor/slot-type'; import { TargetElement, } from './app/utils/editor/target-element'; @@ -41,9 +47,6 @@ import { import { ItemReorderEventDetail, } from '@ionic/core'; -import { - SlotType, -} from './app/utils/editor/slot-type'; export namespace Components { interface AppAbout {} @@ -102,10 +105,6 @@ export namespace Components { 'currentLanguage': PrismLanguage | undefined; 'selectedElement': HTMLElement; } - interface AppColor { - 'selectedElement': HTMLElement; - 'slide': boolean; - } interface AppColorChart { 'initCurrentColors': () => Promise; 'moreColors': boolean; @@ -127,7 +126,9 @@ export namespace Components { 'template': 'split' | 'author'; } interface AppColorTextBackground { + 'colorType': 'text' | 'background'; 'deck': boolean; + 'expander': boolean; 'initCurrentColors': () => Promise; 'moreColors': boolean; 'selectedElement': HTMLElement; @@ -185,7 +186,20 @@ export namespace Components { 'deckId': string; } interface AppElementDelete {} + interface AppElementStyle { + 'code': boolean; + 'image': boolean; + 'imageHelper': ImageHelper; + 'imgDidChange': EventEmitter; + 'math': boolean; + 'selectedElement': HTMLElement; + 'shape': boolean; + 'slide': boolean; + } interface AppEmbed {} + interface AppExpansionPanel { + 'expander': boolean; + } interface AppFaq {} interface AppFeed {} interface AppFeedCard { @@ -209,6 +223,7 @@ export namespace Components { interface AppImage { 'deck': boolean; 'deleteBackground': boolean; + 'expander': boolean; 'selectedElement': HTMLElement; 'slide': boolean; } @@ -217,10 +232,12 @@ export namespace Components { 'imagesOdd': (UnsplashPhoto | TenorGif | StorageFile)[]; } interface AppImageElement { - 'imgDidChange': EventEmitter; 'selectedElement': HTMLElement; 'slide': boolean; } + interface AppImageStyle { + 'selectedElement': HTMLElement; + } interface AppInactivity { 'fullscreen': boolean; } @@ -242,9 +259,7 @@ export namespace Components { } interface AppMoreElementActions { 'copy': boolean; - 'list': boolean; 'notes': boolean; - 'reveal': boolean; } interface AppMoreShareOptions {} interface AppNavigation { @@ -299,13 +314,14 @@ export namespace Components { 'background': boolean; 'chart': boolean; 'code': boolean; - 'colorTarget': boolean; 'fonts': boolean; + 'image': boolean; 'images': boolean; 'qrCode': boolean; 'shapes': boolean; 'sides': boolean; 'slide': boolean; + 'textTarget': boolean; 'transition': boolean; } interface AppServices {} @@ -417,12 +433,6 @@ declare global { new (): HTMLAppCodeLanguagesElement; }; - interface HTMLAppColorElement extends Components.AppColor, HTMLStencilElement {} - var HTMLAppColorElement: { - prototype: HTMLAppColorElement; - new (): HTMLAppColorElement; - }; - interface HTMLAppColorChartElement extends Components.AppColorChart, HTMLStencilElement {} var HTMLAppColorChartElement: { prototype: HTMLAppColorChartElement; @@ -567,12 +577,24 @@ declare global { new (): HTMLAppElementDeleteElement; }; + interface HTMLAppElementStyleElement extends Components.AppElementStyle, HTMLStencilElement {} + var HTMLAppElementStyleElement: { + prototype: HTMLAppElementStyleElement; + new (): HTMLAppElementStyleElement; + }; + interface HTMLAppEmbedElement extends Components.AppEmbed, HTMLStencilElement {} var HTMLAppEmbedElement: { prototype: HTMLAppEmbedElement; new (): HTMLAppEmbedElement; }; + interface HTMLAppExpansionPanelElement extends Components.AppExpansionPanel, HTMLStencilElement {} + var HTMLAppExpansionPanelElement: { + prototype: HTMLAppExpansionPanelElement; + new (): HTMLAppExpansionPanelElement; + }; + interface HTMLAppFaqElement extends Components.AppFaq, HTMLStencilElement {} var HTMLAppFaqElement: { prototype: HTMLAppFaqElement; @@ -657,6 +679,12 @@ declare global { new (): HTMLAppImageElementElement; }; + interface HTMLAppImageStyleElement extends Components.AppImageStyle, HTMLStencilElement {} + var HTMLAppImageStyleElement: { + prototype: HTMLAppImageStyleElement; + new (): HTMLAppImageStyleElement; + }; + interface HTMLAppInactivityElement extends Components.AppInactivity, HTMLStencilElement {} var HTMLAppInactivityElement: { prototype: HTMLAppInactivityElement; @@ -963,7 +991,6 @@ declare global { 'app-breadcrumbs': HTMLAppBreadcrumbsElement; 'app-code': HTMLAppCodeElement; 'app-code-languages': HTMLAppCodeLanguagesElement; - 'app-color': HTMLAppColorElement; 'app-color-chart': HTMLAppColorChartElement; 'app-color-code': HTMLAppColorCodeElement; 'app-color-qrcode': HTMLAppColorQrcodeElement; @@ -988,7 +1015,9 @@ declare global { 'app-edit-slide-qrcode': HTMLAppEditSlideQrcodeElement; 'app-editor': HTMLAppEditorElement; 'app-element-delete': HTMLAppElementDeleteElement; + 'app-element-style': HTMLAppElementStyleElement; 'app-embed': HTMLAppEmbedElement; + 'app-expansion-panel': HTMLAppExpansionPanelElement; 'app-faq': HTMLAppFaqElement; 'app-feed': HTMLAppFeedElement; 'app-feed-card': HTMLAppFeedCardElement; @@ -1003,6 +1032,7 @@ declare global { 'app-image': HTMLAppImageElement; 'app-image-columns': HTMLAppImageColumnsElement; 'app-image-element': HTMLAppImageElementElement; + 'app-image-style': HTMLAppImageStyleElement; 'app-inactivity': HTMLAppInactivityElement; 'app-landing': HTMLAppLandingElement; 'app-landing-content': HTMLAppLandingContentElement; @@ -1114,6 +1144,7 @@ declare namespace LocalJSX { 'slideCopy'?: EventEmitter; } interface AppAlign { + 'onAlignChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; } interface AppAvatar { @@ -1133,36 +1164,33 @@ declare namespace LocalJSX { 'currentLanguage'?: PrismLanguage | undefined; 'selectedElement'?: HTMLElement; } - interface AppColor { - 'onColorDidChange'?: (event: CustomEvent) => void; - 'selectedElement'?: HTMLElement; - 'slide'?: boolean; - } interface AppColorChart { 'moreColors'?: boolean; - 'onColorChange'?: (event: CustomEvent) => void; + 'onColorChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; } interface AppColorCode { 'moreColors'?: boolean; - 'onColorChange'?: (event: CustomEvent) => void; + 'onColorChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; } interface AppColorQrcode { 'moreColors'?: boolean; - 'onColorChange'?: (event: CustomEvent) => void; + 'onColorChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; } interface AppColorSides { 'moreColors'?: boolean; - 'onColorChange'?: (event: CustomEvent) => void; + 'onColorChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; 'template'?: 'split' | 'author'; } interface AppColorTextBackground { + 'colorType'?: 'text' | 'background'; 'deck'?: boolean; + 'expander'?: boolean; 'moreColors'?: boolean; - 'onColorChange'?: (event: CustomEvent) => void; + 'onColorChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; 'shape'?: boolean; 'slide'?: boolean; @@ -1190,7 +1218,6 @@ declare namespace LocalJSX { interface AppDeckStyle { 'blockSlide'?: EventEmitter; 'deckDidChange'?: EventEmitter; - 'onImgDidChange'?: (event: CustomEvent) => void; 'signIn'?: EventEmitter; } interface AppDeckTransition { @@ -1227,7 +1254,21 @@ declare namespace LocalJSX { 'deckId'?: string; } interface AppElementDelete {} + interface AppElementStyle { + 'code'?: boolean; + 'image'?: boolean; + 'imageHelper'?: ImageHelper; + 'imgDidChange'?: EventEmitter; + 'math'?: boolean; + 'onStyleDidChange'?: (event: CustomEvent) => void; + 'selectedElement'?: HTMLElement; + 'shape'?: boolean; + 'slide'?: boolean; + } interface AppEmbed {} + interface AppExpansionPanel { + 'expander'?: boolean; + } interface AppFaq {} interface AppFeed {} interface AppFeedCard { @@ -1258,8 +1299,8 @@ declare namespace LocalJSX { interface AppImage { 'deck'?: boolean; 'deleteBackground'?: boolean; + 'expander'?: boolean; 'onAction'?: (event: CustomEvent) => void; - 'onImgDidChange'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; 'slide'?: boolean; } @@ -1269,10 +1310,13 @@ declare namespace LocalJSX { 'onSelectImage'?: (event: CustomEvent) => void; } interface AppImageElement { - 'imgDidChange'?: EventEmitter; 'selectedElement'?: HTMLElement; 'slide'?: boolean; } + interface AppImageStyle { + 'onImgDidChange'?: (event: CustomEvent) => void; + 'selectedElement'?: HTMLElement; + } interface AppInactivity { 'fullscreen'?: boolean; 'onMouseInactivity'?: (event: CustomEvent) => void; @@ -1282,6 +1326,7 @@ declare namespace LocalJSX { interface AppLandingDeck {} interface AppLandingFooter {} interface AppList { + 'onToggleList'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; } interface AppLogo {} @@ -1295,9 +1340,7 @@ declare namespace LocalJSX { } interface AppMoreElementActions { 'copy'?: boolean; - 'list'?: boolean; 'notes'?: boolean; - 'reveal'?: boolean; } interface AppMoreShareOptions {} interface AppNavigation { @@ -1349,6 +1392,7 @@ declare namespace LocalJSX { interface AppRemoteConnect {} interface AppRemoteRequest {} interface AppReveal { + 'onToggleReveal'?: (event: CustomEvent) => void; 'selectedElement'?: HTMLElement; } interface AppRoot {} @@ -1356,14 +1400,15 @@ declare namespace LocalJSX { 'background'?: boolean; 'chart'?: boolean; 'code'?: boolean; - 'colorTarget'?: boolean; 'fonts'?: boolean; + 'image'?: boolean; 'images'?: boolean; 'onApplyTo'?: (event: CustomEvent) => void; 'qrCode'?: boolean; 'shapes'?: boolean; 'sides'?: boolean; 'slide'?: boolean; + 'textTarget'?: boolean; 'transition'?: boolean; } interface AppServices {} @@ -1415,7 +1460,6 @@ declare namespace LocalJSX { 'app-breadcrumbs': AppBreadcrumbs; 'app-code': AppCode; 'app-code-languages': AppCodeLanguages; - 'app-color': AppColor; 'app-color-chart': AppColorChart; 'app-color-code': AppColorCode; 'app-color-qrcode': AppColorQrcode; @@ -1440,7 +1484,9 @@ declare namespace LocalJSX { 'app-edit-slide-qrcode': AppEditSlideQrcode; 'app-editor': AppEditor; 'app-element-delete': AppElementDelete; + 'app-element-style': AppElementStyle; 'app-embed': AppEmbed; + 'app-expansion-panel': AppExpansionPanel; 'app-faq': AppFaq; 'app-feed': AppFeed; 'app-feed-card': AppFeedCard; @@ -1455,6 +1501,7 @@ declare namespace LocalJSX { 'app-image': AppImage; 'app-image-columns': AppImageColumns; 'app-image-element': AppImageElement; + 'app-image-style': AppImageStyle; 'app-inactivity': AppInactivity; 'app-landing': AppLanding; 'app-landing-content': AppLandingContent; @@ -1525,7 +1572,6 @@ declare module "@stencil/core" { 'app-breadcrumbs': LocalJSX.AppBreadcrumbs & JSXBase.HTMLAttributes; 'app-code': LocalJSX.AppCode & JSXBase.HTMLAttributes; 'app-code-languages': LocalJSX.AppCodeLanguages & JSXBase.HTMLAttributes; - 'app-color': LocalJSX.AppColor & JSXBase.HTMLAttributes; 'app-color-chart': LocalJSX.AppColorChart & JSXBase.HTMLAttributes; 'app-color-code': LocalJSX.AppColorCode & JSXBase.HTMLAttributes; 'app-color-qrcode': LocalJSX.AppColorQrcode & JSXBase.HTMLAttributes; @@ -1550,7 +1596,9 @@ declare module "@stencil/core" { 'app-edit-slide-qrcode': LocalJSX.AppEditSlideQrcode & JSXBase.HTMLAttributes; 'app-editor': LocalJSX.AppEditor & JSXBase.HTMLAttributes; 'app-element-delete': LocalJSX.AppElementDelete & JSXBase.HTMLAttributes; + 'app-element-style': LocalJSX.AppElementStyle & JSXBase.HTMLAttributes; 'app-embed': LocalJSX.AppEmbed & JSXBase.HTMLAttributes; + 'app-expansion-panel': LocalJSX.AppExpansionPanel & JSXBase.HTMLAttributes; 'app-faq': LocalJSX.AppFaq & JSXBase.HTMLAttributes; 'app-feed': LocalJSX.AppFeed & JSXBase.HTMLAttributes; 'app-feed-card': LocalJSX.AppFeedCard & JSXBase.HTMLAttributes; @@ -1565,6 +1613,7 @@ declare module "@stencil/core" { 'app-image': LocalJSX.AppImage & JSXBase.HTMLAttributes; 'app-image-columns': LocalJSX.AppImageColumns & JSXBase.HTMLAttributes; 'app-image-element': LocalJSX.AppImageElement & JSXBase.HTMLAttributes; + 'app-image-style': LocalJSX.AppImageStyle & JSXBase.HTMLAttributes; 'app-inactivity': LocalJSX.AppInactivity & JSXBase.HTMLAttributes; 'app-landing': LocalJSX.AppLanding & JSXBase.HTMLAttributes; 'app-landing-content': LocalJSX.AppLandingContent & JSXBase.HTMLAttributes; diff --git a/studio/src/global/theme/editor/editor-info.scss b/studio/src/global/theme/editor/editor-info.scss index 886deab79..55641ea16 100644 --- a/studio/src/global/theme/editor/editor-info.scss +++ b/studio/src/global/theme/editor/editor-info.scss @@ -1,16 +1,23 @@ -ion-item-divider { +ion-item-divider, +app-expansion-panel { button.info { background: var(--ion-color-light); border: 1px solid #dedede; border-radius: 50%; height: 1.5rem; width: 1.5rem; - margin: 16px 16px 0; padding: 0; outline: 0; ion-icon { color: var(--ion-color-light-contrast); + margin: 0; } } } + +ion-item-divider { + button.info { + margin: 16px 16px 0; + } +} diff --git a/studio/src/global/theme/editor/editor-popover.scss b/studio/src/global/theme/editor/editor-popover.scss index 5c5100a48..6cc788acc 100644 --- a/studio/src/global/theme/editor/editor-popover.scss +++ b/studio/src/global/theme/editor/editor-popover.scss @@ -8,6 +8,10 @@ ion-list.list-ios { padding-bottom: 8px; } +ion-list[class*="list"] { + padding: 0; +} + ion-item { --border-width: 0; --inner-border-width: 0; @@ -55,6 +59,13 @@ ion-button.delete { ion-segment { ion-segment-button { + text-transform: none; + font-size: var(--font-size-normal); + font-weight: 400; + + --indicator-color: black; + --color-checked: black; + &:first-of-type { margin-left: 8px; } diff --git a/studio/src/global/theme/popover.scss b/studio/src/global/theme/popover.scss index 47b2ffa45..0c331f4bb 100644 --- a/studio/src/global/theme/popover.scss +++ b/studio/src/global/theme/popover.scss @@ -3,16 +3,19 @@ ion-popover { ion-router-link[slot="end"] { cursor: pointer; border-bottom-color: transparent; + color: black; } } } ion-popover.popover-menu { &.popover-menu-wide { - --width: 420px; + --width: 380px; --max-width: 100%; } + --width: 284px; + div.popover-content { top: 0 !important; left: inherit !important;