UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

456 lines (455 loc) 16.7 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var IgcTileComponent_1; import { LitElement, html, nothing } from 'lit'; import { property, query, queryAssignedElements, state, } from 'lit/decorators.js'; import { createRef, ref } from 'lit/directives/ref.js'; import { startViewTransition } from '../../animations/player.js'; import { themes } from '../../theming/theming-decorator.js'; import IgcIconButtonComponent from '../button/icon-button.js'; import { tileManagerContext, } from '../common/context.js'; import { createAsyncContext } from '../common/controllers/async-consumer.js'; import { addDragController, } from '../common/controllers/drag.js'; import { addFullscreenController } from '../common/controllers/fullscreen.js'; import { registerComponent } from '../common/definitions/register.js'; import { EventEmitterMixin } from '../common/mixins/event-emitter.js'; import { asNumber, createCounter, findElementFromEventPath, getCenterPoint, isEmpty, partNameMap, } from '../common/util.js'; import IgcDividerComponent from '../divider/divider.js'; import IgcResizeContainerComponent from '../resize-container/resize-container.js'; import { createTileDragStack, swapTiles } from './position.js'; import { createTileResizeState } from './resize-state.js'; import { styles as shared } from './themes/shared/tile/tile.common.css.js'; import { styles } from './themes/tile.base.css.js'; import { all } from './themes/tile.js'; import { createTileDragGhost, createTileGhost } from './tile-ghost-util.js'; let IgcTileComponent = IgcTileComponent_1 = class IgcTileComponent extends EventEmitterMixin(LitElement) { constructor() { super(...arguments); this._dragController = addDragController(this, { skip: this._skipDrag, matchTarget: this._match, ghost: this._createDragGhost, start: this._handleDragStart, over: this._handleDragOver, end: this._handleDragEnd, cancel: this._handleDragCancel, }); this._fullscreenController = addFullscreenController(this, { enter: this._emitFullScreenEvent, exit: this._emitFullScreenEvent, }); this._colSpan = 1; this._rowSpan = 1; this._colStart = null; this._rowStart = null; this._position = -1; this._resizeState = createTileResizeState(); this._dragStack = createTileDragStack(); this._customAdorners = new Map(Object.entries({ side: false, corner: false, bottom: false, })); this._setDragConfiguration = ({ instance: { dragMode }, }) => { this._dragController.set({ enabled: dragMode !== 'none', trigger: dragMode === 'tile-header' ? () => this._headerRef.value : undefined, }); }; this._context = createAsyncContext(this, tileManagerContext, this._setDragConfiguration); this._headerRef = createRef(); this._maximized = false; this._isDragging = false; this._isResizing = false; this.disableResize = false; this.disableFullscreen = false; this.disableMaximize = false; this._createResizeGhost = () => { return createTileGhost(this); }; } static register() { registerComponent(IgcTileComponent_1, IgcIconButtonComponent, IgcDividerComponent, IgcResizeContainerComponent); } get _tileManagerCtx() { return this._context.value; } get _tileManager() { return this._tileManagerCtx?.instance; } get _cssContainer() { return this._tileManagerCtx?.grid.value; } get _resizeMode() { return this._tileManager?.resizeMode ?? 'none'; } get _resizeDisabled() { return (this.disableResize || this.maximized || this.fullscreen || this._resizeMode === 'none'); } set colSpan(value) { this._colSpan = Math.max(1, asNumber(value)); this.style.setProperty('--ig-col-span', this._colSpan.toString()); } get colSpan() { return this._colSpan; } set rowSpan(value) { this._rowSpan = Math.max(1, asNumber(value)); this.style.setProperty('--ig-row-span', this._rowSpan.toString()); } get rowSpan() { return this._rowSpan; } set colStart(value) { this._colStart = Math.max(0, asNumber(value)) || null; this.style.setProperty('--ig-col-start', this._colStart ? this._colStart.toString() : null); } get colStart() { return this._colStart; } set rowStart(value) { this._rowStart = Math.max(0, asNumber(value)) || null; this.style.setProperty('--ig-row-start', this._rowStart ? this._rowStart.toString() : null); } get rowStart() { return this._rowStart; } get fullscreen() { return this._fullscreenController.fullscreen; } set maximized(value) { this._maximized = value; if (this._tileManagerCtx) { this._tileManagerCtx.instance.requestUpdate(); } } get maximized() { return this._maximized; } set position(value) { this._position = asNumber(value); this.style.order = this._position.toString(); } get position() { return this._position; } connectedCallback() { super.connectedCallback(); this.id = this.id || `tile-${IgcTileComponent_1.increment()}`; this.style.viewTransitionName = this.style.viewTransitionName || `tile-transition-${this.id}`; } createRenderRoot() { const root = super.createRenderRoot(); root.addEventListener('slotchange', () => this.requestUpdate()); return root; } _setDragState(state = true) { this._isDragging = state; this._tileContent.style.opacity = state ? '0' : ''; this.style.pointerEvents = state ? 'none' : ''; this.part.toggle('dragging', state); } _handleDragStart() { if (!this._emitTileDragStart()) { return false; } this._setDragState(); this._dragStack.push(this); return true; } _handleDragOver(parameters) { const match = parameters.state.element; const { clientX, clientY } = parameters.event; if (this._dragStack.peek() === match) { const { x, y } = getCenterPoint(match); const shouldSwap = this.position <= match.position ? clientX > x || clientY > y : clientX < x || clientY < y; if (shouldSwap) { this._dragStack.pop(); this._dragStack.push(match); startViewTransition(() => { swapTiles(this, match); }); } return; } this._dragStack.push(match); startViewTransition(() => { swapTiles(this, match); }); } _handleDragCancel() { startViewTransition(() => { this._dragStack.restore(); this._dragStack.reset(); }); this._dragController.dispose(); this._setDragState(false); this.emitEvent('igcTileDragCancel', { detail: this }); } _handleDragEnd() { this._setDragState(false); this._dragStack.reset(); this.emitEvent('igcTileDragEnd', { detail: this }); } _skipDrag(event) { if (this._maximized || this.fullscreen) { return true; } return Boolean(findElementFromEventPath((e) => e.matches('[part*=trigger]') || e.matches('#tile-actions'), event)); } _match(element) { return element !== this && IgcTileComponent_1.tagName === element.localName; } _createDragGhost() { return createTileDragGhost(this); } _setResizeState(state = true) { this._isResizing = state; this.style.zIndex = state ? '1' : ''; this.part.toggle('resizing', state); } _handleResizeStart(event) { if (!this._emitTileResizeStart()) { event.preventDefault(); return; } this._resizeState.updateState(event.detail.state.initial, this, this._cssContainer); this._setResizeState(); } _handleResize({ detail: { state }, }) { const trigger = state.trigger; const isWidthResize = trigger.matches('[part*="side"], [part="trigger"]'); const isHeightResize = trigger.matches('[part*="bottom"], [part="trigger"]'); if (isWidthResize) { state.current.width = this._resizeState.calculateSnappedWidth(state); } if (isHeightResize) { state.current.height = this._resizeState.calculateSnappedHeight(state); } } _handleResizeEnd({ detail: { state }, }) { const { colSpan, rowSpan } = this._resizeState.calculateResizedGridPosition(state.current); state.commit = async () => { await startViewTransition(() => { this.colSpan = colSpan; this.rowSpan = rowSpan; }).transition?.updateCallbackDone; this._setResizeState(false); this.emitEvent('igcTileResizeEnd', { detail: this }); }; } _handleResizeCancel() { this._setResizeState(false); this.emitEvent('igcTileResizeCancel', { detail: this }); } _handleFullscreen() { this._fullscreenController.setState(!this.fullscreen); } _handleMaximize() { if (!this._emitMaximizedEvent()) { return; } this.maximized = !this.maximized; } _emitFullScreenEvent(state) { this.requestUpdate(); return this.emitEvent('igcTileFullscreen', { detail: { tile: this, state }, cancelable: true, }); } _emitMaximizedEvent() { return this.emitEvent('igcTileMaximize', { detail: { tile: this, state: !this.maximized }, cancelable: true, }); } _emitTileDragStart() { return this.emitEvent('igcTileDragStart', { detail: this, cancelable: true, }); } _emitTileResizeStart() { return this.emitEvent('igcTileResizeStart', { detail: this, cancelable: true, }); } _renderDefaultAction(type) { const [icon, listener] = type === 'fullscreen' ? [ this.fullscreen ? 'fullscreen_exit' : 'fullscreen', this._handleFullscreen, ] : [ this._maximized ? 'collapse_content' : 'expand_content', this._handleMaximize, ]; return html ` <igc-icon-button variant="flat" collection="default" exportparts="icon" name=${icon} aria-label=${icon} @click=${listener} ></igc-icon-button> `; } _renderHeader() { const hideHeader = isEmpty(this._titleElements) && isEmpty(this._actionsElements) && this.disableMaximize && this.disableFullscreen; const hasMaximizeSlot = !(this.disableMaximize || this.fullscreen); const hasFullscreenSlot = !this.disableFullscreen; return html ` <section part="header" ?hidden=${hideHeader} ${ref(this._headerRef)}> <header part="title"> <slot name="title"></slot> </header> <section id="tile-actions" part="actions"> ${hasMaximizeSlot ? html ` <slot name="maximize-action"> ${this._renderDefaultAction('maximize')} </slot> ` : nothing} ${hasFullscreenSlot ? html ` <slot name="fullscreen-action"> ${this._renderDefaultAction('fullscreen')} </slot> ` : nothing} <slot name="actions"></slot> </section> </section> <igc-divider></igc-divider> `; } _renderContent() { const parts = partNameMap({ base: true, draggable: this._tileManager?.dragMode !== 'none', fullscreen: this.fullscreen, dragging: this._isDragging, resizable: !this.disableResize && this._tileManager?.resizeMode !== 'none', resizing: this._isResizing, maximized: this.maximized, }); return html ` <div part=${parts}> ${this._renderHeader()} <div part="content-container"> <slot></slot> </div> </div> `; } _renderAdornerSlot(name) { return html ` <slot @slotchange=${() => this._customAdorners.set(name, true)} name="${name}-adorner" slot="${name}-adorner" > </slot> `; } render() { const isActive = this._resizeMode === 'always'; return this._resizeDisabled ? this._renderContent() : html ` <igc-resize part=${partNameMap({ resize: true, 'side-adorner': this._customAdorners.get('side'), 'corner-adorner': this._customAdorners.get('corner'), 'bottom-adorner': this._customAdorners.get('bottom'), })} exportparts="trigger-side, trigger, trigger-bottom" mode="deferred" ?active=${isActive} .ghostFactory=${this._createResizeGhost} @igcResizeStart=${this._handleResizeStart} @igcResize=${this._handleResize} @igcResizeEnd=${this._handleResizeEnd} @igcResizeCancel=${this._handleResizeCancel} > ${this._renderContent()} ${this._renderAdornerSlot('side')} ${this._renderAdornerSlot('corner')} ${this._renderAdornerSlot('bottom')} </igc-resize> `; } }; IgcTileComponent.tagName = 'igc-tile'; IgcTileComponent.styles = [styles, shared]; IgcTileComponent.increment = createCounter(); __decorate([ queryAssignedElements({ slot: 'title' }) ], IgcTileComponent.prototype, "_titleElements", void 0); __decorate([ queryAssignedElements({ slot: 'actions' }) ], IgcTileComponent.prototype, "_actionsElements", void 0); __decorate([ query(IgcResizeContainerComponent.tagName) ], IgcTileComponent.prototype, "_resizeContainer", void 0); __decorate([ query('[part~="base"]', true) ], IgcTileComponent.prototype, "_tileContent", void 0); __decorate([ state() ], IgcTileComponent.prototype, "_maximized", void 0); __decorate([ state() ], IgcTileComponent.prototype, "_isDragging", void 0); __decorate([ state() ], IgcTileComponent.prototype, "_isResizing", void 0); __decorate([ property({ type: Number, attribute: 'col-span' }) ], IgcTileComponent.prototype, "colSpan", null); __decorate([ property({ type: Number, attribute: 'row-span' }) ], IgcTileComponent.prototype, "rowSpan", null); __decorate([ property({ type: Number, attribute: 'col-start' }) ], IgcTileComponent.prototype, "colStart", null); __decorate([ property({ type: Number, attribute: 'row-start' }) ], IgcTileComponent.prototype, "rowStart", null); __decorate([ property({ type: Boolean, reflect: true }) ], IgcTileComponent.prototype, "maximized", null); __decorate([ property({ type: Boolean, reflect: true, attribute: 'disable-resize' }) ], IgcTileComponent.prototype, "disableResize", void 0); __decorate([ property({ type: Boolean, reflect: true, attribute: 'disable-fullscreen' }) ], IgcTileComponent.prototype, "disableFullscreen", void 0); __decorate([ property({ type: Boolean, reflect: true, attribute: 'disable-maximize' }) ], IgcTileComponent.prototype, "disableMaximize", void 0); __decorate([ property({ type: Number }) ], IgcTileComponent.prototype, "position", null); IgcTileComponent = IgcTileComponent_1 = __decorate([ themes(all) ], IgcTileComponent); export default IgcTileComponent; //# sourceMappingURL=tile.js.map