UNPKG

@govbr-ds/webcomponents

Version:

Biblioteca de Web Components baseado no GovBR-DS

120 lines (119 loc) 5.41 kB
/*! * Construído por SERPRO * © https://serpro.gov.br/ - MIT License. */ import { arrow, autoUpdate, computePosition, flip, hide, offset, shift } from "@floating-ui/dom"; /** * FloatingUIManager é uma classe utilitária que gerencia o posicionamento de elementos flutuantes * como tooltips ou popovers em relação a um elemento de disparo (trigger). * Ela utiliza a biblioteca Floating UI para calcular posições e lidar com atualizações. */ export class FloatingUIManager { triggerElement; contentElement; arrowElement; placement; onUpdate; cleanupAutoUpdate; constructor(options) { this.triggerElement = options.triggerElement; this.contentElement = options.contentElement; this.arrowElement = options.arrowElement; this.placement = options.placement ?? 'top'; this.onUpdate = options.onUpdate; } /** * Inicia o gerenciador Floating UI configurando a atualização automática da posição. */ start() { this.cleanupAutoUpdate = autoUpdate(this.triggerElement, this.contentElement, () => this.updatePosition()); } /** * Para o gerenciador Floating UI e limpa os recursos utilizados. */ stop() { this.cleanupAutoUpdate?.(); } /** * Atualiza a posição do elemento flutuante com base no elemento disparador e no elemento de conteúdo. * Esta função é chamada automaticamente quando o gerenciador está ativo. * Ela calcula a nova posição usando a biblioteca Floating UI e aplica as transformações necessárias. * Também atualiza a posição da seta, se fornecida. * Além disso, define o atributo de dados `data-placement` no elemento de conteúdo para refletir a posição atual. * @returns {Promise<void>} Uma promessa que resolve quando a posição é atualizada. */ async updatePosition() { const data = await computePosition(this.triggerElement, this.contentElement, { placement: this.placement, middleware: this.buildMiddleware(), }); this.updateTooltipPosition(data); this.updateArrowPosition(data); this.setPlacementDataAttribute(data); this.onUpdate?.(data); } /** * Constrói os middlewares necessários para o Floating UI. * Esses middlewares são usados para ajustar o posicionamento do elemento flutuante, * incluindo offset, flip, shift e hide. Se uma seta for fornecida, o middleware de seta também é adicionado. * @returns {Middleware[]} Retorna um array de middlewares configurados para o Floating UI. */ buildMiddleware() { const middleware = [offset(8), flip(), shift({ padding: 5 }), hide()]; if (this.arrowElement != null) { middleware.push(arrow({ element: this.arrowElement })); } return middleware; } /** * Adiciona o estilo necessário para posicionar o tooltip com base nas coordenadas fornecidas. * Esta função é chamada após o cálculo da posição do tooltip. * Ela aplica as propriedades CSS `left` e `top` ao elemento de conteúdo do tooltip. * @param data Contém as coordenadas x e y para posicionar o tooltip. */ updateTooltipPosition(data) { const { x, y } = data; Object.assign(this.contentElement.style, { left: `${x}px`, top: `${y}px`, }); } /** * Adiciona o estilo necessário para posicionar a seta do tooltip com base nos dados de middleware. * Esta função é chamada após o cálculo da posição do tooltip. * Ela aplica as propriedades CSS `left`, `top`, `right`, `bottom` e a posição estática da seta. * A posição estática é determinada com base na colocação do tooltip (top, right, bottom, left). * Se a seta não estiver presente ou os dados de middleware não contiverem informações sobre a seta, nada será feito. * @param data Contém a posição da seta e os dados de middleware. */ updateArrowPosition(data) { if (this.arrowElement == null || data.middlewareData.arrow == null) return; const { x: arrowX, y: arrowY } = data.middlewareData.arrow; const basePlacement = data.placement.split('-')[0]; const staticSide = { top: 'bottom', right: 'left', bottom: 'top', left: 'right', }[basePlacement]; Object.assign(this.arrowElement.style, { left: arrowX != null ? `${arrowX}px` : '', top: arrowY != null ? `${arrowY}px` : '', right: '', bottom: '', [staticSide]: '-4px', }); } /** * Define o atributo de dados `data-placement` no elemento de conteúdo. * Este atributo é usado para indicar a posição atual do tooltip ou popover. * Ele é útil para fins de acessibilidade e para permitir que estilos CSS sejam aplicados com base na posição. * @param data Objeto contendo a propriedade `placement` que define a posição do tooltip ou popover. * A propriedade `placement` deve ser uma string representando a posição, como 'top', 'bottom', 'left', 'right', etc. */ setPlacementDataAttribute(data) { this.contentElement.setAttribute('data-placement', data.placement); } } //# sourceMappingURL=floating-ui.js.map