missive / emoji-mart

🏪 One component to pick them all
https://missiveapp.com/open/emoji-mart
MIT License
8.65k stars 831 forks source link

Svelte Integration #904

Open halafi opened 7 months ago

halafi commented 7 months ago

in case anyone would find this useful, as I do not have time for putting it into PR, but I seemed to have resolved most issues I had when using this inside a svelte component (except category click is sometimes not working, but most of time it does)

it shouldn't be too much work to put this into emoji-mart-svelte package

EmojiMart.svelte:

<script>
  import { Picker } from "emoji-mart";
  import { onMount, createEventDispatcher, onDestroy } from "svelte";

  let emojiPickerEl;
  let picker;
  let mounted = false;

  const dispatch = createEventDispatcher();

  onMount(() => {
    picker = new Picker({
      theme: "light",
      autoFocus: true,
      onClickOutside: () => {
        if (mounted) dispatch("close");
      },
      onEmojiSelect: (emoji) => {
        dispatch("select", emoji);
      },
    });
    emojiPickerEl.appendChild(picker);
    setTimeout(() => {
      // ensure click outside works
      mounted = true;
    }, 1);
  });

  onDestroy(() => {
    // the clickoutside handler is not unregistered properly, so this is probably redundant
    picker = null;
    emojiPickerEl = null;
  });
</script>

<div on:click|preventDefault|stopPropagation bind:this={emojiPickerEl} />

usage:

    <EmojiMart
      on:select={(ev) => handleEmojiSelect(ev.detail)}
      on:close={() => emojiPickerVisible = false}
    />
Tenuka22 commented 2 months ago

``

<div on:click|preventDefault|stopPropagation bind:this={emojiPickerEl} role="button" tabindex="0" aria-label="Emoji Picker" />

I've created the component but this gives a ton of errors

`[{ "resource": "/e:/PROJECTS/nemori/src/lib/components/emoji-mart.svelte", "owner": "_generated_diagnostic_collectionname#1", "code": "a11y-click-events-have-key-events", "severity": 4, "message": "A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as <button type=\"button\"> or might be more appropriate. See https://svelte.dev/docs/accessibility-warnings#a11y-click-events-have-key-events for more details.", "source": "svelte", "startLineNumber": 28, "startColumn": 1, "endLineNumber": 34, "endColumn": 3 }] 11:39:39 AM [vite-plugin-svelte] E:/PROJECTS/nemori/src/lib/components/emoji-mart.svelte:23:0 A11y: visible, non-interactive elements with an on:click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as

bastek338 commented 1 month ago

@Tenuka22 Works for me.

onMount(async () => {
    const EmojiMart = await import('emoji-mart');
    picker = new EmojiMart.Picker({
    theme: 'light',
    autoFocus: true,
    onClickOutside: () => {
        if (mounted) dispatch('close');
    },
    onEmojiSelect: (emoji) => {
        dispatch('select', emoji);
    }
     });
    emojiPicker?.appendChild(picker);
});