jm-david / emoji-mart-vue

One component to pick them all 👊🏼
https://jm-david.github.io/emoji-mart-vue
BSD 3-Clause "New" or "Revised" License
603 stars 82 forks source link

Functional components does not seem to work #14

Open RedKage opened 6 years ago

RedKage commented 6 years ago

Hello,

I am trying to use the Emoji object in order to get some html from an Emoji object.

I am doing import { Emoji } from 'emoji-mart-vue' and then in a method I am trying to use the Emoji function const x = Emoji()

This crashes with

Uncaught TypeError: Object(...) is not a function

If I am trying to import everything import Emoji from 'emoji-mart-vue' Then I have

Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_5_emoji_mart_vue___default(...) is not a function

It doesn't matter if I give parameters to const x = Emoji(() It looks like the import itself crashes.

Is it me or is there an issue with emoji-mart?

RedKage commented 6 years ago

Uh, I just noticed something weird too: https://github.com/jm-david/emoji-mart-vue/blob/master/src/components/emoji/emoji.js

There is an import React from 'react' I'm freaking out right now ahah

Hopefully it is not used. :)

RedKage commented 6 years ago

I'm adding more stuff, the more I am trying to make this work.

This whole example doesn't work:

import data from 'emoji-mart-vue/datasets/messenger'
import { NimbleEmojiIndex } from 'emoji-mart-vue'

let emojiIndex = new NimbleEmojiIndex(data)
emojiIndex.search('christmas')

import data from 'emoji-mart-vue/datasets/messenger' fails. At least the path is incorrect, but no JS exports this anyway.

And then let emojiIndex = new NimbleEmojiIndex(data) fails as

Uncaught TypeError: WEBPACK_IMPORTED_MODULE_5_emoji_mart_vue.NimbleEmojiIndex is not a constructor

I will rename this issue with a better title to address these issues

jm-david commented 6 years ago

Hey!

The Emoji export is a component object, not a function - so you have to use it in a template/render function. Also there is no "default" export, which is why webpack was complaining about that. Here's an example of how to use the Emoji component.

// ThumbsupEmoji.js
import { Emoji } from "emoji-mart-vue"

export default {
  template: '<emoji emoji="+1" />',
  components: { Emoji }
}

Also no need to be concerned about the react files haha, I keep them in the repo because it makes it easier to keep up to date with the main react library when I'm merging updates. Those files aren't used at all in the compiled code.

Now that the package has been published to npm properly, NimbleEmojiIndex should work as expected. However, the README actually had the wrong path for the data files! Thanks for flagging it, I've updated it to reflect the correct path: import data from "emoji-mart-vue/data/messenger.json".

Let me know if you have any other issues :)

RedKage commented 6 years ago

Okay! The NimbleEmojiIndex does work well now!

However I was looking for using Emoji outside of the component. Like calling directly

Emoji({
      html: true
      set: 'apple'
      emoji: '+1'
      size: 24
    })

But I guess that's not possible. I'm trying to parse a text that has :colon: tags in it, and replace with the emojis pictures. I was like, I am going to use this call to render the html and replace each :colon: tag with it.

But it's okay, I do have all the info now using NimbleEmojiIndex. I can use emojiIndex.data.emojis.stuff.sheet_x and sheet_y to get the coordinates and build the html myself now!

So far, the issue with instanciating NimbleEmojiIndex is fixed in 2.6.3. And my issue with 'intanciating' Emoji was a misunderstanding from me.

RedKage commented 6 years ago

Well actually... I do not have all the info from the NimbleEmojiIndex. I am missing the skin tones for instance. And other stuff too, like the emoticon support. I guess I could code this myself still, with lots of effort. Pretty much recoding NimbleEmoji.

It's too bad we cannot access Emoji programmatically and get the html output of <emoji emoji="+1" />.

This issue here is pretty much the same with all the emojis libraries I've used in the past: the picker is great but parsing support is always poor.

RedKage commented 6 years ago

For reference, here is what I did

parseEmojis (text) {
      let parsedText = text

      // parses :colon: tags
      const emojiRegex = /:([^:]*)/g
      let match = emojiRegex.exec(text)
      while (match) {
        const shortName = match[1]
        const colonTag = `:${shortName}:`

        // finds emoji in data
        for (let emojiKey of Object.keys(emoji.emojiIndex.data.emojis)) {
          const currentEmoji = emoji.emojiIndex.data.emojis[emojiKey]

          const foundShortName = currentEmoji.short_names.find(n => n === shortName)
          if (foundShortName) {
            const span = `<span class='emoji' style='background-image: url("${emoji.spriteUrl}"); background-size: ${100 * emoji.spriteColumns}%; background-position: ${emoji.cssPercentPerColumn * currentEmoji.sheet_x}% ${emoji.cssPercentPerColumn * currentEmoji.sheet_y}%;' title='${shortName}'>${colonTag}</span>`
            const colonRegexEscaped = colonTag.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') // RegEx escape
            parsedText = parsedText.replace(new RegExp(colonRegexEscaped, 'gm'), span) // Replace :colon: with <span>
            break
          }

          // todo search in .emoticons
          // todo search in .text
          // todo skin tones
        }
        match = emojiRegex.exec(text)
      }

      return parsedText
    }

There is an emoji object in this piece of code, this one is 'required' in my component so there is only one instance in my application.

import emojiData from 'emoji-mart-vue/data/google'
import { NimbleEmojiIndex } from 'emoji-mart-vue'

const emojiSize = 32
const spriteUrl = `http://myAwesomeUrl/emojis/google-sheet-${emojiSize}-4.0.4.png`
const spriteColumns = 52
const cssPercentPerColumn = 100 / (spriteColumns - 1)

// Load emoji data once
const emojiIndex = new NimbleEmojiIndex(emojiData)

export default {
  emojiIndex: emojiIndex,
  emojiSize: emojiSize,
  spriteUrl: spriteUrl,
  spriteColumns: spriteColumns,
  cssPercentPerColumn: cssPercentPerColumn
}
jm-david commented 6 years ago

Ahh yeah, dynamically replacing ":emoji:" strings is definitely a challenge. Here's what I recommended to someone else: https://gist.github.com/jm-david/7f98c3ee4fe235c596cff26d7aa26b7b

It's a render function which takes a string and replaces ":emoji:" with an Emoji component. Check it out and let me know if you think this will work for you :)

RedKage commented 6 years ago

Nice! I may try this out! Thanks I understand this gist is a component to use to render 'text' which contains :emoji: stuff.

My issue with this, is that my 'text' in my application is already sent to a custom component (which uses a v-html) and I have no control on its Vue template. Hence, why I am programmatically parsing the text myself and then sending it to this custom component. One way to solve my issue, would be to fork this custom component so I can edit its structure to instead of using a simple v-html I'd use your gist component.

Wait... maybe I can use your Gist outside of a component... but what is this h object that is a function?

jm-david commented 6 years ago

Ah I see, hmm I don't have any ideas sorry 😕

Here's the page in the vue docs which documents the createElement function (I've just used h cause it's shorter) https://vuejs.org/v2/guide/render-function.html#createElement-Arguments

However I don't think you can use this function to create an HTML representation of the element. That function returns a VNode object thing, which vue then uses internally to diff and update the DOM.

Forking the custom component may be your best option, but let me know if you figure out another solution! :)

vijaythecoder commented 6 years ago

any solution on this? @RedKage I am also looking for solution to replace I am on my way:laughing:

RedKage commented 6 years ago

No solution. We stopped using emojimart.

We are now using the simple 'node-emoji' https://github.com/omnidan/node-emoji and are building the UI ourselves, using 'unicode-emoji-modifier-base' https://github.com/mathiasbynens/unicode-emoji-modifier-base for minimal skin tone support.

Now we store the unicode character directly in our message. We do not handle any images at all. We completely changed how we would deal with emojis, and are storing unicode characters instead.

The lack of support from emoji-mart pushed us to do this, but now that we've switched to unicode only, I can see only benefits. Our code is uch faster, no need to DL huge sprites, easier to maintain etc.

We will integrate and implement custom emojis ourselves in the future. If we have to.

vijaythecoder commented 6 years ago

@RedKage thanks for the reply.