Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use .update method ? #919

Open
midnightgamer opened this issue Jun 5, 2024 · 0 comments
Open

How to use .update method ? #919

midnightgamer opened this issue Jun 5, 2024 · 0 comments

Comments

@midnightgamer
Copy link

midnightgamer commented Jun 5, 2024

``I am using emoji-mart in my application for making Emoji Picker as Popup and I wanted picker to have focus every time i open I was getting .update method but was not able to found any document for the same

My Picker Util, which makes a popup

import { Picker } from 'emoji-mart';

type Props = {
  triggerElement: HTMLElement;
  position?: 'center' | 'baseline';
  actionOnEmojiSelect: (emoji: string) => void;
};

class EmojiPicker {
  private static instance: EmojiPicker;
  private picker: Picker | null = null;
  private isOpen: boolean = false;
  private triggerElement: HTMLElement | null = null;
  private parentElement: HTMLElement | null = null;
  private actionOnEmojiSelect: (data: any) => void;

  private constructor(triggerElement) {
    this.triggerElement = triggerElement;
    this.parentElement = document.getElementById('emojiPickerContainer');
    this.init(triggerElement);
  }

  init(triggerElement) {
    this.triggerElement = triggerElement;
    this.hidePicker();
    this.picker = new Picker({
      parent: this.parentElement,
      onEmojiSelect: e => {
        if (this.actionOnEmojiSelect) {
          this.actionOnEmojiSelect({ emoji: e.native });
        }
        this.closePicker();
      },
      onClickOutside: e => {
        const isTrigger = this.triggerElement?.dataset.trigger === 'emojiPicker';
        const position = this.triggerElement?.dataset.triggerPosition;

        if (isTrigger && (e.target === this.triggerElement || this.triggerElement?.contains(e.target))) {
          return this.getTriggerPositionAndSetToContainer(
            this.triggerElement,
            this.parentElement,
            position ? position : 'center'
          );
        }

        this.closePicker();
      }
    });
  }

  public static getInstance(triggerElement): EmojiPicker {
    if (!EmojiPicker.instance) {
      EmojiPicker.instance = new EmojiPicker(triggerElement);
    }
    EmojiPicker.instance.triggerElement = triggerElement;
    return EmojiPicker.instance;
  }

  public openPicker = (props: Props) => {
    console.log('🚀 ~ EmojiPicker ~ openPicker:', this.picker);

    this.isOpen = true;
    this.showPicker(props);
    this.autoFocus();
    this.actionOnEmojiSelect = props.actionOnEmojiSelect;
  };

  public closePicker = () => {
    this.isOpen = false;
    this.hidePicker();
    this.actionOnEmojiSelect = () => {
      return;
    };
  };

  public togglePicker = (props: Props) => {
    if (this.isOpen) {
      this.closePicker();
    } else {
      this.openPicker(props);
    }
  };

  private hidePicker(): void {
    if (this.parentElement) {
      this.parentElement.style.display = 'none';
    }
  }

  private showPicker(props: Props): void {
    if (this.parentElement) {
      this.getTriggerPositionAndSetToContainer(this.triggerElement, this.parentElement, props.position);
    }
  }

  private autoFocus = () => {
    this.picker?.update({ autoFocus: true });
  };

  private getTriggerPositionAndSetToContainer = (triggerElement, emojiPickerContainer, vertical = 'center') => {
    const triggerElementRect = triggerElement.getBoundingClientRect();
    const emojiPickerRect = { width: 352, height: 435 };
    const viewportHeight = window.innerHeight || document.documentElement.clientHeight;

    let top;

    if (vertical === 'baseline') {
      // Align picker baseline with trigger baseline
      top = triggerElementRect.bottom - emojiPickerRect.height - 40;
    } else {
      // Center align vertically
      top = Math.max(0, triggerElementRect.top + (triggerElementRect.height - emojiPickerRect.height) / 2);
    }

    // Check if there's enough space below, if not, adjust the top position
    if (top + emojiPickerRect.height > viewportHeight) {
      top = viewportHeight - emojiPickerRect.height;
    }

    // Check if there's enough space above, if not, adjust the top position
    if (top < 0) {
      top = 0;
    }

    // Calculate left position to place the picker to the left of the trigger
    const left = triggerElementRect.left - emojiPickerRect.width;

    // Set position and display style
    emojiPickerContainer.style.left = `${left}px`;
    emojiPickerContainer.style.top = `${top}px`;
    emojiPickerContainer.style.position = 'absolute';
    emojiPickerContainer.style.display = 'block';
  };
}

export default EmojiPicker;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant